aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS38
-rw-r--r--COPYING.BSD93
-rw-r--r--COPYING.LGPL6
-rw-r--r--COPYRIGHT1
-rw-r--r--Makefile2
-rw-r--r--Makefile.common3
-rw-r--r--NEWS47
-rw-r--r--README29
-rw-r--r--backends/events/default/default-events.cpp4
-rw-r--r--backends/fs/amigaos4/amigaos4-fs.cpp2
-rw-r--r--backends/fs/ds/ds-fs-factory.cpp2
-rw-r--r--backends/fs/ds/ds-fs.cpp192
-rw-r--r--backends/fs/ds/ds-fs.h57
-rw-r--r--backends/fs/palmos/palmos-fs.cpp212
-rw-r--r--backends/fs/psp/psp-stream.cpp308
-rw-r--r--backends/keymapper/remap-dialog.cpp14
-rw-r--r--backends/midi/alsa.cpp321
-rw-r--r--backends/midi/camd.cpp13
-rw-r--r--backends/midi/coreaudio.cpp13
-rw-r--r--backends/midi/coremidi.cpp13
-rw-r--r--backends/midi/dmedia.cpp13
-rw-r--r--backends/midi/seq.cpp17
-rw-r--r--backends/midi/stmidi.cpp14
-rw-r--r--backends/midi/timidity.cpp13
-rw-r--r--backends/midi/windows.cpp51
-rw-r--r--backends/midi/ypa1.cpp150
-rw-r--r--backends/midi/zodiac.cpp170
-rw-r--r--backends/module.mk51
-rw-r--r--backends/platform/PalmOS/Rsc/Resource.Frk/Starter.rsrcbin52995 -> 0 bytes
-rw-r--r--backends/platform/PalmOS/Rsc/Starter.rsrc0
-rw-r--r--backends/platform/PalmOS/Rsc/StarterRsc.h395
-rw-r--r--backends/platform/PalmOS/Rsc/batLow.bmpbin1592 -> 0 bytes
-rw-r--r--backends/platform/PalmOS/Rsc/keyAlt.bmpbin1336 -> 0 bytes
-rw-r--r--backends/platform/PalmOS/Rsc/keyCommand.bmpbin1336 -> 0 bytes
-rw-r--r--backends/platform/PalmOS/Rsc/keyCtrl.bmpbin1336 -> 0 bytes
-rw-r--r--backends/platform/PalmOS/Rsc/modules.rcp71
-rw-r--r--backends/platform/PalmOS/Rsc/modulesrsc.h6
-rw-r--r--backends/platform/PalmOS/Rsc/numpad.bmpbin1336 -> 0 bytes
-rw-r--r--backends/platform/PalmOS/Src/args.cpp106
-rw-r--r--backends/platform/PalmOS/Src/base_event.cpp458
-rw-r--r--backends/platform/PalmOS/Src/base_gfx.cpp198
-rw-r--r--backends/platform/PalmOS/Src/base_mouse.cpp101
-rw-r--r--backends/platform/PalmOS/Src/be_68k.cpp27
-rw-r--r--backends/platform/PalmOS/Src/be_68k.h27
-rw-r--r--backends/platform/PalmOS/Src/be_base.cpp203
-rw-r--r--backends/platform/PalmOS/Src/be_base.h265
-rw-r--r--backends/platform/PalmOS/Src/be_os5.cpp169
-rw-r--r--backends/platform/PalmOS/Src/be_os5.h189
-rw-r--r--backends/platform/PalmOS/Src/be_os5ex.cpp103
-rw-r--r--backends/platform/PalmOS/Src/be_os5ex.h68
-rw-r--r--backends/platform/PalmOS/Src/be_zodiac.cpp74
-rw-r--r--backends/platform/PalmOS/Src/be_zodiac.h76
-rw-r--r--backends/platform/PalmOS/Src/cd_aeroplayer.cpp166
-rw-r--r--backends/platform/PalmOS/Src/cd_default.cpp104
-rw-r--r--backends/platform/PalmOS/Src/cd_default.h51
-rw-r--r--backends/platform/PalmOS/Src/cd_msa.cpp261
-rw-r--r--backends/platform/PalmOS/Src/cd_pockettunes.cpp238
-rw-r--r--backends/platform/PalmOS/Src/cd_pockettunes.h69
-rw-r--r--backends/platform/PalmOS/Src/cdaudio.h67
-rw-r--r--backends/platform/PalmOS/Src/extend.cpp109
-rw-r--r--backends/platform/PalmOS/Src/features.h17
-rw-r--r--backends/platform/PalmOS/Src/globals.h114
-rw-r--r--backends/platform/PalmOS/Src/i_zodiac.cpp41
-rw-r--r--backends/platform/PalmOS/Src/i_zodiac.h12
-rw-r--r--backends/platform/PalmOS/Src/init_golcd.cpp121
-rw-r--r--backends/platform/PalmOS/Src/init_golcd.h22
-rw-r--r--backends/platform/PalmOS/Src/init_mathlib.cpp29
-rw-r--r--backends/platform/PalmOS/Src/init_mathlib.h7
-rw-r--r--backends/platform/PalmOS/Src/init_pa1lib.cpp32
-rw-r--r--backends/platform/PalmOS/Src/init_pa1lib.h22
-rw-r--r--backends/platform/PalmOS/Src/init_palmos.cpp172
-rw-r--r--backends/platform/PalmOS/Src/init_sony.cpp163
-rw-r--r--backends/platform/PalmOS/Src/init_stuffs.cpp134
-rw-r--r--backends/platform/PalmOS/Src/init_stuffs.h11
-rw-r--r--backends/platform/PalmOS/Src/launcher/app.cpp360
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formCards.cpp383
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formEditGame.cpp612
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formMisc.cpp275
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formSelect.cpp278
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp267
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formUtil.cpp60
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formUtil.h23
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/forminfo.cpp146
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formmain.cpp364
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp388
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/forms.h23
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formtabs.cpp242
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formtabs.h24
-rw-r--r--backends/platform/PalmOS/Src/launcher/games.cpp548
-rw-r--r--backends/platform/PalmOS/Src/launcher/games.h212
-rw-r--r--backends/platform/PalmOS/Src/launcher/launch.cpp512
-rw-r--r--backends/platform/PalmOS/Src/launcher/skin.cpp612
-rw-r--r--backends/platform/PalmOS/Src/launcher/skin.h131
-rw-r--r--backends/platform/PalmOS/Src/launcher/start.cpp367
-rw-r--r--backends/platform/PalmOS/Src/launcher/start.h98
-rw-r--r--backends/platform/PalmOS/Src/modules.cpp156
-rw-r--r--backends/platform/PalmOS/Src/modules.h22
-rw-r--r--backends/platform/PalmOS/Src/native/oscalls.cpp92
-rw-r--r--backends/platform/PalmOS/Src/native/pace.h103
-rw-r--r--backends/platform/PalmOS/Src/native/pnoARM.c60
-rw-r--r--backends/platform/PalmOS/Src/native/pnoStartup.c28
-rw-r--r--backends/platform/PalmOS/Src/native/zodiacARM.cpp150
-rw-r--r--backends/platform/PalmOS/Src/native/zodiacStartup.cpp161
-rw-r--r--backends/platform/PalmOS/Src/os5_event.cpp82
-rw-r--r--backends/platform/PalmOS/Src/os5_gfx.cpp309
-rw-r--r--backends/platform/PalmOS/Src/os5_mouse.cpp157
-rw-r--r--backends/platform/PalmOS/Src/os5_overlay.cpp76
-rw-r--r--backends/platform/PalmOS/Src/os5_renderer.cpp118
-rw-r--r--backends/platform/PalmOS/Src/os5_sound.cpp156
-rw-r--r--backends/platform/PalmOS/Src/os5ex_sound.cpp43
-rw-r--r--backends/platform/PalmOS/Src/palmdefs.h21
-rw-r--r--backends/platform/PalmOS/Src/prefixes/compile.h76
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_agi.h11
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_agos.h7
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_cine.h12
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_common.h19
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_cruise.h11
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_drascula.h7
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_gob.h7
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_kyra.h7
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_lure.h11
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_m4.h7
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_made.h7
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_parallaction.h11
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_queen.h7
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_saga.h7
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_scumm.h12
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_sky.h7
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_sword1.h9
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_sword2.h10
-rw-r--r--backends/platform/PalmOS/Src/prefixes/native_touche.h7
-rw-r--r--backends/platform/PalmOS/Src/prefixes/prefix_frontend.h9
-rw-r--r--backends/platform/PalmOS/Src/prefixes/prefix_os5.h13
-rw-r--r--backends/platform/PalmOS/Src/prefixes/prefix_zodiac.h13
-rw-r--r--backends/platform/PalmOS/Src/rumble.cpp140
-rw-r--r--backends/platform/PalmOS/Src/rumble.h34
-rw-r--r--backends/platform/PalmOS/Src/snd_pa1.cpp113
-rw-r--r--backends/platform/PalmOS/Src/stuffs.h32
-rw-r--r--backends/platform/PalmOS/Src/vibrate.h61
-rw-r--r--backends/platform/PalmOS/Src/zodiac_event.cpp100
-rw-r--r--backends/platform/PalmOS/Src/zodiac_gfx.cpp309
-rw-r--r--backends/platform/PalmOS/Src/zodiac_mouse.cpp153
-rw-r--r--backends/platform/PalmOS/Src/zodiac_overlay.cpp67
-rwxr-xr-xbackends/platform/PalmOS/arm.bat3
-rw-r--r--backends/platform/PalmOS/scummvm.mcpbin1147982 -> 0 bytes
-rw-r--r--backends/platform/android/README.build91
-rw-r--r--backends/platform/android/android.cpp1412
-rw-r--r--backends/platform/android/android.mk59
-rw-r--r--backends/platform/android/asset-archive.cpp414
-rw-r--r--backends/platform/android/asset-archive.h (renamed from backends/platform/PalmOS/Src/cd_msa.h)53
-rw-r--r--backends/platform/android/module.mk84
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java59
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/Event.java330
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java52
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVM.java353
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java466
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java29
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/Unpacker.java370
-rw-r--r--backends/platform/android/video.cpp334
-rw-r--r--backends/platform/android/video.h140
-rw-r--r--backends/platform/dc/Makefile2
-rw-r--r--backends/platform/dc/dc.h5
-rw-r--r--backends/platform/dc/dcmain.cpp11
-rw-r--r--backends/platform/dc/display.cpp2
-rw-r--r--backends/platform/dc/module.mk9
-rw-r--r--backends/platform/dc/selector.cpp98
-rw-r--r--backends/platform/ds/arm7/source/main.cpp24
-rw-r--r--backends/platform/ds/arm9/makefile188
-rw-r--r--backends/platform/ds/arm9/source/blitters.cpp79
-rw-r--r--backends/platform/ds/arm9/source/blitters.h27
-rw-r--r--backends/platform/ds/arm9/source/cdaudio.cpp165
-rw-r--r--backends/platform/ds/arm9/source/cdaudio.h11
-rw-r--r--backends/platform/ds/arm9/source/compressor/lz.cpp539
-rw-r--r--backends/platform/ds/arm9/source/compressor/lz.h50
-rw-r--r--backends/platform/ds/arm9/source/dsmain.cpp141
-rw-r--r--backends/platform/ds/arm9/source/dsmain.h27
-rw-r--r--backends/platform/ds/arm9/source/dsoptions.cpp78
-rw-r--r--backends/platform/ds/arm9/source/dsoptions.h51
-rw-r--r--backends/platform/ds/arm9/source/elf32.h196
-rw-r--r--backends/platform/ds/arm9/source/fat/gba_nds_fat.c12
-rw-r--r--backends/platform/ds/arm9/source/gbampsave.cpp67
-rw-r--r--backends/platform/ds/arm9/source/gbampsave.h20
-rw-r--r--backends/platform/ds/arm9/source/keys.cpp36
-rw-r--r--backends/platform/ds/arm9/source/keys.h27
-rw-r--r--backends/platform/ds/arm9/source/libcartreset/cartreset.c107
-rw-r--r--backends/platform/ds/arm9/source/libcartreset/cartreset_nolibfat.h57
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.cpp106
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.h43
-rw-r--r--backends/platform/ds/arm9/source/portdefs.cpp35
-rw-r--r--backends/platform/ds/arm9/source/portdefs.h59
-rw-r--r--backends/platform/ds/arm9/source/ramsave.cpp538
-rw-r--r--backends/platform/ds/arm9/source/ramsave.h150
-rw-r--r--backends/platform/ds/arm9/source/scummhelp.cpp12
-rw-r--r--backends/platform/ds/arm9/source/scummhelp.h12
-rw-r--r--backends/platform/ds/arm9/source/touchkeyboard.cpp214
-rw-r--r--backends/platform/ds/arm9/source/touchkeyboard.h25
-rw-r--r--backends/platform/ds/arm9/source/wordcompletion.cpp36
-rw-r--r--backends/platform/ds/arm9/source/wordcompletion.h27
-rw-r--r--backends/platform/ds/arm9/source/zipreader.cpp17
-rw-r--r--backends/platform/ds/arm9/source/zipreader.h23
-rw-r--r--backends/platform/ds/commoninclude/NDS/scummvm_ipc.h60
-rw-r--r--backends/platform/ds/ds.mk192
-rw-r--r--backends/platform/ds/makefile20
-rw-r--r--backends/platform/ds/module.mk32
-rwxr-xr-xbackends/platform/ds/setup-builddirs.sh57
-rwxr-xr-xbackends/platform/gp2x/build/bundle.sh50
-rw-r--r--backends/platform/gp2x/events.cpp1
-rwxr-xr-xbackends/platform/gp2x/gp2x-bundle.mk60
-rw-r--r--backends/platform/gp2x/module.mk9
-rwxr-xr-xbackends/platform/gp2xwiz/build/bundle-debug.sh51
-rwxr-xr-xbackends/platform/gp2xwiz/build/bundle.sh54
-rwxr-xr-xbackends/platform/gp2xwiz/gp2xwiz-bundle.mk73
-rw-r--r--backends/platform/gp2xwiz/gp2xwiz-events.cpp1
-rw-r--r--backends/platform/gp2xwiz/gp2xwiz-graphics.cpp2
-rw-r--r--backends/platform/gp2xwiz/module.mk9
-rw-r--r--backends/platform/iphone/iphone_video.m2
-rw-r--r--backends/platform/iphone/module.mk9
-rw-r--r--backends/platform/iphone/osys_events.cpp5
-rw-r--r--backends/platform/linuxmoto/module.mk9
-rw-r--r--backends/platform/n64/Makefile2
-rw-r--r--backends/platform/n64/README.N642
-rw-r--r--backends/platform/n64/module.mk16
-rw-r--r--backends/platform/null/module.mk9
-rw-r--r--backends/platform/ps2/Makefile.gdb2
-rw-r--r--backends/platform/ps2/Makefile.ps25
-rw-r--r--backends/platform/ps2/module.mk9
-rw-r--r--backends/platform/psp/Makefile16
-rw-r--r--backends/platform/psp/README.PSP2
-rw-r--r--backends/platform/psp/README.PSP.in2
-rw-r--r--backends/platform/psp/audio.cpp150
-rw-r--r--backends/platform/psp/audio.h69
-rw-r--r--backends/platform/psp/cursor.cpp4
-rw-r--r--backends/platform/psp/default_display_client.h4
-rw-r--r--backends/platform/psp/display_client.cpp34
-rw-r--r--backends/platform/psp/display_manager.cpp51
-rw-r--r--backends/platform/psp/display_manager.h34
-rw-r--r--backends/platform/psp/input.cpp4
-rw-r--r--backends/platform/psp/memory.cpp457
-rw-r--r--backends/platform/psp/memory.h61
-rw-r--r--backends/platform/psp/module.mk16
-rw-r--r--backends/platform/psp/mp3.cpp487
-rw-r--r--backends/platform/psp/mp3.h121
-rw-r--r--backends/platform/psp/osys_psp.cpp106
-rw-r--r--backends/platform/psp/osys_psp.h15
-rw-r--r--backends/platform/psp/powerman.cpp352
-rw-r--r--backends/platform/psp/powerman.h75
-rw-r--r--backends/platform/psp/psp.spec2
-rw-r--r--backends/platform/psp/psp_main.cpp14
-rw-r--r--backends/platform/psp/rtc.cpp87
-rw-r--r--backends/platform/psp/rtc.h (renamed from backends/fs/palmos/palmos-fs-factory.h)49
-rw-r--r--backends/platform/psp/tests.cpp565
-rw-r--r--backends/platform/psp/tests.h (renamed from backends/platform/PalmOS/Src/launcher/forms/formCards.h)17
-rw-r--r--backends/platform/psp/thread.cpp234
-rw-r--r--backends/platform/psp/thread.h112
-rw-r--r--backends/platform/psp/trace.cpp11
-rw-r--r--backends/platform/psp/trace.h12
-rw-r--r--backends/platform/samsungtv/module.mk9
-rw-r--r--backends/platform/sdl/events.cpp1
-rw-r--r--backends/platform/sdl/graphics.cpp132
-rw-r--r--backends/platform/sdl/main.cpp1
-rw-r--r--backends/platform/sdl/module.mk9
-rw-r--r--backends/platform/sdl/sdl.cpp9
-rw-r--r--backends/platform/sdl/sdl.h9
-rw-r--r--backends/platform/symbian/BuildPackageUpload_AllVersions.pl1
-rw-r--r--backends/platform/symbian/BuildPackageUpload_LocalSettings.pl43
-rw-r--r--backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in7
-rw-r--r--backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in7
-rw-r--r--backends/platform/symbian/mmp/scummvm_sci.mmp.in2
-rw-r--r--backends/platform/symbian/src/SymbianActions.cpp41
-rw-r--r--backends/platform/symbian/src/SymbianOS.cpp3
-rw-r--r--backends/platform/wii/module.mk9
-rw-r--r--backends/platform/wii/options.cpp82
-rw-r--r--backends/platform/wii/osystem.h2
-rw-r--r--backends/platform/wii/osystem_gfx.cpp2
-rw-r--r--backends/platform/wince/CEActionsPocket.cpp46
-rw-r--r--backends/platform/wince/CEActionsSmartphone.cpp36
-rw-r--r--backends/platform/wince/CELauncherDialog.cpp10
-rw-r--r--backends/platform/wince/module.mk9
-rw-r--r--backends/platform/wince/wince-sdl.cpp6
-rw-r--r--backends/plugins/win32/win32-provider.cpp1
-rw-r--r--backends/vkeybd/virtual-keyboard.cpp2
-rw-r--r--base/commandLine.cpp10
-rw-r--r--base/internal_version.h5
-rw-r--r--base/internal_version.h.in5
-rw-r--r--base/main.cpp38
-rw-r--r--base/plugins.cpp14
-rw-r--r--base/version.cpp4
-rw-r--r--common/algorithm.h15
-rw-r--r--common/config-file.cpp2
-rw-r--r--common/error.cpp30
-rw-r--r--common/error.h2
-rw-r--r--common/events.h9
-rw-r--r--common/file.cpp4
-rw-r--r--common/hashmap.h3
-rw-r--r--common/macresman.cpp10
-rw-r--r--common/messages.cpp2722
-rw-r--r--common/module.mk1
-rw-r--r--common/ptr.h6
-rw-r--r--common/savefile.h4
-rw-r--r--common/scummsys.h21
-rw-r--r--common/singleton.h2
-rw-r--r--common/str.cpp12
-rw-r--r--common/str.h3
-rw-r--r--common/stream.cpp27
-rw-r--r--common/stream.h2
-rw-r--r--common/system.h4
-rw-r--r--common/textconsole.cpp22
-rw-r--r--common/translation.cpp217
-rw-r--r--common/translation.h145
-rw-r--r--common/unarj.cpp4
-rw-r--r--common/unzip.cpp49
-rw-r--r--common/unzip.h4
-rw-r--r--common/util.cpp154
-rw-r--r--common/util.h21
-rwxr-xr-xconfigure543
-rw-r--r--dists/android/AndroidManifest.xml58
-rw-r--r--dists/android/AndroidManifest.xml.in58
-rwxr-xr-xdists/android/mkmanifest.pl170
-rw-r--r--dists/android/res/drawable/gradient.xml7
-rw-r--r--dists/android/res/drawable/scummvm.pngbin0 -> 6502 bytes
-rw-r--r--dists/android/res/drawable/scummvm_big.pngbin0 -> 33931 bytes
-rw-r--r--dists/android/res/layout/main.xml10
-rw-r--r--dists/android/res/layout/splash.xml19
-rw-r--r--dists/android/res/values/strings.xml22
-rw-r--r--dists/engine-data/kyra.datbin353834 -> 355807 bytes
-rw-r--r--dists/iphone/Info.plist5
-rw-r--r--dists/iphone/icon-72.pngbin0 -> 9695 bytes
-rwxr-xr-xdists/iphone/scummvm.xcodeproj/project.pbxproj302
-rw-r--r--engines/advancedDetector.cpp69
-rw-r--r--engines/advancedDetector.h22
-rw-r--r--engines/agi/agi.cpp42
-rw-r--r--engines/agi/agi.h295
-rw-r--r--engines/agi/console.cpp26
-rw-r--r--engines/agi/console.h17
-rw-r--r--engines/agi/cycle.cpp25
-rw-r--r--engines/agi/detection.cpp847
-rw-r--r--engines/agi/detection_tables.h863
-rw-r--r--engines/agi/keyboard.cpp11
-rw-r--r--engines/agi/loader_v2.cpp2
-rw-r--r--engines/agi/loader_v3.cpp18
-rw-r--r--engines/agi/module.mk5
-rw-r--r--engines/agi/op_cmd.cpp1432
-rw-r--r--engines/agi/op_test.cpp101
-rw-r--r--engines/agi/picture.cpp14
-rw-r--r--engines/agi/preagi.cpp4
-rw-r--r--engines/agi/saveload.cpp10
-rw-r--r--engines/agi/sound.cpp1209
-rw-r--r--engines/agi/sound.h425
-rw-r--r--engines/agi/sound_2gs.cpp919
-rw-r--r--engines/agi/sound_2gs.h353
-rw-r--r--engines/agi/sound_coco3.cpp80
-rw-r--r--engines/agi/sound_coco3.h (renamed from engines/sci/graphics/gui32.h)65
-rw-r--r--engines/agi/sound_midi.cpp345
-rw-r--r--engines/agi/sound_midi.h114
-rw-r--r--engines/agi/sound_pcjr.cpp512
-rw-r--r--engines/agi/sound_pcjr.h127
-rw-r--r--engines/agi/sound_sarien.cpp357
-rw-r--r--engines/agi/sound_sarien.h120
-rw-r--r--engines/agi/sprite.cpp67
-rw-r--r--engines/agi/sprite.h4
-rw-r--r--engines/agi/text.cpp14
-rw-r--r--engines/agi/view.cpp36
-rw-r--r--engines/agi/view.h1
-rw-r--r--engines/agi/wagparser.cpp6
-rw-r--r--engines/agi/words.cpp6
-rw-r--r--engines/agos/agos.cpp55
-rw-r--r--engines/agos/agos.h2
-rw-r--r--engines/agos/cursor.cpp18
-rw-r--r--engines/agos/detection.cpp11
-rw-r--r--engines/agos/draw.cpp8
-rw-r--r--engines/agos/event.cpp11
-rw-r--r--engines/agos/gfx.cpp6
-rw-r--r--engines/agos/icons.cpp2
-rw-r--r--engines/agos/input.cpp18
-rw-r--r--engines/agos/midi.cpp14
-rw-r--r--engines/agos/verb.cpp6
-rw-r--r--engines/agos/vga_e2.cpp6
-rw-r--r--engines/agos/vga_s2.cpp2
-rw-r--r--engines/cine/anim.cpp16
-rw-r--r--engines/cine/anim.h2
-rw-r--r--engines/cine/bg_list.cpp21
-rw-r--r--engines/cine/bg_list.h1
-rw-r--r--engines/cine/cine.cpp48
-rw-r--r--engines/cine/cine.h35
-rw-r--r--engines/cine/detection.cpp499
-rw-r--r--engines/cine/detection_tables.h513
-rw-r--r--engines/cine/gfx.cpp137
-rw-r--r--engines/cine/gfx.h4
-rw-r--r--engines/cine/main_loop.cpp28
-rw-r--r--engines/cine/msg.cpp10
-rw-r--r--engines/cine/msg.h2
-rw-r--r--engines/cine/object.cpp85
-rw-r--r--engines/cine/object.h3
-rw-r--r--engines/cine/pal.cpp23
-rw-r--r--engines/cine/pal.h2
-rw-r--r--engines/cine/part.cpp54
-rw-r--r--engines/cine/part.h2
-rw-r--r--engines/cine/prc.cpp13
-rw-r--r--engines/cine/prc.h3
-rw-r--r--engines/cine/rel.cpp16
-rw-r--r--engines/cine/rel.h2
-rw-r--r--engines/cine/saveload.cpp104
-rw-r--r--engines/cine/saveload.h2
-rw-r--r--engines/cine/script.h3
-rw-r--r--engines/cine/script_fw.cpp73
-rw-r--r--engines/cine/script_os.cpp12
-rw-r--r--engines/cine/various.cpp314
-rw-r--r--engines/cine/various.h6
-rw-r--r--engines/cruise/actor.cpp28
-rw-r--r--engines/cruise/background.cpp12
-rw-r--r--engines/cruise/cruise.cpp10
-rw-r--r--engines/cruise/cruise.h20
-rw-r--r--engines/cruise/cruise_main.cpp50
-rw-r--r--engines/cruise/cruise_main.h2
-rw-r--r--engines/cruise/ctp.cpp10
-rw-r--r--engines/cruise/ctp.h3
-rw-r--r--engines/cruise/decompiler.cpp2
-rw-r--r--engines/cruise/detection.cpp6
-rw-r--r--engines/cruise/font.cpp27
-rw-r--r--engines/cruise/function.cpp12
-rw-r--r--engines/cruise/gfxModule.cpp97
-rw-r--r--engines/cruise/gfxModule.h6
-rw-r--r--engines/cruise/mainDraw.cpp26
-rw-r--r--engines/cruise/perso.cpp13
-rw-r--r--engines/cruise/saveload.cpp20
-rw-r--r--engines/cruise/script.cpp4
-rw-r--r--engines/cruise/vars.cpp37
-rw-r--r--engines/cruise/vars.h63
-rw-r--r--engines/cruise/volume.cpp62
-rw-r--r--engines/dialogs.cpp64
-rw-r--r--engines/dialogs.h43
-rw-r--r--engines/draci/animation.cpp6
-rw-r--r--engines/draci/barchive.cpp5
-rw-r--r--engines/draci/detection.cpp16
-rw-r--r--engines/draci/draci.cpp78
-rw-r--r--engines/draci/game.cpp151
-rw-r--r--engines/draci/game.h20
-rw-r--r--engines/draci/module.mk3
-rw-r--r--engines/draci/script.cpp8
-rw-r--r--engines/draci/sound.cpp203
-rw-r--r--engines/draci/sound.h130
-rw-r--r--engines/draci/walking.cpp4
-rw-r--r--engines/drascula/actors.cpp11
-rw-r--r--engines/drascula/animation.cpp142
-rw-r--r--engines/drascula/console.cpp (renamed from backends/platform/PalmOS/Src/native/oscalls.h)51
-rw-r--r--engines/drascula/console.h (renamed from backends/platform/PalmOS/Src/launcher/forms/formEditGame.h)34
-rw-r--r--engines/drascula/converse.cpp10
-rw-r--r--engines/drascula/detection.cpp6
-rw-r--r--engines/drascula/drascula.cpp47
-rw-r--r--engines/drascula/drascula.h5
-rw-r--r--engines/drascula/graphics.cpp25
-rw-r--r--engines/drascula/interface.cpp8
-rw-r--r--engines/drascula/module.mk1
-rw-r--r--engines/drascula/objects.cpp3
-rw-r--r--engines/drascula/palette.cpp4
-rw-r--r--engines/drascula/rooms.cpp4
-rw-r--r--engines/drascula/talk.cpp39
-rw-r--r--engines/engine.cpp3
-rw-r--r--engines/game.cpp4
-rw-r--r--engines/game.h1
-rw-r--r--engines/gob/demos/demoplayer.cpp103
-rw-r--r--engines/gob/demos/demoplayer.h4
-rw-r--r--engines/gob/detection.cpp4995
-rw-r--r--engines/gob/detection_tables.h5013
-rw-r--r--engines/gob/draw.cpp12
-rw-r--r--engines/gob/draw.h7
-rw-r--r--engines/gob/draw_fascin.cpp12
-rw-r--r--engines/gob/draw_playtoons.cpp10
-rw-r--r--engines/gob/draw_v1.cpp10
-rw-r--r--engines/gob/draw_v2.cpp30
-rw-r--r--engines/gob/game.cpp18
-rw-r--r--engines/gob/gob.cpp13
-rw-r--r--engines/gob/hotspots.cpp2
-rw-r--r--engines/gob/init.cpp8
-rw-r--r--engines/gob/inter_bargon.cpp155
-rw-r--r--engines/gob/inter_fascin.cpp40
-rw-r--r--engines/gob/inter_playtoons.cpp4
-rw-r--r--engines/gob/inter_v1.cpp25
-rw-r--r--engines/gob/inter_v2.cpp78
-rw-r--r--engines/gob/inter_v3.cpp4
-rw-r--r--engines/gob/inter_v4.cpp97
-rw-r--r--engines/gob/inter_v6.cpp96
-rw-r--r--engines/gob/mult.cpp6
-rw-r--r--engines/gob/mult_v1.cpp8
-rw-r--r--engines/gob/mult_v2.cpp95
-rw-r--r--engines/gob/scenery.cpp58
-rw-r--r--engines/gob/totfile.cpp2
-rw-r--r--engines/gob/videoplayer.cpp1049
-rw-r--r--engines/gob/videoplayer.h191
-rw-r--r--engines/groovie/cell.h6
-rw-r--r--engines/groovie/cursor.cpp13
-rw-r--r--engines/groovie/cursor.h3
-rw-r--r--engines/groovie/debug.cpp6
-rw-r--r--engines/groovie/debug.h4
-rw-r--r--engines/groovie/detection.cpp10
-rw-r--r--engines/groovie/font.cpp158
-rw-r--r--engines/groovie/font.h36
-rw-r--r--engines/groovie/graphics.cpp3
-rw-r--r--engines/groovie/graphics.h2
-rw-r--r--engines/groovie/groovie.cpp51
-rw-r--r--engines/groovie/groovie.h21
-rw-r--r--engines/groovie/music.cpp101
-rw-r--r--engines/groovie/music.h13
-rw-r--r--engines/groovie/player.cpp2
-rw-r--r--engines/groovie/resource.cpp2
-rw-r--r--engines/groovie/roq.cpp3
-rw-r--r--engines/groovie/script.cpp68
-rw-r--r--engines/groovie/script.h15
-rw-r--r--engines/groovie/vdx.cpp125
-rw-r--r--engines/groovie/vdx.h4
-rw-r--r--engines/kyra/debugger.cpp4
-rw-r--r--engines/kyra/detection.cpp1178
-rw-r--r--engines/kyra/detection_tables.h1209
-rw-r--r--engines/kyra/gui_lok.cpp2
-rw-r--r--engines/kyra/gui_lol.cpp4
-rw-r--r--engines/kyra/gui_v2.cpp2
-rw-r--r--engines/kyra/kyra_hof.cpp5
-rw-r--r--engines/kyra/kyra_lok.cpp1
-rw-r--r--engines/kyra/kyra_lok.h35
-rw-r--r--engines/kyra/kyra_mr.cpp11
-rw-r--r--engines/kyra/kyra_mr.h1
-rw-r--r--engines/kyra/kyra_v1.cpp30
-rw-r--r--engines/kyra/kyra_v2.cpp1
-rw-r--r--engines/kyra/kyra_v2.h1
-rw-r--r--engines/kyra/lol.cpp6
-rw-r--r--engines/kyra/lol.h2
-rw-r--r--engines/kyra/module.mk1
-rw-r--r--engines/kyra/resource.h1
-rw-r--r--engines/kyra/saveload.cpp2
-rw-r--r--engines/kyra/scene_lol.cpp2
-rw-r--r--engines/kyra/scene_mr.cpp2
-rw-r--r--engines/kyra/screen.cpp8
-rw-r--r--engines/kyra/screen_lol.cpp62
-rw-r--r--engines/kyra/screen_lol.h1
-rw-r--r--engines/kyra/screen_v2.cpp69
-rw-r--r--engines/kyra/screen_v2.h2
-rw-r--r--engines/kyra/script_tim.cpp4
-rw-r--r--engines/kyra/sequences_lok.cpp74
-rw-r--r--engines/kyra/sound_intern.h47
-rw-r--r--engines/kyra/sound_lok.cpp6
-rw-r--r--engines/kyra/sound_lol.cpp2
-rw-r--r--engines/kyra/sound_midi.cpp8
-rw-r--r--engines/kyra/sound_towns.cpp4254
-rw-r--r--engines/kyra/staticres.cpp864
-rw-r--r--engines/kyra/staticres_lol.cpp883
-rw-r--r--engines/kyra/text_hof.cpp3
-rw-r--r--engines/kyra/text_lok.cpp37
-rw-r--r--engines/kyra/text_mr.cpp3
-rw-r--r--engines/kyra/timer_hof.cpp3
-rw-r--r--engines/kyra/timer_lok.cpp94
-rw-r--r--engines/kyra/vqa.cpp4
-rw-r--r--engines/kyra/vqa.h3
-rw-r--r--engines/lure/debugger.cpp2
-rw-r--r--engines/lure/detection.cpp6
-rw-r--r--engines/lure/fights.cpp3
-rw-r--r--engines/lure/game.cpp5
-rw-r--r--engines/lure/game.h4
-rw-r--r--engines/lure/sound.cpp31
-rw-r--r--engines/lure/sound.h14
-rw-r--r--engines/m4/animation.cpp601
-rw-r--r--engines/m4/animation.h115
-rw-r--r--engines/m4/assets.cpp116
-rw-r--r--engines/m4/assets.h34
-rw-r--r--engines/m4/console.cpp10
-rw-r--r--engines/m4/converse.cpp4
-rw-r--r--engines/m4/detection.cpp6
-rw-r--r--engines/m4/events.cpp7
-rw-r--r--engines/m4/events.h1
-rw-r--r--engines/m4/font.cpp60
-rw-r--r--engines/m4/font.h48
-rw-r--r--engines/m4/globals.cpp33
-rw-r--r--engines/m4/globals.h18
-rw-r--r--engines/m4/graphics.cpp324
-rw-r--r--engines/m4/graphics.h57
-rw-r--r--engines/m4/hotspot.cpp7
-rw-r--r--engines/m4/hotspot.h4
-rw-r--r--engines/m4/m4.cpp48
-rw-r--r--engines/m4/m4.h12
-rw-r--r--engines/m4/m4_scene.cpp14
-rw-r--r--engines/m4/m4_scene.h2
-rw-r--r--engines/m4/mads_anim.cpp210
-rw-r--r--engines/m4/mads_anim.h42
-rw-r--r--engines/m4/mads_logic.cpp334
-rw-r--r--engines/m4/mads_logic.h19
-rw-r--r--engines/m4/mads_menus.cpp23
-rw-r--r--engines/m4/mads_menus.h2
-rw-r--r--engines/m4/mads_player.cpp792
-rw-r--r--engines/m4/mads_player.h116
-rw-r--r--engines/m4/mads_scene.cpp1180
-rw-r--r--engines/m4/mads_scene.h169
-rw-r--r--engines/m4/mads_views.cpp1521
-rw-r--r--engines/m4/mads_views.h306
-rw-r--r--engines/m4/midi.cpp2
-rw-r--r--engines/m4/module.mk1
-rw-r--r--engines/m4/rails.cpp2
-rw-r--r--engines/m4/rails.h2
-rw-r--r--engines/m4/scene.cpp29
-rw-r--r--engines/m4/scene.h10
-rw-r--r--engines/m4/sound.cpp38
-rw-r--r--engines/m4/sound.h2
-rw-r--r--engines/m4/sprite.cpp103
-rw-r--r--engines/m4/sprite.h14
-rw-r--r--engines/m4/viewmgr.h13
-rw-r--r--engines/made/database.cpp7
-rw-r--r--engines/made/detection.cpp61
-rw-r--r--engines/made/made.cpp8
-rw-r--r--engines/made/resource.cpp7
-rw-r--r--engines/made/scriptfuncs.cpp83
-rw-r--r--engines/made/scriptfuncs.h17
-rw-r--r--engines/mohawk/console.cpp43
-rw-r--r--engines/mohawk/console.h1
-rw-r--r--engines/mohawk/detection.cpp847
-rw-r--r--engines/mohawk/detection_tables.h1030
-rw-r--r--engines/mohawk/dialogs.cpp17
-rw-r--r--engines/mohawk/graphics.cpp53
-rw-r--r--engines/mohawk/graphics.h12
-rw-r--r--engines/mohawk/jpeg.cpp87
-rw-r--r--engines/mohawk/module.mk10
-rw-r--r--engines/mohawk/mohawk.cpp2
-rw-r--r--engines/mohawk/myst.cpp2
-rw-r--r--engines/mohawk/myst_scripts.cpp2
-rw-r--r--engines/mohawk/resource.cpp2
-rw-r--r--engines/mohawk/riven.cpp119
-rw-r--r--engines/mohawk/riven.h20
-rw-r--r--engines/mohawk/riven_external.cpp258
-rw-r--r--engines/mohawk/riven_external.h3
-rw-r--r--engines/mohawk/riven_saveload.cpp67
-rw-r--r--engines/mohawk/riven_saveload.h3
-rw-r--r--engines/mohawk/riven_scripts.cpp86
-rw-r--r--engines/mohawk/riven_scripts.h33
-rw-r--r--engines/mohawk/riven_vars.cpp2
-rw-r--r--engines/mohawk/sound.cpp15
-rw-r--r--engines/mohawk/video.cpp415
-rw-r--r--engines/mohawk/video.h114
-rw-r--r--engines/parallaction/callables_ns.cpp17
-rw-r--r--engines/parallaction/detection.cpp6
-rw-r--r--engines/parallaction/exec.cpp4
-rw-r--r--engines/parallaction/exec_br.cpp7
-rw-r--r--engines/parallaction/gfxbase.cpp60
-rw-r--r--engines/parallaction/graphics.cpp8
-rw-r--r--engines/parallaction/gui_br.cpp30
-rw-r--r--engines/parallaction/input.cpp11
-rw-r--r--engines/parallaction/parallaction.h3
-rw-r--r--engines/parallaction/parallaction_br.cpp31
-rw-r--r--engines/parallaction/parallaction_ns.cpp5
-rw-r--r--engines/parallaction/parser.h1
-rw-r--r--engines/parallaction/parser_br.cpp13
-rw-r--r--engines/parallaction/walk.cpp35
-rw-r--r--engines/queen/music.cpp9
-rw-r--r--engines/queen/queen.cpp6
-rw-r--r--engines/queen/resource.cpp11
-rw-r--r--engines/saga/actor.cpp4
-rw-r--r--engines/saga/console.cpp3
-rw-r--r--engines/saga/detection.cpp6
-rw-r--r--engines/saga/events.cpp1
-rw-r--r--engines/saga/font.h2
-rw-r--r--engines/saga/interface.cpp9
-rw-r--r--engines/saga/music.cpp275
-rw-r--r--engines/saga/music.h52
-rw-r--r--engines/saga/puzzle.cpp10
-rw-r--r--engines/saga/render.cpp6
-rw-r--r--engines/saga/saga.cpp21
-rw-r--r--engines/saga/saga.h1
-rw-r--r--engines/saga/scene.cpp12
-rw-r--r--engines/saga/script.cpp2
-rw-r--r--engines/saga/script.h3
-rw-r--r--engines/saga/sfuncs.cpp19
-rw-r--r--engines/saga/sfuncs_ihnm.cpp12
-rw-r--r--engines/saga/sndres.cpp2
-rw-r--r--engines/saga/sound.cpp13
-rw-r--r--engines/saga/sound.h3
-rw-r--r--engines/saga/sthread.cpp8
-rw-r--r--engines/sci/console.cpp1272
-rw-r--r--engines/sci/console.h22
-rw-r--r--engines/sci/debug.h7
-rw-r--r--engines/sci/decompressor.cpp16
-rw-r--r--engines/sci/detection.cpp370
-rw-r--r--engines/sci/detection_tables.h1225
-rw-r--r--engines/sci/engine/features.cpp254
-rw-r--r--engines/sci/engine/features.h16
-rw-r--r--engines/sci/engine/game.cpp320
-rw-r--r--engines/sci/engine/gc.cpp163
-rw-r--r--engines/sci/engine/gc.h15
-rw-r--r--engines/sci/engine/kernel.cpp1254
-rw-r--r--engines/sci/engine/kernel.h256
-rw-r--r--engines/sci/engine/kernel32.cpp790
-rw-r--r--engines/sci/engine/kernel_tables.h1031
-rw-r--r--engines/sci/engine/kevent.cpp99
-rw-r--r--engines/sci/engine/kfile.cpp992
-rw-r--r--engines/sci/engine/kgraphics.cpp1019
-rw-r--r--engines/sci/engine/klists.cpp459
-rw-r--r--engines/sci/engine/kmath.cpp64
-rw-r--r--engines/sci/engine/kmenu.cpp8
-rw-r--r--engines/sci/engine/kmisc.cpp197
-rw-r--r--engines/sci/engine/kmovement.cpp276
-rw-r--r--engines/sci/engine/kparse.cpp51
-rw-r--r--engines/sci/engine/kpathing.cpp331
-rw-r--r--engines/sci/engine/kscripts.cpp152
-rw-r--r--engines/sci/engine/ksound.cpp106
-rw-r--r--engines/sci/engine/kstring.cpp246
-rw-r--r--engines/sci/engine/kvideo.cpp306
-rw-r--r--engines/sci/engine/message.cpp20
-rw-r--r--engines/sci/engine/savegame.cpp760
-rw-r--r--engines/sci/engine/savegame.h8
-rw-r--r--engines/sci/engine/script.cpp913
-rw-r--r--engines/sci/engine/script.h364
-rw-r--r--engines/sci/engine/script_patches.cpp353
-rw-r--r--engines/sci/engine/scriptdebug.cpp285
-rw-r--r--engines/sci/engine/seg_manager.cpp480
-rw-r--r--engines/sci/engine/seg_manager.h149
-rw-r--r--engines/sci/engine/segment.cpp623
-rw-r--r--engines/sci/engine/segment.h382
-rw-r--r--engines/sci/engine/selector.cpp87
-rw-r--r--engines/sci/engine/selector.h153
-rw-r--r--engines/sci/engine/state.cpp134
-rw-r--r--engines/sci/engine/state.h92
-rw-r--r--engines/sci/engine/static_selectors.cpp154
-rw-r--r--engines/sci/engine/vm.cpp1423
-rw-r--r--engines/sci/engine/vm.h449
-rw-r--r--engines/sci/engine/vm_types.h1
-rw-r--r--engines/sci/engine/workarounds.cpp457
-rw-r--r--engines/sci/engine/workarounds.h109
-rw-r--r--engines/sci/event.cpp85
-rw-r--r--engines/sci/event.h58
-rw-r--r--engines/sci/graphics/animate.cpp582
-rw-r--r--engines/sci/graphics/animate.h23
-rw-r--r--engines/sci/graphics/cache.cpp6
-rw-r--r--engines/sci/graphics/cache.h2
-rw-r--r--engines/sci/graphics/compare.cpp155
-rw-r--r--engines/sci/graphics/compare.h6
-rw-r--r--engines/sci/graphics/controls.cpp25
-rw-r--r--engines/sci/graphics/coordadjuster.cpp43
-rw-r--r--engines/sci/graphics/coordadjuster.h11
-rw-r--r--engines/sci/graphics/cursor.cpp109
-rw-r--r--engines/sci/graphics/cursor.h10
-rw-r--r--engines/sci/graphics/font.cpp7
-rw-r--r--engines/sci/graphics/font.h16
-rw-r--r--engines/sci/graphics/fontsjis.h6
-rw-r--r--engines/sci/graphics/frameout.cpp528
-rw-r--r--engines/sci/graphics/frameout.h39
-rw-r--r--engines/sci/graphics/gui.cpp144
-rw-r--r--engines/sci/graphics/gui.h93
-rw-r--r--engines/sci/graphics/gui32.cpp83
-rw-r--r--engines/sci/graphics/helpers.h4
-rw-r--r--engines/sci/graphics/maciconbar.cpp92
-rw-r--r--engines/sci/graphics/maciconbar.h (renamed from backends/platform/PalmOS/Src/init_palmos.h)33
-rw-r--r--engines/sci/graphics/menu.cpp121
-rw-r--r--engines/sci/graphics/menu.h11
-rw-r--r--engines/sci/graphics/paint.cpp4
-rw-r--r--engines/sci/graphics/paint.h6
-rw-r--r--engines/sci/graphics/paint16.cpp149
-rw-r--r--engines/sci/graphics/paint16.h31
-rw-r--r--engines/sci/graphics/paint32.cpp7
-rw-r--r--engines/sci/graphics/paint32.h3
-rw-r--r--engines/sci/graphics/palette.cpp503
-rw-r--r--engines/sci/graphics/palette.h56
-rw-r--r--engines/sci/graphics/picture.cpp273
-rw-r--r--engines/sci/graphics/picture.h15
-rw-r--r--engines/sci/graphics/portrait.cpp12
-rw-r--r--engines/sci/graphics/portrait.h5
-rw-r--r--engines/sci/graphics/ports.cpp186
-rw-r--r--engines/sci/graphics/ports.h21
-rw-r--r--engines/sci/graphics/robot.cpp42
-rw-r--r--engines/sci/graphics/robot.h7
-rw-r--r--engines/sci/graphics/screen.cpp164
-rw-r--r--engines/sci/graphics/screen.h52
-rw-r--r--engines/sci/graphics/text16.cpp165
-rw-r--r--engines/sci/graphics/text16.h8
-rw-r--r--engines/sci/graphics/transitions.cpp144
-rw-r--r--engines/sci/graphics/transitions.h4
-rw-r--r--engines/sci/graphics/view.cpp483
-rw-r--r--engines/sci/graphics/view.h37
-rw-r--r--engines/sci/module.mk17
-rw-r--r--engines/sci/parser/grammar.cpp49
-rw-r--r--engines/sci/parser/said.cpp2830
-rw-r--r--engines/sci/parser/said.y838
-rw-r--r--engines/sci/parser/vocabulary.cpp382
-rw-r--r--engines/sci/parser/vocabulary.h39
-rw-r--r--engines/sci/resource.cpp1839
-rw-r--r--engines/sci/resource.h361
-rw-r--r--engines/sci/resource_audio.cpp783
-rw-r--r--engines/sci/resource_intern.h219
-rw-r--r--engines/sci/sci.cpp475
-rw-r--r--engines/sci/sci.h187
-rw-r--r--engines/sci/sound/audio.cpp112
-rw-r--r--engines/sci/sound/audio.h5
-rw-r--r--engines/sci/sound/drivers/adlib.cpp14
-rw-r--r--engines/sci/sound/drivers/amigamac.cpp (renamed from engines/sci/sound/drivers/amiga.cpp)562
-rw-r--r--engines/sci/sound/drivers/fb01.cpp4
-rw-r--r--engines/sci/sound/drivers/midi.cpp25
-rw-r--r--engines/sci/sound/drivers/mididriver.h3
-rw-r--r--engines/sci/sound/midiparser_sci.cpp654
-rw-r--r--engines/sci/sound/midiparser_sci.h31
-rw-r--r--engines/sci/sound/music.cpp278
-rw-r--r--engines/sci/sound/music.h53
-rw-r--r--engines/sci/sound/soundcmd.cpp1070
-rw-r--r--engines/sci/sound/soundcmd.h98
-rw-r--r--engines/sci/video/seq_decoder.cpp5
-rw-r--r--engines/sci/video/seq_decoder.h2
-rw-r--r--engines/sci/video/vmd_decoder.cpp119
-rw-r--r--engines/sci/video/vmd_decoder.h89
-rw-r--r--engines/scumm/charset.cpp7
-rw-r--r--engines/scumm/debugger.cpp12
-rw-r--r--engines/scumm/detection.cpp60
-rw-r--r--engines/scumm/detection_tables.h29
-rw-r--r--engines/scumm/dialogs.cpp7
-rw-r--r--engines/scumm/gfx.cpp4
-rw-r--r--engines/scumm/gfx.h1
-rw-r--r--engines/scumm/imuse/instrument.cpp6
-rw-r--r--engines/scumm/player_nes.cpp3
-rw-r--r--engines/scumm/saveload.cpp8
-rw-r--r--engines/scumm/script_v5.cpp11
-rw-r--r--engines/scumm/scumm-md5.h50
-rw-r--r--engines/scumm/scumm.cpp43
-rw-r--r--engines/scumm/sound.cpp2
-rw-r--r--engines/scumm/string.cpp4
-rw-r--r--engines/scumm/verbs.h2
-rw-r--r--engines/sky/sky.cpp13
-rw-r--r--engines/sword1/control.cpp3
-rw-r--r--engines/sword1/memman.h4
-rw-r--r--engines/sword1/music.cpp2
-rw-r--r--engines/sword2/anims.cpp8
-rw-r--r--engines/sword2/music.cpp6
-rw-r--r--engines/sword2/resman.h4
-rw-r--r--engines/sword2/sword2.cpp22
-rw-r--r--engines/teenagent/detection.cpp4
-rw-r--r--engines/teenagent/module.mk24
-rw-r--r--engines/teenagent/teenagent.cpp4
-rw-r--r--engines/tinsel/actors.cpp6
-rw-r--r--engines/tinsel/bmv.cpp12
-rw-r--r--engines/tinsel/cliprect.cpp12
-rw-r--r--engines/tinsel/detection.cpp550
-rw-r--r--engines/tinsel/detection_tables.h567
-rw-r--r--engines/tinsel/graphics.cpp23
-rw-r--r--engines/tinsel/handle.cpp16
-rw-r--r--engines/tinsel/object.cpp6
-rw-r--r--engines/tinsel/pcode.cpp7
-rw-r--r--engines/tinsel/saveload.cpp3
-rw-r--r--engines/tinsel/savescn.cpp6
-rw-r--r--engines/tinsel/strres.cpp14
-rw-r--r--engines/tinsel/tinlib.cpp2
-rw-r--r--engines/tinsel/tinsel.cpp11
-rw-r--r--engines/tinsel/tinsel.h6
-rw-r--r--engines/touche/detection.cpp11
-rw-r--r--engines/touche/midi.cpp6
-rw-r--r--engines/touche/touche.cpp6
-rw-r--r--engines/tucker/detection.cpp4
-rw-r--r--engines/tucker/sequences.cpp67
-rw-r--r--engines/tucker/tucker.h5
-rw-r--r--graphics/conversion.h7
-rw-r--r--graphics/font.cpp8
-rw-r--r--graphics/font.h6
-rw-r--r--graphics/fontman.cpp22
-rw-r--r--graphics/fontman.h8
-rw-r--r--graphics/module.mk12
-rw-r--r--graphics/pict.cpp (renamed from engines/mohawk/myst_pict.cpp)213
-rw-r--r--graphics/pict.h (renamed from engines/mohawk/myst_pict.h)56
-rw-r--r--graphics/scaler.h2
-rw-r--r--graphics/scaler/thumbnail_intern.cpp20
-rw-r--r--graphics/thumbnail.cpp2
-rw-r--r--graphics/thumbnail.h6
-rw-r--r--graphics/video/avi_decoder.cpp35
-rw-r--r--graphics/video/avi_decoder.h2
-rw-r--r--graphics/video/codecs/cinepak.cpp285
-rw-r--r--graphics/video/codecs/cinepak.h81
-rw-r--r--graphics/video/codecs/indeo3.cpp3431
-rw-r--r--graphics/video/codecs/indeo3.h94
-rw-r--r--graphics/video/codecs/mjpeg.cpp73
-rw-r--r--graphics/video/codecs/mjpeg.h (renamed from engines/mohawk/jpeg.h)25
-rw-r--r--graphics/video/codecs/qdm2.cpp3282
-rw-r--r--graphics/video/codecs/qdm2.h (renamed from backends/fs/palmos/palmos-fs-factory.cpp)40
-rw-r--r--graphics/video/codecs/qdm2data.h531
-rw-r--r--graphics/video/codecs/qtrle.cpp420
-rw-r--r--graphics/video/codecs/qtrle.h58
-rw-r--r--graphics/video/codecs/rpza.cpp208
-rw-r--r--graphics/video/codecs/rpza.h (renamed from backends/platform/PalmOS/Src/args.h)31
-rw-r--r--graphics/video/codecs/smc.cpp385
-rw-r--r--graphics/video/codecs/smc.h (renamed from backends/platform/PalmOS/Src/cd_aeroplayer.h)52
-rw-r--r--graphics/video/coktel_decoder.cpp2469
-rw-r--r--graphics/video/coktel_decoder.h505
-rw-r--r--graphics/video/dxa_decoder.cpp4
-rw-r--r--graphics/video/dxa_decoder.h4
-rw-r--r--graphics/video/flic_decoder.cpp23
-rw-r--r--graphics/video/flic_decoder.h6
-rw-r--r--graphics/video/mpeg_player.cpp126
-rw-r--r--graphics/video/mpeg_player.h4
-rw-r--r--graphics/video/qt_decoder.cpp1326
-rw-r--r--graphics/video/qt_decoder.h289
-rw-r--r--graphics/video/smk_decoder.cpp8
-rw-r--r--graphics/video/smk_decoder.h2
-rw-r--r--graphics/video/video_decoder.cpp13
-rw-r--r--graphics/video/video_decoder.h2
-rw-r--r--gui/EditTextWidget.cpp8
-rw-r--r--gui/EditTextWidget.h4
-rw-r--r--gui/GuiManager.cpp60
-rw-r--r--gui/GuiManager.h12
-rw-r--r--gui/KeysDialog.cpp27
-rw-r--r--gui/ListWidget.cpp17
-rw-r--r--gui/ListWidget.h4
-rw-r--r--gui/PopUpWidget.cpp4
-rw-r--r--gui/PopUpWidget.h3
-rw-r--r--gui/ScrollBarWidget.cpp29
-rw-r--r--gui/ScrollBarWidget.h3
-rw-r--r--gui/TabWidget.cpp18
-rw-r--r--gui/TabWidget.h3
-rw-r--r--gui/ThemeEngine.cpp286
-rw-r--r--gui/ThemeEngine.h32
-rw-r--r--gui/ThemeParser.cpp9
-rw-r--r--gui/Tooltip.cpp101
-rw-r--r--gui/Tooltip.h (renamed from backends/platform/PalmOS/Src/init_sony.h)34
-rw-r--r--gui/about.cpp20
-rw-r--r--gui/browser.cpp8
-rw-r--r--gui/chooser.cpp5
-rw-r--r--gui/console.cpp8
-rw-r--r--gui/credits.h39
-rw-r--r--gui/debugger.cpp61
-rw-r--r--gui/debugger.h116
-rw-r--r--gui/dialog.cpp2
-rw-r--r--gui/dialog.h1
-rw-r--r--gui/editable.cpp8
-rw-r--r--gui/editable.h4
-rw-r--r--gui/error.cpp4
-rw-r--r--gui/launcher.cpp191
-rw-r--r--gui/massadd.cpp17
-rw-r--r--gui/message.cpp4
-rw-r--r--gui/module.mk1
-rw-r--r--gui/options.cpp531
-rw-r--r--gui/options.h31
-rw-r--r--gui/saveload.cpp35
-rw-r--r--gui/themebrowser.cpp8
-rw-r--r--gui/themes/default.inc357
-rw-r--r--gui/themes/fonts/Arial.bdf1537
-rw-r--r--gui/themes/fonts/Arial12.bdf7119
-rw-r--r--gui/themes/fonts/ArialBold.bdf1538
-rw-r--r--gui/themes/fonts/README3
-rw-r--r--gui/themes/fonts/clR6x12-iso-8859-1.bdf4290
-rw-r--r--gui/themes/fonts/clR6x12-iso-8859-5.bdf4291
-rw-r--r--gui/themes/fonts/clR6x12.bdf22736
-rw-r--r--gui/themes/fonts/courr12-iso-8859-1.bdf2926
-rw-r--r--gui/themes/fonts/fixed5x8-iso-8859-1.bdf3380
-rw-r--r--gui/themes/fonts/fixed5x8-iso-8859-5.bdf2309
-rw-r--r--gui/themes/fonts/helvB12-iso-8859-1.bdf3059
-rw-r--r--gui/themes/fonts/helvB12-iso-8859-5.bdf2763
-rw-r--r--gui/themes/fonts/helvB12.bdf12708
-rw-r--r--gui/themes/fonts/helvBO12-iso-8859-1.bdf3058
-rw-r--r--gui/themes/fonts/helvBO12.bdf12195
-rw-r--r--gui/themes/fonts/helvR12-iso-8859-1.bdf3048
-rw-r--r--gui/themes/fonts/helvR12.bdf12688
-rw-r--r--gui/themes/fonts/topaz/README.ScummVM6
-rw-r--r--gui/themes/fonts/topaz/topazLT.fontbin0 -> 264 bytes
-rw-r--r--gui/themes/fonts/topaz/topazLT.readme63
-rw-r--r--gui/themes/fonts/topaz/topazlt/8bin0 -> 2600 bytes
-rw-r--r--gui/themes/scummclassic.zipbin54108 -> 73968 bytes
-rw-r--r--gui/themes/scummclassic/clR6x12-iso-8859-5.fccbin0 -> 6403 bytes
-rw-r--r--gui/themes/scummclassic/classic_gfx.stx98
-rw-r--r--gui/themes/scummclassic/classic_layout.stx87
-rw-r--r--gui/themes/scummclassic/classic_layout_lowres.stx113
-rw-r--r--gui/themes/scummclassic/fixed5x8-iso-8859-5.fccbin0 -> 3985 bytes
-rw-r--r--gui/themes/scummclassic/helvb12-iso-8859-5.fccbin0 -> 5234 bytes
-rw-r--r--gui/themes/scummmodern.zipbin159866 -> 181317 bytes
-rw-r--r--gui/themes/scummmodern/clR6x12-iso-8859-5.fccbin0 -> 6403 bytes
-rw-r--r--gui/themes/scummmodern/fixed5x8-iso-8859-5.fccbin0 -> 3985 bytes
-rw-r--r--gui/themes/scummmodern/helvb12-iso-8859-1.fcc (renamed from gui/themes/scummmodern/helvr12-l1.fcc)bin5615 -> 5615 bytes
-rw-r--r--gui/themes/scummmodern/helvb12-iso-8859-5.fccbin0 -> 5234 bytes
-rw-r--r--gui/themes/scummmodern/radiobutton.bmpbin0 -> 774 bytes
-rw-r--r--gui/themes/scummmodern/radiobutton_empty.bmpbin0 -> 774 bytes
-rw-r--r--gui/themes/scummmodern/scummmodern_gfx.stx72
-rw-r--r--gui/themes/scummmodern/scummmodern_layout.stx91
-rw-r--r--gui/themes/scummmodern/scummmodern_layout_lowres.stx110
-rw-r--r--gui/widget.cpp184
-rw-r--r--gui/widget.h81
-rw-r--r--po/POTFILES45
-rw-r--r--po/ca_ES.po1456
-rw-r--r--po/de_DE.po1451
-rw-r--r--po/es_ES.po1428
-rw-r--r--po/fr_FR.po1549
-rw-r--r--po/hu_HU.po1393
-rw-r--r--po/it_IT.po1371
-rw-r--r--po/module.mk43
-rw-r--r--po/remove-potcdate.sed19
-rw-r--r--po/ru_RU.po1367
-rw-r--r--po/scummvm.pot1348
-rw-r--r--po/uk_UA.po1433
-rw-r--r--ports.mk10
-rw-r--r--sound/audiocd.cpp37
-rw-r--r--sound/audiocd.h5
-rw-r--r--sound/audiostream.cpp8
-rw-r--r--sound/audiostream.h48
-rw-r--r--sound/decoders/adpcm.h2
-rw-r--r--sound/decoders/aiff.cpp13
-rw-r--r--sound/decoders/aiff.h9
-rw-r--r--sound/decoders/flac.cpp6
-rw-r--r--sound/decoders/flac.h4
-rw-r--r--sound/decoders/mac_snd.cpp116
-rw-r--r--sound/decoders/mac_snd.h58
-rw-r--r--sound/decoders/mp3.cpp15
-rw-r--r--sound/decoders/mp3.h4
-rw-r--r--sound/decoders/vag.h2
-rw-r--r--sound/decoders/voc.h2
-rw-r--r--sound/decoders/vorbis.cpp2
-rw-r--r--sound/decoders/vorbis.h4
-rw-r--r--sound/decoders/wave.h4
-rw-r--r--sound/fmopl.cpp5
-rw-r--r--sound/mididrv.cpp403
-rw-r--r--sound/mididrv.h152
-rw-r--r--sound/midiparser.cpp30
-rw-r--r--sound/midiparser.h8
-rw-r--r--sound/midiparser_smf.cpp6
-rw-r--r--sound/mods/protracker.h2
-rw-r--r--sound/module.mk5
-rw-r--r--sound/musicplugin.cpp20
-rw-r--r--sound/musicplugin.h32
-rw-r--r--sound/null.cpp54
-rw-r--r--sound/null.h56
-rw-r--r--sound/rate_arm_asm.s30
-rw-r--r--sound/softsynth/adlib.cpp16
-rw-r--r--sound/softsynth/fluidsynth.cpp13
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_audio.cpp1578
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_audio.h178
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_euphony.cpp907
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_euphony.h187
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_pc98_driver.cpp1403
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_pc98_driver.h129
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp1513
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h177
-rw-r--r--sound/softsynth/mt32.cpp27
-rw-r--r--sound/softsynth/opl/dbopl.cpp2
-rw-r--r--sound/softsynth/opl/mame.cpp4
-rw-r--r--sound/softsynth/pcspk.cpp57
-rw-r--r--sound/softsynth/sid.cpp15
-rw-r--r--sound/softsynth/sid.h13
-rw-r--r--sound/softsynth/wave6581.cpp15
-rw-r--r--sound/softsynth/ym2612.cpp16
-rw-r--r--test/common/tokenizer.h10
-rw-r--r--tools/convbdf.c10
-rw-r--r--tools/create_kyradat/create_kyradat.cpp7
-rw-r--r--tools/create_kyradat/create_kyradat.h1
-rw-r--r--tools/create_kyradat/games.cpp3
-rw-r--r--tools/create_kyradat/tables.cpp10
-rw-r--r--tools/create_msvc/create_msvc.cpp100
-rwxr-xr-xtools/credits.pl46
-rw-r--r--tools/make-scumm-fontdata.c2
-rw-r--r--tools/md5table.c1
-rw-r--r--tools/module.mk1
-rwxr-xr-xtools/po2c277
-rw-r--r--tools/scumm-md5.txt43
-rwxr-xr-xtools/update-version.pl1
1047 files changed, 193161 insertions, 57502 deletions
diff --git a/AUTHORS b/AUTHORS
index 7a8490ddf7..76ff47e9db 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -166,6 +166,9 @@ ScummVM Team
Backend Teams
-------------
+ Android:
+ Angus Lees
+
Dreamcast:
Marcus Comstedt
@@ -187,9 +190,6 @@ ScummVM Team
Nintendo DS:
Neil Millstone
- PalmOS:
- Chris Apers
-
PocketPC / WinCE:
Nicolas Bacca - (retired)
Kostas Nakos
@@ -253,6 +253,7 @@ ScummVM Team
Retired Team Members
--------------------
+ Chris Apers - Former PalmOS porter
Ralph Brorsen - Help with GUI implementation
Jamieson Christian - iMUSE, MIDI, all things musical
Felix Jakschitsch - Zak256 reverse engineering
@@ -315,6 +316,35 @@ Other contributions
Chris Gray - (retired)
Johannes Schickel
+ Translations
+ ------------
+ Thierry Crozat - Translation Lead
+
+ Catalan:
+ Jordi Vilalta Prat
+
+ French:
+ Thierry Crozat
+
+ German:
+ Simon Sawatzki
+ Lothar Serra Mari
+
+ Hungarian:
+ Alex Bevilacqua
+
+ Italian:
+ Matteo Angelino
+
+ Russian:
+ Eugene Sandulenko
+
+ Spanish:
+ Tomas Maidagan
+
+ Ukrainian:
+ Lubomyr Lisen
+
Websites (design)
-----------------
Dobo Balazs - Website design
@@ -392,7 +422,7 @@ Other contributions
Ravi I. - SCI0 sound resource specification
Ruediger Hanke - Port to the MorphOS platform
Rune Orsval - Configuration file editor
- Rickard Lind - MT32->GM MIDI mapping magic, sound research
+ Rickard Lind - MT-32->GM MIDI mapping magic, sound research
Rink Springer - Port to the DOS platform, several bug fixes
Robey Pointer - Bug tracking system hosting
Sergey Lapin - Port of Carl's type 2 decompression code
diff --git a/COPYING.BSD b/COPYING.BSD
new file mode 100644
index 0000000000..e67b79359a
--- /dev/null
+++ b/COPYING.BSD
@@ -0,0 +1,93 @@
+NOTE: Only certain parts of the ScummVM project are under the BSD license.
+The majority of the files are under the GNU GPL. See the headers of the
+individual files to find out the exact license.
+
+The term "BSD license" refers to any BSD-like license, as they are sometimes
+hard to tell apart. No slight against other licenses is intended.
+
+
+Parts of the Nintendo DS port use the following license:
+
+Copyright (c) 2006 Michael "Chishm" Chisholm
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+Parts of the MPEG decoder use the following license:
+
+Copyright (c) 1995 The Regents of the University of California.
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose, without fee, and without written agreement is
+hereby granted, provided that the above copyright notice and the following
+two paragraphs appear in all copies of this software.
+
+IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+Copyright (c) 1995 Erik Corry
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose, without fee, and without written agreement is
+hereby granted, provided that the above copyright notice and the following
+two paragraphs appear in all copies of this software.
+
+IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
+THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
+BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
+UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+Portions of this software Copyright (c) 1995 Brown University.
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose, without fee, and without written agreement
+is hereby granted, provided that the above copyright notice and the
+following two paragraphs appear in all copies of this software.
+
+IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
+UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
+BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
+SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
diff --git a/COPYING.LGPL b/COPYING.LGPL
index 00b4fedfe7..56a87b85ed 100644
--- a/COPYING.LGPL
+++ b/COPYING.LGPL
@@ -1,3 +1,9 @@
+NOTE: Only certain parts of the ScummVM project are under the GNU LGPL.
+The majority of the files are under the GNU GPL. See the headers of the
+individual files to find out the exact license.
+
+
+
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
diff --git a/COPYRIGHT b/COPYRIGHT
index 980ca32463..cc522d2215 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -48,6 +48,7 @@ Martin Kiewitz
Pawel Kolodziejski
Mutwin Kraus
Andrew Kurushin
+Angus Lees
Claudio Matsuoka
Thomas Mayer
Neil Millstone
diff --git a/Makefile b/Makefile
index 8c3882da32..6b64759ebd 100644
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ ifeq "$(HAVE_GCC)" "1"
# Turn off some annoying and not-so-useful warnings
CXXFLAGS+= -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder
# Enable even more warnings...
- CXXFLAGS+= -Wpointer-arith -Wcast-qual -Wcast-align
+ CXXFLAGS+= -Wpointer-arith -Wcast-qual
CXXFLAGS+= -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings
# Currently we disable this gcc flag, since it will also warn in cases,
diff --git a/Makefile.common b/Makefile.common
index 419090a705..f8b758b4ba 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -28,6 +28,7 @@ MODULES += \
engines \
graphics \
common \
+ po
ifdef USE_MT32EMU
MODULES += sound/softsynth/mt32
@@ -223,7 +224,7 @@ dist-src: \
@#DEB-src?
# Common files
-DIST_FILES_DOCS:=$(addprefix $(srcdir)/,AUTHORS COPYING COPYING.LGPL COPYRIGHT NEWS README)
+DIST_FILES_DOCS:=$(addprefix $(srcdir)/,AUTHORS COPYING COPYING.BSD COPYING.LGPL COPYRIGHT NEWS README)
# Themes files
DIST_FILES_THEMES:=$(addprefix $(srcdir)/gui/themes/,scummmodern.zip)
diff --git a/NEWS b/NEWS
index 9ab98dc4e5..aac0b7f7e4 100644
--- a/NEWS
+++ b/NEWS
@@ -2,13 +2,52 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
http://scummvm.svn.sourceforge.net/viewvc/scummvm/?view=log
1.2.0 (????-??-??)
- PSP port:
- - Switched to new backend design which fixes minor graphical issues,
- speeds things up, and provides 16-bit support.
+ New Ports:
+ - Added Android port.
General:
+ - Removed the outdated PalmOS port.
- Switched to the "fast" DOSBox OPL emulator.
- Fixed a crash in the rjp1 player code affecting the FOTAQ Amiga version.
+ - Added support for more original media layouts.
+ - Added support for GUI localization.
+ - Improved GUI by adding tooltips and radiobuttons.
+ - Improved GUI usability by hiding more irrelevant options not supported by
+ specific games.
+
+ AGI:
+ - Fixed number of GFX glitches.
+ - Made PIC drawing code picture perfect.
+ - Added support of MIDI devices.
+ - Added support for accurate Tandy sound emulation. Switched to it as default.
+
+ Drascula:
+ - Fixed number of GFX glitches.
+ - Made many cutscenes smoother.
+ - Changed behavior of items menu. Now it shows up on mouse up.
+
+ Groovie:
+ - Added support for the Macintosh version of The 7th Guest.
+ - Added support for custom MT-32 instruments.
+
+ KYRA:
+ - Fixed some minor graphical glitches.
+ - Implemented formerly missing recreation of some in game items.
+
+ Parallaction:
+ - Made part one of The Big Red Adventure completable.
+
+ SAGA:
+ - Fixed graphics glitches in several scenes.
+
+ SCUMM:
+ - Several improvements in Maniac Mansion NES.
+
+ PSP port:
+ - Switched to new backend design which fixes minor graphical issues,
+ speeds things up, and provides 16-bit support.
+ - Enabled playback of MP3 files using the hardware decoder (ME). This means that
+ the port is now optimized for MP3 playback (as opposed to OGG).
1.1.2 (????-??-??)
Broken Sword 2
@@ -18,7 +57,7 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
1.1.1 (2010-05-02)
New Ports:
- - Added Nintendo 64 Port. (Actually added in 1.1.0, but forgot to mention it. oops)
+ - Added Nintendo 64 port. (Actually added in 1.1.0, but forgot to mention it. oops)
General:
- Fixed several minor bugs here and there.
diff --git a/README b/README
index 043a087fab..c583cf994c 100644
--- a/README
+++ b/README
@@ -81,9 +81,10 @@ You can find a thorough list with details on which games are supported
and how well on the compatibility page. ScummVM is continually
improving, so check back often.
-Among the systems on which you can play those games are Windows, Linux,
-Mac OS X, Dreamcast, PocketPC, PalmOS, AmigaOS, BeOS, OS/2, PSP, PS2,
-SymbianOS/EPOC, iPhone and many more.
+Among the systems on which you can play those games are regular desktop
+computers (running Windows, Linux, Mac OS X, ...), game consoles
+(Dreamcast, Nintendo DS & Wii, PS2, PSP, ...), smartphones (Android,
+iPhone, PocketPC, Symbian ...) and more.
At this time ScummVM should be considered beta software, and is still
under heavy development. Be aware that whilst we attempt to make sure
@@ -843,28 +844,30 @@ contact us!
Supported platforms include (but are not limited to):
- UNIX (Linux, Solaris, IRIX, *BSD)
+ UNIX (Linux, Solaris, IRIX, *BSD, ...)
Windows
Windows CE and Windows Mobile (including Smartphones and PocketPCs)
Mac OS X
AmigaOS
+ Android
BeOS
Dreamcast
- iPhone (also includes the iPod Touch)
+ GP2x
+ iPhone (also includes iPod Touch and iPad)
+ Maemo (Nokia Internet tablets 770, N800, N810, N900)
+ Nintendo 64
Nintendo DS
- PalmOS
+ Nintendo Wii
+ OS/2
PlayStation 2
PlayStation Portable
- RISC OS
Symbian
- Maemo (Nokia Internet tablets 770, N800, N810, N900)
The Dreamcast port does not support The Curse of Monkey Island, nor The
-Dig. The PalmOS port does not support The Curse of Monkey Island,
-Beneath a Steel Sky, nor either Simon the Sorcerer 1 or 2. The Dig will
-only work on some Palm devices (those with a large dynamic heap). The
-Nintendo DS port does not support Full Throttle, The Dig, or The Curse
-of Monkey Island.
+Dig. The Nintendo DS port does not support Full Throttle, The Dig, or
+The Curse of Monkey Island.
+For more platform specific limitations, please refer to our Wiki:
+ http://wiki.scummvm.org/index.php/Platforms
In the Macintosh port, the right mouse button is emulated via Cmd-Click
(that is, you click the mouse button while holding the
diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index 212cb130c1..0616713eab 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -95,13 +95,11 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
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)
_currentKeyDown.ascii = event.kbd.ascii;
_currentKeyDown.keycode = event.kbd.keycode;
_currentKeyDown.flags = event.kbd.flags;
_keyRepeatTime = time + kKeyRepeatInitialDelay;
-#endif
+
// Global Main Menu
if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_F5) {
if (g_engine && !g_engine->isPaused()) {
diff --git a/backends/fs/amigaos4/amigaos4-fs.cpp b/backends/fs/amigaos4/amigaos4-fs.cpp
index fe6164cb0c..8a57a3cf1c 100644
--- a/backends/fs/amigaos4/amigaos4-fs.cpp
+++ b/backends/fs/amigaos4/amigaos4-fs.cpp
@@ -368,7 +368,7 @@ bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
}
if (ERROR_NO_MORE_ENTRIES != IDOS->IoErr() ) {
- debug(6, "An error occured during ExamineDir");
+ debug(6, "An error occurred during ExamineDir");
ret = false;
} else {
ret = true;
diff --git a/backends/fs/ds/ds-fs-factory.cpp b/backends/fs/ds/ds-fs-factory.cpp
index 0dfa70b716..4919c04174 100644
--- a/backends/fs/ds/ds-fs-factory.cpp
+++ b/backends/fs/ds/ds-fs-factory.cpp
@@ -27,7 +27,7 @@
#include "backends/fs/ds/ds-fs.h"
#include "dsmain.h" //for the isGBAMPAvailable() function
-DECLARE_SINGLETON(DSFilesystemFactory);
+DECLARE_SINGLETON(DSFilesystemFactory)
AbstractFSNode *DSFilesystemFactory::makeRootFileNode() const {
if (DS::isGBAMPAvailable()) {
diff --git a/backends/fs/ds/ds-fs.cpp b/backends/fs/ds/ds-fs.cpp
index 6fc2894925..675084ff56 100644
--- a/backends/fs/ds/ds-fs.cpp
+++ b/backends/fs/ds/ds-fs.cpp
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -115,7 +118,7 @@ DSFileSystemNode::DSFileSystemNode(const Common::String& path, bool isDir) {
// consolePrintf("Found: %d, Dir: %d\n", _isValid, _isDirectory);
}
-DSFileSystemNode::DSFileSystemNode(const DSFileSystemNode* node) {
+DSFileSystemNode::DSFileSystemNode(const DSFileSystemNode *node) {
//TODO: not implemented?
}
@@ -144,7 +147,7 @@ bool DSFileSystemNode::getChildren(AbstractFSList &dirList, ListMode mode, bool
_zipFile->changeToRoot();
/* // This is the root dir, so add the RAM folder
- DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/ram");
+ DSFileSystemNode *dsfsn = new DSFileSystemNode("ds:/ram");
dsfsn->_isDirectory = true;
dirList->push_back(wrap(dsfsn));
*/
@@ -162,7 +165,7 @@ bool DSFileSystemNode::getChildren(AbstractFSList &dirList, ListMode mode, bool
if ( (_zipFile->isDirectory() && ((mode == Common::FSNode::kListDirectoriesOnly) || (mode == Common::FSNode::kListAll)) )
|| (!_zipFile->isDirectory() && ((mode == Common::FSNode::kListFilesOnly) || (mode == Common::FSNode::kListAll)) ) )
{
- DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + Common::String(n), _zipFile->isDirectory());
+ DSFileSystemNode *dsfsn = new DSFileSystemNode("ds:/" + Common::String(n), _zipFile->isDirectory());
dsfsn->_isDirectory = _zipFile->isDirectory();
dirList.push_back((dsfsn));
}
@@ -173,15 +176,15 @@ bool DSFileSystemNode::getChildren(AbstractFSList &dirList, ListMode mode, bool
return true;
}
-AbstractFSNode* DSFileSystemNode::getParent() const {
+AbstractFSNode *DSFileSystemNode::getParent() const {
// consolePrintf("parent\n");
DSFileSystemNode *p;
if (_path != "ds:/") {
- char *path = (char *) _path.c_str();
+ const char *path = (const char *)_path.c_str();
int lastSlash = 4;
- for (int r = 4; r < (int) _path.size(); r++) {
+ for (uint r = 4; r < _path.size(); r++) {
if (path[r] == '\\') {
lastSlash = r;
}
@@ -259,7 +262,7 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path) {
_path = path;
}
-GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path, bool isDirectory) {
+GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path, bool isDir) {
//consolePrintf("'%s'",path.c_str());
int lastSlash = 3;
@@ -272,11 +275,11 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path, bool isDire
_displayName = Common::String(path.c_str() + lastSlash + 1);
_path = path;
_isValid = true;
- _isDirectory = isDirectory;
+ _isDirectory = isDir;
}
-GBAMPFileSystemNode::GBAMPFileSystemNode(const GBAMPFileSystemNode* node) {
+GBAMPFileSystemNode::GBAMPFileSystemNode(const GBAMPFileSystemNode *node) {
//TODO: not implemented?
}
@@ -319,7 +322,7 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo
if ( ((entryType == TYPE_DIR) && ((mode == Common::FSNode::kListDirectoriesOnly) || (mode == Common::FSNode::kListAll)))
|| ((entryType == TYPE_FILE) && ((mode == Common::FSNode::kListFilesOnly) || (mode == Common::FSNode::kListAll))) ) {
- GBAMPFileSystemNode* dsfsn;
+ GBAMPFileSystemNode *dsfsn;
//consolePrintf("Fname: %s\n", fname);
@@ -348,15 +351,15 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo
return true;
}
-AbstractFSNode* GBAMPFileSystemNode::getParent() const {
+AbstractFSNode *GBAMPFileSystemNode::getParent() const {
// consolePrintf("parent\n");
GBAMPFileSystemNode *p;
if (_path != "mp:/") {
- char *path = (char *) _path.c_str();
+ const char *path = (const char *)_path.c_str();
int lastSlash = 4;
- for (int r = 4; r < (int) strlen((char *) path); r++) {
+ for (uint r = 4; r < strlen(path); r++) {
if (path[r] == '/') {
lastSlash = r;
}
@@ -413,18 +416,12 @@ bool DSFileStream::eos() const {
}
int32 DSFileStream::pos() const {
- if (_writeBufferPos > 0) {
- // Discard constness. Bad, but I can't see another way.
- ((DSFileStream *) (this))->flush();
- }
+ assert(_writeBufferPos == 0); // This method may only be called when reading!
return std_ftell((FILE *)_handle);
}
int32 DSFileStream::size() const {
- if (_writeBufferPos > 0) {
- // Discard constness. Bad, but I can't see another way.
- ((DSFileStream *) (this))->flush();
- }
+ assert(_writeBufferPos == 0); // This method may only be called when reading!
int32 oldPos = std_ftell((FILE *)_handle);
std_fseek((FILE *)_handle, 0, SEEK_END);
int32 length = std_ftell((FILE *)_handle);
@@ -444,16 +441,15 @@ uint32 DSFileStream::read(void *ptr, uint32 len) {
if (_writeBufferPos > 0) {
flush();
}
- return std_fread((byte *)ptr, 1, len, (FILE *)_handle);
+ return std_fread(ptr, 1, len, (FILE *)_handle);
}
uint32 DSFileStream::write(const void *ptr, uint32 len) {
if (_writeBufferPos + len < WRITE_BUFFER_SIZE) {
memcpy(_writeBuffer + _writeBufferPos, ptr, len);
_writeBufferPos += len;
- }
- else
- {
+ return len;
+ } else {
if (_writeBufferPos > 0) {
flush();
}
@@ -483,29 +479,31 @@ DSFileStream *DSFileStream::makeFromPath(const Common::String &path, bool writeM
// Stdio replacements
-#define MAX_FILE_HANDLES 32
+enum {
+ MAX_FILE_HANDLES = 32
+};
-bool inited = false;
-DS::fileHandle handle[MAX_FILE_HANDLES];
+static bool inited = false;
+static DS::fileHandle s_handle[MAX_FILE_HANDLES];
-FILE* std_fopen(const char* name, const char* mode) {
+FILE *std_fopen(const char *name, const char *mode) {
if (!inited) {
for (int r = 0; r < MAX_FILE_HANDLES; r++) {
- handle[r].used = false;
+ s_handle[r].used = false;
}
inited = true;
currentDir[0] = '\0';
}
- char* realName = (char *) name;
+ char realName[MAXPATHLEN];
// Remove file system prefix
if ((name[0] == 'd') && (name[1] == 's') && (name[2] == ':') && (name[3] == '/')) {
- realName += 4;
- }
-
- if ((name[0] == 'm') && (name[1] == 'p') && (name[2] == ':') && (name[3] == '/')) {
- realName += 4;
+ strlcpy(realName, name + 4, MAXPATHLEN);
+ } else if ((name[0] == 'm') && (name[1] == 'p') && (name[2] == ':') && (name[3] == '/')) {
+ strlcpy(realName, name + 4, MAXPATHLEN);
+ } else {
+ strlcpy(realName, name, MAXPATHLEN);
}
// consolePrintf("Open file:");
@@ -515,13 +513,14 @@ FILE* std_fopen(const char* name, const char* mode) {
FAT_chdir("/");
// Turn all back slashes into forward slashes for gba_nds_fat
- char* p = realName;
+ char *p = realName;
while (*p) {
- if (*p == '\\') *p = '/';
+ if (*p == '\\')
+ *p = '/';
p++;
}
- FAT_FILE* result = FAT_fopen(realName, mode);
+ FAT_FILE *result = FAT_fopen(realName, mode);
if (result == 0) {
// consolePrintf("Error code %d\n", result);
@@ -531,42 +530,21 @@ FILE* std_fopen(const char* name, const char* mode) {
}
// MT_memoryReport();
- return (FILE *) result;
+ return (FILE *)result;
}
// Fail to open file for writing. It's in ROM!
// Allocate a file handle
int r = 0;
- while (handle[r].used) {
+ while (s_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);
- } else {
-// consolePrintf("Reading %s\n", realName);
- handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, false);
- }
-#endif
-
- if (handle[r].sramFile) {
- handle[r].used = true;
- handle[r].pos = 0;
- handle[r].data = NULL;
- handle[r].size = handle[r].sramFile->getSize();
-// consolePrintf("Found it");
- return &handle[r];
- }
-
-// consolePrintf("Not in SRAM!");
-
- char* data;
+ char *data;
- ZipFile* zip = DSFileSystemNode::getZip();
+ ZipFile *zip = DSFileSystemNode::getZip();
if (!zip) {
// consolePrintf("No zip yet!");
return NULL;
@@ -578,7 +556,7 @@ FILE* std_fopen(const char* name, const char* mode) {
if (currentDir[0] != 0) {
char nameWithPath[128];
- sprintf(nameWithPath, "%s\%s", currentDir, realName);
+ sprintf(nameWithPath, "%s\\%s", currentDir, realName);
strcpy(realName, nameWithPath);
}
@@ -589,17 +567,18 @@ FILE* std_fopen(const char* name, const char* mode) {
zip->setAllFilesVisible(false);
// Allocate a file handle
- int r = 0;
- while (handle[r].used) r++;
+ r = 0;
+ while (s_handle[r].used)
+ r++;
- handle[r].used = true;
- handle[r].pos = 0;
- handle[r].data = data;
- handle[r].size = zip->getFileSize();
+ s_handle[r].used = true;
+ s_handle[r].pos = 0;
+ s_handle[r].data = data;
+ s_handle[r].size = zip->getFileSize();
// consolePrintf("Opened file %d: %s (%s) ", r, realName, name);
- return &handle[r];
+ return &s_handle[r];
} else {
zip->setAllFilesVisible(false);
// consolePrintf("Not found: %s (%s) ", realName, name);
@@ -607,7 +586,7 @@ FILE* std_fopen(const char* name, const char* mode) {
}
}
-void std_fclose(FILE* handle) {
+void std_fclose(FILE *handle) {
if (DS::isGBAMPAvailable()) {
FAT_fclose((FAT_FILE *) handle);
@@ -615,19 +594,15 @@ void std_fclose(FILE* handle) {
}
handle->used = false;
- if (handle->sramFile) {
- delete handle->sramFile;
- handle->sramFile = NULL;
- }
}
-size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
+size_t std_fread(void *ptr, size_t size, size_t numItems, FILE *handle) {
// consolePrintf("fread %d,%d %d ", size, numItems, ptr);
if (DS::isGBAMPAvailable()) {
readPastEndOfFile = false;
- int bytes = FAT_fread((void *) ptr, size, numItems, (FAT_FILE *) handle);
+ int bytes = FAT_fread(ptr, size, numItems, (FAT_FILE *) handle);
if (!FAT_feof((FAT_FILE *) handle)) {
return numItems;
} else {
@@ -638,36 +613,22 @@ size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
return numItems;
}
- if (handle->sramFile) {
- int bytes = 0;
- int result = 1;
- //consolePrintf("fread size=", size * numItems);
- for (int r = 0; (r < (s32) size * (s32) numItems) && (result > 0); r++) {
- result = handle->sramFile->read((void *) ( ((char *) (ptr)) + r), 1);
- bytes += result;
- //consolePrintf("'%d',", ((char *) (ptr))[0]);
- }
-
- handle->pos += bytes;
-
- return bytes / size;
- }
-
- if ((int)(handle->pos + size * numItems) > handle->size) {
+ if (handle->pos > handle->size)
+ numItems = 0;
+ else if ((int)(handle->pos + size * numItems) > handle->size)
numItems = (handle->size - handle->pos) / size;
- if (numItems < 0) numItems = 0;
- }
// consolePrintf("read %d ", size * numItems);
- memcpy((void *) ptr, handle->data + handle->pos, size * numItems);
+ memcpy(ptr, handle->data + handle->pos, size * numItems);
handle->pos += size * numItems;
return numItems;
}
-size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
- if ((handle == stdin)) return 0;
+size_t std_fwrite(const void *ptr, size_t size, size_t numItems, FILE *handle) {
+ if ((handle == stdin))
+ return 0;
if ((handle == stderr) || (handle == stdout)) {
// consolePrintf((char *) ptr);
@@ -677,7 +638,7 @@ size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
//consolePrintf("fwrite size=%d\n", size * numItems);
if (DS::isGBAMPAvailable()) {
- FAT_fwrite(((char *) (ptr)), size, numItems, (FAT_FILE *) handle);
+ FAT_fwrite(ptr, size, numItems, (FAT_FILE *) handle);
return numItems;
int length = size * numItems;
@@ -694,36 +655,27 @@ size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
return numItems;
}
- if (handle->sramFile) {
- handle->sramFile->write(ptr, size);
- return size;
- } else {
- return 0;
- }
+ return 0;
}
-bool std_feof(FILE* handle) {
+bool std_feof(FILE *handle) {
// consolePrintf("feof ");
if (DS::isGBAMPAvailable()) {
return readPastEndOfFile && FAT_feof((FAT_FILE *) handle);
}
- if (handle->sramFile) {
- return handle->sramFile->eos();
- }
-
// consolePrintf("feof %s", handle->pos >= handle->size? "true": "false");
return handle->pos >= handle->size;
}
-int std_fflush(FILE* handle) {
+int std_fflush(FILE *handle) {
//FIXME: not implemented?
// consolePrintf("fflush ");
return 0;
}
-long int std_ftell(FILE* handle) {
+long int std_ftell(FILE *handle) {
if (DS::isGBAMPAvailable()) {
return FAT_ftell((FAT_FILE *) handle);
}
@@ -731,7 +683,7 @@ long int std_ftell(FILE* handle) {
return handle->pos;
}
-int std_fseek(FILE* handle, long int offset, int whence) {
+int std_fseek(FILE *handle, long int offset, int whence) {
// consolePrintf("fseek %d %d ", offset, whence);
if (DS::isGBAMPAvailable()) {
@@ -756,14 +708,14 @@ int std_fseek(FILE* handle, long int offset, int whence) {
return 0;
}
-int std_ferror(FILE* handle) {
+int std_ferror(FILE *handle) {
//FIXME: not implemented?
// consolePrintf("ferror ");
return readPastEndOfFile;
}
-void std_clearerr(FILE* handle) {
+void std_clearerr(FILE *handle) {
//FIXME: not implemented?
readPastEndOfFile = false;
// consolePrintf("clearerr ");
diff --git a/backends/fs/ds/ds-fs.h b/backends/fs/ds/ds-fs.h
index c8bf7d6cf2..6961022848 100644
--- a/backends/fs/ds/ds-fs.h
+++ b/backends/fs/ds/ds-fs.h
@@ -8,27 +8,30 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
#ifndef _DS_FS_H
#define _DS_FS_H
-//#include <NDS/ARM9/console.h>
#include "common/fs.h"
+#include "common/stream.h"
+#include "backends/fs/abstract-fs.h"
+
#include "zipreader.h"
-#include "ramsave.h"
#include "fat/gba_nds_fat.h"
-#include "backends/fs/abstract-fs.h"
namespace DS {
@@ -40,7 +43,7 @@ namespace DS {
*/
class DSFileSystemNode : public AbstractFSNode {
protected:
- static ZipFile* _zipFile;
+ static ZipFile *_zipFile;
Common::String _displayName;
Common::String _path;
@@ -96,7 +99,7 @@ public:
* Returns the zip file this node points to.
* TODO: check this documentation.
*/
- static ZipFile* getZip() { return _zipFile; }
+ static ZipFile *getZip() { return _zipFile; }
};
/**
@@ -161,16 +164,16 @@ public:
struct fileHandle {
int pos;
bool used;
- char* data;
+ char *data;
int size;
-
- DSSaveFile* sramFile;
};
class DSFileStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable {
protected:
- static const int WRITE_BUFFER_SIZE = 512;
+ enum {
+ WRITE_BUFFER_SIZE = 512
+ };
/** File handle to the actual file. */
void *_handle;
@@ -206,24 +209,24 @@ public:
#undef stdout
#undef stdin
-#define stdout ((DS::fileHandle*) -1)
-#define stderr ((DS::fileHandle*) -2)
-#define stdin ((DS::fileHandle*) -3)
+#define stdout ((DS::fileHandle *) -1)
+#define stderr ((DS::fileHandle *) -2)
+#define stdin ((DS::fileHandle *) -3)
#define FILE DS::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);
-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);
-int std_fflush(FILE* handle);
-int std_ferror(FILE* handle);
-
-} //namespace DS
+FILE* std_fopen(const char *name, const char *mode);
+void std_fclose(FILE *handle);
+size_t std_fread(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);
+int std_fflush(FILE *handle);
+int std_ferror(FILE *handle);
+
+} // End of namespace DS
#endif //_DS_FS_H
diff --git a/backends/fs/palmos/palmos-fs.cpp b/backends/fs/palmos/palmos-fs.cpp
deleted file mode 100644
index 4e05f75d19..0000000000
--- a/backends/fs/palmos/palmos-fs.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- */
-
-#if defined(PALMOS_MODE)
-
-#include "PalmVersion.h"
-#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.
- *
- * Parts of this class are documented in the base interface class, AbstractFSNode.
- */
-class PalmOSFilesystemNode : public AbstractFSNode {
-protected:
- Common::String _displayName;
- Common::String _path;
- bool _isDirectory;
- bool _isValid;
- bool _isPseudoRoot; // TODO: get rid of this
-
-public:
- /**
- * Creates a PalmOSFilesystemNode with the root node as path.
- */
- PalmOSFilesystemNode();
-
- /**
- * Creates a PalmOSFilesystemNode for a given path.
- *
- * @param path Common::String with the path the new node should point to.
- */
- PalmOSFilesystemNode(const Common::String &p);
-
- virtual bool exists() const { return _isValid; }
- 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 AbstractFSNode *getChild(const Common::String &n) const;
- virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
- virtual AbstractFSNode *getParent() const;
-
- virtual Common::SeekableReadStream *createReadStream();
- virtual Common::WriteStream *createWriteStream();
-
-private:
- /**
- * Adds a single PalmOSFilesystemNode to a given list.
- * This method is used by getChildren() to populate the directory entries list.
- *
- * @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 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);
-};
-
-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 == Common::FSNode::kListDirectoriesOnly) ||
- (isDir && mode == Common::FSNode::kListFilesOnly))
- return;
-
- entry._isDirectory = isDir;
- entry._displayName = find_data->nameP;
- entry._path = base;
- entry._path += find_data->nameP;
-
- if (entry._isDirectory)
- entry._path += "/";
-
- entry._isValid = true;
- entry._isPseudoRoot = false;
-
- list.push_back(new PalmOSFilesystemNode(entry));
-}
-
-PalmOSFilesystemNode::PalmOSFilesystemNode() {
- _isDirectory = true;
- _displayName = "Root";
- _isValid = true;
- _path = "/";
- _isPseudoRoot = false;
-}
-
-PalmOSFilesystemNode::PalmOSFilesystemNode(const Common::String &p) {
- assert(p.size() > 0);
-
- _path = p;
- _displayName = lastPathComponent(_path, '/');
-
- UInt32 attr;
- FileRef handle;
- Err error = VFSFileOpen(gVars->VFS.volRefNum, _path.c_str(), vfsModeRead, &handle);
- if (!error) {
- error = VFSFileGetAttributes(handle, &attr);
- VFSFileClose(handle);
- }
-
- if (error) {
- _isValid = false;
- _isDirectory = false;
-
- } else {
- _isValid = true;
- _isDirectory = (attr & vfsFileAttrDirectory);
- }
-
- _isPseudoRoot = false;
-}
-
-AbstractFSNode *PalmOSFilesystemNode::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);
-
- Common::String newPath(_path);
- if (_path.lastChar() != '/')
- newPath += '/';
- newPath += n;
-
- return new PalmOSFilesystemNode(newPath);
-}
-
-bool PalmOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
- assert(_isDirectory);
-
- //TODO: honor the hidden flag
-
- Err error;
- Char nameP[256];
- FileInfoType desc;
- FileRef handle;
- UInt32 dirIterator = expIteratorStart;
-
- desc.nameP = nameP;
- desc.nameBufLen = 256;
-
- error = VFSFileOpen(gVars->VFS.volRefNum, _path.c_str(), vfsModeRead, &handle);
- if (error)
- return false;
-
- while (dirIterator != expIteratorStop) {
- error = VFSDirEntryEnumerate(handle, &dirIterator, &desc);
- if (!error)
- addFile(myList, mode, _path.c_str(), &desc);
- }
-
- VFSFileClose(handle);
- return true;
-}
-
-AbstractFSNode *PalmOSFilesystemNode::getParent() const {
- PalmOSFilesystemNode *p = 0;
-
- if (!_isPseudoRoot) {
- const char *start = _path.c_str();
- const char *end = lastPathComponent(_path, '/');
-
- p = new PalmOSFilesystemNode();
- p->_path = Common::String(start, end - start);
- p->_isValid = true;
- p->_isDirectory = true;
- p->_displayName = lastPathComponent(p->_path, '/');
- p->_isPseudoRoot =(p->_path == "/");
- }
-
- return p;
-}
-
-Common::SeekableReadStream *PalmOSFilesystemNode::createReadStream() {
- return StdioStream::makeFromPath(getPath().c_str(), false);
-}
-
-Common::WriteStream *PalmOSFilesystemNode::createWriteStream() {
- return StdioStream::makeFromPath(getPath().c_str(), true);
-}
-
-#endif // PALMOS_MODE
diff --git a/backends/fs/psp/psp-stream.cpp b/backends/fs/psp/psp-stream.cpp
index 8cb7dfea17..67c73beeaa 100644
--- a/backends/fs/psp/psp-stream.cpp
+++ b/backends/fs/psp/psp-stream.cpp
@@ -24,6 +24,8 @@
*/
#ifdef __PSP__
+#include <pspiofilemgr_stat.h>
+#include <pspiofilemgr.h>
#include <SDL/SDL_thread.h>
#include <SDL/SDL_mutex.h>
@@ -32,40 +34,63 @@
#include <errno.h>
-//#define __PSP_PRINT_TO_FILE__
-//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
+#define MIN2(a,b) ((a < b) ? a : b)
+#define MIN3(a,b,c) ( (a < b) ? (a < c ? a : c) : (b < c ? b : c) )
+
+//#define __PSP_PRINT_TO_FILE__ /* For debugging suspend stuff, we have no screen output */
+//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
+
#include "backends/platform/psp/trace.h"
+//#define DEBUG_BUFFERS /* to see the contents of the buffers being read */
+
+#ifdef DEBUG_BUFFERS
+void printBuffer(byte *ptr, uint32 len) {
+ uint32 printLen = len <= 10 ? len : 10;
+
+ for (int i = 0; i < printLen; i++) {
+ PSP_INFO_PRINT("%x ", ptr[i]);
+ }
+
+ if (len > 10) {
+ PSP_INFO_PRINT("... ");
+ for (int i = len - 10; i < len; i++)
+ PSP_INFO_PRINT("%x ", ptr[i]);
+ }
+
+ PSP_INFO_PRINT("\n");
+}
+#endif
+
+
PSPIoStream::PSPIoStream(const Common::String &path, bool writeMode)
- : StdioStream((void *)1), _path(path), _writeMode(writeMode) {
+ : StdioStream((void *)1), _path(path), _writeMode(writeMode),
+ _ferror(false), _pos(0),
+ _physicalPos(0), _fileSize(0), _inCache(false), _eos(false),
+ _cacheStartOffset(-1), _cache(0),
+ _errorSuspend(0), _errorSource(0),
+ _errorPos(0), _errorHandle(0), _suspendCount(0) {
DEBUG_ENTER_FUNC();
- assert(!path.empty());
+ // assert(!path.empty()); // do we need this?
_handle = (void *)0; // Need to do this since base class asserts not 0.
- _ferror = false;
- _feof = false;
- _pos = 0;
-
- /* for error checking */
- _errorSuspend = 0;
- _errorSource = 0;
- _errorPos = 0;
- _errorHandle = 0;
- _suspendCount = 0;
}
PSPIoStream::~PSPIoStream() {
DEBUG_ENTER_FUNC();
- if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ if (PowerMan.beginCriticalSection())
PSP_DEBUG_PRINT_FUNC("Suspended\n");
- PowerMan.unregisterSuspend(this); // Unregister with powermanager to be suspended
- // Must do this before fclose() or resume() will reopen.
+ PowerMan.unregisterForSuspend(this); // Unregister with powermanager to be suspended
+ // Must do this before fclose() or resume() will reopen.
- fclose((FILE *)_handle); // We don't need a critical section(?). Worst case, the handle gets closed on its own
+ fclose((FILE *)_handle); // We don't need a critical section. Worst case, the handle gets closed on its own
+
+ if (_cache)
+ free(_cache);
PowerMan.endCriticalSection();
}
@@ -75,14 +100,25 @@ PSPIoStream::~PSPIoStream() {
*/
void *PSPIoStream::open() {
DEBUG_ENTER_FUNC();
- if (PowerMan.beginCriticalSection() == PowerManager::Blocked) {
+ if (PowerMan.beginCriticalSection()) {
// No need to open. Just return the _handle resume() already opened.
PSP_DEBUG_PRINT_FUNC("Suspended\n");
}
_handle = fopen(_path.c_str(), _writeMode ? "wb" : "rb"); // open
- PowerMan.registerSuspend(this); // Register with the powermanager to be suspended
+ if (_handle) {
+ // Get the file size. This way is much faster than going to the end of the file and back
+ SceIoStat stat;
+ sceIoGetstat(_path.c_str(), &stat);
+ _fileSize = *((uint32 *)(void *)&stat.st_size); // 4GB file is big enough for us
+ PSP_DEBUG_PRINT("%s filesize = %d\n", _path.c_str(), _fileSize);
+
+ // Allocate the cache
+ _cache = (char *)memalign(64, CACHE_SIZE);
+ }
+
+ PowerMan.registerForSuspend(this); // Register with the powermanager to be suspended
PowerMan.endCriticalSection();
@@ -91,120 +127,215 @@ void *PSPIoStream::open() {
bool PSPIoStream::err() const {
DEBUG_ENTER_FUNC();
- if (_ferror)
- PSP_ERROR("mem_ferror[%d], source[%d], suspend error[%d], pos[%d], _errorPos[%d], _errorHandle[%p], suspendCount[%d]\n",
- _ferror, _errorSource, _errorSuspend, _pos, _errorPos, _errorHandle, _suspendCount);
+
+ if (_ferror) // We dump since no printing to screen with suspend
+ PSP_ERROR("mem_ferror[%d], source[%d], suspend error[%d], pos[%d], \
+ _errorPos[%d], _errorHandle[%p], suspendCount[%d]\n",
+ _ferror, _errorSource, _errorSuspend, _pos,
+ _errorPos, _errorHandle, _suspendCount);
return _ferror;
}
void PSPIoStream::clearErr() {
- _ferror = false; // Remove regular error bit
+ _ferror = false;
}
bool PSPIoStream::eos() const {
- return _feof;
+ return _eos;
}
int32 PSPIoStream::pos() const {
return _pos;
}
-
int32 PSPIoStream::size() const {
- DEBUG_ENTER_FUNC();
- if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
- PSP_DEBUG_PRINT_FUNC("Suspended\n");
-
- fseek((FILE *)_handle, 0, SEEK_END);
- int32 length = ftell((FILE *)_handle);
- fseek((FILE *)_handle, _pos, SEEK_SET);
-
- if (_pos < 0 || length < 0) { // Check for errors
- _errorSource = 2;
- PSP_ERROR("pos[%d] or length[%d] < 0!\n", _pos, length);
- _ferror = true;
- length = -1; // If our oldPos is bad, we want length to be bad too to signal
- clearerr((FILE *)_handle);
- }
-
- PowerMan.endCriticalSection();
-
- return length;
+ return _fileSize;
}
bool PSPIoStream::seek(int32 offs, int whence) {
DEBUG_ENTER_FUNC();
-
- // Check if we can access the file
- if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
- PSP_DEBUG_PRINT_FUNC("Suspended\n");
-
- int ret = fseek((FILE *)_handle, offs, whence);
-
- if (ret != 0) {
+ PSP_DEBUG_PRINT_FUNC("offset[0x%x], whence[%d], _pos[0x%x], _physPos[0x%x]\n", offs, whence, _pos, _physicalPos);
+ _eos = false;
+
+ int32 posToSearchFor = 0;
+ switch (whence) {
+ case SEEK_CUR:
+ posToSearchFor = _pos;
+ break;
+ case SEEK_END:
+ posToSearchFor = _fileSize; // unsure. Does it take us here or to EOS - 1?
+ break;
+ }
+ posToSearchFor += offs;
+
+ // Check for bad values
+ if (posToSearchFor < 0) {
_ferror = true;
- PSP_ERROR("fseek returned with [%d], non-zero\n", ret);
- clearerr((FILE *)_handle);
- _feof = feof((FILE *)_handle);
- _errorSource = 3;
- } else { // everything ok
- _feof = false; // Reset eof flag since we know it was ok
+ return false;
}
-
- _pos = ftell((FILE *)_handle); // update pos
-
- PowerMan.endCriticalSection();
-
- return (ret == 0);
+
+ if (posToSearchFor > _fileSize) {
+ _ferror = true;
+ _eos = true;
+ return false;
+ }
+
+ // See if we can find it in cache
+ if (isOffsetInCache(posToSearchFor)) {
+ PSP_DEBUG_PRINT("seek offset[0x%x] found in cache. Cache starts[0x%x]\n", posToSearchFor, _cacheStartOffset);
+ _inCache = true;
+ } else { // not in cache
+ _inCache = false;
+ }
+ _pos = posToSearchFor;
+ return true;
}
uint32 PSPIoStream::read(void *ptr, uint32 len) {
DEBUG_ENTER_FUNC();
- // Check if we can access the file
- if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
- PSP_DEBUG_PRINT_FUNC("Suspended\n");
-
- PSP_DEBUG_PRINT_FUNC("filename[%s], len[%d]\n", _path.c_str(), len);
-
- size_t ret = fread((byte *)ptr, 1, len, (FILE *)_handle);
-
- _pos += ret; // Update pos
+ PSP_DEBUG_PRINT_FUNC("filename[%s], len[0x%x], ptr[%p]\n", _path.c_str(), len, ptr);
+
+ if (_ferror || _eos)
+ return 0;
+
+ byte *destPtr = (byte *)ptr;
+ uint32 lenFromFile = len; // how much we read from the actual file
+ uint32 lenFromCache = 0; // how much we read from cache
+ uint32 lenRemainingInFile = _fileSize - _pos;
+
+ if (lenFromFile > lenRemainingInFile) {
+ lenFromFile = lenRemainingInFile;
+ _eos = true;
+ }
+
+ // Are we in cache?
+ if (_inCache && isCacheValid()) {
+ uint32 offsetInCache = _pos - _cacheStartOffset;
+ // We can read at most what's in the cache or the remaining size of the file
+ lenFromCache = MIN2(lenFromFile, CACHE_SIZE - offsetInCache); // unsure
+
+ PSP_DEBUG_PRINT("reading 0x%x bytes from cache to %p. pos[0x%x] physPos[0x%x] cacheStart[0x%x]\n", lenFromCache, destPtr, _pos, _physicalPos, _cacheStartOffset);
+
+ memcpy(destPtr, &_cache[offsetInCache], lenFromCache);
+ _pos += lenFromCache;
+
+ if (lenFromCache < lenFromFile) { // there's more to copy from the file
+ lenFromFile -= lenFromCache;
+ lenRemainingInFile -= lenFromCache; // since we moved pos
+ destPtr += lenFromCache;
+ } else { // we're done
+#ifdef DEBUG_BUFFERS
+ printBuffer((byte *)ptr, len);
+#endif
+
+ return lenFromCache; // how much we actually read
+ }
+ }
- if (ret != len) { // Check for eof
- _feof = feof((FILE *)_handle);
- if (!_feof) { // It wasn't an eof. Must be an error
+ if (PowerMan.beginCriticalSection())
+ PSP_DEBUG_PRINT_FUNC("Suspended\n");
+
+
+ synchronizePhysicalPos(); // we need to update our physical position
+
+ if (lenFromFile <= MIN_READ_SIZE) { // We load the cache in case the read is small enough
+ // This optimization is based on the principle that reading 1 byte is as expensive as 1000 bytes
+ uint32 lenToCopyToCache = MIN2((uint32)MIN_READ_SIZE, lenRemainingInFile); // at most remaining file size
+
+ PSP_DEBUG_PRINT("filling cache with 0x%x bytes from physicalPos[0x%x]. cacheStart[0x%x], pos[0x%x], fileSize[0x%x]\n", lenToCopyToCache, _physicalPos, _cacheStartOffset, _pos, _fileSize);
+
+ size_t ret = fread(_cache, 1, lenToCopyToCache, (FILE *)_handle);
+ if (ret != lenToCopyToCache) {
+ PSP_ERROR("in filling cache, failed to get 0x%x bytes. Only got 0x%x\n", lenToCopyToCache, ret);
+ _ferror = true;
+ clearerr((FILE *)_handle);
+ }
+ _cacheStartOffset = _physicalPos;
+ _inCache = true;
+
+ _physicalPos += ret;
+
+ PSP_DEBUG_PRINT("copying 0x%x bytes from cache to %p\n", lenFromFile, destPtr);
+
+ // Copy to the destination buffer from cache
+ memcpy(destPtr, _cache, lenFromFile);
+ _pos += lenFromFile;
+
+ } else { // Too big for cache. No caching
+ PSP_DEBUG_PRINT("reading 0x%x bytes from file to %p. Pos[0x%x], physPos[0x%x]\n", lenFromFile, destPtr, _pos, _physicalPos);
+ size_t ret = fread(destPtr, 1, lenFromFile, (FILE *)_handle);
+
+ _physicalPos += ret; // Update pos
+ _pos = _physicalPos;
+
+ if (ret != lenFromFile) { // error
+ PSP_ERROR("fread returned [0x%x] instead of len[0x%x]\n", ret, lenFromFile);
_ferror = true;
clearerr((FILE *)_handle);
- _pos = ftell((FILE *)_handle); // Update our position
- _errorSource = 4;
- PSP_ERROR("fread returned ret[%d] instead of len[%d]\n", ret, len);
+ _errorSource = 4;
}
+ _inCache = false;
}
PowerMan.endCriticalSection();
- return ret;
+#ifdef DEBUG_BUFFERS
+ printBuffer((byte *)ptr, len);
+#endif
+
+ return lenFromCache + lenFromFile; // total of what was copied
+}
+
+// TODO: Test if seeking backwards/forwards has any effect on performance
+inline bool PSPIoStream::synchronizePhysicalPos() {
+ if (_pos != _physicalPos) {
+ if (fseek((FILE *)_handle, _pos - _physicalPos, SEEK_CUR) != 0)
+ return false;
+ _physicalPos = _pos;
+ }
+
+ return true;
+}
+
+inline bool PSPIoStream::isOffsetInCache(uint32 offset) {
+ if (_cacheStartOffset != -1 &&
+ offset >= (uint32)_cacheStartOffset &&
+ offset < (uint32)(_cacheStartOffset + CACHE_SIZE))
+ return true;
+ return false;
}
uint32 PSPIoStream::write(const void *ptr, uint32 len) {
DEBUG_ENTER_FUNC();
// Check if we can access the file
- if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ if (PowerMan.beginCriticalSection())
PSP_DEBUG_PRINT_FUNC("Suspended\n");
- PSP_DEBUG_PRINT_FUNC("filename[%s], len[%d]\n", _path.c_str(), len);
+ PSP_DEBUG_PRINT_FUNC("filename[%s], len[0x%x]\n", _path.c_str(), len);
+ if (_ferror)
+ return 0;
+
+ _eos = false; // we can't have eos with write
+ synchronizePhysicalPos();
+
size_t ret = fwrite(ptr, 1, len, (FILE *)_handle);
- _pos += ret;
+ // If we're making the file bigger, adjust the size
+ if (_physicalPos + (int)ret > _fileSize)
+ _fileSize = _physicalPos + ret;
+ _physicalPos += ret;
+ _pos = _physicalPos;
+ _inCache = false;
+ _cacheStartOffset = -1; // invalidate cache
if (ret != len) { // Set error
_ferror = true;
clearerr((FILE *)_handle);
_pos = ftell((FILE *)_handle); // Update pos
_errorSource = 5;
- PSP_ERROR("fwrite returned[%d] instead of len[%d]\n", ret, len);
+ PSP_ERROR("fwrite returned[0x%x] instead of len[0x%x]\n", ret, len);
}
PowerMan.endCriticalSection();
@@ -215,7 +346,7 @@ uint32 PSPIoStream::write(const void *ptr, uint32 len) {
bool PSPIoStream::flush() {
DEBUG_ENTER_FUNC();
// Enter critical section
- if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ if (PowerMan.beginCriticalSection())
PSP_DEBUG_PRINT_FUNC("Suspended\n");
int ret = fflush((FILE *)_handle);
@@ -224,7 +355,7 @@ bool PSPIoStream::flush() {
_ferror = true;
clearerr((FILE *)_handle);
_errorSource = 6;
- PSP_ERROR("fflush returned ret[%u]\n", ret);
+ PSP_ERROR("fflush returned ret[%d]\n", ret);
}
PowerMan.endCriticalSection();
@@ -286,6 +417,9 @@ int PSPIoStream::resume() {
// Resume our previous position
if (_handle > 0 && _pos > 0) {
ret = fseek((FILE *)_handle, _pos, SEEK_SET);
+
+ _physicalPos = _pos;
+ _inCache = false;
if (ret != 0) { // Check for problem
_errorSuspend = ResumeError;
diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp
index fd90b67d60..067d8453a5 100644
--- a/backends/keymapper/remap-dialog.cpp
+++ b/backends/keymapper/remap-dialog.cpp
@@ -31,6 +31,8 @@
#include "gui/ScrollBarWidget.h"
#include "gui/ThemeEval.h"
+#include "common/translation.h"
+
namespace Common {
enum {
@@ -44,12 +46,12 @@ RemapDialog::RemapDialog()
_keymapper = g_system->getEventManager()->getKeymapper();
assert(_keymapper);
- _kmPopUpDesc = new GUI::StaticTextWidget(this, "KeyMapper.PopupDesc", "Keymap:");
+ _kmPopUpDesc = new GUI::StaticTextWidget(this, "KeyMapper.PopupDesc", _("Keymap:"));
_kmPopUp = new GUI::PopUpWidget(this, "KeyMapper.Popup");
_scrollBar = new GUI::ScrollBarWidget(this, 0, 0, 0, 0);
- new GUI::ButtonWidget(this, "KeyMapper.Close", "Close", kCloseCmd);
+ new GUI::ButtonWidget(this, "KeyMapper.Close", _("Close"), 0, kCloseCmd);
}
RemapDialog::~RemapDialog() {
@@ -61,7 +63,7 @@ void RemapDialog::open() {
const Stack<Keymapper::MapRecord> &activeKeymaps = _keymapper->getActiveStack();
if (!(activeKeymaps.size() > 0)) {
- _kmPopUp->appendEntry(activeKeymaps.top().keymap->getName() + " (Active)");
+ _kmPopUp->appendEntry(activeKeymaps.top().keymap->getName() + _(" (Active)"));
divider = true;
}
@@ -95,7 +97,7 @@ void RemapDialog::open() {
if (divider)
_kmPopUp->appendEntry("");
for (it = _globalKeymaps->begin(); it != _globalKeymaps->end(); ++it) {
- _kmPopUp->appendEntry(it->_value->getName() + " (Global)", idx);
+ _kmPopUp->appendEntry(it->_value->getName() + _(" (Global)"), idx);
_keymapTable[idx++] = it->_value;
}
divider = true;
@@ -105,7 +107,7 @@ void RemapDialog::open() {
if (divider)
_kmPopUp->appendEntry("");
for (it = _gameKeymaps->begin(); it != _gameKeymaps->end(); ++it) {
- _kmPopUp->appendEntry(it->_value->getName() + " (Game)", idx);
+ _kmPopUp->appendEntry(it->_value->getName() + _(" (Game)"), idx);
_keymapTable[idx++] = it->_value;
}
}
@@ -168,7 +170,7 @@ void RemapDialog::reflowLayout() {
widg.actionText =
new GUI::StaticTextWidget(this, 0, 0, 0, 0, "", Graphics::kTextAlignRight);
widg.keyButton =
- new GUI::ButtonWidget(this, 0, 0, 0, 0, "", kRemapCmd + i);
+ new GUI::ButtonWidget(this, 0, 0, 0, 0, "", 0, kRemapCmd + i);
_keymapWidgets.push_back(widg);
} else {
widg = _keymapWidgets[i];
diff --git a/backends/midi/alsa.cpp b/backends/midi/alsa.cpp
index c38537248c..4f73d7384b 100644
--- a/backends/midi/alsa.cpp
+++ b/backends/midi/alsa.cpp
@@ -24,7 +24,7 @@
#include "common/scummsys.h"
-#if defined(UNIX) && defined(USE_ALSA)
+#if defined(USE_ALSA)
#include "common/config-manager.h"
#include "common/util.h"
@@ -48,6 +48,17 @@
#define my_snd_seq_open(seqp) snd_seq_open(seqp, SND_SEQ_OPEN)
#endif
+#define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
+
+static int check_permission(snd_seq_port_info_t *pinfo)
+{
+ if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) {
+ if (!(snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_NO_EXPORT))
+ return 1;
+ }
+ return 0;
+}
+
/*
* parse address string
*/
@@ -56,7 +67,7 @@
class MidiDriver_ALSA:public MidiDriver_MPU401 {
public:
- MidiDriver_ALSA();
+ MidiDriver_ALSA(int client, int port);
int open();
void close();
void send(uint32 b);
@@ -69,34 +80,19 @@ private:
snd_seq_t *seq_handle;
int seq_client, seq_port;
int my_client, my_port;
- static int parse_addr(const char *arg, int *client, int *port);
};
-MidiDriver_ALSA::MidiDriver_ALSA()
- : _isOpen(false), seq_handle(0), seq_client(0), seq_port(0), my_client(0), my_port(0)
+MidiDriver_ALSA::MidiDriver_ALSA(int client, int port)
+ : _isOpen(false), seq_handle(0), seq_client(client), seq_port(port), my_client(0), my_port(0)
{
memset(&ev, 0, sizeof(ev));
}
int MidiDriver_ALSA::open() {
- const char *var = NULL;
-
if (_isOpen)
return MERR_ALREADY_OPEN;
_isOpen = true;
- var = getenv("SCUMMVM_PORT");
- if (!var && ConfMan.hasKey("alsa_port")) {
- var = ConfMan.get("alsa_port").c_str();
- }
-
- if (var) {
- if (parse_addr(var, &seq_client, &seq_port) < 0) {
- error("Invalid port %s", var);
- return -1;
- }
- }
-
if (my_snd_seq_open(&seq_handle) < 0) {
error("Can't open sequencer");
return -1;
@@ -108,9 +104,14 @@ int MidiDriver_ALSA::open() {
}
snd_seq_set_client_group(seq_handle, "input");
- my_port = snd_seq_create_simple_port(seq_handle, "SCUMMVM port 0",
- SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE |
- SND_SEQ_PORT_CAP_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC);
+ // According to http://www.alsa-project.org/~tiwai/alsa-subs.html
+ // you can set read or write capabilities to allow other clients to
+ // read or write the port. I don't think we need that, unless maybe
+ // to be able to record the sound, but I can't get that to work even
+ // with those capabilities.
+
+ my_port = snd_seq_create_simple_port(seq_handle, "SCUMMVM port 0", 0,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);
if (my_port < 0) {
snd_seq_close(seq_handle);
@@ -118,29 +119,45 @@ int MidiDriver_ALSA::open() {
return -1;
}
- if (var) {
- if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) {
- // subscribe to MIDI port
- if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) {
- error("Can't subscribe to MIDI port (%d:%d) see README for help", seq_client, seq_port);
+ if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) {
+ // Subscribe to MIDI port. Prefer one that doesn't already have
+ // any connections, unless we've forced a port number already.
+ if (seq_port == -1) {
+ snd_seq_client_info_t *cinfo;
+ snd_seq_port_info_t *pinfo;
+
+ snd_seq_client_info_alloca(&cinfo);
+ snd_seq_port_info_alloca(&pinfo);
+
+ snd_seq_get_any_client_info(seq_handle, seq_client, cinfo);
+
+ int first_port = -1;
+ int found_port = -1;
+
+ snd_seq_port_info_set_client(pinfo, seq_client);
+ snd_seq_port_info_set_port(pinfo, -1);
+ while (found_port == -1 && snd_seq_query_next_port(seq_handle, pinfo) >= 0) {
+ if (check_permission(pinfo)) {
+ if (first_port == -1)
+ first_port = snd_seq_port_info_get_port(pinfo);
+ if (found_port == -1 && snd_seq_port_info_get_write_use(pinfo) == 0)
+ found_port = snd_seq_port_info_get_port(pinfo);
+ }
+ }
+
+ if (found_port == -1) {
+ // Should we abort here? For now, use the first
+ // available port.
+ seq_port = first_port;
+ warning("MidiDriver_ALSA: All ports on client %d (%s) are already in use", seq_client, snd_seq_client_info_get_name(cinfo));
+ } else {
+ seq_port = found_port;
}
- }
- } else {
- int defaultPorts[] = {
- 65, 0,
- 17, 0
- };
- int i;
-
- for (i = 0; i < ARRAYSIZE(defaultPorts); i += 2) {
- seq_client = defaultPorts[i];
- seq_port = defaultPorts[i + 1];
- if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) >= 0)
- break;
}
- if (i >= ARRAYSIZE(defaultPorts))
- error("Can't subscribe to MIDI port (65:0) or (17:0)");
+ if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) {
+ error("Can't subscribe to MIDI port (%d:%d) see README for help", seq_client, seq_port);
+ }
}
printf("Connected to Alsa sequencer client [%d:%d]\n", seq_client, seq_port);
@@ -150,10 +167,13 @@ int MidiDriver_ALSA::open() {
}
void MidiDriver_ALSA::close() {
- _isOpen = false;
- MidiDriver_MPU401::close();
- if (seq_handle)
- snd_seq_close(seq_handle);
+ if (_isOpen) {
+ _isOpen = false;
+ MidiDriver_MPU401::close();
+ if (seq_handle)
+ snd_seq_close(seq_handle);
+ } else
+ warning("MidiDriver_ALSA: Closing the driver before opening it");
}
void MidiDriver_ALSA::send(uint32 b) {
@@ -227,24 +247,6 @@ void MidiDriver_ALSA::sysEx(const byte *msg, uint16 length) {
send_event(1);
}
-int MidiDriver_ALSA::parse_addr(const char *arg, int *client, int *port) {
- const char *p;
-
- if (isdigit(*arg)) {
- if ((p = strpbrk(arg, ADDR_DELIM)) == NULL)
- return -1;
- *client = atoi(arg);
- *port = atoi(p + 1);
- } else {
- if (*arg == 's' || *arg == 'S') {
- *client = SND_SEQ_ADDRESS_SUBSCRIBERS;
- *port = 0;
- } else
- return -1;
- }
- return 0;
-}
-
void MidiDriver_ALSA::send_event(int do_flush) {
snd_seq_ev_set_direct(&ev);
snd_seq_ev_set_source(&ev, my_port);
@@ -258,6 +260,37 @@ void MidiDriver_ALSA::send_event(int do_flush) {
// Plugin interface
+class AlsaDevice {
+public:
+ AlsaDevice(Common::String name, MusicType mt, int client);
+ Common::String getName();
+ MusicType getType();
+ int getClient();
+
+private:
+ Common::String _name;
+ MusicType _type;
+ int _client;
+};
+
+typedef Common::List<AlsaDevice> AlsaDevices;
+
+AlsaDevice::AlsaDevice(Common::String name, MusicType mt, int client)
+ : _name(name), _type(mt), _client(client) {
+}
+
+Common::String AlsaDevice::getName() {
+ return _name;
+}
+
+MusicType AlsaDevice::getType() {
+ return _type;
+}
+
+int AlsaDevice::getClient() {
+ return _client;
+}
+
class AlsaMusicPlugin : public MusicPluginObject {
public:
const char *getName() const {
@@ -268,26 +301,18 @@ public:
return "alsa";
}
+ AlsaDevices getAlsaDevices() const;
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
-};
-
-#define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
-static int check_permission(snd_seq_port_info_t *pinfo)
-{
- if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) {
- if (!(snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_NO_EXPORT))
- return 1;
- }
- return 0;
-}
-
-MusicDevices AlsaMusicPlugin::getDevices() const {
- MusicDevices devices;
+private:
+ static int parse_addr(const char *arg, int *client, int *port);
+};
- snd_seq_t *seq;
- if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0)
+AlsaDevices AlsaMusicPlugin::getAlsaDevices() const {
+ AlsaDevices devices;
+ snd_seq_t *seq_handle;
+ if (my_snd_seq_open(&seq_handle) < 0)
return devices; // can't open sequencer
snd_seq_client_info_t *cinfo;
@@ -295,39 +320,145 @@ MusicDevices AlsaMusicPlugin::getDevices() const {
snd_seq_port_info_t *pinfo;
snd_seq_port_info_alloca(&pinfo);
snd_seq_client_info_set_client(cinfo, -1);
- while (snd_seq_query_next_client(seq, cinfo) >= 0) {
+ while (snd_seq_query_next_client(seq_handle, cinfo) >= 0) {
bool found_valid_port = false;
/* reset query info */
snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
snd_seq_port_info_set_port(pinfo, -1);
- while (!found_valid_port && snd_seq_query_next_port(seq, pinfo) >= 0) {
+ while (!found_valid_port && snd_seq_query_next_port(seq_handle, pinfo) >= 0) {
if (check_permission(pinfo)) {
found_valid_port = true;
- // TODO: Return a different music type depending on the configuration
- devices.push_back(MusicDevice(this, snd_seq_client_info_get_name(cinfo), MT_GM));
- //snd_seq_client_info_get_client(cinfo) : snd_seq_port_info_get_port(pinfo)
+
+ const char *name = snd_seq_client_info_get_name(cinfo);
+ // TODO: Can we figure out the appropriate music type?
+ MusicType type = MT_GM;
+ int client = snd_seq_client_info_get_client(cinfo);
+ devices.push_back(AlsaDevice(name, type, client));
}
}
}
- snd_seq_close(seq);
+ snd_seq_close(seq_handle);
return devices;
}
-Common::Error AlsaMusicPlugin::createInstance(MidiDriver **mididriver) const {
- *mididriver = new MidiDriver_ALSA();
+MusicDevices AlsaMusicPlugin::getDevices() const {
+ MusicDevices devices;
+ AlsaDevices::iterator d;
- return Common::kNoError;
+ AlsaDevices alsaDevices = getAlsaDevices();
+
+ // Since the default behaviour is to use the first device in the list,
+ // try to put something sensible there. We used to have 17:0 and 65:0
+ // as defaults.
+
+ for (d = alsaDevices.begin(); d != alsaDevices.end();) {
+ const int client = d->getClient();
+
+ if (client == 17 || client == 65) {
+ devices.push_back(MusicDevice(this, d->getName(), d->getType()));
+ d = alsaDevices.erase(d);
+ } else {
+ ++d;
+ }
+ }
+
+ // 128:0 is probably TiMidity, or something like that, so that's
+ // probably a good second choice.
+
+ for (d = alsaDevices.begin(); d != alsaDevices.end();) {
+ if (d->getClient() == 128) {
+ devices.push_back(MusicDevice(this, d->getName(), d->getType()));
+ d = alsaDevices.erase(d);
+ } else {
+ ++d;
+ }
+ }
+
+ // Add the remaining devices in the order they were found.
+
+ for (d = alsaDevices.begin(); d != alsaDevices.end(); ++d)
+ devices.push_back(MusicDevice(this, d->getName(), d->getType()));
+
+ return devices;
}
-MidiDriver *MidiDriver_ALSA_create() {
- MidiDriver *mididriver;
+Common::Error AlsaMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle dev) const {
+ bool found = false;
+ int seq_client, seq_port;
+
+ const char *var = NULL;
+
+ // TODO: Upgrade from old alsa_port setting. This probably isn't the
+ // right place to do that, though.
- AlsaMusicPlugin p;
- p.createInstance(&mididriver);
+ if (ConfMan.hasKey("alsa_port")) {
+ warning("AlsaMusicPlugin: Found old 'alsa_port' setting, which will be ignored");
+ }
+
+ // The SCUMMVM_PORT environment variable can still be used to override
+ // any config setting.
- return mididriver;
+ var = getenv("SCUMMVM_PORT");
+ if (var) {
+ warning("AlsaMusicPlugin: SCUMMVM_PORT environment variable overrides config settings");
+ if (parse_addr(var, &seq_client, &seq_port) >= 0) {
+ found = true;
+ } else {
+ warning("AlsaMusicPlugin: Invalid port %s, using config settings instead", var);
+ }
+ }
+
+ // Try to match the setting to an available ALSA device.
+
+ if (!found && dev) {
+ AlsaDevices alsaDevices = getAlsaDevices();
+
+ for (AlsaDevices::iterator d = alsaDevices.begin(); d != alsaDevices.end(); ++d) {
+ MusicDevice device(this, d->getName(), d->getType());
+
+ if (device.getCompleteId().equals(MidiDriver::getDeviceString(dev, MidiDriver::kDeviceId))) {
+ found = true;
+ seq_client = d->getClient();
+ seq_port = -1;
+ break;
+ }
+ }
+ }
+
+ // Still nothing? Try a sensible default.
+
+ if (!found) {
+ // TODO: What's a sensible default anyway? And exactly when do
+ // we get to this case?
+
+ warning("AlsaMusicPlugin: Using 17:0 as default ALSA port");
+ seq_client = 17;
+ seq_port = 0;
+ }
+
+ *mididriver = new MidiDriver_ALSA(seq_client, seq_port);
+
+ return Common::kNoError;
+}
+
+int AlsaMusicPlugin::parse_addr(const char *arg, int *client, int *port) {
+ const char *p;
+
+ if (isdigit(*arg)) {
+ if ((p = strpbrk(arg, ADDR_DELIM)) == NULL)
+ return -1;
+ *client = atoi(arg);
+ *port = atoi(p + 1);
+ } else {
+ if (*arg == 's' || *arg == 'S') {
+ *client = SND_SEQ_ADDRESS_SUBSCRIBERS;
+ *port = 0;
+ } else
+ return -1;
+ }
+ return 0;
}
//#if PLUGIN_ENABLED_DYNAMIC(ALSA)
diff --git a/backends/midi/camd.cpp b/backends/midi/camd.cpp
index e4ca3569f2..3486532549 100644
--- a/backends/midi/camd.cpp
+++ b/backends/midi/camd.cpp
@@ -177,7 +177,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices CamdMusicPlugin::getDevices() const {
@@ -188,21 +188,12 @@ MusicDevices CamdMusicPlugin::getDevices() const {
return devices;
}
-Common::Error CamdMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error CamdMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_CAMD();
return Common::kNoError;
}
-MidiDriver *MidiDriver_CAMD_create() {
- MidiDriver *mididriver;
-
- CamdMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(CAMD)
//REGISTER_PLUGIN_DYNAMIC(CAMD, PLUGIN_TYPE_MUSIC, CamdMusicPlugin);
//#else
diff --git a/backends/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp
index d52547c997..aa0ad75f0a 100644
--- a/backends/midi/coreaudio.cpp
+++ b/backends/midi/coreaudio.cpp
@@ -218,7 +218,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices CoreAudioMusicPlugin::getDevices() const {
@@ -229,21 +229,12 @@ MusicDevices CoreAudioMusicPlugin::getDevices() const {
return devices;
}
-Common::Error CoreAudioMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error CoreAudioMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_CORE();
return Common::kNoError;
}
-MidiDriver *MidiDriver_CORE_create() {
- MidiDriver *mididriver;
-
- CoreAudioMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(COREAUDIO)
//REGISTER_PLUGIN_DYNAMIC(COREAUDIO, PLUGIN_TYPE_MUSIC, CoreAudioMusicPlugin);
//#else
diff --git a/backends/midi/coremidi.cpp b/backends/midi/coremidi.cpp
index e48b98a807..08f36a8b0f 100644
--- a/backends/midi/coremidi.cpp
+++ b/backends/midi/coremidi.cpp
@@ -190,7 +190,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices CoreMIDIMusicPlugin::getDevices() const {
@@ -201,21 +201,12 @@ MusicDevices CoreMIDIMusicPlugin::getDevices() const {
return devices;
}
-Common::Error CoreMIDIMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error CoreMIDIMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_CoreMIDI();
return Common::kNoError;
}
-MidiDriver *MidiDriver_CoreMIDI_create() {
- MidiDriver *mididriver;
-
- CoreMIDIMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(COREMIDI)
//REGISTER_PLUGIN_DYNAMIC(COREMIDI, PLUGIN_TYPE_MUSIC, CoreMIDIMusicPlugin);
//#else
diff --git a/backends/midi/dmedia.cpp b/backends/midi/dmedia.cpp
index 1ec79d8513..8c006b2cd9 100644
--- a/backends/midi/dmedia.cpp
+++ b/backends/midi/dmedia.cpp
@@ -199,7 +199,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices DMediaMusicPlugin::getDevices() const {
@@ -224,21 +224,12 @@ MusicDevices DMediaMusicPlugin::getDevices() const {
return devices;
}
-Common::Error DMediaMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error DMediaMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_DMEDIA();
return Common::kNoError;
}
-MidiDriver *MidiDriver_DMEDIA_create() {
- MidiDriver *mididriver;
-
- DMediaMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(DMEDIA)
//REGISTER_PLUGIN_DYNAMIC(DMEDIA, PLUGIN_TYPE_MUSIC, DMediaMusicPlugin);
//#else
diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp
index 55c8239562..e3d2c35b39 100644
--- a/backends/midi/seq.cpp
+++ b/backends/midi/seq.cpp
@@ -28,7 +28,9 @@
* both the QuickTime support and (vkeybd http://www.alsa-project.org/~iwai/alsa.html)
*/
-#if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__)
+#include "common/scummsys.h"
+
+#if defined(USE_SEQ_MIDI)
#include "common/util.h"
#include "sound/musicplugin.h"
@@ -184,7 +186,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices SeqMusicPlugin::getDevices() const {
@@ -195,21 +197,12 @@ MusicDevices SeqMusicPlugin::getDevices() const {
return devices;
}
-Common::Error SeqMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error SeqMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_SEQ();
return Common::kNoError;
}
-MidiDriver *MidiDriver_SEQ_create() {
- MidiDriver *mididriver;
-
- SeqMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(SEQ)
//REGISTER_PLUGIN_DYNAMIC(SEQ, PLUGIN_TYPE_MUSIC, SeqMusicPlugin);
//#else
diff --git a/backends/midi/stmidi.cpp b/backends/midi/stmidi.cpp
index f99f8f74dd..b00188dfea 100644
--- a/backends/midi/stmidi.cpp
+++ b/backends/midi/stmidi.cpp
@@ -127,8 +127,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver)
- const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices StMidiMusicPlugin::getDevices() const {
@@ -139,21 +138,12 @@ MusicDevices StMidiMusicPlugin::getDevices() const {
return devices;
}
-Common::Error StMidiMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error StMidiMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_STMIDI();
return Common::kNoError;
}
-MidiDriver *MidiDriver_STMIDI_create() {
- MidiDriver *mididriver;
-
- StMidiMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(STMIDI)
//REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//#else
diff --git a/backends/midi/timidity.cpp b/backends/midi/timidity.cpp
index 1a44e62b16..f507f1e00a 100644
--- a/backends/midi/timidity.cpp
+++ b/backends/midi/timidity.cpp
@@ -530,7 +530,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices TimidityMusicPlugin::getDevices() const {
@@ -539,21 +539,12 @@ MusicDevices TimidityMusicPlugin::getDevices() const {
return devices;
}
-Common::Error TimidityMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error TimidityMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_TIMIDITY();
return Common::kNoError;
}
-MidiDriver *MidiDriver_TIMIDITY_create() {
- MidiDriver *mididriver;
-
- TimidityMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(TIMIDITY)
//REGISTER_PLUGIN_DYNAMIC(TIMIDITY, PLUGIN_TYPE_MUSIC, TimidityMusicPlugin);
//#else
diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp
index 036029644e..da44c40978 100644
--- a/backends/midi/windows.cpp
+++ b/backends/midi/windows.cpp
@@ -24,12 +24,15 @@
#if defined(WIN32) && !defined(_WIN32_WCE)
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// winnt.h defines ARRAYSIZE, but we want our own one...
#undef ARRAYSIZE
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
+#include "common/config-manager.h"
+#include "common/translation.h"
#include <mmsystem.h>
@@ -46,11 +49,12 @@ private:
HANDLE _streamEvent;
HMIDIOUT _mo;
bool _isOpen;
+ int _device;
void check_error(MMRESULT result);
public:
- MidiDriver_WIN() : _isOpen(false) { }
+ MidiDriver_WIN(int deviceIndex) : _isOpen(false), _device(deviceIndex) { }
int open();
void close();
void send(uint32 b);
@@ -62,7 +66,7 @@ int MidiDriver_WIN::open() {
return MERR_ALREADY_OPEN;
_streamEvent = CreateEvent(NULL, true, true, NULL);
- MMRESULT res = midiOutOpen((HMIDIOUT *)&_mo, MIDI_MAPPER, (DWORD_PTR)_streamEvent, 0, CALLBACK_EVENT);
+ MMRESULT res = midiOutOpen((HMIDIOUT *)&_mo, _device, (DWORD_PTR)_streamEvent, 0, CALLBACK_EVENT);
if (res != MMSYSERR_NOERROR) {
check_error(res);
CloseHandle(_streamEvent);
@@ -150,7 +154,7 @@ void MidiDriver_WIN::check_error(MMRESULT result) {
class WindowsMusicPlugin : public MusicPluginObject {
public:
const char *getName() const {
- return "Windows MIDI";
+ return _s("Windows MIDI");
}
const char *getId() const {
@@ -158,32 +162,43 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices WindowsMusicPlugin::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));
+ int numDevs = midiOutGetNumDevs();
+ MIDIOUTCAPS tmp;
+
+ for (int i = 0; i < numDevs; i++) {
+ if (midiOutGetDevCaps(i, &tmp, sizeof(MIDIOUTCAPS)) != MMSYSERR_NOERROR)
+ break;
+ // There is no way to detect the "MusicType" so I just set it to MT_GM
+ // The user will have to manually select his MT32 type device and his GM type device.
+ devices.push_back(MusicDevice(this, tmp.szPname, MT_GM));
+ }
return devices;
}
-Common::Error WindowsMusicPlugin::createInstance(MidiDriver **mididriver) const {
- *mididriver = new MidiDriver_WIN();
+Common::Error WindowsMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle dev) const {
+ int devIndex = 0;
+ bool found = false;
+
+ if (dev) {
+ MusicDevices i = getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) {
+ if (d->getCompleteId().equals(MidiDriver::getDeviceString(dev, MidiDriver::kDeviceId))) {
+ found = true;
+ break;
+ }
+ devIndex++;
+ }
+ }
+ *mididriver = new MidiDriver_WIN(found ? devIndex : 0);
return Common::kNoError;
}
-MidiDriver *MidiDriver_WIN_create() {
- MidiDriver *mididriver;
-
- WindowsMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(WINDOWS)
//REGISTER_PLUGIN_DYNAMIC(WINDOWS, PLUGIN_TYPE_MUSIC, WindowsMusicPlugin);
//#else
diff --git a/backends/midi/ypa1.cpp b/backends/midi/ypa1.cpp
deleted file mode 100644
index fe65d02c10..0000000000
--- a/backends/midi/ypa1.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- */
-
-#include "common/util.h"
-#include "sound/musicplugin.h"
-#include "sound/mpu401.h"
-
-#include "Pa1Lib.h"
-
-class MidiDriver_YamahaPa1:public MidiDriver_MPU401 {
-public:
- MidiDriver_YamahaPa1();
- int open();
- void close();
- void send(uint32 b);
-
-private:
- UInt8 _midiHandle;
- Boolean _isOpen;
- };
-
-MidiDriver_YamahaPa1::MidiDriver_YamahaPa1() {
- _isOpen = false;
- _midiHandle = 0;
-}
-
-int MidiDriver_YamahaPa1::open() {
- if (!(_isOpen = Pa1Lib_midiOpen(NULL, &_midiHandle)))
- return MERR_DEVICE_NOT_AVAILABLE;
-
- return 0;
-}
-
-void MidiDriver_YamahaPa1::close() {
- if (_isOpen) {
- _isOpen = false;
- MidiDriver_MPU401::close();
- for (UInt8 channel = 0; channel < 16; channel++) {
- Pa1Lib_midiControlChange(_midiHandle, channel, 120,0); // all sound off
- Pa1Lib_midiControlChange(_midiHandle, channel, 121,0); // reset all controller
- Pa1Lib_midiControlChange(_midiHandle, channel, 123, 0); // all notes off
- }
- Pa1Lib_midiClose(_midiHandle);
- }
-}
-
-void MidiDriver_YamahaPa1::send(uint32 b) {
- if (!_isOpen)
- return;
-
- UInt8 midiCmd[4];
- UInt8 chanID,mdCmd;
-
- midiCmd[3] = (b & 0xFF000000) >> 24;
- midiCmd[2] = (b & 0x00FF0000) >> 16;
- midiCmd[1] = (b & 0x0000FF00) >> 8;
- midiCmd[0] = (b & 0x000000FF);
-
- chanID = (midiCmd[0] & 0x0F) ;
- mdCmd = midiCmd[0] & 0xF0;
-
- switch (mdCmd) {
- case 0x80: // note off
- Pa1Lib_midiNoteOff(_midiHandle, chanID, midiCmd[1], 0);
- break;
-
- case 0x90: // note on
- Pa1Lib_midiNoteOn(_midiHandle, chanID, midiCmd[1], midiCmd[2]);
- break;
-
- case 0xB0: // control change
- Pa1Lib_midiControlChange(_midiHandle, chanID, midiCmd[1], midiCmd[2]);
- break;
-
- case 0xC0: // progam change
- Pa1Lib_midiProgramChange(_midiHandle, chanID, midiCmd[1]);
- break;
-
- case 0xE0: // pitchBend
- Pa1Lib_midiPitchBend(_midiHandle, chanID, (short)(midiCmd[1] | (midiCmd[2] << 8)));
- break;
- }
-}
-
-
-// Plugin interface
-
-class YamahaPa1MusicPlugin : public MusicPluginObject {
-public:
- const char *getName() const {
- return "Yamaha Pa1";
- }
-
- const char *getId() const {
- return "ypa1";
- }
-
- MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
-};
-
-MusicDevices YamahaPa1MusicPlugin::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;
-}
-
-Common::Error YamahaPa1MusicPlugin::createInstance(MidiDriver **mididriver) const {
- *mididriver = new MidiDriver_YamahaPa1();
-
- return Common::kNoError;
-}
-
-MidiDriver *MidiDriver_YamahaPa1_create() {
- MidiDriver *mididriver;
-
- YamahaPa1MusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(YPA1)
- //REGISTER_PLUGIN_DYNAMIC(YPA1, PLUGIN_TYPE_MUSIC, YamahaPa1MusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(YPA1, PLUGIN_TYPE_MUSIC, YamahaPa1MusicPlugin);
-//#endif
diff --git a/backends/midi/zodiac.cpp b/backends/midi/zodiac.cpp
deleted file mode 100644
index b9cb46912a..0000000000
--- a/backends/midi/zodiac.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- */
-
-#include "common/util.h"
-#include "sound/musicplugin.h"
-#include "sound/mpu401.h"
-
-#ifndef DISABLE_TAPWAVE
-
-#include <tapwave.h>
-
-
-class MidiDriver_Zodiac:public MidiDriver_MPU401 {
-public:
- MidiDriver_Zodiac();
- int open();
- void close();
- void send(uint32 b);
- void sysEx(const byte *msg, uint16 length);
-
-private:
- TwMidiHandle _midiHandle;
- Boolean _isOpen;
- Int32 _oldVol;
- };
-
-MidiDriver_Zodiac::MidiDriver_Zodiac() {
- _isOpen = false;
- _midiHandle = 0;
-}
-
-int MidiDriver_Zodiac::open() {
- Err e;
-
- if (e = TwMidiOpen(&_midiHandle))
- return MERR_DEVICE_NOT_AVAILABLE;
-
- TwMidiGetMasterVolume(&_oldVol);
- TwMidiSetMasterVolume(twMidiMaxVolume); // TODO : set volume based on gVars
-
- _isOpen = true;
- return 0;
-}
-
-void MidiDriver_Zodiac::close() {
- if (_isOpen) {
- _isOpen = false;
- MidiDriver_MPU401::close();
-
- TwMidiSetMasterVolume(_oldVol);
- TwMidiClose(_midiHandle);
- }
-}
-
-void MidiDriver_Zodiac::send(uint32 b) {
- if (!_isOpen)
- return;
-
- UInt8 midiCmd[4];
- UInt8 chanID,mdCmd;
-
- midiCmd[3] = (b & 0xFF000000) >> 24;
- midiCmd[2] = (b & 0x00FF0000) >> 16;
- midiCmd[1] = (b & 0x0000FF00) >> 8;
- midiCmd[0] = (b & 0x000000FF);
-
- chanID = (midiCmd[0] & 0x0F) ;
- mdCmd = midiCmd[0] & 0xF0;
-
- switch (mdCmd) {
- case 0x80: // note off
- TwMidiNoteOff(_midiHandle, chanID, midiCmd[1], 0);
- break;
-
- case 0x90: // note on
- TwMidiNoteOn(_midiHandle, chanID, midiCmd[1], midiCmd[2]);
- break;
-
- case 0xB0: // control change
- TwMidiControlChange(_midiHandle, chanID, midiCmd[1], midiCmd[2]);
- break;
-
- case 0xC0: // progam change
- TwMidiProgramChange(_midiHandle, chanID, midiCmd[1]);
- break;
-
- case 0xE0: // pitchBend
- TwMidiPitchBend(_midiHandle, chanID, (short)(midiCmd[1] | (midiCmd[2] << 8)));
- break;
- }
-}
-
-void MidiDriver_Zodiac::sysEx(const byte *msg, uint16 length) {
- unsigned char buf[266];
-
- buf[0] = 0xF0;
- memcpy(buf + 1, msg, length);
- buf[length + 1] = 0xF7;
-
- TwMidiSysEx(_midiHandle, 0, (byte *)buf, length + 2);
-}
-
-
-// Plugin interface
-
-class ZodiacMusicPlugin : public MusicPluginObject {
-public:
- const char *getName() const {
- return "Tapwave Zodiac";
- }
-
- const char *getId() const {
- return "zodiac";
- }
-
- MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
-};
-
-MusicDevices ZodiacMusicPlugin::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;
-}
-
-Common::Error ZodiacMusicPlugin::createInstance(MidiDriver **mididriver) const {
- *mididriver = new MidiDriver_Zodiac();
-
- return Common::kNoError;
-}
-
-MidiDriver *MidiDriver_Zodiac_create() {
- MidiDriver *mididriver;
-
- ZodiacMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(ZODIAC)
- //REGISTER_PLUGIN_DYNAMIC(ZODIAC, PLUGIN_TYPE_MUSIC, ZodiacMusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(ZODIAC, PLUGIN_TYPE_MUSIC, ZodiacMusicPlugin);
-//#endif
-
-#endif
diff --git a/backends/module.mk b/backends/module.mk
index 50ef1596ae..c0457d8062 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -6,17 +6,9 @@ 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 \
fs/posix/posix-fs-factory.o \
- fs/ps2/ps2-fs-factory.o \
- fs/psp/psp-fs-factory.o \
- fs/psp/psp-stream.o \
fs/symbian/symbian-fs-factory.o \
fs/windows/windows-fs-factory.o \
- fs/wii/wii-fs-factory.o \
- fs/n64/n64-fs-factory.o \
- fs/n64/romfsstream.o \
keymapper/action.o \
keymapper/keymap.o \
keymapper/keymapper.o \
@@ -36,23 +28,56 @@ MODULE_OBJS := \
plugins/arm-loader.o \
plugins/elf-provider.o \
plugins/dc/dc-provider.o \
- plugins/ds/ds-provider.o \
plugins/posix/posix-provider.o \
plugins/sdl/sdl-provider.o \
plugins/win32/win32-provider.o \
- plugins/psp/psp-provider.o \
- plugins/ps2/ps2-provider.o \
saves/savefile.o \
saves/default/default-saves.o \
saves/posix/posix-saves.o \
- saves/psp/psp-saves.o \
timer/default/default-timer.o \
- timer/psp/timer.o \
vkeybd/image-map.o \
vkeybd/polygon.o \
vkeybd/virtual-keyboard.o \
vkeybd/virtual-keyboard-gui.o \
vkeybd/virtual-keyboard-parser.o
+ifeq ($(BACKEND),dc)
+MODULE_OBJS += \
+ plugins/dc/dc-provider.o
+endif
+
+ifeq ($(BACKEND),ds)
+MODULE_OBJS += \
+ fs/ds/ds-fs-factory.o \
+ fs/ds/ds-fs.o \
+ plugins/ds/ds-provider.o
+endif
+
+ifeq ($(BACKEND),n64)
+MODULE_OBJS += \
+ fs/n64/n64-fs-factory.o \
+ fs/n64/romfsstream.o
+endif
+
+ifeq ($(BACKEND),ps2)
+MODULE_OBJS += \
+ fs/ps2/ps2-fs-factory.o \
+ plugins/ps2/ps2-provider.o
+endif
+
+ifeq ($(BACKEND),psp)
+MODULE_OBJS += \
+ fs/psp/psp-fs-factory.o \
+ fs/psp/psp-stream.o \
+ plugins/psp/psp-provider.o \
+ saves/psp/psp-saves.o \
+ timer/psp/timer.o
+endif
+
+ifeq ($(BACKEND),wii)
+MODULE_OBJS += \
+ fs/wii/wii-fs-factory.o
+endif
+
# Include common rules
include $(srcdir)/rules.mk
diff --git a/backends/platform/PalmOS/Rsc/Resource.Frk/Starter.rsrc b/backends/platform/PalmOS/Rsc/Resource.Frk/Starter.rsrc
deleted file mode 100644
index 70f74412e7..0000000000
--- a/backends/platform/PalmOS/Rsc/Resource.Frk/Starter.rsrc
+++ /dev/null
Binary files differ
diff --git a/backends/platform/PalmOS/Rsc/Starter.rsrc b/backends/platform/PalmOS/Rsc/Starter.rsrc
deleted file mode 100644
index e69de29bb2..0000000000
--- a/backends/platform/PalmOS/Rsc/Starter.rsrc
+++ /dev/null
diff --git a/backends/platform/PalmOS/Rsc/StarterRsc.h b/backends/platform/PalmOS/Rsc/StarterRsc.h
deleted file mode 100644
index fba46b310b..0000000000
--- a/backends/platform/PalmOS/Rsc/StarterRsc.h
+++ /dev/null
@@ -1,395 +0,0 @@
-#ifndef STARTERRSC_H
-#define STARTERRSC_H
-
-// Header generated by Constructor for Palm OS (R) 1.9.1
-//
-// Generated at 12:00:06 on samedi 25 août 2007
-//
-// Generated for file: Starter.rsrc
-//
-// THIS IS AN AUTOMATICALLY GENERATED HEADER FILE
-// DO NOT EDIT - CHANGES MADE TO THIS FILE WILL BE LOST
-//
-// Palm App Name: "ScummVM"
-//
-// Palm App Version: "1.0"
-
-
-// Resource: tFRM 1000
-#define MainForm 1000 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 160, Usable = 1, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 1000, Default Button ID = 0)
-#define MainCardsButton 1003 //(Left Origin = 135, Top Origin = 1, Width = 12, Height = 12, Usable = 1, Anchor Left = 1, Frame = 0, Non-bold Frame = 0, Font = Standard)
-#define MainAboutButton 1012 //(Left Origin = 148, Top Origin = 1, Width = 12, Height = 12, Usable = 1, Anchor Left = 1, Frame = 0, Non-bold Frame = 1, Font = Standard)
-#define MainMSBitMap 1100 //(Left Origin = 135, Top Origin = 1, Bitmap Resource ID = 1100, Usable = 0)
-#define MainMSNoneBitMap 1110 //(Left Origin = 135, Top Origin = 1, Bitmap Resource ID = 1110, Usable = 0)
-#define MainUnnamed1010BitMap 2000 //(Left Origin = 148, Top Origin = 1, Bitmap Resource ID = 2000, Usable = 1)
-
-// Resource: tFRM 1200
-#define SkinsForm 1200 //(Left Origin = 2, Top Origin = 2, Width = 156, Height = 156, Usable = 1, Modal = 1, Save Behind = 1, Help ID = 0, Menu Bar ID = 0, Default Button ID = 1203)
-#define SkinsOKButton 1202 //(Left Origin = 5, Top Origin = 139, Width = 32, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define SkinsCancelButton 1203 //(Left Origin = 43, Top Origin = 139, Width = 32, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define SkinsDeleteButton 1205 //(Left Origin = 119, Top Origin = 139, Width = 32, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define SkinsBeamButton 1206 //(Left Origin = 81, Top Origin = 139, Width = 32, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define SkinsSoundClickCheckbox 1204 //(Left Origin = 5, Top Origin = 118, Width = 93, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define SkinsSkinList 1201 //(Left Origin = 5, Top Origin = 17, Width = 146, Usable = 1, Font = Standard, Visible Items = 9)
-
-// Resource: tFRM 1500
-#define CardSlotForm 1500 //(Left Origin = 2, Top Origin = 2, Width = 156, Height = 156, Usable = 1, Modal = 1, Save Behind = 1, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define CardSlotOkButton 1510 //(Left Origin = 3, Top Origin = 140, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define CardSlotCancelButton 1511 //(Left Origin = 44, Top Origin = 140, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-
-// Resource: tFRM 2700
-#define MiscForm 2700 //(Left Origin = 2, Top Origin = 2, Width = 156, Height = 156, Usable = 1, Modal = 1, Save Behind = 1, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define MiscOKButton 2710 //(Left Origin = 5, Top Origin = 139, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define MiscCancelButton 2711 //(Left Origin = 46, Top Origin = 139, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-
-// Resource: tFRM 2000
-#define ConvertForm 2000 //(Left Origin = 34, Top Origin = 64, Width = 91, Height = 32, Usable = 1, Modal = 1, Save Behind = 1, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define ConvertUnnamed2001Label 2001 //(Left Origin = 7, Top Origin = 4, Usable = 1, Font = Standard)
-#define ConvertUnnamed2002Label 2002 //(Left Origin = 16, Top Origin = 16, Usable = 1, Font = Bold)
-
-// Resource: tFRM 2100
-#define BeamForm 2100 //(Left Origin = 2, Top Origin = 72, Width = 156, Height = 86, Usable = 1, Modal = 1, Save Behind = 1, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define BeamSendButton 2105 //(Left Origin = 5, Top Origin = 69, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define BeamCancelButton 2106 //(Left Origin = 47, Top Origin = 69, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define BeamMathlibCheckbox 2101 //(Left Origin = 4, Top Origin = 28, Width = 55, Height = 12, Usable = 1, Selected = 1, Group ID = 0, Font = Standard)
-#define BeamGamesCheckbox 2103 //(Left Origin = 4, Top Origin = 40, Width = 86, Height = 12, Usable = 1, Selected = 1, Group ID = 0, Font = Standard)
-#define BeamSkinCheckbox 2104 //(Left Origin = 4, Top Origin = 52, Width = 84, Height = 12, Usable = 1, Selected = 1, Group ID = 0, Font = Standard)
-#define BeamUnnamed2102Label 2102 //(Left Origin = 4, Top Origin = 16, Usable = 1, Font = Bold)
-
-// Resource: tFRM 2200
-#define MusicForm 2200 //(Left Origin = 2, Top Origin = 2, Width = 156, Height = 156, Usable = 1, Modal = 1, Save Behind = 1, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define MusicOKButton 2210 //(Left Origin = 5, Top Origin = 139, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define MusicCancelButton 2211 //(Left Origin = 46, Top Origin = 139, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-
-// Resource: tFRM 2300
-#define TabMusicForm 2300 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 120, Usable = 0, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabMusicMusicCheckbox 2301 //(Left Origin = 4, Top Origin = 12, Width = 100, Height = 12, Usable = 1, Selected = 1, Group ID = 0, Font = Standard)
-#define TabMusicMultiMidiCheckbox 2308 //(Left Origin = 4, Top Origin = 24, Width = 120, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMusicTempoField 2302 //(Left Origin = 54, Top Origin = 36, Width = 16, Height = 12, Usable = 1, Editable = 1, Underline = 1, Single Line = 1, Dynamic Size = 0, Left Justified = 1, Max Characters = 3, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 1)
-#define TabMusicTitleLabel 2303 //(Left Origin = 6, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabMusicUnnamed2304Label 2304 //(Left Origin = 21, Top Origin = 48, Usable = 1, Font = Standard)
-#define TabMusicUnnamed2305Label 2305 //(Left Origin = 16, Top Origin = 60, Usable = 1, Font = Standard)
-#define TabMusicUnnamed2306Label 2306 //(Left Origin = 18, Top Origin = 36, Usable = 1, Font = Standard)
-#define TabMusicUnnamed2307Label 2307 //(Left Origin = 72, Top Origin = 36, Usable = 1, Font = Standard)
-#define TabMusicUnnamed2309Label 2309 //(Left Origin = 28, Top Origin = 72, Usable = 1, Font = Standard)
-#define TabMusicRateList 2311 //(Left Origin = 54, Top Origin = 73, Width = 55, Usable = 0, Font = Standard, Visible Items = 3)
-#define TabMusicQualityList 2313 //(Left Origin = 54, Top Origin = 60, Width = 60, Usable = 0, Font = Standard, Visible Items = 3)
-#define TabMusicDriverList 2331 //(Left Origin = 54, Top Origin = 24, Width = 65, Usable = 0, Font = Standard, Visible Items = 4)
-#define TabMusicRatePopTrigger 2310 //(Left Origin = 54, Top Origin = 72, Width = 55, Height = 12, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 2311)
-#define TabMusicQualityPopTrigger 2312 //(Left Origin = 54, Top Origin = 60, Width = 50, Height = 12, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 2313)
-#define TabMusicDriverPopTrigger 2330 //(Left Origin = 54, Top Origin = 48, Width = 65, Height = 12, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 2331)
-
-// Resource: tFRM 2500
-#define TabAudioCDForm 2500 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 110, Usable = 0, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabAudioCDMP3Checkbox 2502 //(Left Origin = 4, Top Origin = 12, Width = 125, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabAudioCDLengthSecsField 2504 //(Left Origin = 112, Top Origin = 60, Width = 16, Height = 12, Usable = 1, Editable = 1, Underline = 1, Single Line = 1, Dynamic Size = 0, Left Justified = 1, Max Characters = 3, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 1)
-#define TabAudioCDFirstTrackField 2507 //(Left Origin = 112, Top Origin = 50, Width = 16, Height = 12, Usable = 1, Editable = 1, Underline = 1, Single Line = 1, Dynamic Size = 0, Left Justified = 1, Max Characters = 80, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 1)
-#define TabAudioCDUnnamed2501Label 2501 //(Left Origin = 6, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabAudioCDUnnamed2503Label 2503 //(Left Origin = 20, Top Origin = 60, Usable = 1, Font = Standard)
-#define TabAudioCDUnnamed2505Label 2505 //(Left Origin = 130, Top Origin = 61, Usable = 1, Font = Standard)
-#define TabAudioCDUnnamed2506Label 2506 //(Left Origin = 21, Top Origin = 48, Usable = 1, Font = Standard)
-#define TabAudioCDUnnamed2508Label 2508 //(Left Origin = 25, Top Origin = 24, Usable = 1, Font = Standard)
-#define TabAudioCDUnnamed2511Label 2511 //(Left Origin = 21, Top Origin = 36, Usable = 1, Font = Standard)
-#define TabAudioCDUnnamed2514Label 2514 //(Left Origin = 4, Top Origin = 80, Usable = 1, Font = Standard)
-#define TabAudioCDDriverList 2510 //(Left Origin = 58, Top Origin = 24, Width = 90, Usable = 0, Font = Standard, Visible Items = 4)
-#define TabAudioCDFormatList 2513 //(Left Origin = 58, Top Origin = 36, Width = 70, Usable = 0, Font = Standard, Visible Items = 2)
-#define TabAudioCDDriverPopTrigger 2509 //(Left Origin = 58, Top Origin = 24, Width = 90, Height = 12, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 2510)
-#define TabAudioCDFormatPopTrigger 2512 //(Left Origin = 58, Top Origin = 36, Width = 70, Height = 12, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 2513)
-
-// Resource: tFRM 2600
-#define TabVolumeForm 2600 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 100, Usable = 0, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabVolumeUnnamed2601Label 2601 //(Left Origin = 29, Top Origin = 69, Usable = 1, Font = Standard)
-#define TabVolumeUnnamed2603Label 2603 //(Left Origin = 6, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabVolumeUnnamed2606Label 2606 //(Left Origin = 26, Top Origin = 15, Usable = 1, Font = Standard)
-#define TabVolumeUnnamed2607Label 2607 //(Left Origin = 12, Top Origin = 30, Usable = 1, Font = Standard)
-#define TabVolumeUnnamed2608Label 2608 //(Left Origin = 20, Top Origin = 45, Usable = 1, Font = Standard)
-#define TabVolumeUnnamed2610Label 2610 //(Left Origin = 14, Top Origin = 84, Usable = 1, Font = Standard)
-#define TabVolumeMusicSliderControl 2602 //(Left Origin = 58, Top Origin = 12, Width = 93, Height = 15, Usable = 1, Initial Value = 0, Minimum Value = 0, Maximum Value = 255, Page Jump Amount = 1, Thumb Bitmap = 0, Background Bitmap = 0)
-#define TabVolumeSfxSliderControl 2604 //(Left Origin = 58, Top Origin = 27, Width = 93, Height = 15, Usable = 1, Initial Value = 0, Minimum Value = 0, Maximum Value = 255, Page Jump Amount = 1, Thumb Bitmap = 0, Background Bitmap = 0)
-#define TabVolumePalmSliderControl 2605 //(Left Origin = 58, Top Origin = 66, Width = 93, Height = 15, Usable = 1, Initial Value = 0, Minimum Value = 0, Maximum Value = 100, Page Jump Amount = 1, Thumb Bitmap = 0, Background Bitmap = 0)
-#define TabVolumeSpeechSliderControl 2609 //(Left Origin = 58, Top Origin = 42, Width = 93, Height = 15, Usable = 1, Initial Value = 0, Minimum Value = 0, Maximum Value = 255, Page Jump Amount = 1, Thumb Bitmap = 0, Background Bitmap = 0)
-#define TabVolumeAudioCDSliderControl 2611 //(Left Origin = 58, Top Origin = 81, Width = 93, Height = 15, Usable = 1, Initial Value = 0, Minimum Value = 0, Maximum Value = 100, Page Jump Amount = 1, Thumb Bitmap = 0, Background Bitmap = 0)
-
-// Resource: tFRM 2800
-#define TabMiscPalmOSForm 2800 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 120, Usable = 0, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabMiscPalmOSVibratorCheckbox 2802 //(Left Origin = 4, Top Origin = 12, Width = 128, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscPalmOSNoAutoOffCheckbox 2803 //(Left Origin = 4, Top Origin = 24, Width = 152, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscPalmOSStdPaletteCheckbox 2804 //(Left Origin = 4, Top Origin = 84, Width = 146, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscPalmOSLargerStackCheckbox 2805 //(Left Origin = 4, Top Origin = 36, Width = 100, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscPalmOSAdvancedCheckbox 2806 //(Left Origin = 4, Top Origin = 96, Width = 100, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscPalmOSArrowCheckbox 2807 //(Left Origin = 4, Top Origin = 72, Width = 150, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscPalmOSExitLauncherCheckbox 2810 //(Left Origin = 4, Top Origin = 48, Width = 150, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscPalmOSStylusClickCheckbox 2811 //(Left Origin = 4, Top Origin = 60, Width = 120, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscPalmOSTabTitlePalmLabel 2801 //(Left Origin = 4, Top Origin = 0, Usable = 1, Font = Bold)
-
-// Resource: tFRM 2900
-#define TabMiscScummVMForm 2900 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 120, Usable = 0, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabMiscScummVMAutosaveCheckbox 2902 //(Left Origin = 4, Top Origin = 48, Width = 90, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscScummVMDebugCheckbox 2904 //(Left Origin = 4, Top Origin = 60, Width = 90, Height = 12, Usable = 0, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscScummVMDemoCheckbox 2905 //(Left Origin = 4, Top Origin = 12, Width = 100, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscScummVMCopyProtectionCheckbox 2906 //(Left Origin = 4, Top Origin = 24, Width = 120, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscScummVMAltIntroCheckbox 2908 //(Left Origin = 4, Top Origin = 36, Width = 120, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscScummVMDebugLevelField 2907 //(Left Origin = 101, Top Origin = 60, Width = 12, Height = 12, Usable = 1, Editable = 1, Underline = 1, Single Line = 1, Dynamic Size = 0, Left Justified = 1, Max Characters = 1, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 1)
-#define TabMiscScummVMAutosaveField 2910 //(Left Origin = 101, Top Origin = 48, Width = 20, Height = 12, Usable = 1, Editable = 1, Underline = 1, Single Line = 1, Dynamic Size = 0, Left Justified = 1, Max Characters = 4, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 1)
-#define TabMiscScummVMTabTitleScummLabel 2901 //(Left Origin = 4, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabMiscScummVMUnnamed2903Label 2903 //(Left Origin = 97, Top Origin = 61, Usable = 1, Font = Standard)
-#define TabMiscScummVMUnnamed2909Label 2909 //(Left Origin = 97, Top Origin = 48, Usable = 1, Font = Standard)
-#define TabMiscScummVMUnnamed2911Label 2911 //(Left Origin = 123, Top Origin = 48, Usable = 1, Font = Standard)
-
-// Resource: tFRM 3000
-#define GameEditForm 3000 //(Left Origin = 2, Top Origin = 2, Width = 156, Height = 156, Usable = 1, Modal = 1, Save Behind = 1, Help ID = 0, Menu Bar ID = 0, Default Button ID = 1411)
-#define GameEditOKButton 3020 //(Left Origin = 5, Top Origin = 139, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define GameEditCancelButton 3021 //(Left Origin = 46, Top Origin = 139, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define GameEditDeleteButton 3023 //(Left Origin = 109, Top Origin = 139, Width = 42, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define GameEditUnnamed3022GraffitiShift 3022 //(Left Origin = 87, Top Origin = 140)
-
-// Resource: tFRM 3100
-#define TabGameInfoForm 3100 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 120, Usable = 1, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabGameInfoEntryNameField 3102 //(Left Origin = 4, Top Origin = 12, Width = 151, Height = 24, Usable = 1, Editable = 1, Underline = 1, Single Line = 0, Dynamic Size = 0, Left Justified = 1, Max Characters = 50, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 0)
-#define TabGameInfoPathField 3104 //(Left Origin = 37, Top Origin = 38, Width = 118, Height = 24, Usable = 1, Editable = 1, Underline = 1, Single Line = 0, Dynamic Size = 0, Left Justified = 1, Max Characters = 150, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 0)
-#define TabGameInfoGameField 3106 //(Left Origin = 37, Top Origin = 64, Width = 52, Height = 12, Usable = 1, Editable = 1, Underline = 1, Single Line = 1, Dynamic Size = 0, Left Justified = 1, Max Characters = 15, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 0)
-#define TabGameInfoUnnamed3101Label 3101 //(Left Origin = 4, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabGameInfoUnnamed3103Label 3103 //(Left Origin = 11, Top Origin = 38, Usable = 1, Font = Standard)
-#define TabGameInfoUnnamed3105Label 3105 //(Left Origin = 6, Top Origin = 64, Usable = 1, Font = Standard)
-#define TabGameInfoUnnamed3107Label 3107 //(Left Origin = 4, Top Origin = 79, Usable = 1, Font = Standard)
-#define TabGameInfoEngineList 3109 //(Left Origin = 37, Top Origin = 57, Width = 115, Usable = 0, Font = Standard, Visible Items = 3)
-#define TabGameInfoBrowsePushButton 3110 //(Left Origin = 11, Top Origin = 50, Width = 22, Height = 12, Usable = 1, Group ID = 0, Font = Standard)
-#define TabGameInfoEnginePopTrigger 3108 //(Left Origin = 37, Top Origin = 79, Width = 115, Height = 12, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 3109)
-
-// Resource: tFRM 3200
-#define TabGameDisplayForm 3200 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 95, Usable = 1, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabGameDisplayFilterCheckbox 3205 //(Left Origin = 4, Top Origin = 36, Width = 80, Height = 12, Usable = 1, Selected = 1, Group ID = 0, Font = Standard)
-#define TabGameDisplayFullscreenCheckbox 3206 //(Left Origin = 4, Top Origin = 60, Width = 100, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabGameDisplayAspectRatioCheckbox 3207 //(Left Origin = 4, Top Origin = 48, Width = 120, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabGameDisplayUnnamed3201Label 3201 //(Left Origin = 4, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabGameDisplayUnnamed3202Label 3202 //(Left Origin = 5, Top Origin = 24, Usable = 1, Font = Standard)
-#define TabGameDisplayUnnamed3208Label 3208 //(Left Origin = 10, Top Origin = 12, Usable = 1, Font = Standard)
-#define TabGameDisplayGfxListList 3204 //(Left Origin = 38, Top Origin = 12, Width = 75, Usable = 0, Font = Standard, Visible Items = 2)
-#define TabGameDisplayRenderList 3210 //(Left Origin = 38, Top Origin = 24, Width = 75, Usable = 0, Font = Standard, Visible Items = 6)
-#define TabGameDisplayGfxPopupPopTrigger 3203 //(Left Origin = 38, Top Origin = 12, Width = 80, Height = 12, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 3204)
-#define TabGameDisplayRenderPopTrigger 3209 //(Left Origin = 38, Top Origin = 24, Width = 85, Height = 12, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 3209)
-
-// Resource: tFRM 3300
-#define TabGameOptionsForm 3300 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 160, Usable = 1, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabGameOptionsLoadSlotCheckbox 3302 //(Left Origin = 4, Top Origin = 24, Width = 85, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabGameOptionsStartRoomCheckbox 3303 //(Left Origin = 4, Top Origin = 36, Width = 84, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabGameOptionsAmigaCheckbox 3306 //(Left Origin = 4, Top Origin = 48, Width = 81, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabGameOptionsSubtitlesCheckbox 3307 //(Left Origin = 4, Top Origin = 60, Width = 82, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabGameOptionsTalkSpeedCheckbox 3308 //(Left Origin = 4, Top Origin = 12, Width = 66, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabGameOptionsLoadSlotField 3304 //(Left Origin = 92, Top Origin = 24, Width = 12, Height = 12, Usable = 1, Editable = 1, Underline = 1, Single Line = 1, Dynamic Size = 0, Left Justified = 1, Max Characters = 2, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 1)
-#define TabGameOptionsStartRoomField 3305 //(Left Origin = 92, Top Origin = 36, Width = 18, Height = 12, Usable = 1, Editable = 1, Underline = 1, Single Line = 1, Dynamic Size = 0, Left Justified = 1, Max Characters = 4, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 1)
-#define TabGameOptionsTalkSpeedField 3309 //(Left Origin = 92, Top Origin = 12, Width = 18, Height = 12, Usable = 1, Editable = 1, Underline = 1, Single Line = 1, Dynamic Size = 0, Left Justified = 1, Max Characters = 3, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 1)
-#define TabGameOptionsUnnamed3301Label 3301 //(Left Origin = 4, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabGameOptionsUnnamed3314Label 3314 //(Left Origin = 88, Top Origin = 24, Usable = 1, Font = Standard)
-#define TabGameOptionsUnnamed3315Label 3315 //(Left Origin = 88, Top Origin = 36, Usable = 1, Font = Standard)
-#define TabGameOptionsUnnamed3316Label 3316 //(Left Origin = 88, Top Origin = 12, Usable = 1, Font = Standard)
-#define TabGameOptionsUnnamed3317Label 3317 //(Left Origin = 88, Top Origin = 48, Usable = 1, Font = Standard)
-#define TabGameOptionsUnnamed3318Label 3318 //(Left Origin = 88, Top Origin = 60, Usable = 1, Font = Standard)
-#define TabGameOptionsLanguageList 3311 //(Left Origin = 92, Top Origin = 15, Width = 64, Usable = 0, Font = Standard, Visible Items = 5)
-#define TabGameOptionsPlatformList 3313 //(Left Origin = 92, Top Origin = 15, Width = 64, Usable = 0, Font = Standard, Visible Items = 4)
-#define TabGameOptionsLanguagePopTrigger 3310 //(Left Origin = 90, Top Origin = 60, Width = 65, Height = 12, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 3311)
-#define TabGameOptionsPlatformPopTrigger 3312 //(Left Origin = 90, Top Origin = 48, Width = 65, Height = 12, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 3313)
-
-// Resource: tFRM 3400
-#define ImportForm 3400 //(Left Origin = 34, Top Origin = 64, Width = 91, Height = 32, Usable = 1, Modal = 1, Save Behind = 1, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define ImportUnnamed3401Label 3401 //(Left Origin = 4, Top Origin = 4, Usable = 1, Font = Standard)
-#define ImportUnnamed3402Label 3402 //(Left Origin = 16, Top Origin = 16, Usable = 1, Font = Bold)
-
-// Resource: tFRM 1400
-#define EngineForm 1400 //(Left Origin = 2, Top Origin = 2, Width = 156, Height = 156, Usable = 1, Modal = 1, Save Behind = 1, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define EngineOkButton 1403 //(Left Origin = 4, Top Origin = 139, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define EngineCancelButton 1420 //(Left Origin = 45, Top Origin = 139, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-#define EngineUnnamed1402Label 1402 //(Left Origin = 4, Top Origin = 16, Usable = 1, Font = Bold)
-#define EngineUnnamed1404Label 1404 //(Left Origin = 4, Top Origin = 88, Usable = 1, Font = Bold)
-#define EngineListList 1401 //(Left Origin = 4, Top Origin = 30, Width = 148, Usable = 1, Font = Standard, Visible Items = 5)
-#define EngineSupportedList 1405 //(Left Origin = 4, Top Origin = 102, Width = 148, Usable = 1, Font = Standard, Visible Items = 3)
-
-// Resource: tFRM 4000
-#define InfoForm 4000 //(Left Origin = 2, Top Origin = 2, Width = 156, Height = 156, Usable = 1, Modal = 1, Save Behind = 1, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define InfoOKButton 4020 //(Left Origin = 5, Top Origin = 139, Width = 36, Height = 12, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
-
-// Resource: tFRM 4100
-#define TabInfoAboutForm 4100 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 125, Usable = 1, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabInfoAboutTabTitleAboutLabel 4101 //(Left Origin = 4, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabInfoAboutUnnamed4103Label 4103 //(Left Origin = 23, Top Origin = 58, Usable = 1, Font = Bold)
-#define TabInfoAboutUnnamed4104Label 4104 //(Left Origin = 34, Top Origin = 70, Usable = 1, Font = Standard)
-#define TabInfoAboutUnnamed4105Label 4105 //(Left Origin = 8, Top Origin = 82, Usable = 1, Font = Bold)
-
-// Resource: tFRM 4200
-#define TabInfoVersionForm 4200 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 100, Usable = 1, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabInfoVersionTabTitleAboutLabel 4201 //(Left Origin = 4, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabInfoVersionUnnamed4202Label 4202 //(Left Origin = 10, Top Origin = 12, Usable = 1, Font = Standard)
-#define TabInfoVersionUnnamed4203Label 4203 //(Left Origin = 24, Top Origin = 24, Usable = 1, Font = Standard)
-#define TabInfoVersionUnnamed4204Label 4204 //(Left Origin = 4, Top Origin = 42, Usable = 1, Font = Bold)
-#define TabInfoVersionUnnamed4205Label 4205 //(Left Origin = 5, Top Origin = 53, Usable = 1, Font = Standard)
-#define TabInfoVersionUnnamed4206Label 4206 //(Left Origin = 4, Top Origin = 72, Usable = 1, Font = Bold)
-#define TabInfoVersionUnnamed4207Label 4207 //(Left Origin = 4, Top Origin = 84, Usable = 1, Font = Standard)
-
-// Resource: tFRM 4300
-#define TabInfoSystemForm 4300 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 100, Usable = 1, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabInfoSystemTabTitleAboutLabel 4301 //(Left Origin = 4, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabInfoSystemUnnamed4302Label 4302 //(Left Origin = 10, Top Origin = 12, Usable = 1, Font = Standard)
-#define TabInfoSystemUnnamed4303Label 4303 //(Left Origin = 13, Top Origin = 24, Usable = 1, Font = Standard)
-#define TabInfoSystemUnnamed4304Label 4304 //(Left Origin = 5, Top Origin = 36, Usable = 1, Font = Standard)
-#define TabInfoSystemUnnamed4305Label 4305 //(Left Origin = 96, Top Origin = 0, Usable = 1, Font = Standard)
-#define TabInfoSystemUnnamed4306Label 4306 //(Left Origin = 132, Top Origin = 0, Usable = 1, Font = Standard)
-
-// Resource: tFRM 1600
-#define TabCardConfigForm 1600 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 110, Usable = 1, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabCardConfigDetectCheckbox 1602 //(Left Origin = 4, Top Origin = 86, Width = 150, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabCardConfigCacheCheckbox 1604 //(Left Origin = 4, Top Origin = 62, Width = 120, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabCardConfigLedCheckbox 1608 //(Left Origin = 4, Top Origin = 50, Width = 130, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabCardConfigCacheSizeField 1606 //(Left Origin = 68, Top Origin = 74, Width = 18, Height = 12, Usable = 1, Editable = 1, Underline = 1, Single Line = 1, Dynamic Size = 0, Left Justified = 1, Max Characters = 3, Font = Standard, Auto Shift = 0, Has Scroll Bar = 0, Numeric = 1)
-#define TabCardConfigTabTitleAboutLabel 1601 //(Left Origin = 4, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabCardConfigUnnamed1605Label 1605 //(Left Origin = 21, Top Origin = 74, Usable = 1, Font = Standard)
-#define TabCardConfigUnnamed1607Label 1607 //(Left Origin = 88, Top Origin = 74, Usable = 1, Font = Standard)
-#define TabCardConfigSlotList 1620 //(Left Origin = 7, Top Origin = 14, Width = 146, Usable = 1, Font = Standard, Visible Items = 3)
-
-// Resource: tFRM 1700
-#define TabCardGameListForm 1700 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 100, Usable = 1, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabCardGameListMoveCheckbox 1702 //(Left Origin = 4, Top Origin = 12, Width = 143, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabCardGameListDeleteCheckbox 1703 //(Left Origin = 4, Top Origin = 24, Width = 142, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabCardGameListConfirmCheckbox 1704 //(Left Origin = 4, Top Origin = 36, Width = 152, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabCardGameListUnnamed1701Label 1701 //(Left Origin = 4, Top Origin = 0, Usable = 1, Font = Bold)
-
-// Resource: tFRM 3500
-#define TabMiscExtsForm 3500 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 80, Usable = 1, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
-#define TabMiscExtsLightspeedCheckbox 3502 //(Left Origin = 4, Top Origin = 24, Width = 95, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscExtsGolcdCheckbox 3505 //(Left Origin = 4, Top Origin = 12, Width = 120, Height = 12, Usable = 1, Selected = 0, Group ID = 0, Font = Standard)
-#define TabMiscExtsTabTitleMoreLabel 3501 //(Left Origin = 4, Top Origin = 0, Usable = 1, Font = Bold)
-#define TabMiscExtsNothingLabel 3506 //(Left Origin = 4, Top Origin = 36, Usable = 0, Font = Standard)
-#define TabMiscExtsLightspeedList 3504 //(Left Origin = 96, Top Origin = 24, Width = 50, Usable = 0, Font = Standard, Visible Items = 3)
-#define TabMiscExtsLightspeedPopTrigger 3503 //(Left Origin = 96, Top Origin = 24, Width = 60, Height = 12, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 3504)
-
-
-// Resource: Talt 1001
-#define RomIncompatibleAlert 1001
-#define RomIncompatibleOK 0
-
-// Resource: Talt 1000
-#define FrmWarnAlert 1000
-#define FrmWarnOK 0
-
-// Resource: Talt 1100
-#define FrmErrorAlert 1100
-#define FrmErrorCancel 0
-
-// Resource: Talt 1300
-#define FrmConfirmAlert 1300
-#define FrmConfirmYes 0
-#define FrmConfirmNo 1
-
-// Resource: Talt 1400
-#define FrmInfoAlert 1400
-#define FrmInfoOK 0
-
-
-// Resource: MBAR 1000
-#define MainFormMenuBar 1000
-
-
-// Resource: MENU 1000
-#define MainOptionsMenu 1000
-#define MainOptionsMisc 1000 // Command Key: I
-#define MainOptionsSkins 1001
-#define MainOptionsBeam 1003
-#define MainOptionsAbout 1005
-
-// Resource: MENU 1100
-#define MainGamesMenu 1100
-#define MainGamesNew 1100 // Command Key: N
-#define MainGamesEdit 1101 // Command Key: E
-#define MainGamesMusicSound 1102 // Command Key: M
-#define MainGamesDelete 1103
-#define MainGamesMemoryCard 1105 // Command Key: C
-
-
-// Resource: tSTR 9991
-#define ClieCatString 9991 // "32779"
-
-// Resource: tSTR 9990
-#define ClieDescString 9990 // "Play your favorite Point'n'Click games"
-
-
-// Resource: PICT 1001
-#define Bitmap 1001
-
-// Resource: PICT 1002
-#define Bitmap2 1002
-
-// Resource: PICT 1008
-#define Bitmap3 1008
-
-// Resource: PICT 1011
-#define Bitmap4 1011
-
-// Resource: PICT 1012
-#define Bitmap5 1012
-
-// Resource: PICT 1018
-#define Bitmap6 1018
-
-// Resource: PICT 2000
-#define infoBitmap 2000
-
-// Resource: PICT 1100
-#define msOnBitmap 1100
-
-// Resource: PICT 1009
-#define Bitmap7 1009
-
-// Resource: PICT 1010
-#define Bitmap8 1010
-
-// Resource: PICT 1110
-#define msNoneBitmap 1110
-
-// Resource: PICT 1020
-#define BitmapID1020Bitmap 1020
-
-// Resource: PICT 1019
-#define BitmapID1019Bitmap 1019
-
-// Resource: PICT 1200
-#define msOnD2Bitmap 1200
-
-// Resource: PICT 1300
-#define msNoneD2Bitmap 1300
-
-// Resource: PICT 2100
-#define infoD2Bitmap 2100
-
-// Resource: PICT 1501
-#define ScummVMlogoD1Bitmap 1501
-
-// Resource: PICT 1502
-#define ScummVMlogoD2Bitmap 1502
-
-// Resource: PICT 1000
-#define icon16bitD2Bitmap 1000
-
-
-// Resource: tbmf 1000
-#define Icon_infoBitmapFamily 1000
-
-// Resource: tbmf 1100
-#define MsOnBitmapFamily 1100
-
-// Resource: tbmf 2000
-#define InfoBitmapFamily 2000
-
-// Resource: tbmf 1110
-#define MsNoneBitmapFamily 1110
-
-// Resource: tbmf 1200
-#define LogoBitmapFamily 1200
-
-
-// Resource: taif 1000
-#define Largeicons12and8bitsAppIconFamily 1000
-
-// Resource: taif 1001
-#define Smallicons12and8bitsAppIconFamily 1001
-
-
-#endif // STARTERRSC_H
diff --git a/backends/platform/PalmOS/Rsc/batLow.bmp b/backends/platform/PalmOS/Rsc/batLow.bmp
deleted file mode 100644
index 1d18131450..0000000000
--- a/backends/platform/PalmOS/Rsc/batLow.bmp
+++ /dev/null
Binary files differ
diff --git a/backends/platform/PalmOS/Rsc/keyAlt.bmp b/backends/platform/PalmOS/Rsc/keyAlt.bmp
deleted file mode 100644
index 28165394f8..0000000000
--- a/backends/platform/PalmOS/Rsc/keyAlt.bmp
+++ /dev/null
Binary files differ
diff --git a/backends/platform/PalmOS/Rsc/keyCommand.bmp b/backends/platform/PalmOS/Rsc/keyCommand.bmp
deleted file mode 100644
index 1324037cd3..0000000000
--- a/backends/platform/PalmOS/Rsc/keyCommand.bmp
+++ /dev/null
Binary files differ
diff --git a/backends/platform/PalmOS/Rsc/keyCtrl.bmp b/backends/platform/PalmOS/Rsc/keyCtrl.bmp
deleted file mode 100644
index fed20fd8d0..0000000000
--- a/backends/platform/PalmOS/Rsc/keyCtrl.bmp
+++ /dev/null
Binary files differ
diff --git a/backends/platform/PalmOS/Rsc/modules.rcp b/backends/platform/PalmOS/Rsc/modules.rcp
deleted file mode 100644
index c7b17221b2..0000000000
--- a/backends/platform/PalmOS/Rsc/modules.rcp
+++ /dev/null
@@ -1,71 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- * Copyright (C) 2001 Ludvig Strigeus
- * Copyright (C) 2001-2010 The ScummVM project
- * Copyright (C) 2002-2006 Chris Apers - PalmOS Backend
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public 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$
- *
- */
-
-BITMAP ID 3100
-BEGIN
- BITMAP "keyCommand.bmp" BPP 1 DENSITY 2
-END
-BITMAP ID 3101
-BEGIN
- BITMAP "keyAlt.bmp" BPP 1 DENSITY 2
-END
-BITMAP ID 3102
-BEGIN
- BITMAP "keyCtrl.bmp" BPP 1 DENSITY 2
-END
-BITMAP ID 3120
-BEGIN
- BITMAP "batLow.bmp" BPP 1 DENSITY 2
-END
-BITMAP ID 3130
-BEGIN
- BITMAP "numpad.bmp" BPP 1 DENSITY 2
-END
-
-/*
-BITMAP ID 3100 "keyCommand.bmp" DENSITY 2
-BITMAP ID 3101 "keyAlt.bmp" DENSITY 2
-BITMAP ID 3102 "keyCtrl.bmp" DENSITY 2
-BITMAP ID 3120 "batLow.bmp" DENSITY 2
-BITMAP ID 3130 "numpad.bmp" DENSITY 2
-*/
-BITMAP ID 3000 "keyCommand.bmp" DENSITY 1
-BITMAP ID 3001 "keyAlt.bmp" DENSITY 1
-BITMAP ID 3002 "keyCtrl.bmp" DENSITY 1
-BITMAP ID 3020 "batLow.bmp" DENSITY 1
-BITMAP ID 3030 "numpad.bmp" DENSITY 1
-
-ALERT ID 1200
- DEFAULTBUTTON 0
- ERROR
-BEGIN
- TITLE "ScummVM Fatal Error"
- MESSAGE "^1"
- BUTTONS "Exit"
-END
-
diff --git a/backends/platform/PalmOS/Rsc/modulesrsc.h b/backends/platform/PalmOS/Rsc/modulesrsc.h
deleted file mode 100644
index 14b32ee0b6..0000000000
--- a/backends/platform/PalmOS/Rsc/modulesrsc.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef MODULESRSC_H
-#define MODULESRSC_H
-
-#define FrmFatalErrorAlert 1200
-
-#endif
diff --git a/backends/platform/PalmOS/Rsc/numpad.bmp b/backends/platform/PalmOS/Rsc/numpad.bmp
deleted file mode 100644
index 7763d76c05..0000000000
--- a/backends/platform/PalmOS/Rsc/numpad.bmp
+++ /dev/null
Binary files differ
diff --git a/backends/platform/PalmOS/Src/args.cpp b/backends/platform/PalmOS/Src/args.cpp
deleted file mode 100644
index bfc34866e3..0000000000
--- a/backends/platform/PalmOS/Src/args.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include <PalmOS.h>
-#include "palmdefs.h"
-#include "args.h"
-#include "pace.h"
-#include "endianutils.h"
-
-Char **ArgsInit() {
- // first 4 bytes keep the real address of the chunk
- MemHandle argvH = MemHandleNew(sizeof(Char *) + (MAX_ARG * sizeof(Char **) + 2));
- // real addr
- Char *lockP = (Char *)MemHandleLock(argvH);
- // 4byte aligned
- Char **argvP = (Char **)ALIGN_4BYTE(lockP);
- // save real addr
- argvP[0] = lockP;
- // initial position
- argvP++;
-
- for (UInt8 count = 0; count < MAX_ARG; count++)
- argvP[count] = NULL;
-
- return argvP;
-}
-
-void ArgsAdd(Char **argvP, const Char *argP, const Char *parmP, UInt8 *countArgP) {
- if (argP) {
- MemHandle newArg;
- UInt16 len2 = 0;
- UInt16 len1 = StrLen(argP);
-
- if (len1 > 0) {
- if (parmP)
- len2 = StrLen(parmP);
-
- (*countArgP)++;
- newArg = MemHandleNew(len1 + len2 + 1); // +1 = NULL CHAR
- *argvP = (Char *)MemHandleLock(newArg);
- StrCopy(*argvP, argP);
-
- if (parmP)
- StrCat(*argvP, parmP);
- }
- }
-}
-
-void ArgsFree(Char **argvP) {
- if (!argvP)
- return;
-
- MemHandle oldH;
-
- for (UInt8 count = 0; count < MAX_ARG; count++)
- if (argvP[count]) {
- oldH = MemPtrRecoverHandle(argvP[count]);
- MemHandleUnlock(oldH);
- MemHandleFree(oldH);
- }
-
- argvP--;
- oldH = MemPtrRecoverHandle(argvP[0]);
- MemHandleUnlock(oldH);
- MemHandleFree(oldH);
-}
-
-void ArgsSetOwner(Char **argvP, UInt16 owner) {
- if (!argvP)
- return;
-
- MemHandle oldH;
-
- for (UInt8 count = 0; count < MAX_ARG; count++)
- if (argvP[count]) {
- oldH = MemPtrRecoverHandle(argvP[count]);
- MemHandleSetOwner(oldH, owner);
- }
-
- argvP--;
- oldH = MemPtrRecoverHandle(argvP[0]);
- MemHandleSetOwner(oldH, owner);
-}
-
-void ArgsExportInit(Char **argvP, UInt32 countArg, Boolean arm) {
- if (arm) {
- for (UInt8 count = 0; count < MAX_ARG; count++)
- if (argvP[count])
- argvP[count] = (Char *)ByteSwap32(argvP[count]);
- }
-
- FtrSet(appFileCreator, ftrArgsData , (UInt32)argvP);
- FtrSet(appFileCreator, ftrArgsCount, (UInt32)countArg);
-}
-
-void ArgsExportRelease(Boolean arm) {
- if (arm) {
- Char **argvP;
- Err e = FtrGet(appFileCreator, ftrArgsData, (UInt32 *)&argvP);
-
- if (argvP)
- for (UInt8 count = 0; count < MAX_ARG; count++)
- if (argvP[count])
- argvP[count] = (Char *)ByteSwap32(argvP[count]);
- }
-
- FtrUnregister(appFileCreator, ftrArgsCount);
- FtrUnregister(appFileCreator, ftrArgsData);
-}
diff --git a/backends/platform/PalmOS/Src/base_event.cpp b/backends/platform/PalmOS/Src/base_event.cpp
deleted file mode 100644
index ae93514e34..0000000000
--- a/backends/platform/PalmOS/Src/base_event.cpp
+++ /dev/null
@@ -1,458 +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 "be_base.h"
-#include "common/events.h"
-
-#ifdef STDLIB_TRACE_MEMORY
-# include <stdlib.h>
-#endif
-
-#if defined(COMPILE_OS5) && defined(PALMOS_ARM)
-extern "C" void SysEventGet(EventType *eventP, Int32 timeout);
-extern "C" void SysEventAddToQueue (const EventType *eventP);
-#endif
-
-void OSystem_PalmBase::timer_handler() {
- UInt32 msecs = getMillis();
-
- if (_timer.active && (msecs >= _timer.nextExpiry)) {
- _timer.duration = _timer.callback(_timer.duration);
- _timer.nextExpiry = msecs + _timer.duration;
- }
-}
-
-void OSystem_PalmBase::battery_handler() {
- // check battery level every 15secs
- if ((TimGetTicks() - _batCheckLast) > _batCheckTicks) {
- UInt16 voltage, warnThreshold, criticalThreshold;
- Boolean pluggedIn;
- voltage = SysBatteryInfoV20(false, &warnThreshold, &criticalThreshold, NULL, NULL, &pluggedIn);
-
- if (!pluggedIn) {
- if (voltage <= warnThreshold) {
- if (!_showBatLow) {
- _showBatLow = true;
- draw_osd(kDrawBatLow, _screenDest.w - 18, -16, true, 2);
- displayMessageOnOSD("Battery low.");
- }
- } else {
- if (_showBatLow) {
- _showBatLow = false;
- draw_osd(kDrawBatLow, _screenDest.w - 18, -16, false);
- }
- }
-
- if (voltage <= criticalThreshold) {
- ::EventType event;
- event.eType = keyDownEvent;
- event.data.keyDown.chr = vchrPowerOff;
- event.data.keyDown.modifiers = commandKeyMask;
-#if defined(COMPILE_OS5) && defined(PALMOS_ARM)
- SysEventAddToQueue(&event);
-#else
- EvtAddEventToQueue(&event);
-#endif
- }
- }
-
- _batCheckLast = TimGetTicks();
- }
-}
-
-bool OSystem_PalmBase::pollEvent(Common::Event &event) {
- ::EventType ev;
- Boolean handled;
- UInt32 keyCurrentState;
- Coord x, y;
-
- battery_handler();
- timer_handler();
- sound_handler();
-
- for (;;) {
- // check for hardkey repeat for mouse emulation
- keyCurrentState = KeyCurrentState();
-
- // if it was a key pressed, let the keyup event raise
- if (_keyExtraPressed) {
- if (gVars->arrowKeys) {
- if (_keyExtraPressed & _keyExtra.bitLeft) {
- if (!(keyCurrentState & _keyExtra.bitLeft)) {
- _keyExtraPressed &= ~_keyExtra.bitLeft;
-
- event.type = Common::EVENT_KEYUP;
- event.kbd.keycode = Common::KEYCODE_LEFT;
- event.kbd.ascii = event.kbd.keycode;
- event.kbd.flags = 0;
- return true;
- }
- }
- if (_keyExtraPressed & _keyExtra.bitRight) {
- if (!(keyCurrentState & _keyExtra.bitRight)) {
- _keyExtraPressed &= ~_keyExtra.bitRight;
-
- event.type = Common::EVENT_KEYUP;
- event.kbd.keycode = Common::KEYCODE_RIGHT;
- event.kbd.ascii = event.kbd.keycode;
- event.kbd.flags = 0;
- return true;
- }
- }
- if (_keyExtraPressed & _keyExtra.bitUp) {
- if (!(keyCurrentState & _keyExtra.bitUp)) {
- _keyExtraPressed &= ~_keyExtra.bitUp;
-
- event.type = Common::EVENT_KEYUP;
- event.kbd.keycode = Common::KEYCODE_UP;
- event.kbd.ascii = event.kbd.keycode;
- event.kbd.flags = 0;
- return true;
- }
- }
- if (_keyExtraPressed & _keyExtra.bitDown) {
- if (!(keyCurrentState & _keyExtra.bitDown)) {
- _keyExtraPressed &= ~_keyExtra.bitDown;
-
- event.type = Common::EVENT_KEYUP;
- event.kbd.keycode = Common::KEYCODE_DOWN;
- event.kbd.ascii = event.kbd.keycode;
- event.kbd.flags = 0;
- return true;
- }
- }
- }
-
- if (_keyExtraPressed & _keyExtra.bitActionA) {
- if (!(keyCurrentState & _keyExtra.bitActionA)) {
- _keyExtraPressed &= ~_keyExtra.bitActionA;
-
- event.type = Common::EVENT_LBUTTONUP;
- event.mouse.x = _mouseCurState.x;
- event.mouse.y = _mouseCurState.y;
- return true;
- }
- }
-
- if (_keyExtraPressed & _keyExtra.bitActionB) {
- if (!(keyCurrentState & _keyExtra.bitActionB)) {
- _keyExtraPressed &= ~_keyExtra.bitActionB;
-
- event.type = Common::EVENT_RBUTTONUP;
- event.mouse.x = _mouseCurState.x;
- event.mouse.y = _mouseCurState.y;
- return true;
- }
- }
-
- // no more event till up is raised
- return false;
- }
-
- if (!(keyCurrentState & _keyExtraMask)) {
- _lastKeyRepeat = 0;
-
- } else if (getMillis() >= (_keyExtraRepeat + _keyExtraDelay)) {
- _keyExtraRepeat = getMillis();
-
- if (gVars->arrowKeys) {
- if (keyCurrentState & _keyExtra.bitLeft) {
- _keyExtraPressed |= _keyExtra.bitLeft;
- event.kbd.keycode = Common::KEYCODE_LEFT;
-
- } else if (keyCurrentState & _keyExtra.bitRight) {
- _keyExtraPressed |= _keyExtra.bitRight;
- event.kbd.keycode = Common::KEYCODE_RIGHT;
-
- } else if (keyCurrentState & _keyExtra.bitUp) {
- _keyExtraPressed |= _keyExtra.bitUp;
- event.kbd.keycode = Common::KEYCODE_UP;
-
- } else if (keyCurrentState & _keyExtra.bitDown) {
- _keyExtraPressed |= _keyExtra.bitDown;
- event.kbd.keycode = Common::KEYCODE_DOWN;
- }
-
- event.type = Common::EVENT_KEYDOWN;
- event.kbd.ascii = event.kbd.keycode;
- event.kbd.flags = 0;
- return true;
-
- } else {
- Int8 sx = 0;
- Int8 sy = 0;
-
- if (keyCurrentState & _keyExtra.bitUp)
- sy = -1;
- else if (keyCurrentState & _keyExtra.bitDown)
- sy = +1;
-
- if (keyCurrentState & _keyExtra.bitLeft)
- sx = -1;
- else if (keyCurrentState & _keyExtra.bitRight)
- sx = +1;
-
- if (sx || sy) {
- simulate_mouse(event, sx, sy, &x, &y);
- event.type = Common::EVENT_MOUSEMOVE;
- event.mouse.x = x;
- event.mouse.y = y;
- warpMouse(x, y);
-
- return true;
- }
- }
- }
-
-#if defined(COMPILE_OS5) && defined(PALMOS_ARM)
- SysEventGet(&ev, evtNoWait);
-#else
- EvtGetEvent(&ev, evtNoWait);
-#endif
-
- if (ev.eType == keyUpEvent) {
- Common::KeyCode k = Common::KEYCODE_INVALID;
- switch (ev.data.keyUp.chr) {
-
- // arrow keys
- case chrUpArrow:
- k = Common::KEYCODE_UP; break;
- case chrDownArrow:
- k = Common::KEYCODE_DOWN; break;
- case chrRightArrow:
- k = Common::KEYCODE_RIGHT; break;
- case chrLeftArrow:
- k = Common::KEYCODE_LEFT; break;
- }
-
- if (k) {
- event.type = Common::EVENT_KEYUP;
- event.kbd.keycode = k;
- event.kbd.ascii = k;
- event.kbd.flags = 0;
- return true;
- }
-
- } else if (ev.eType == keyDownEvent) {
- Common::KeyCode k = Common::KEYCODE_INVALID;
- switch (ev.data.keyDown.chr) {
- // ESC key
- case vchrLaunch:
- event.type = Common::EVENT_KEYDOWN;
- event.kbd.keycode = Common::KEYCODE_ESCAPE;
- event.kbd.ascii = Common::ASCII_ESCAPE;
- event.kbd.flags = 0;
- return true;
-
- // F5 = menu
- case vchrMenu:
- event.type = Common::EVENT_KEYDOWN;
- event.kbd.keycode = Common::KEYCODE_F5;
- event.kbd.ascii = Common::ASCII_F5;
- event.kbd.flags = 0;
- return true;
-
- // if hotsync pressed, etc...
- case vchrHardCradle:
- case vchrHardCradle2:
- case vchrLowBattery:
- case vchrFind:
-// case vchrBrightness: // volume control on Zodiac, let other backends disable it
- case vchrContrast:
- // do nothing
- return true;
-
- // arrow keys
- case chrUpArrow:
- k = Common::KEYCODE_UP; break;
- case chrDownArrow:
- k = Common::KEYCODE_DOWN; break;
- case chrRightArrow:
- k = Common::KEYCODE_RIGHT; break;
- case chrLeftArrow:
- k = Common::KEYCODE_LEFT; break;
-
- // return
- case chrLineFeed:
- case chrCarriageReturn:
- k = Common::KEYCODE_RETURN; break;
-
- }
-
- if (k) {
- event.type = Common::EVENT_KEYDOWN;
- event.kbd.keycode = k;
- event.kbd.ascii = k;
- event.kbd.flags = 0;
- return true;
- }
- }
-
- if (check_event(event, &ev))
- return true;
-
- // prevent crash when alarm is raised
- handled = ((ev.eType == keyDownEvent) &&
- (ev.data.keyDown.modifiers & commandKeyMask) &&
- ((ev.data.keyDown.chr == vchrAttnStateChanged) ||
- (ev.data.keyDown.chr == vchrAttnUnsnooze)));
-
- // graffiti strokes, auto-off, etc...
- if (!handled)
- if (SysHandleEvent(&ev))
- continue;
-
- switch (ev.eType) {
- case penMoveEvent:
- get_coordinates(&ev, x, y);
-
- if (y > _screenHeight || y < 0 || x > _screenWidth || x < 0)
- return false;
-
- if (abs(y - event.mouse.y) <= 2 || abs(x - event.mouse.x) <= 2)
- return false;
-
- event.type = Common::EVENT_MOUSEMOVE;
- event.mouse.x = x;
- event.mouse.y = y;
- warpMouse(x, y);
- return true;
-
- case penDownEvent:
- get_coordinates(&ev, x, y);
-
- // indy fight mode
- if (_useNumPad && !_overlayVisible) {
- char num = '1';
- num += 9 -
- (3 - (3 * x / _screenWidth )) -
- (3 * (3 * y / _screenHeight));
-
- event.type = Common::EVENT_KEYDOWN;
- event.kbd.keycode = (Common::KeyCode)num;
- event.kbd.ascii = num;
- event.kbd.flags = 0;
-
- _wasKey = true;
- return true;
- }
-
- if (y > _screenHeight || y < 0 || x > _screenWidth || x < 0)
- return false;
-
- event.type = ((gVars->stylusClick || _overlayVisible) ? Common::EVENT_LBUTTONDOWN : Common::EVENT_MOUSEMOVE);
- event.mouse.x = x;
- event.mouse.y = y;
- warpMouse(x, y);
- return true;
-
- case penUpEvent:
- get_coordinates(&ev, x, y);
-
- event.type = ((gVars->stylusClick || _overlayVisible) ? Common::EVENT_LBUTTONUP : Common::EVENT_MOUSEMOVE);
- if (y > _screenHeight || y < 0 || x > _screenWidth || x < 0)
- return false;
-
- event.mouse.x = x;
- event.mouse.y = y;
- warpMouse(x, y);
- return true;
-
- case keyDownEvent:
- if (ev.data.keyDown.chr == vchrCommand &&
- (ev.data.keyDown.modifiers & commandKeyMask)) {
-
- _lastKeyModifier++;
- _lastKeyModifier %= kModifierCount;
-
- if (_lastKeyModifier)
- draw_osd((kDrawKeyState + _lastKeyModifier - 1), 2, _screenDest.h + 2, true);
- else
- draw_osd(kDrawKeyState, 2, _screenDest.h + 2, false);
-
- return false;
- }
-
- char mask = 0;
- UInt16 key = ev.data.keyDown.chr;
-
- if (_lastKeyModifier == kModifierNone) {
- // for keyboard mode
- if (ev.data.keyDown.modifiers & shiftKeyMask) mask |= Common::KBD_SHIFT;
- if (ev.data.keyDown.modifiers & controlKeyMask) mask |= Common::KBD_CTRL;
- if (ev.data.keyDown.modifiers & optionKeyMask) mask |= Common::KBD_ALT;
- if (ev.data.keyDown.modifiers & commandKeyMask) mask |= Common::KBD_CTRL|Common::KBD_ALT;
- } else {
- // for grafiti mode
- if (_lastKeyModifier == kModifierCommand) mask = Common::KBD_CTRL|Common::KBD_ALT;
- if (_lastKeyModifier == kModifierAlt) mask = Common::KBD_ALT;
- if (_lastKeyModifier == kModifierCtrl) mask = Common::KBD_CTRL;
- }
-
- if (_lastKeyModifier)
- draw_osd(kDrawKeyState, 2, _screenDest.h + 2, false);
- _lastKeyModifier = kModifierNone;
-
- // F1 -> F10 key
- if (key >= '0' && key <= '9' && mask == (Common::KBD_CTRL|Common::KBD_ALT)) {
- key = (key == '0') ? 324 : (315 + key - '1');
- mask = 0;
-
-#ifdef STDLIB_TRACE_MEMORY
- // print memory
- } else if (key == 'm' && mask == (Common::KBD_CTRL|Common::KBD_ALT)) {
- printf("Used memory: %d\n", __stdlib_trace_memory);
-#endif
- // exit
- } else if ((key == 'z' && mask == Common::KBD_CTRL) || (mask == Common::KBD_ALT && key == 'x')) {
- event.type = Common::EVENT_QUIT;
- return true;
-
- // num pad (indy fight mode)
- } else if (key == 'n' && mask == (Common::KBD_CTRL|Common::KBD_ALT) && !_overlayVisible) {
- _useNumPad = !_useNumPad;
- draw_osd(kDrawFight, _screenDest.w - 34, _screenDest.h + 2, _useNumPad, 1);
- displayMessageOnOSD(_useNumPad ? "Fight mode on." : "Fight mode off.");
- return false;
- }
-
- // other keys
- _wasKey = true;
- event.type = Common::EVENT_KEYDOWN;
- event.kbd.keycode = (Common::KeyCode)key;
- event.kbd.ascii = key;
- event.kbd.flags = mask;
- return true;
-
- default:
- if (_wasKey && ev.eType != keyHoldEvent) {
- event.type = Common::EVENT_KEYUP;
- _wasKey = false;
- return true;
- }
- return false;
- };
- }
-}
diff --git a/backends/platform/PalmOS/Src/base_gfx.cpp b/backends/platform/PalmOS/Src/base_gfx.cpp
deleted file mode 100644
index 46238efdc2..0000000000
--- a/backends/platform/PalmOS/Src/base_gfx.cpp
+++ /dev/null
@@ -1,198 +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 "be_base.h"
-
-/*
- * Graphics modes
- *
- */
-
-static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
- {"1x", "Normal", GFX_NORMAL},
- {"wide", "Wide", GFX_WIDE},
- {0, 0, 0}
-};
-
-int OSystem_PalmBase::getDefaultGraphicsMode() const {
- return GFX_NORMAL;
-}
-
-const OSystem::GraphicsMode *OSystem_PalmBase::getSupportedGraphicsModes() const {
- return int_getSupportedGraphicsModes();
-}
-
-const OSystem::GraphicsMode *OSystem_PalmBase::int_getSupportedGraphicsModes() const {
- return s_supportedGraphicsModes;
-}
-
-int OSystem_PalmBase::getGraphicsMode() const {
- return _mode;
-}
-
-bool OSystem_PalmBase::setGraphicsMode(int mode) {
- switch (mode) {
- case GFX_NORMAL:
- case GFX_WIDE:
- _setMode = mode;
- break;
-
- default:
- warning("unknown gfx mode %d", mode);
- _setMode = GFX_NORMAL;
- return false;
- }
-
- return true;
-}
-
-/*
- * Init
- *
- */
-
-void OSystem_PalmBase::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
- _screenWidth = w;
- _screenHeight = h;
-
- _screenDest.w = _screenWidth;
- _screenDest.h = _screenHeight;
-
- unload_gfx_mode();
- _mode = _setMode;
- load_gfx_mode();
-
- warpMouse(200, 150);
- int_initSize(w, h);
-}
-
-/*
- * Palette
- *
- */
-void OSystem_PalmBase::setPalette(const byte *colors, uint start, uint num) {
- RGBColorType *base = _currentPalette + start;
-
- for (uint i = 0; i < num; i++) {
- base[i].r = colors[0];
- base[i].g = colors[1];
- base[i].b = colors[2];
-
- extras_palette(i + start, colors[0], colors[1], colors[2]);
- colors += 4;
- }
-
- if (start < _paletteDirtyStart)
- _paletteDirtyStart = start;
-
- if (start + num > _paletteDirtyEnd)
- _paletteDirtyEnd = start + num;
-}
-
-void OSystem_PalmBase::grabPalette(byte *colors, uint start, uint num) {
- const RGBColorType *base = _currentPalette + start;
-
- for (uint i = 0; i < num; ++i) {
- colors[i * 4] = base[i].r;
- colors[i * 4 + 1] = base[i].g;
- colors[i * 4 + 2] = base[i].b;
- colors[i * 4 + 3] = 0xFF;
- }
-}
-
-/*
- * Screen
- *
- */
-
-void OSystem_PalmBase::setShakePos(int shakeOffset) {
- _new_shake_pos = shakeOffset;
- int_setShakePos(shakeOffset);
-}
-
-void OSystem_PalmBase::updateScreen() {
- // Check whether the palette was changed in the meantime and update the
- // screen surface accordingly.
- if (_paletteDirtyEnd != 0 && _setPalette) {
- WinSetDrawWindow(WinGetDisplayWindow());
- WinPalette(winPaletteSet, _paletteDirtyStart, _paletteDirtyEnd - _paletteDirtyStart, _currentPalette + _paletteDirtyStart);
- _paletteDirtyEnd = 0;
- //_redawOSD = true;
- }
- if (_redawOSD) {
- _redawOSD = false;
- draw_osd(kDrawBatLow, _screenDest.w - 18, -16, _showBatLow, 2);
- draw_osd(kDrawFight, _screenDest.w - 34, _screenDest.h + 2, (_useNumPad && !_overlayVisible), 1);
- }
- int_updateScreen();
-
-}
-
-void OSystem_PalmBase::draw_osd(UInt16 id, Int32 x, Int32 y, Boolean show, UInt8 color) {
-//return;
-
- MemHandle hTemp = DmGetResource('abmp', id + 100);
-
- if (hTemp) {
- /*static const UInt32 pal[3] = {
- (TwGfxComponentsToPackedRGB(0,255,0)),
- (TwGfxComponentsToPackedRGB(255,255,0)),
- (TwGfxComponentsToPackedRGB(255,0,0))
- };*/
-
- BitmapType *bmTemp;
- bmTemp = (BitmapType *)MemHandleLock(hTemp);
-
- Coord w, h;
- BmpGetDimensions(bmTemp, &w, &h, 0);
-
- PointType dst = { _screenOffset.x + x, _screenOffset.y + y };
- RectangleType r = { dst.x, dst.y, w, h };
-
- RectangleType c;
-
- UInt16 old = WinSetCoordinateSystem(kCoordinatesNative);
- WinGetClip(&c);
- WinResetClip();
- if (show) {
- WinSetDrawWindow(_screenH);
- WinSetBackColor(0);
- WinSetForeColor(120); // pal[color]
- WinFillRectangle(&r, 0);
- WinSetDrawMode(winOverlay);
- WinDrawBitmap(bmTemp, 0, 0);
- WinSetDrawMode(winPaint);
-
- } else {
- WinSetBackColor(0);
- WinFillRectangle(&r, 0);
- }
- WinSetClip(&c);
- WinSetCoordinateSystem(old);
-
- MemPtrUnlock(bmTemp);
- DmReleaseResource(hTemp);
- }
-}
diff --git a/backends/platform/PalmOS/Src/base_mouse.cpp b/backends/platform/PalmOS/Src/base_mouse.cpp
deleted file mode 100644
index bf11a4b106..0000000000
--- a/backends/platform/PalmOS/Src/base_mouse.cpp
+++ /dev/null
@@ -1,101 +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 "be_base.h"
-
-void OSystem_PalmBase::warpMouse(int x, int y) {
- if (x != _mouseCurState.x || y != _mouseCurState.y) {
- x = x >= _screenWidth ? _screenWidth - 1 : x;
- y = y >= _screenHeight ? _screenHeight - 1 : y;
-
- _mouseCurState.x = x;
- _mouseCurState.y = y;
- }
-}
-
-bool OSystem_PalmBase::showMouse(bool visible) {
- bool last = _mouseVisible;
- _mouseVisible = visible;
-
- return last;
-}
-
-void OSystem_PalmBase::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
- if (w == 0 || h == 0)
- return;
-
- _mouseHotspotX = hotspotX;
- _mouseHotspotY = hotspotY;
-
- _mouseKeyColor = keycolor;
-
- if (_mouseCurState.w != w || _mouseCurState.h != h) {
- _mouseCurState.w = w;
- _mouseCurState.h = h;
-
- if (_mouseDataP)
- free(_mouseDataP);
-
- if (_mouseBackupP)
- free(_mouseBackupP);
-
- _mouseDataP = (byte *)malloc(w * h);
- _mouseBackupP = (byte *)malloc(w * h * 2); // if 16bit = *2
- }
-
- if (!_mouseBackupP) {
- free(_mouseDataP);
- _mouseDataP = NULL;
- }
-
- if (_mouseDataP)
- memcpy(_mouseDataP, buf, w * h);
-}
-
-void OSystem_PalmBase::simulate_mouse(Common::Event &event, Int8 iHoriz, Int8 iVert, Coord *xr, Coord *yr) {
- Int16 x = _mouseCurState.x;
- Int16 y = _mouseCurState.y;
- Int16 slow, fact;
-
- _lastKeyRepeat++;
- fact = _screenWidth / 320;
- fact = (fact) ? fact : 1;
-
- if (_lastKeyRepeat > 32 * fact)
- _lastKeyRepeat = 32 * fact;
-
- slow = (iHoriz && iVert) ? 2 : 1;
-
- x += iHoriz * (_lastKeyRepeat >> 2) / slow * fact;
- y += iVert * (_lastKeyRepeat >> 2) / slow * fact;
-
- x = (x < 0 ) ? 0 : x;
- x = (x >= _screenWidth ) ? _screenWidth - 1 : x;
- y = (y < 0 ) ? 0 : y;
- y = (y >= _screenHeight ) ? _screenHeight - 1 : y;
-
- *xr = x;
- *yr = y;
-}
diff --git a/backends/platform/PalmOS/Src/be_68k.cpp b/backends/platform/PalmOS/Src/be_68k.cpp
deleted file mode 100644
index 77b1e22615..0000000000
--- a/backends/platform/PalmOS/Src/be_68k.cpp
+++ /dev/null
@@ -1,27 +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$
- *
- */
-
-
-/* More to come */
diff --git a/backends/platform/PalmOS/Src/be_68k.h b/backends/platform/PalmOS/Src/be_68k.h
deleted file mode 100644
index 77b1e22615..0000000000
--- a/backends/platform/PalmOS/Src/be_68k.h
+++ /dev/null
@@ -1,27 +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$
- *
- */
-
-
-/* More to come */
diff --git a/backends/platform/PalmOS/Src/be_base.cpp b/backends/platform/PalmOS/Src/be_base.cpp
deleted file mode 100644
index b3caee105d..0000000000
--- a/backends/platform/PalmOS/Src/be_base.cpp
+++ /dev/null
@@ -1,203 +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 "be_base.h"
-#include "common/config-file.h"
-#include "common/config-manager.h"
-#include "backends/saves/default/default-saves.h"
-#include "backends/timer/default/default-timer.h"
-#include "backends/fs/palmos/palmos-fs-factory.h"
-#include "sound/mixer_intern.h"
-
-#define DEFAULT_SAVE_PATH "/PALM/Programs/ScummVM/Saved/"
-
-
-OSystem_PalmBase::OSystem_PalmBase() {
- _overlayVisible = false;
-
- _current_shake_pos = 0;
- _new_shake_pos = 0;
-
- _paletteDirtyStart = 0;
- _paletteDirtyEnd = 0;
-
- _gfxLoaded = false;
- _modeChanged = false;
- _setMode = GFX_NORMAL;
- _mode = _setMode;
- _redawOSD = false;
- _setPalette = true;
-
- _offScreenH = NULL;
- _screenH = NULL;
- _offScreenP = NULL;
- _screenP = NULL;
- _screenPitch = gVars->screenPitch;
-
- _wasKey = false;
- _lastKeyModifier = kModifierNone;
- _lastKeyRepeat = 100;
- _useNumPad = false;
- _showBatLow = false;
- _batCheckTicks = SysTicksPerSecond() * 15;
- _batCheckLast = TimGetTicks();
-
- _saveMgr = 0;
- _timerMgr = 0;
- _mixerMgr = 0;
-
- _mouseDataP = NULL;
- _mouseBackupP = NULL;
- _mouseVisible = false;
- _mouseDrawn = false;
- MemSet(&_keyExtra, sizeof(_keyExtra), 0);
- MemSet(&_mouseCurState, sizeof(_mouseCurState), 0);
- MemSet(&_mouseOldState, sizeof(_mouseOldState), 0);
- MemSet(&_timer, sizeof(TimerType), 0);
- MemSet(&_sound, sizeof(SoundType), 0);
-
- _keyExtraRepeat = 0;
- _keyExtraPressed = 0;
- _keyExtraDelay = (gVars->arrowKeys) ? computeMsecs(125) : computeMsecs(25);
-}
-
-static int timer_handler(int t) {
- DefaultTimerManager *tm = (DefaultTimerManager *)g_system->getTimerManager();
- tm->handler();
- return t;
-}
-
-void OSystem_PalmBase::initBackend() {
- if (gVars->autoSave != -1)
- ConfMan.setInt("autosave_period", gVars->autoSave);
-
- _keyExtra.bitUp = keyBitPageUp;
- _keyExtra.bitDown = keyBitPageDown;
- _keyExtra.bitLeft = keyBitHard2;
- _keyExtra.bitRight = keyBitHard3;
-
- int_initBackend();
- _keyExtraMask = (_keyExtra.bitUp | _keyExtra.bitDown | _keyExtra.bitLeft | _keyExtra.bitRight | _keyExtra.bitActionA | _keyExtra.bitActionB);
-
- // Create the savefile manager, if none exists yet (we check for this to
- // allow subclasses to provide their own).
- if (_saveMgr == 0) {
- _saveMgr = new DefaultSaveFileManager(DEFAULT_SAVE_PATH);
- }
-
- // Create and hook up the mixer, if none exists yet (we check for this to
- // allow subclasses to provide their own).
- if (_mixerMgr == 0) {
- setupMixer();
- }
-
- // Create and hook up the timer manager, if none exists yet (we check for
- // this to allow subclasses to provide their own).
- if (_timerMgr == 0) {
- _timerMgr = new DefaultTimerManager();
- setTimerCallback(::timer_handler, 10);
- }
-
- OSystem::initBackend();
-}
-
-void OSystem_PalmBase::getTimeAndDate(TimeDate &td) const {
- time_t curTime = time(0);
- struct tm t = *localtime(&curTime);
- td.tm_sec = t.tm_sec;
- td.tm_min = t.tm_min;
- td.tm_hour = t.tm_hour;
- td.tm_mday = t.tm_mday;
- td.tm_mon = t.tm_mon;
- td.tm_year = t.tm_year;
-}
-
-uint32 OSystem_PalmBase::getMillis() {
- return TimGetTicks() * 1000 / SysTicksPerSecond();
-}
-
-void OSystem_PalmBase::delayMillis(uint msecs) {
- Int32 delay = computeMsecs(msecs);
-
- if (delay > 0)
- SysTaskDelay(delay);
-}
-
-void OSystem_PalmBase::setTimerCallback(TimerProc callback, int timer) {
- if (callback != NULL) {
- _timer.duration = timer;
- _timer.nextExpiry = getMillis() + timer;
- _timer.callback = callback;
- _timer.active = true;
- } else {
- _timer.active = false;
- }
-}
-
-void OSystem_PalmBase::quit() {
- int_quit();
- clearSoundCallback();
- unload_gfx_mode();
-
- if (_mouseDataP) {
- MemPtrFree(_mouseBackupP);
- MemPtrFree(_mouseDataP);
- }
-
- delete _saveMgr;
- delete _timerMgr;
- delete _mixerMgr;
-
- exit(0);
-}
-
-Common::SaveFileManager *OSystem_PalmBase::getSavefileManager() {
- return _saveMgr;
-}
-
-Audio::Mixer *OSystem_PalmBase::getMixer() {
- return _mixerMgr;
-}
-
-Common::TimerManager *OSystem_PalmBase::getTimerManager() {
- return _timerMgr;
-}
-
-FilesystemFactory *OSystem_PalmBase::getFilesystemFactory() {
- return &PalmOSFilesystemFactory::instance();
-}
-
-
-#define PALMOS_CONFIG_FILE "/PALM/Programs/ScummVM/scummvm.ini"
-
-Common::SeekableReadStream *OSystem_PalmBase::createConfigReadStream() {
- Common::FSNode file(PALMOS_CONFIG_FILE);
- return file.createReadStream();
-}
-
-Common::WriteStream *OSystem_PalmBase::createConfigWriteStream() {
- Common::FSNode file(PALMOS_CONFIG_FILE);
- return file.createWriteStream();
-}
diff --git a/backends/platform/PalmOS/Src/be_base.h b/backends/platform/PalmOS/Src/be_base.h
deleted file mode 100644
index 1885114ace..0000000000
--- a/backends/platform/PalmOS/Src/be_base.h
+++ /dev/null
@@ -1,265 +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$
- *
- */
-
-#ifndef BE_BASE_H
-#define BE_BASE_H
-
-#include <time.h>
-
-#include "PalmVersion.h"
-#include "globals.h"
-
-#include "backends/base-backend.h"
-#include "common/scummsys.h"
-#include "common/events.h"
-#include "graphics/surface.h"
-#include "graphics/colormasks.h"
-
-namespace Audio {
- class MixerImpl;
-}
-
-namespace Common {
- class SaveFileManager;
- class TimerManager;
-}
-
-enum {
- GFX_NORMAL = 0,
- GFX_WIDE,
-};
-
-// OSD key state
-enum {
- kModifierNone = 0,
- kModifierCommand,
- kModifierAlt,
- kModifierCtrl,
- kModifierCount
-};
-
-// Mouse button event
-enum {
- vchrMouseLeft = vchrHardKeyMax - 2,
- vchrMouseRight = vchrHardKeyMax - 1
-};
-
-// OSD resource id
-#define kDrawKeyState 3000
-#define kDrawNumPad 3010
-#define kDrawBatLow 3020
-#define kDrawFight 3030
-
-#define computeMsecs(x) ((SysTicksPerSecond() * x) / 1000)
-
-
-//typedef void (*SoundProc)(void *param, byte *buf, int len);
-typedef void (*SoundProc)(byte *buf, uint len);
-typedef int (*TimerProc)(int interval);
-
-typedef struct {
- UInt32 duration, nextExpiry;
- Boolean active;
- TimerProc callback;
-} TimerType, *TimerPtr;
-
-typedef struct {
- Boolean active;
- void *proc;
- void *param;
-} SoundType, *SoundPtr;
-
-class OSystem_PalmBase : public BaseBackend {
-private:
- virtual void int_initBackend() { }
-
- virtual const GraphicsMode *int_getSupportedGraphicsModes() const;
- virtual void int_updateScreen() = 0;
- virtual void int_initSize(uint w, uint h) = 0;
- virtual void int_setShakePos(int shakeOffset) { }
-
- virtual void extras_palette(uint8 index, uint8 r, uint8 g, uint8 b) { }
- virtual void int_quit() { }
-
- virtual void unload_gfx_mode() = 0;
- virtual void load_gfx_mode() = 0;
-
- virtual void draw_mouse() = 0;
- virtual void undraw_mouse() = 0;
-
- virtual bool check_event(Common::Event &event, EventPtr ev) = 0;
-
- virtual void timer_handler();
- void battery_handler();
- virtual void get_coordinates(EventPtr ev, Coord &x, Coord &y) = 0;
- void simulate_mouse(Common::Event &event, Int8 iHoriz, Int8 iVert, Coord *xr, Coord *yr);
-
- virtual void sound_handler() = 0;
- virtual bool setupMixer() = 0;
- virtual void clearSoundCallback() = 0;
-
-protected:
- OSystem_PalmBase();
-
- virtual void draw_osd(UInt16 id, Int32 x, Int32 y, Boolean show, UInt8 color = 0);
- virtual void clear_screen() = 0;
-
- struct MousePos {
- int16 x,y,w,h;
- };
-
- TimerType _timer;
- SoundType _sound;
-
- Common::SaveFileManager *_saveMgr;
- Audio::MixerImpl *_mixerMgr;
- Common::TimerManager *_timerMgr;
-
- RGBColorType _currentPalette[256];
- uint _paletteDirtyStart, _paletteDirtyEnd;
-
- int _mode, _setMode;
- int16 _screenWidth, _screenHeight;
- Boolean _modeChanged, _gfxLoaded;
- UInt32 _screenPitch;
-
- PointType _screenOffset;
- struct {
- Coord w, h;
- } _screenDest;
- byte *_screenP, *_offScreenP;
- WinHandle _screenH, _offScreenH;
-
- int _current_shake_pos;
- int _new_shake_pos;
-
- Boolean _overlayVisible;
- Boolean _redawOSD, _setPalette;
-
- UInt32 _keyExtraMask, _keyExtraPressed, _keyExtraRepeat, _keyExtraDelay;
- struct {
- UInt32 bitUp;
- UInt32 bitDown;
- UInt32 bitLeft;
- UInt32 bitRight;
- UInt32 bitActionA; // left mouse button
- UInt32 bitActionB; // right mouse button
- } _keyExtra;
-
- bool _mouseVisible;
- bool _mouseDrawn;
- MousePos _mouseCurState;
- MousePos _mouseOldState;
- int16 _mouseHotspotX;
- int16 _mouseHotspotY;
- byte _mouseKeyColor;
- byte *_mouseDataP, *_mouseBackupP;
-
-
- bool _wasKey;
- UInt8 _lastKeyModifier;
- UInt32 _lastKeyRepeat;
- Boolean _useNumPad, _showBatLow;
- UInt32 _batCheckTicks, _batCheckLast;
-
-public:
- void initBackend();
-
-/*
- virtual void setFeatureState(Feature f, bool enable) {};
-
-
- bool hasFeature(Feature f);
- bool getFeatureState(Feature f);
-
- virtual void beginGFXTransaction();
- virtual void endGFXTransaction();
-
- virtual int16 getOverlayHeight();
- virtual int16 getOverlayWidth();
-
- virtual void setCursorPalette(const byte *colors, uint start, uint num);
- virtual void disableCursorPalette(bool disable);
-
- virtual void displayMessageOnOSD(const char *msg);
-*/
- const GraphicsMode *getSupportedGraphicsModes() const;
- int getGraphicsMode() const;
- virtual int getDefaultGraphicsMode() const;
- virtual bool setGraphicsMode(int mode);
-
- void initSize(uint w, uint h, const Graphics::PixelFormat *format);
- int16 getWidth() { return _screenWidth; }
- int16 getHeight() { return _screenHeight; }
-
- void setShakePos(int shakeOffset);
- virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) = 0;
- virtual void updateScreen();
-
- bool showMouse(bool visible);
- void warpMouse(int x, int y);
- void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format);
-
- virtual void showOverlay() = 0;
- virtual void hideOverlay() = 0;
- virtual void clearOverlay() = 0;
- virtual void grabOverlay(OverlayColor *buf, int pitch) = 0;
- virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) = 0;
-
- int16 getOverlayWidth() { return getWidth(); }
- int16 getOverlayHeight() { return getHeight(); }
-
- void setPalette(const byte *colors, uint start, uint num);
- void grabPalette(byte *colors, uint start, uint num);
- virtual Graphics::PixelFormat getOverlayFormat() const { return Graphics::createPixelFormat<565>(); }
-
- bool pollEvent(Common::Event &event);
-
-
- void getTimeAndDate(TimeDate& td) const;
- virtual uint32 getMillis();
- virtual void delayMillis(uint msecs);
-
- virtual void setTimerCallback(TimerProc callback, int interval);
-
- virtual MutexRef createMutex() { return NULL; }
- virtual void lockMutex(MutexRef mutex) {}
- virtual void unlockMutex(MutexRef mutex) {}
- virtual void deleteMutex(MutexRef mutex) {}
-
- virtual Audio::Mixer *getMixer();
-
- void quit();
- virtual void setWindowCaption(const char *caption) = 0;
-
- Common::SaveFileManager *getSavefileManager();
- Common::TimerManager *getTimerManager();
- FilesystemFactory *getFilesystemFactory();
-
- virtual Common::SeekableReadStream *createConfigReadStream();
- virtual Common::WriteStream *createConfigWriteStream();
-};
-
-#endif
diff --git a/backends/platform/PalmOS/Src/be_os5.cpp b/backends/platform/PalmOS/Src/be_os5.cpp
deleted file mode 100644
index c9ef9ecf7c..0000000000
--- a/backends/platform/PalmOS/Src/be_os5.cpp
+++ /dev/null
@@ -1,169 +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 "be_os5.h"
-#include <HsKeyCommon.h>
-
-OSystem_PalmOS5::OSystem_PalmOS5() : OSystem_PalmBase() {
- _sound.active = false;
- _setPalette = false;
-
- _workScreenH = NULL;
- _overlayH = NULL;
- _isSwitchable = false;
- _wasRotated = false;
- _cursorPaletteDisabled = true;
-
- MemSet(&_soundEx, sizeof(SoundExType), 0);
- _soundEx.sound = &_sound;
-}
-
-void OSystem_PalmOS5::calc_scale() {
- for (int y = 0; y < _screenDest.h; y++) {
- int ys = y * _screenHeight / _screenDest.h;
- _scaleTableY[y] = ys * _screenWidth;
- }
-
- for (int x = 0; x < _screenDest.w; x++) {
- int xs = x * _screenWidth / _screenDest.w;
- _scaleTableX[x] = xs;
- }
-}
-
-void OSystem_PalmOS5::calc_rect(Boolean fullscreen) {
- Int32 w, h;
-
- if (fullscreen) {
- w = (_ratio.adjustAspect == kRatioWidth) ? _ratio.width : gVars->screenFullWidth;
- h = (_ratio.adjustAspect == kRatioHeight) ? _ratio.height : gVars->screenFullHeight;
-
- _screenOffset.x = (_ratio.adjustAspect == kRatioWidth) ? (gVars->screenFullWidth - _ratio.width) / 2 : 0;
- _screenOffset.y = (_ratio.adjustAspect == kRatioHeight) ? (gVars->screenFullHeight - _ratio.height) / 2 : 0;
-
- } else {
- w = gVars->screenWidth;
- h = gVars->screenHeight * _screenHeight / _screenWidth;
-
- _screenOffset.x = 0;
- _screenOffset.y = (gVars->screenHeight - h) / 2;
- }
-
- _screenDest.w = w;
- _screenDest.h = h;
-}
-
-void OSystem_PalmOS5::int_initBackend() {
- _keyExtra.bitUp = keyBitRockerUp|keyBitPageUp;
- _keyExtra.bitDown = keyBitRockerDown|keyBitPageDown;
- _keyExtra.bitLeft = keyBitRockerLeft;
- _keyExtra.bitRight = keyBitRockerRight;
- _keyExtra.bitActionA = keyBitHard3;
- _keyExtra.bitActionB = keyBitHard4;
-}
-
-bool OSystem_PalmOS5::hasFeature(Feature f) {
- switch (f) {
- case kFeatureCursorHasPalette:
- return true;
- }
-
- return false;
-}
-
-void OSystem_PalmOS5::setFeatureState(Feature f, bool enable) {
- switch (f) {
-/* case kFeatureFullscreenMode:
- if (_gfxLoaded)
- if (OPTIONS_TST(kOptModeWide) && _initMode != GFX_WIDE) {
- _fullscreen = enable;
- hotswap_gfx_mode(_mode);
- }
- break;
-*/
- case kFeatureAspectRatioCorrection:
- if (_mode == GFX_WIDE) {
- _ratio.adjustAspect = (_ratio.adjustAspect + 1) % 3;
- //calc_rect(true);
- hotswap_gfx_mode(_mode);
-// TwGfxSetClip(_palmScreenP, &_dstRect);
- clear_screen();
- }
- break;
- }
-}
-
-void OSystem_PalmOS5::setWindowCaption(const char *caption) {
-/*
-FIXME/TODO: Convert caption from ISO Latin 1 to "right" encoding ?
-If the output encoding is unclear or conversion impossible,
-then one could just skip over any chars > 0x7F and display the rest
-*/
- Err e;
- Char buf[64];
- Coord w, y, h = FntLineHeight() + 2;
- const Char *loading = "Loading, please wait\0";
-
- // allocate bitmap
- BitmapTypeV3 *bmp2P;
- BitmapType *bmp1P = BmpCreate(320, (h * 3), 8, NULL, &e);
- WinHandle tmpH = WinCreateBitmapWindow(bmp1P, &e);
-
- WinSetDrawWindow(tmpH);
- WinSetBackColor(0);
- WinSetTextColor(255);
- WinEraseWindow();
-
- // loading message
- FntSetFont(boldFont);
- w = FntCharsWidth(loading, StrLen(loading));
- w = (320 - w) / 2;
- WinDrawChars(loading, StrLen(loading), w, 0 + h);
-
- // caption
- FntSetFont(stdFont);
- w = FntCharsWidth(caption, StrLen(caption));
- w = (320 - w) / 2;
- WinDrawChars(caption, StrLen(caption), w, 0);
-
- // memory size
- StrPrintF(buf, "memory : %ld KB", gVars->startupMemory);
- w = FntCharsWidth(buf, StrLen(buf));
- w = (320 - w) / 2;
- WinDrawChars(buf, StrLen(buf), w, h * 2);
-
- // set the bitmap as v3
- bmp2P = BmpCreateBitmapV3(bmp1P, kDensityDouble, BmpGetBits(bmp1P), NULL);
- y = (80 - (h / 4) - 5);
-
- // draw it
- WinSetDrawWindow(WinGetDisplayWindow());
- WinEraseWindow();
- WinDrawBitmap((BitmapPtr)bmp2P, 0, y);
-
- // free
- WinDeleteWindow(tmpH, 0);
- BmpDelete((BitmapPtr)bmp2P);
- BmpDelete(bmp1P);
-}
diff --git a/backends/platform/PalmOS/Src/be_os5.h b/backends/platform/PalmOS/Src/be_os5.h
deleted file mode 100644
index 2040c7faea..0000000000
--- a/backends/platform/PalmOS/Src/be_os5.h
+++ /dev/null
@@ -1,189 +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$
- *
- */
-
-#ifndef BE_OS5_H
-#define BE_OS5_H
-
-#include "be_base.h"
-
-#if !defined(SYSTEM_CALLBACK) || defined(PALMOS_68K)
-# define SYSTEM_CALLBACK
-# ifdef PALMOS_ARM
-# define CALLBACK_PROLOGUE \
- __asm { \
- stmfd r13!,{r9,r10}; \
- ldr r9,[r0]; \
- ldr r10,[r0,#4]; \
- }
-# define CALLBACK_EPILOGUE __asm { ldmfd r13!,{r9,r10} }
-# define CALLBACK_INIT(regs) \
- __asm { \
- ldr r0, = regs; \
- add r0,r0,r10; \
- str r9,[r0]; \
- str r10,[r0,#4]; \
- }
-# else
-# define CALLBACK_PROLOGUE \
- asm ( \
- movem.l a4-a5, -(sp); \
- move.l UserDataP, a0; \
- move.l 0(a0), a4; \
- move.l 4(a0), a5; \
- );
-# define CALLBACK_EPILOGUE asm ( movem.l (sp)+, a4-a5 );
-# define CALLBACK_INIT(regs) \
- { \
- void *ptr = &regs; \
- asm ( \
- move.l ptr, a0; \
- move.l a4, 0(a0); \
- move.l a5, 4(a0); \
- ); \
- }
-# endif
-#else
-# define CALLBACK_PROLOGUE
-# define CALLBACK_EPILOGUE
-# define CALLBACK_INIT(regs)
-#endif
-
-// TODO : change / remove this
-#define gfxMakeDisplayRGB_BigEndian(_r,_g,_b) \
- ( (((_g) & 0xFC) << 11) | (((_b) & 0xF8) << 5) | ((_r) & 0xF8) | (((_g) & 0xFF) >> 5) )
-
-#define gfxMakeDisplayRGB_LittleEndian(_r,_g,_b) \
- ( (((_r) & 0xF8) << 8) | (((_g) & 0xFC) << 3) | (((_b) & 0xF8) >> 3) )
-
-#if CPU_TYPE == CPU_68K
-#define gfxMakeDisplayRGB(_r,_g,_b) gfxMakeDisplayRGB_BigEndian(_r,_g,_b)
-#else
-#define gfxMakeDisplayRGB(_r,_g,_b) gfxMakeDisplayRGB_LittleEndian(_r,_g,_b)
-#endif
-
-typedef struct {
- // for real thread version only
- UInt32 __reg1;
- UInt32 __reg2;
-
- // no real thread version
- Boolean set;
- UInt32 size;
- void *dataP;
-
- // default sound stuff
- SndStreamRef handle;
- SoundPtr sound;
-} SoundExType, *SoundExPtr;
-extern SoundExType _soundEx;
-
-class OSystem_PalmOS5 : public OSystem_PalmBase {
-protected:
- uint16 _nativePal[256], _mousePal[256];
-
-private:
- uint16 _scaleTableX[512];
- uint32 _scaleTableY[512];
-
- typedef void (OSystem_PalmOS5::*RendererProc)(RectangleType &r, PointType &p);
- RendererProc _render;
-
- Graphics::Surface _framebuffer;
-
- OverlayColor *_overlayP;
- WinHandle _overlayH, _workScreenH;
- uint16 *_workScreenP;
-
- Boolean _isSwitchable, _wasRotated;
-
- virtual void int_initBackend();
- virtual void int_updateScreen();
- virtual void int_initSize(uint w, uint h);
-
- virtual void unload_gfx_mode();
- virtual void load_gfx_mode();
- virtual void hotswap_gfx_mode(int mode);
-
- void draw_mouse();
- void undraw_mouse();
- virtual bool check_event(Common::Event &event, EventPtr ev);
- void extras_palette(uint8 index, uint8 r, uint8 g, uint8 b);
- void calc_scale();
-
- void render_landscapeAny(RectangleType &r, PointType &p);
- void render_landscape15x(RectangleType &r, PointType &p);
- void render_1x(RectangleType &r, PointType &p);
- WinHandle alloc_screen(Coord w, Coord h);
- virtual void draw_osd(UInt16 id, Int32 x, Int32 y, Boolean show, UInt8 color = 0);
-
- virtual SndStreamVariableBufferCallback sound_callback();
- virtual void sound_handler();
- virtual bool setupMixer();
- void clearSoundCallback();
-
-protected:
- UInt16 _sysOldCoord, _sysOldOrientation, _sysOldTriggerState;
- Boolean _stretched, _cursorPaletteDisabled;
-
- enum {
- kRatioNone = 0,
- kRatioHeight,
- kRatioWidth
- };
- struct {
- UInt8 adjustAspect;
- Coord width; // (width x 320)
- Coord height; // (480 x height)
- } _ratio;
-
- void calc_rect(Boolean fullscreen);
- void get_coordinates(EventPtr ev, Coord &x, Coord &y);
- void clear_screen();
-
-public:
- OSystem_PalmOS5();
- static OSystem *create();
-
- bool hasFeature(Feature f);
- void setFeatureState(Feature f, bool enable);
-
- void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
- virtual Graphics::Surface *lockScreen();
- virtual void unlockScreen();
-
- void setCursorPalette(const byte *colors, uint start, uint num);
- void disableCursorPalette(bool disable);
-
- void showOverlay();
- void hideOverlay();
- virtual void clearOverlay();
- virtual void grabOverlay(OverlayColor *buf, int pitch);
- virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
-
- void setWindowCaption(const char *caption);
-
-};
-
-#endif
diff --git a/backends/platform/PalmOS/Src/be_os5ex.cpp b/backends/platform/PalmOS/Src/be_os5ex.cpp
deleted file mode 100644
index 05bf5e49ce..0000000000
--- a/backends/platform/PalmOS/Src/be_os5ex.cpp
+++ /dev/null
@@ -1,103 +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$
- *
- */
-
-// for DAL.h
-#define ALLOW_ACCESS_TO_INTERNALS_OF_BITMAPS
-
-#include "be_os5ex.h"
-#include "palmdefs.h"
-
-#include <System/WIP.h>
-#include <System/DAL.h>
-
-static TimerExType _timerEx;
-
-OSystem_PalmOS5Ex::OSystem_PalmOS5Ex() : OSystem_PalmOS5() {
- _timerEx.timerID = 0;
- _timerEx.timer = &_timer;
- _timerEx.ticks = SysTicksPerSecond();
-}
-
-static SYSTEM_CALLBACK void timer_handler(void *userDataP) {
- CALLBACK_PROLOGUE
- TimerExPtr _timerEx = (TimerExPtr)userDataP;
- TimerPtr _timer = _timerEx->timer;
- _timer->duration = _timer->callback(_timer->duration);
- KALTimerSet(_timerEx->timerID, (_timer->duration * _timerEx->ticks / 1000));
- CALLBACK_EPILOGUE
-}
-
-void OSystem_PalmOS5Ex::setTimerCallback(TimerProc callback, int timer) {
- if (_timer.active && _timerEx.timerID)
- KALTimerDelete(_timerEx.timerID);
-
- if (callback != NULL) {
- Err e;
- CALLBACK_INIT(_timerEx);
- _timer.duration = timer;
- _timer.callback = callback;
-
- // create the timer
- e = KALTimerCreate(&_timerEx.timerID, appFileCreator, &::timer_handler, &_timerEx);
- if (!e) {
- e = KALTimerSet(_timerEx.timerID, (timer * _timerEx.ticks / 1000));
- if (e) KALTimerDelete(_timerEx.timerID);
- }
- _timer.active = (!e);
-
- } else {
- _timer.active = false;
- }
-
- if (!_timer.active)
- _timerEx.timerID = 0;
-}
-
-OSystem::MutexRef OSystem_PalmOS5Ex::createMutex() {
- UInt32 mutexID;
- Err e = KALMutexCreate(&mutexID, appFileCreator);
- return (MutexRef)(e ? NULL : mutexID);
-
-}
-
-void OSystem_PalmOS5Ex::lockMutex(MutexRef mutex) {
- if (mutex)
- KALMutexReserve((UInt32)mutex);
-}
-
-void OSystem_PalmOS5Ex::unlockMutex(MutexRef mutex) {
- if (mutex)
- KALMutexRelease((UInt32)mutex, 0);
-}
-
-void OSystem_PalmOS5Ex::deleteMutex(MutexRef mutex) {
- if (mutex)
- KALMutexDelete((UInt32)mutex);
-}
-
-void OSystem_PalmOS5Ex::int_quit() {
- if (_timerEx.timerID)
- KALTimerDelete(_timerEx.timerID);
-}
diff --git a/backends/platform/PalmOS/Src/be_os5ex.h b/backends/platform/PalmOS/Src/be_os5ex.h
deleted file mode 100644
index f9842d82ac..0000000000
--- a/backends/platform/PalmOS/Src/be_os5ex.h
+++ /dev/null
@@ -1,68 +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$
- *
- */
-
-#ifndef BE_OS5EX_H
-#define BE_OS5EX_H
-
-#include "be_os5.h"
-
-#undef dprintf // fix compilation in Zodiac mode
-
-#ifndef PALMOS_ARM
-// Not usable with 68k mode (?), so ...
-#define OSystem_PalmOS5Ex OSystem_PalmOS5
-#else
-
-typedef struct {
- UInt32 __r9;
- UInt32 __r10;
- UInt32 timerID;
- UInt32 ticks;
-
- TimerPtr timer;
-} TimerExType, *TimerExPtr;
-
-class OSystem_PalmOS5Ex : public OSystem_PalmOS5 {
-private:
- void timer_handler() {}
- void sound_handler() {}
- void int_quit();
-
- SndStreamVariableBufferCallback sound_callback();
-
-public:
- OSystem_PalmOS5Ex();
- static OSystem *create();
-
- void setTimerCallback(TimerProc callback, int interval);
-
- MutexRef createMutex();
- void lockMutex(MutexRef mutex);
- void unlockMutex(MutexRef mutex);
- void deleteMutex(MutexRef mutex);
-};
-#endif
-
-#endif
diff --git a/backends/platform/PalmOS/Src/be_zodiac.cpp b/backends/platform/PalmOS/Src/be_zodiac.cpp
deleted file mode 100644
index d6e7e2c292..0000000000
--- a/backends/platform/PalmOS/Src/be_zodiac.cpp
+++ /dev/null
@@ -1,74 +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 "be_zodiac.h"
-
-OSystem_PalmZodiac::OSystem_PalmZodiac() : OSystem_PalmOS5Ex() {
- _gfxH = NULL;
- _overlayP = NULL;
- _palmScreenP = NULL;
- _tmpScreenP = NULL;
- _stretched = false;
-}
-
-void OSystem_PalmZodiac::int_initBackend() {
- _keyExtra.bitUp = keyBitRockerUp;
- _keyExtra.bitDown = keyBitRockerDown;
- _keyExtra.bitLeft = keyBitRockerLeft;
- _keyExtra.bitRight = keyBitRockerRight;
-
-// _keyExtra.bitActionA = keyBitActionD;
-// _keyExtra.bitActionB = keyBitActionB;
-}
-
-void OSystem_PalmZodiac::calc_rect(Boolean fullscreen) {
- OSystem_PalmOS5::calc_rect(fullscreen);
-
- _dstRect.x = _screenOffset.x;
- _dstRect.y = _screenOffset.y;
- _dstRect.w = _screenDest.w;
- _dstRect.h = _screenDest.h;
-}
-
-void OSystem_PalmZodiac::setFeatureState(Feature f, bool enable) {
- switch (f) {
-/* case kFeatureFullscreenMode:
- if (_gfxLoaded)
- if (OPTIONS_TST(kOptModeWide) && _initMode != GFX_WIDE) {
- _fullscreen = enable;
- hotswap_gfx_mode(_mode);
- }
- break;
-*/
- case kFeatureAspectRatioCorrection:
- if (_mode == GFX_WIDE) {
- _ratio.adjustAspect = (_ratio.adjustAspect + 1) % 3;
- calc_rect(true);
- TwGfxSetClip(_palmScreenP, &_dstRect);
- clear_screen();
- }
- break;
- }
-}
diff --git a/backends/platform/PalmOS/Src/be_zodiac.h b/backends/platform/PalmOS/Src/be_zodiac.h
deleted file mode 100644
index 28fcf29ddd..0000000000
--- a/backends/platform/PalmOS/Src/be_zodiac.h
+++ /dev/null
@@ -1,76 +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$
- *
- */
-
-#ifndef BE_ZODIAC_H
-#define BE_ZODIAC_H
-
-#include <tapwave.h>
-#include "be_os5ex.h"
-
-#define MIN_OFFSET 20
-
-class OSystem_PalmZodiac : public OSystem_PalmOS5Ex {
-private:
-
- TwGfxType *_gfxH;
- TwGfxSurfaceType *_palmScreenP, *_tmpScreenP;
- TwGfxSurfaceType *_overlayP;
- Boolean _fullscreen;
-
- TwGfxPointType _srcPos;
- TwGfxRectType _srcRect, _dstRect;
- TwGfxBitmapType _srcBmp;
-
- void int_initBackend();
- void int_setShakePos(int shakeOffset);
-
- void draw_mouse();
- void undraw_mouse();
-
- void unload_gfx_mode();
- void load_gfx_mode();
- void hotswap_gfx_mode(int mode);
-
- void calc_rect(Boolean fullscreen);
- bool check_event(Common::Event &event, EventPtr ev);
- void draw_osd(UInt16 id, Int32 x, Int32 y, Boolean show, UInt8 color = 0);
-
-public:
- OSystem_PalmZodiac();
-
- static OSystem *create();
-
- void setFeatureState(Feature f, bool enable);
-
- int getDefaultGraphicsMode() const;
-
- void updateScreen();
-
- void clearOverlay();
- void grabOverlay(OverlayColor *buf, int pitch);
- void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
-};
-
-#endif
diff --git a/backends/platform/PalmOS/Src/cd_aeroplayer.cpp b/backends/platform/PalmOS/Src/cd_aeroplayer.cpp
deleted file mode 100644
index c30fba595c..0000000000
--- a/backends/platform/PalmOS/Src/cd_aeroplayer.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/system.h"
-#include "common/config-manager.h"
-
-#include "cd_aeroplayer.h"
-
-AeroCDPlayer::AeroCDPlayer(OSystem *sys) {
- _sys = sys;
- StrCopy(gameP, ConfMan.getActiveDomainName().c_str());
-}
-
-bool AeroCDPlayer::init() {
- aeroplayer_Startup();
- _isInitialized = aeroplayer_PlayerIsActive();
-
- if (_isInitialized)
- _volumeLimit = aeroplayer_GetMaxVolumeIndex();
-
- return _isInitialized;
-}
-
-void AeroCDPlayer::release() {
- aeroplayer_Shutdown();
-
- // self delete
- delete this;
-}
-
-UInt32 AeroCDPlayer::getStatus() {
- return aeroplayer_GetPlaybackStatus();
-}
-
-UInt32 AeroCDPlayer::getPosition() {
- return aeroplayer_GetPosition_msec();
-}
-
-UInt32 AeroCDPlayer::getDuration() {
- return aeroplayer_GetDuration_msec();
-}
-
-void AeroCDPlayer::setPosition(UInt32 value) {
- aeroplayer_Seek_abs_msec(value);
-}
-
-void AeroCDPlayer::setVolume(int volume) {
- _volumeLevel = volume;
- aeroplayer_SetVolumeIndex((_volumeLimit * volume) / 100);
-}
-
-bool AeroCDPlayer::poll() {
- return
- ( _pckLoops != 0 &&
- ( getPosition() < _pckTrackEndFrame &&
- getStatus() == AEROPLAYER_STATUS_PLAY
- )
- );
-}
-
-void AeroCDPlayer::update() {
-
- // stop replay upon request of stopCD()
- if (_pckStopTime != 0 && _sys->getMillis() >= _pckStopTime) {
- forceStop();
- _pckLoops = 0;
- _pckStopTime = 0;
- _pckTrackEndFrame = 0;
- return;
- }
-
- // not fully played
- if (getPosition() < _pckTrackEndFrame && getStatus() == AEROPLAYER_STATUS_PLAY)
- return;
-
- aeroplayer_Pause();
-// _pckStopTime = _sys->getMillis();
-
- // loop again ?
- if (_pckLoops > 0)
- _pckLoops--;
-
- // loop if needed
- if (_pckLoops == 0)
- forceStop();
- else {
- //_pckStopTime = 0;
-
- if (_pckTrackStartFrame == 0 && _pckTrackDuration == 0) {
- setPosition(0);
- } else {
- setPosition(_pckTrackStartFrame);
- }
-
- aeroplayer_Play();
- _pckEndTime = _sys->getMillis() + _pckTrackDuration;
- }
-}
-
-void AeroCDPlayer::stop() {
- _pckStopTime = _sys->getMillis();
- _pckLoops = 0;
- return;
-}
-
-void AeroCDPlayer::forceStop() {
- if (getStatus() != AEROPLAYER_STATUS_STOP)
- aeroplayer_PlayTrack(vfsInvalidVolRef, NULL);
-}
-
-void AeroCDPlayer::play(int track, int num_loops, int start_frame, int duration) {
- if (!num_loops && !start_frame)
- return;
-
- Char fileP[100];
- static const Char *ext[] = { "mp3", "ogg" };
-
-// if (duration > 0)
-// duration += 5;
-
- _pckTrack = track;
- _pckLoops = num_loops;
- _pckTrackStartFrame = TO_MSECS(start_frame);
- _pckTrackDuration = TO_MSECS(duration);
-
- StrPrintF(fileP, "/Palm/Programs/ScummVM/Audio/%s_%03ld.%s", gameP, (track + gVars->CD.firstTrack - 1), ext[gVars->CD.format]);
- aeroplayer_Pause();
- aeroplayer_PlayTrack(gVars->VFS.volRefNum, fileP);
- aeroplayer_Pause();
-
- if (_pckTrackStartFrame == 0 && _pckTrackDuration == 0) {
- _pckTrackDuration = getDuration();
- } else {
- setPosition(_pckTrackStartFrame);
- if (_pckTrackDuration == 0)
- _pckTrackDuration = getDuration() - _pckTrackStartFrame;
- }
-
- aeroplayer_Play();
-
- _pckStopTime = 0;
- _pckTrackEndFrame = _pckTrackStartFrame + _pckTrackDuration;
- _pckEndTime = _sys->getMillis() + _pckTrackDuration;
-}
diff --git a/backends/platform/PalmOS/Src/cd_default.cpp b/backends/platform/PalmOS/Src/cd_default.cpp
deleted file mode 100644
index 416701524d..0000000000
--- a/backends/platform/PalmOS/Src/cd_default.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-#include "common/system.h"
-#include "cd_default.h"
-
-DefaultCDPlayer::DefaultCDPlayer(OSystem *sys) {
- _sys = sys;
-}
-
-bool DefaultCDPlayer::init() {
- _isInitialized = true;
- return _isInitialized;
-}
-
-void DefaultCDPlayer::release() {
- // self delete
- delete this;
-}
-
-bool DefaultCDPlayer::poll() {
- return (_defLoops != 0 && _sys->getMillis() < _defTrackEndFrame);
-}
-
-void DefaultCDPlayer::update() {
-
- // stop replay upon request of stopCD()
- if (_defStopTime != 0 && _sys->getMillis() >= _defStopTime) {
- _defLoops = 0;
- _defStopTime = 0;
- _defTrackEndFrame = 0;
- return;
- }
-
- // not fully played
- if (_sys->getMillis() < _defTrackEndFrame)
- return;
-
- if (_defLoops == 0)
- return;
-
- // loop again ?
- if (_defLoops > 0)
- _defLoops--;
-
- // loop if needed
- if (_defLoops != 0) {
- _defTrackEndFrame = _sys->getMillis() + _defTrackLength;
- }
-}
-
-void DefaultCDPlayer::stop() { /* Stop CD Audio in 1/10th of a second */
- _defStopTime = _sys->getMillis() + 100;
- _defLoops = 0;
- return;
-}
-
-void DefaultCDPlayer::play(int track, int num_loops, int start_frame, int duration) {
- if (!num_loops && !start_frame)
- return;
-
- UInt32 fullLength;
-
- _defLoops = num_loops;
- start_frame = TO_MSECS(start_frame);
- duration = TO_MSECS(duration);
-
- // frame in milli-seconds
- _defStopTime = 0;
- fullLength = start_frame + gVars->CD.defaultTrackLength * 1000;
-
- if (duration > 0) {
- _defTrackLength = duration;
- } else if (start_frame > 0) {
- _defTrackLength = fullLength;
- _defTrackLength -= start_frame;
- } else {
- _defTrackLength = fullLength;
- }
-
- // try to play the track
- _defTrackEndFrame = _sys->getMillis() + _defTrackLength;
-}
diff --git a/backends/platform/PalmOS/Src/cd_default.h b/backends/platform/PalmOS/Src/cd_default.h
deleted file mode 100644
index 69d909b1e7..0000000000
--- a/backends/platform/PalmOS/Src/cd_default.h
+++ /dev/null
@@ -1,51 +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$
- *
- */
-
- #ifndef CD_DEFAULT_H
- #define CD_DEFAULT_H
-
- #include "cdaudio.h"
-
- class DefaultCDPlayer : public CDAudio {
- public:
- DefaultCDPlayer(OSystem *sys);
-
- bool init();
- void release();
-
- bool poll();
- void update();
- void play(int track, int num_loops, int start_frame, int duration);
- void stop();
-
- private:
- OSystem *_sys;
-
- // cdrom
- UInt16 _defLoops;
- UInt32 _defStopTime, _defTrackEndFrame, _defTrackLength;
- };
-
- #endif
diff --git a/backends/platform/PalmOS/Src/cd_msa.cpp b/backends/platform/PalmOS/Src/cd_msa.cpp
deleted file mode 100644
index 5812d49b6d..0000000000
--- a/backends/platform/PalmOS/Src/cd_msa.cpp
+++ /dev/null
@@ -1,261 +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 <SonyClie.h>
-#include "common/system.h"
-#include "cd_msa.h"
-#include "start.h" // for appFileCreat
-
-static void doErr(Err e, const Char *msg) {
- Char err[100];
- StrPrintF(err, "%ld : " , e);
- StrCat(err,msg);
- FrmCustomAlert(1000,err,0,0);
-}
-
-MsaCDPlayer::MsaCDPlayer(OSystem *sys) {
- _sys = sys;
- _msaRefNum = sysInvalidRefNum;
-
- _msaLoops = 0;
- _msaStopTime = 0;
- _msaTrackEndSu = 0;
-}
-
-bool MsaCDPlayer::init() {
- SonySysFtrSysInfoP sonySysFtrSysInfoP;
- Err error = errNone;
-
- if (!(error = FtrGet(sonySysFtrCreator, sonySysFtrNumSysInfoP, (UInt32*)&sonySysFtrSysInfoP))) {
- // not found with audio adapter ?!
- //if (sonySysFtrSysInfoP->libr & sonySysFtrSysInfoLibrMsa) {
- if ((error = SysLibFind(sonySysLibNameMsa, &_msaRefNum)))
- if (error == sysErrLibNotFound)
- error = SysLibLoad(sonySysFileTMsaLib, sonySysFileCMsaLib, &_msaRefNum);
-
- // FIXME : still don't understand how this lib works, it seems to be very unstable
- // and with the very bad documentation provided by Sony it's difficult to find out why
- // this doesn't work the same way on build-in MP3 device and external MP3 devices
- if (!error) {
- //MsaLibClose(_msaRefNum, msaLibOpenModeAlbum); // close the lib if we previously let it open (?) Need to add Notify for sonySysNotifyMsaEnforceOpenEvent just in case ...
- error = MsaLibOpen(_msaRefNum, msaLibOpenModeAlbum);
-
- //if (error == msaErrAlreadyOpen)
- // error = MsaLibEnforceOpen(_msaRefNum, msaLibOpenModeAlbum, appFileCreator);
-
- //error = (error != msaErrStillOpen) ? error : errNone;
- }
- //}
- }
-
-// if (error)
-// _msaRefNum = sysInvalidRefNum;
-
- _isInitialized = (_msaRefNum != sysInvalidRefNum);
- initInternal();
- return _isInitialized;
-}
-
-void MsaCDPlayer::initInternal() {
- if (!_isInitialized)
- return;
-
- Err e;
- Char nameP[256];
- UInt32 dummy, albumIterater = albumIteratorStart;
-
- MemSet(&_msaAlbum, sizeof(_msaAlbum), 0);
- _msaAlbum.maskflag = msa_INF_ALBUM;
- _msaAlbum.code = msa_LANG_CODE_ASCII;
- _msaAlbum.nameP = nameP;
- _msaAlbum.fileNameLength = 256;
-
- e = MsaAlbumEnumerate(_msaRefNum, &albumIterater, &_msaAlbum);
- e = MsaSetAlbum(_msaRefNum, _msaAlbum.albumRefNum, &dummy);
-
- // TODO : use RMC to control volume
- MsaOutCapabilityType capability;
- MsaOutGetCapability(_msaRefNum, &capability);
- _volumeLLimit = capability.volumeLLimit;
- _volumeRLimit = capability.volumeRLimit;
-}
-
-void MsaCDPlayer::setVolume(int volume) {
- _volumeLevel = volume;
- MsaOutSetVolume(_msaRefNum, (_volumeLLimit * volume) / 100, (_volumeRLimit * volume) / 100);
-}
-
-void MsaCDPlayer::release() {
- if (_isInitialized) {
- if (_msaRefNum != sysInvalidRefNum) {
- // stop the current track if any (needed if we use enforce open to prevent the track to play after exit)
- MsaStop(_msaRefNum, true);
- MsaLibClose(_msaRefNum, msaLibOpenModeAlbum);
- }
- }
-
- // self delete
- delete this;
-}
-
-bool MsaCDPlayer::poll() {
- if (!_isInitialized)
- return false;
-
- MsaPBStatus pb;
- MsaGetPBStatus(_msaRefNum, &pb);
- return (_msaLoops != 0 && (pb.currentSU < _msaTrackEndSu || pb.status != msa_STOPSTATUS));
-}
-
-void MsaCDPlayer::update() {
- if (!_isInitialized)
- return;
-
- // get playback status
- MsaPBStatus pb;
- MsaGetPBStatus(_msaRefNum, &pb);
-
- // stop replay upon request of stopCD()
- if (_msaStopTime != 0 && _sys->getMillis() >= _msaStopTime) {
- MsaStop(_msaRefNum, true);
- _msaLoops = 0;
- _msaStopTime = 0;
- _msaTrackEndSu = 0;
- return;
- }
-
- // not fully played nad still playing the correct track
- // (when playing a full track the return SU is not correct
- // and so we need to check if we are still playing the correct track)
- if (pb.currentSU < _msaTrackEndSu) {
- UInt16 trackNo;
- MsaPBListIndexToTrackNo(_msaRefNum, pb.currentpblistindex, &trackNo);
- if (trackNo == _msaTrack)
- return;
- }
-
- MsaStop(_msaRefNum, true);
-
- if (_msaLoops == 0)
- return;
-
- // track ends and last play, force stop if still playing
-/* if (_msaLoops != 1 && pb.status != msa_STOPSTATUS) {
- MsaStop(_msaRefNum, true);
- return;
- }
-*/
- // loop again ?
- if (_msaLoops > 0)
- _msaLoops--;
-
- // loop if needed
- if (_msaLoops != 0) {
- if (_msaStartFrame == 0 && _msaDuration == 0)
- MsaPlay(_msaRefNum, _msaTrack, 0, msa_PBRATE_SP);
- else
- MsaPlay(_msaRefNum, _msaTrack, _msaTrackStartSu, msa_PBRATE_SP);
- }
-}
-
-void MsaCDPlayer::stop() { /* Stop CD Audio in 1/10th of a second */
- if (!_isInitialized)
- return;
-
- _msaStopTime = _sys->getMillis() + 100;
- _msaLoops = 0;
- return;
-}
-
-void MsaCDPlayer::play(int track, int num_loops, int start_frame, int duration) {
- if (!_isInitialized)
- return;
-
- if (!num_loops && !start_frame)
- return;
-
- _msaTrack = track + gVars->CD.firstTrack - 1; // first track >= 1 ?, not 0 (0=album)
- _msaLoops = num_loops;
- _msaStartFrame = TO_MSECS(start_frame);
- _msaDuration = TO_MSECS(duration);
-
- Err e;
- MemHandle trackH;
-
- // stop current play if any
- MsaStop(_msaRefNum, true);
- _msaStopTime = 0;
-
- // retreive track infos
- e = MsaGetTrackInfo(_msaRefNum, _msaTrack, 0, msa_LANG_CODE_ASCII, &trackH);
-
- // track exists
- if (!e && trackH) {
- MsaTime msaTime;
- MsaTrackInfo *trackP;
- UInt32 SU, fullLength;
-
- // FIXME (?) : this enable MsaSuToTime to return the right value in some cases
- MsaPlay(_msaRefNum, _msaTrack, 0, msa_PBRATE_SP);
- MsaStop(_msaRefNum, true);
-
- // get the msa time
- trackP = (MsaTrackInfo *)MemHandleLock(trackH);
- MsaSuToTime(_msaRefNum, trackP->totalsu, &msaTime);
- SU = trackP->totalsu;
- MemPtrUnlock(trackP);
- MemHandleFree(trackH);
-
- // MSA frame in milli-seconds
- fullLength = FROM_MIN(msaTime.minute);
- fullLength += FROM_SEC(msaTime.second);
- fullLength += msaTime.frame;
-
- if (_msaDuration > 0) {
- _msaTrackLength = _msaDuration;
- } else if (_msaStartFrame > 0) {
- _msaTrackLength = fullLength;
- _msaTrackLength -= _msaStartFrame;
- } else {
- _msaTrackLength = fullLength;
- }
-
- // try to play the track
- if (start_frame == 0 && duration == 0) {
- MsaPlay(_msaRefNum, _msaTrack, 0, msa_PBRATE_SP);
- _msaTrackEndSu = SU;
- } else {
- // FIXME : MsaTimeToSu doesn't work ... (may work with previous FIXME)
- _msaTrackStartSu = (UInt32) ((float)(_msaStartFrame) / ((float)fullLength / (float)SU));
- _msaTrackEndSu = (UInt32) ((float)(_msaTrackLength) / ((float)fullLength / (float)SU));
- _msaTrackEndSu += _msaTrackStartSu;
-
- if (_msaTrackEndSu > SU)
- _msaTrackEndSu = SU;
-
- MsaPlay(_msaRefNum, _msaTrack, _msaTrackStartSu, msa_PBRATE_SP);
- }
- }
- // TODO : use default track length if track not found
-}
diff --git a/backends/platform/PalmOS/Src/cd_pockettunes.cpp b/backends/platform/PalmOS/Src/cd_pockettunes.cpp
deleted file mode 100644
index 5a9f3874eb..0000000000
--- a/backends/platform/PalmOS/Src/cd_pockettunes.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-#include "common/system.h"
-#include "common/config-manager.h"
-
-#include "cd_pockettunes.h"
-
-PckTunesCDPlayer::PckTunesCDPlayer(OSystem *sys) {
- _sys = sys;
- StrCopy(gameP, ConfMan.getActiveDomainName().c_str());
-}
-
-bool PckTunesCDPlayer::init() {
- PocketTunesStart();
- _isInitialized = PocketTunesIsRunning();
- _isPlaying = false;
- _pAction = NULL;
-
- if (_isInitialized) {
- _pAction = (PocketTunesAction*)MemPtrNew(sizeof(PocketTunesAction));
- _volumeLimit = getVolumeLimit();
- }
-
- _isInitialized = (_isInitialized && _pAction);
- return _isInitialized;
-}
-
-void PckTunesCDPlayer::release() {
- PocketTunesStop();
- if (_pAction)
- MemPtrFree(_pAction);
-
- // self delete
- delete this;
-}
-
-UInt32 PckTunesCDPlayer::getVolumeLimit() {
- UInt32 value = 0;
-
- if (!_pAction)
- return value;
-
- _pAction->action = kPocketTunesActionGetValue;
- _pAction->data.getValueAction.which = kPtunesValueMaxVolume;
-
- EvtGetEvent(&_eAction, evtNoWait);
- if (PocketTunesCallSynch(_pAction) == errNone)
- value = _pAction->data.getValueAction.value;
-
- return value;
-}
-
-UInt32 PckTunesCDPlayer::getStatus() {
- UInt32 status = kPtunesStopped;
-
- if (!_isPlaying || !_pAction)
- return status;
-
- _pAction->action = kPocketTunesActionGetStatus;
-
- EvtGetEvent(&_eAction, evtNoWait);
- if (PocketTunesCallSynch(_pAction) == errNone)
- status = _pAction->data.getStatusAction.status;
-
- return status;
-}
-
-UInt32 PckTunesCDPlayer::getPosition(UInt32 deflt) {
- UInt32 value = deflt;
-
- if (!_isPlaying || !_pAction)
- return value;
-
- _pAction->action = kPocketTunesActionGetValue;
- _pAction->data.getValueAction.which = kPtunesValueSongPosition;
-
- EvtGetEvent(&_eAction, evtNoWait);
- if (PocketTunesCallSynch(_pAction) == errNone)
- value = _pAction->data.getValueAction.value;
-
- return value;
-}
-
-UInt32 PckTunesCDPlayer::getDuration() {
- UInt32 value = gVars->CD.defaultTrackLength;
-
- if (!_isPlaying || !_pAction)
- return value;
-
- _pAction->action = kPocketTunesActionGetValue;
- _pAction->data.getValueAction.which = kPtunesValueSongDuration;
-
- EvtGetEvent(&_eAction, evtNoWait);
- if (PocketTunesCallSynch(_pAction) == errNone)
- value = _pAction->data.getValueAction.value;
-
- return value;
-}
-
-void PckTunesCDPlayer::setPosition(UInt32 value) {
- if (!_isPlaying)
- return;
-
- PocketTunesAction *pAction = AllocateAsynchronousActionStruct();
- if (!pAction)
- return;
-
- pAction->action = kPocketTunesActionSetValue;
- pAction->data.getValueAction.which = kPtunesValueSongPosition;
- pAction->data.getValueAction.value = value;
-
- EvtGetEvent(&_eAction, evtNoWait);
- PocketTunesCall(pAction);
-}
-
-void PckTunesCDPlayer::setVolume(int volume) {
- _volumeLevel = volume;
-
- PocketTunesAction *pAction = AllocateAsynchronousActionStruct();
- if (!pAction)
- return;
-
- pAction->action = kPocketTunesActionSetValue;
- pAction->data.getValueAction.which = kPtunesValueVolume;
- pAction->data.getValueAction.value = (_volumeLimit * volume) / 100;
-
- EvtGetEvent(&_eAction, evtNoWait);
- PocketTunesCall(pAction);
-}
-
-bool PckTunesCDPlayer::poll() {
- return (_pckLoops != 0 && (getPosition(_pckTrackEndFrame) < _pckTrackEndFrame || getStatus() != kPtunesStopped));
-}
-
-void PckTunesCDPlayer::update() {
-
- // stop replay upon request of stopCD()
- if (_pckStopTime != 0 && _sys->getMillis() >= _pckStopTime) {
- PocketTunesStop();
- _pckLoops = 0;
- _pckStopTime = 0;
- _pckTrackEndFrame = 0;
- return;
- }
-
- // not fully played
- if (getPosition(_pckTrackEndFrame) < _pckTrackEndFrame && getStatus() != kPtunesStopped)
- return;
-
- PocketTunesStop();
-
- if (_pckLoops == 0)
- return;
-
- // loop again ?
- if (_pckLoops > 0)
- _pckLoops--;
-
- // loop if needed
- if (_pckLoops != 0 && _isPlaying) {
- if (_pckTrackStartFrame == 0 && _pckTrackDuration == 0) {
- setPosition(0);
- } else {
- setPosition(_pckTrackStartFrame);
- }
-
- PocketTunesPlay();
- }
-}
-
-void PckTunesCDPlayer::stop() { /* Stop CD Audio in 1/10th of a second */
- _pckStopTime = _sys->getMillis() + 100;
- _pckLoops = 0;
- return;
-}
-
-void PckTunesCDPlayer::play(int track, int num_loops, int start_frame, int duration) {
- if (!num_loops && !start_frame)
- return;
-
- EventType e;
- Char nameP[256], fileP[100];
- static const Char *ext[] = { "mp3", "ogg" };
-
- _pckTrack = track;
- _pckLoops = num_loops;
- _pckTrackStartFrame = TO_MSECS(start_frame);
- _pckTrackDuration = TO_MSECS(duration);
-
- VFSVolumeGetLabel(gVars->VFS.volRefNum, nameP, 256);
-
- StrPrintF(fileP, "/Palm/Programs/ScummVM/Audio/%s_%03ld.%s", gameP, (track + gVars->CD.firstTrack - 1), ext[gVars->CD.format]);
-
- if (PocketTunesOpenFile(nameP, fileP, 0) == errNone) {
- EvtGetEvent(&e, evtNoWait);
- PocketTunesPauseIfPlaying();
- _isPlaying = true;
-
- if (_pckTrackStartFrame == 0 && _pckTrackDuration == 0) {
- _pckTrackDuration = getDuration();
- } else {
- setPosition(_pckTrackStartFrame);
- if (_pckTrackDuration == 0)
- _pckTrackDuration = getDuration() - _pckTrackStartFrame;
- }
-
- PocketTunesPlay();
-
- } else {
- _isPlaying = false;
- _pckTrackDuration = gVars->CD.defaultTrackLength * 1000;
- }
-
- _pckStopTime = 0;
- _pckTrackEndFrame = _pckTrackStartFrame + _pckTrackDuration;
-}
diff --git a/backends/platform/PalmOS/Src/cd_pockettunes.h b/backends/platform/PalmOS/Src/cd_pockettunes.h
deleted file mode 100644
index 77938d846a..0000000000
--- a/backends/platform/PalmOS/Src/cd_pockettunes.h
+++ /dev/null
@@ -1,69 +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$
- *
- */
-
- #ifndef CD_POCKETTUNES_H
- #define CD_POCKETTUNES_H
-
- #include "cdaudio.h"
- #include "pockettunes.h"
-
- class PckTunesCDPlayer : public CDAudio {
- public:
- PckTunesCDPlayer(OSystem *sys);
-
- bool init();
- void release();
-
- bool poll();
- void update();
- void play(int track, int num_loops, int start_frame, int duration);
- void stop();
-
- void setVolume(int volume);
-
- private:
- OSystem *_sys;
- Char gameP[15];
-
- PocketTunesAction *_pAction; // prevent memory fragmentation
- EventType _eAction;
-
- UInt32 getStatus();
- void setPosition(UInt32 value);
- UInt32 getDuration();
- UInt32 getPosition(UInt32 deft);
-
- UInt32 _volumeLimit;
- UInt32 getVolumeLimit();
-
- Boolean _isPlaying;
- // cdrom
- UInt16 _pckLoops, _pckTrack;
- UInt32 _pckTrackStartFrame, _pckTrackEndFrame;
- UInt32 _pckStopTime, _pckTrackDuration;
- };
-
- #endif
-
diff --git a/backends/platform/PalmOS/Src/cdaudio.h b/backends/platform/PalmOS/Src/cdaudio.h
deleted file mode 100644
index 7a3f5e56e4..0000000000
--- a/backends/platform/PalmOS/Src/cdaudio.h
+++ /dev/null
@@ -1,67 +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$
- *
- */
-
-#ifndef CDAUDIO_H
-#define CDAUDIO_H
-
-#include "common/system.h"
-
-// CD frames are 1/75 sec
-#define CD_FPS 75
-#define TO_MSECS(frame) ((UInt32)((frame) * 1000 / CD_FPS))
-
-// consider frame at 1/1000 sec
-#define FROM_MIN(mins) ((UInt32)((mins) * 60 * 1000))
-#define FROM_SEC(secs) ((UInt32)((secs) * 1000))
-
-class CDAudio {
-public:
- CDAudio() {
- _isInitialized = false;
- _volumeLevel = 100;
- };
-
- virtual bool init() = 0;
- virtual void release() = 0;
-
- // OSystem functions
- virtual bool poll() = 0;
- virtual void play(int track, int num_loops, int start_frame, int duration) = 0;
- virtual void stop() = 0;
- virtual void update() = 0;
-
- // volume in percent
- virtual void setVolume(int volume) { _volumeLevel = volume; }
- virtual int getVolume() const { return _volumeLevel; }
-
- virtual void upVolume(int value) {}
- virtual void downVolume(int value) {}
-
-protected:
- int _volumeLevel;
- bool _isInitialized;
-};
-
-#endif
diff --git a/backends/platform/PalmOS/Src/extend.cpp b/backends/platform/PalmOS/Src/extend.cpp
deleted file mode 100644
index 430563a302..0000000000
--- a/backends/platform/PalmOS/Src/extend.cpp
+++ /dev/null
@@ -1,109 +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 "PalmVersion.h"
-#include <stdlib.h>
-#include "globals.h"
-
-#include "modulesrsc.h"
-
-void PalmFatalError(const char *err) {
- WinSetDrawWindow(WinGetDisplayWindow());
- WinPalette(winPaletteSetToDefault,0,0,0);
- WinSetBackColor(0);
- WinEraseWindow();
- FrmCustomAlert(FrmFatalErrorAlert, err, 0,0);
-}
-
-void DrawStatus(Boolean show) {
- if (OPTIONS_TST(kOptDisableOnScrDisp))
- return;
-
- UInt8 x,y;
- UInt32 depth, d1;
- Boolean d2;
- WinScreenMode(winScreenModeGet, &d1, &d1, &depth, &d2);
- Int16 color = (show ? gVars->indicator.on : gVars->indicator.off);
-
- if (depth == 8) {
- UInt8 *src = (UInt8 *)BmpGetBits(WinGetBitmap(WinGetDisplayWindow()));
- src += gVars->screenPitch + 1;
- for (y=0; y < 4; y++) {
- for (x=0; x < 4; x++)
- src[x] = color;
-
- src += gVars->screenPitch;
- }
-
- } else if (depth == 16) {
- Int16 *src = (Int16 *)BmpGetBits(WinGetBitmap(WinGetDisplayWindow()));
- src += gVars->screenPitch + 1;
- for (y=0; y < 4; y++) {
- for (x=0; x < 4; x++)
- src[x] = color;
-
- src += gVars->screenPitch;
- }
- }
-}
-
-#ifndef PALMOS_ARM
-
-// This is now required since some classes are now very big :)
-#include "MemGlue.h"
-void *operator new(UInt32 size) {
- void *ptr = MemGluePtrNew(size);
- MemSet(ptr, 0, size);
- return ptr;
-}
-
-void *operator new [] (UInt32 size) {
- void *ptr = MemGluePtrNew(size);
- MemSet(ptr, 0, size);
- return ptr;
-}
-#elif defined(COMPILE_OS5) || defined(STDLIB_TRACE_MEMORY)
-
-void *operator new(UInt32 size) {
- void *ptr = malloc(size);
- MemSet(ptr, 0, size);
- return ptr;
-}
-
-void *operator new [] (UInt32 size) {
- void *ptr = malloc(size);
- MemSet(ptr, 0, size);
- return ptr;
-}
-
-void operator delete(void *ptr) throw() {
- if (ptr) free(ptr);
-}
-
-void operator delete[](void *ptr) throw() {
- if (ptr) free(ptr);
-}
-
-#endif
diff --git a/backends/platform/PalmOS/Src/features.h b/backends/platform/PalmOS/Src/features.h
deleted file mode 100644
index f82c7692fa..0000000000
--- a/backends/platform/PalmOS/Src/features.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __FEATURES_H__
-#define __FEATURES_H__
-
-enum {
- ftrBufferOverlay = 1000,
- ftrBufferBackup,
- ftrBufferHotSwap
-};
-
-#define FREE_FTR(num) \
- { \
- UInt32 ptr; \
- FtrGet(appFileCreator, num, &ptr); \
- if (ptr) FtrPtrFree(appFileCreator, num); \
- }
-
-#endif
diff --git a/backends/platform/PalmOS/Src/globals.h b/backends/platform/PalmOS/Src/globals.h
deleted file mode 100644
index 796832df82..0000000000
--- a/backends/platform/PalmOS/Src/globals.h
+++ /dev/null
@@ -1,114 +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$
- *
- */
-
-#ifndef GLOBALS_H
-#define GLOBALS_H
-
-#include <VFSMgr.h>
-#include "stuffs.h"
-
-enum {
- INIT_VIBRATOR = 1 << 0x00,
- INIT_PA1LIB = 1 << 0x01,
- INIT_ARM = 1 << 0x02,
- INIT_AUTOOFF = 1 << 0x03,
- INIT_GOLCD = 1 << 0x04
-};
-
-enum {
- FM_QUALITY_LOW = 0,
- FM_QUALITY_MED,
- FM_QUALITY_HI,
- FM_QUALITY_INI
-};
-
-typedef struct {
- // common parts
- UInt32 _4B, _2B;
-
- // 4 bytes part
- UInt32 startupMemory;
- UInt32 slkVersion;
- UInt32 options;
- UInt32 screenPitch;
-
- struct {
- FileRef logFile;
- UInt32 cacheSize;
- UInt16 volRefNum;
- UInt16 dummy;
- } VFS;
-
- // 2 bytes part
- UInt16 HRrefNum;
- UInt16 slkRefNum;
- Coord screenWidth, screenHeight; // silkarea shown
- Coord screenFullWidth, screenFullHeight; // silkarea hidden
- Int16 autoSave;
- struct {
- Int16 on;
- Int16 off;
- Int16 showLED;
- } indicator;
-
- // 1 byte part
- Boolean vibrator;
- Boolean stdPalette;
- Boolean filter;
- Boolean stylusClick;
- Boolean arrowKeys;
- UInt8 init;
- UInt8 palmVolume;
- UInt8 fmQuality;
- UInt8 advancedMode;
-
-} GlobalsDataType, *GlobalsDataPtr;
-
-extern GlobalsDataPtr gVars;
-
-#define VARS_EXPORT() gVars->_4B = 6; \
- gVars->_2B = 12;
-
-#define DO_VARS(z, t, o) \
- { Int8 *tmp = (Int8 *)gVars + o + 8; \
- for (Int8 cnt = 0; cnt < gVars->z; cnt++) \
- { UInt##t val = *((UInt##t *)tmp); \
- val = ByteSwap##t(val); \
- *((UInt##t *)tmp) = val; \
- tmp += (t / 8); \
- } \
- }
-
-#define OPTIONS_DEF() gVars->options
-
-#define HWR_INIT(x) (gVars->init & (x))
-#define HWR_SET(x) gVars->init |= (x)
-#define HWR_RST(x) gVars->init &= ~(x)
-#define HWR_RSTALL() gVars->init = 0
-#define HWR_GET() (gVars->init)
-
-#define ARM(x) gVars->arm[x]
-
-#endif
diff --git a/backends/platform/PalmOS/Src/i_zodiac.cpp b/backends/platform/PalmOS/Src/i_zodiac.cpp
deleted file mode 100644
index 20b06aa61f..0000000000
--- a/backends/platform/PalmOS/Src/i_zodiac.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <PalmOS.h>
-#include "extend.h"
-
-#ifndef DISABLE_TAPWAVE
-
-#include "tapwave.h"
-#include "i_zodiac.h"
-
-// _twBmpV3 = offscreen bitmap, must be set before this call
-Err ZodiacInit(void **ptrP, Int32 w, Int32 h) {
- Err e;
-
- TwGfxSurfaceInfoType surface = {
- sizeof(TwGfxSurfaceInfoType),
- w, h, w * 2,
- twGfxLocationAcceleratorMemory,
- twGfxPixelFormatRGB565_LE
- };
-
- e = SysSetOrientation(sysOrientationLandscape);
- e = TwGfxOpen((TwGfxType **)&_twGfxLib, NULL);
- e = TwGfxAllocSurface( (TwGfxType *)_twGfxLib,
- (TwGfxSurfaceType **)&_twSrc,
- &surface);
-
- e = TwGfxGetPalmDisplaySurface( (TwGfxType *)_twGfxLib,
- (TwGfxSurfaceType **)&_twDst);
-
- return e;
-}
-
-Err ZodiacRelease(void **ptrP) {
- Err e = errNone;
-
- TwGfxFreeSurface((TwGfxSurfaceType *)_twSrc);
- TwGfxClose((TwGfxType *)_twGfxLib);
-
- return e;
-}
-
-#endif
diff --git a/backends/platform/PalmOS/Src/i_zodiac.h b/backends/platform/PalmOS/Src/i_zodiac.h
deleted file mode 100644
index 96a373a22e..0000000000
--- a/backends/platform/PalmOS/Src/i_zodiac.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _I_ZODIAC_H_
-#define _I_ZODIAC_H_
-
-#define _twGfxLib ptrP[0]
-#define _twSrc ptrP[1]
-#define _twDst ptrP[2]
-#define _twBmpV3 ptrP[3]
-
-Err ZodiacInit(void **ptrP, Int32 w, Int32 h);
-Err ZodiacRelease(void **ptrP);
-
-#endif
diff --git a/backends/platform/PalmOS/Src/init_golcd.cpp b/backends/platform/PalmOS/Src/init_golcd.cpp
deleted file mode 100644
index b09d3b104e..0000000000
--- a/backends/platform/PalmOS/Src/init_golcd.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-#include <PalmOS.h>
-#include <PalmGoLCD.h>
-
-#include "init_golcd.h"
-
-// you can use this handle directly
-MemHandle gGoLcdH;
-
-Err GoLCDInit(MemHandle *goLcdH) {
- if (!goLcdH)
- return sysErrParamErr;
-
- Err e;
- UInt16 refNum;
- Boolean loaded = false;
- *goLcdH = NULL;
-
- if (e = SysLibFind(goLcdLibName, &refNum))
- loaded = !(e = SysLibLoad(goLcdLibType, goLcdLibCreator, &refNum));
-
- if (!e)
- if ((e = GoLcdLibOpen(refNum)))
- SysLibRemove(refNum);
-
- if (!e) {
- MemHandle lcdH = MemHandleNew(sizeof(GoLCDType));
- GoLCDType *lcdP = (GoLCDType *)MemHandleLock(lcdH);
- MemSet(lcdP, MemHandleSize(lcdH), 0);
- lcdP->refNum = refNum;
- lcdP->timeout = GoLcdGetTimeout(refNum, goLcdPenTapMode);
- MemPtrUnlock(lcdP);
- *goLcdH = lcdH;
- }
-
- return e;
-}
-
-Err GoLCDRelease(MemHandle goLcdH) {
- if (!goLcdH)
- return sysErrParamErr;
-
- Err e;
- GoLCDType *lcdP = (GoLCDType *)MemHandleLock(goLcdH);
- if (lcdP->refNum != sysInvalidRefNum)
- if (!(e = GoLcdLibClose(lcdP->refNum)))
- e = SysLibRemove(lcdP->refNum);
-
- MemPtrUnlock(lcdP);
- MemHandleFree(goLcdH);
-
- return e;
-}
-
-Boolean GoLCDPointInBounds(MemHandle goLcdH, Coord x, Coord y) {
- Boolean inBounds = false;
-
- if (!goLcdH)
- return inBounds;
-
- GoLCDType *lcdP = (GoLCDType *)MemHandleLock(goLcdH);
- inBounds = (lcdP->active && RctPtInRectangle(x, y, &(lcdP->bounds)));
- MemPtrUnlock(lcdP);
-
- return inBounds;
-}
-
-void GoLCDSetInk(MemHandle goLcdH, RGBColorType *inkP) {
- if (!goLcdH)
- return;
-
- GoLCDType *lcdP = (GoLCDType *)MemHandleLock(goLcdH);
- MemMove(&(lcdP->ink), inkP, sizeof(RGBColorType));
- MemPtrUnlock(lcdP);
-}
-
-void GoLCDSetBounds(MemHandle goLcdH, RectangleType *boundsP) {
- if (!goLcdH)
- return;
-
- GoLCDType *lcdP = (GoLCDType *)MemHandleLock(goLcdH);
- MemMove(&(lcdP->bounds), boundsP, sizeof(RectangleType));
- MemPtrUnlock(lcdP);
-}
-
-void GoLCDActivate(MemHandle goLcdH, Boolean active) {
- if (!goLcdH)
- return;
-
- GoLCDType *lcdP = (GoLCDType *)MemHandleLock(goLcdH);
-
- if (active) {
- if (!lcdP->active) {
- lcdP->active = true;
- GoLcdSetInkState(lcdP->refNum, goLcdInkEnabled, goLcdColorOverride, &(lcdP->ink));
- GoLcdSetBounds(lcdP->refNum, &(lcdP->bounds));
- GoLcdSetGsiState(lcdP->refNum, goLcdGsiNormal, goLcdColorDefault, 0);
- GoLcdSetTimeout(lcdP->refNum, goLcdPenTapMode, lcdP->timeout);
- GoLcdSetStatus(lcdP->refNum, goLcdEnabled);
- }
-
- } else {
- lcdP->active = false;
- GoLcdSetInkState(lcdP->refNum, goLcdInkDisabled, goLcdColorDefault, 0);
- GoLcdSetStatus(lcdP->refNum, goLcdDisabled);
- }
-
- MemPtrUnlock(lcdP);
-}
-
-Boolean GoLCDToggle(MemHandle goLcdH) {
- if (!goLcdH)
- return;
-
- Boolean active;
- GoLCDType *lcdP = (GoLCDType *)MemHandleLock(goLcdH);
- active = lcdP->active;
- MemPtrUnlock(lcdP);
-
- GoLCDActivate(goLcdH, !active);
- return (!active);
-}
diff --git a/backends/platform/PalmOS/Src/init_golcd.h b/backends/platform/PalmOS/Src/init_golcd.h
deleted file mode 100644
index 7750a13a52..0000000000
--- a/backends/platform/PalmOS/Src/init_golcd.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef INIT_GOLCD_H
-#define INIT_GOLCD_H
-
-typedef struct {
- Boolean active;
- UInt16 refNum;
- RectangleType bounds;
- RGBColorType ink;
- UInt32 timeout;
-} GoLCDType;
-
-extern MemHandle gGoLcdH;
-
-Err GoLCDInit(MemHandle *goLcdH);
-Err GoLCDRelease(MemHandle goLcdH);
-void GoLCDSetInk(MemHandle goLcdH, RGBColorType *inkP);
-void GoLCDSetBounds(MemHandle goLcdH, RectangleType *boundsP);
-void GoLCDActivate(MemHandle goLcdH, Boolean active);
-Boolean GoLCDToggle(MemHandle goLcdH);
-Boolean GoLCDPointInBounds(MemHandle goLcdH, Coord x, Coord y);
-
-#endif
diff --git a/backends/platform/PalmOS/Src/init_mathlib.cpp b/backends/platform/PalmOS/Src/init_mathlib.cpp
deleted file mode 100644
index 1ea39c3e0a..0000000000
--- a/backends/platform/PalmOS/Src/init_mathlib.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <PalmOS.h>
-
-#include "globals.h"
-#include "init_mathlib.h"
-#include "mathlib.h"
-
-Err MathlibInit() {
- Err e;
-
- if ((e = SysLibFind(MathLibName, &MathLibRef)))
- if (e == sysErrLibNotFound) // couldn't find lib
- e = SysLibLoad(LibType, MathLibCreator, &MathLibRef);
-
- if (e) return sysErrLibNotFound;
-
- e = MathLibOpen(MathLibRef, MathLibVersion);
- return e;
-}
-
-void MathlibRelease() {
- UInt16 useCount;
-
- if (MathLibRef != sysInvalidRefNum) {
- MathLibClose(MathLibRef, &useCount);
-
- if (!useCount)
- SysLibRemove(MathLibRef);
- }
-}
diff --git a/backends/platform/PalmOS/Src/init_mathlib.h b/backends/platform/PalmOS/Src/init_mathlib.h
deleted file mode 100644
index 1901e1330d..0000000000
--- a/backends/platform/PalmOS/Src/init_mathlib.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef INIT_MATHLIB_H
-#define INIT_MATHLIB_H
-
-Err MathlibInit();
-void MathlibRelease();
-
-#endif
diff --git a/backends/platform/PalmOS/Src/init_pa1lib.cpp b/backends/platform/PalmOS/Src/init_pa1lib.cpp
deleted file mode 100644
index d5b0340cae..0000000000
--- a/backends/platform/PalmOS/Src/init_pa1lib.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include <PalmOS.h>
-#include <Sonyclie.h>
-
-#include "pa1lib.h"
-#include "init_pa1lib.h"
-
-void *sndStateOnFuncP = NULL;
-void *sndStateOffFuncP = NULL;
-
-#define SndStateOn(a,b,c) if (sndStateOnFuncP)((sndStateOnType)(sndStateOnFuncP))(a, b, c);
-#define SndStateOff(a) if (sndStateOffFuncP)((sndStateOffType)(sndStateOffFuncP))(a);
-
-void Pa1libInit(UInt16 vol) {
- Pa1Lib_Open();
-
- // Doesn't work on T4xx and T6xx series ?
- FtrGet(sonySysFtrCreatorSystem, sonySysFtrNumSystemAOutSndStateOnHandlerP, (UInt32*) &sndStateOnFuncP);
- FtrGet(sonySysFtrCreatorSystem, sonySysFtrNumSystemAOutSndStateOffHandlerP, (UInt32*) &sndStateOffFuncP);
-
- SndStateOn(aOutSndKindSp, vol, vol);
- SndStateOn(aOutSndKindHp, vol, vol);
-
- Pa1Lib_devHpVolume(vol, vol);
- Pa1Lib_devSpVolume(vol);
-}
-
-void Pa1libRelease() {
- SndStateOff(aOutSndKindSp);
- SndStateOff(aOutSndKindHp);
-
- Pa1Lib_Close();
-}
diff --git a/backends/platform/PalmOS/Src/init_pa1lib.h b/backends/platform/PalmOS/Src/init_pa1lib.h
deleted file mode 100644
index d5be11d278..0000000000
--- a/backends/platform/PalmOS/Src/init_pa1lib.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef INIT_PA1LIB_H
-#define INIT_PA1LIB_H
-
-// need to move this on a .h file
-#define sonySysFileCSystem 'SsYs' /* Sony overall System */
-#define sonySysFtrCreatorSystem sonySysFileCSystem
-
-#define sonySysFtrNumSystemBase 10000
-#define sonySysFtrNumSystemAOutSndStateOnHandlerP (sonySysFtrNumSystemBase + 4)
-#define sonySysFtrNumSystemAOutSndStateOffHandlerP (sonySysFtrNumSystemBase + 5)
-
-typedef void (*sndStateOnType) (UInt8 /* kind */, UInt8 /* L volume 0-31 */, UInt8 /* R volume 0-31 */);
-typedef void (*sndStateOffType) (UInt8 /* kind */);
-
-/* kind */
-#define aOutSndKindSp (0) /* Speaker volume */
-#define aOutSndKindHp (2) /* HeadPhone volume */
-
-void Pa1libInit(UInt16 vol);
-void Pa1libRelease();
-
-#endif
diff --git a/backends/platform/PalmOS/Src/init_palmos.cpp b/backends/platform/PalmOS/Src/init_palmos.cpp
deleted file mode 100644
index 3a72382362..0000000000
--- a/backends/platform/PalmOS/Src/init_palmos.cpp
+++ /dev/null
@@ -1,172 +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 <PalmOS.h>
-
-#include "globals.h"
-#include "init_palmos.h"
-
-static UInt16 autoOffDelay;
-
-void PalmInit(UInt8 init) {
- // set screen depth
- UInt32 depth = 8;
- WinScreenMode(winScreenModeSet, NULL, NULL, &depth, NULL);
-
- if (init & INIT_AUTOOFF) {
- autoOffDelay = SysSetAutoOffTime(0);
- EvtResetAutoOffTimer();
- }
-
-}
-
-void PalmRelease(UInt8 init) {
- if (init & INIT_AUTOOFF) {
- SysSetAutoOffTime(autoOffDelay);
- EvtResetAutoOffTimer();
- }
-}
-
-Err PalmHRInit(UInt32 depth) {
- Err e;
- UInt32 width = 320;
- UInt32 height = 320;
- Boolean color = true;
-
- e = WinScreenMode (winScreenModeSet, &width, &height, &depth, &color);
-
- if (!e) {
- UInt32 attr;
- WinScreenGetAttribute(winScreenDensity, &attr);
- e = (attr != kDensityDouble);
- }
-
- return e;
-}
-
-void PalmHRRelease() {
- // should i do something here ?
-}
-
-UInt8 PalmScreenSize(Coord *stdw, Coord *stdh, Coord *fullw, Coord *fullh) {
- UInt32 ftr;
- UInt8 mode = 0;
-
- Coord sw = 160;
- Coord sh = 160;
-
- // Hi-Density present ?
- if (!FtrGet(sysFtrCreator, sysFtrNumWinVersion, &ftr)) {
- if (ftr >= 4) {
- sw = 320;
- sh = 320;
- }
- }
-
- Coord fw = sw;
- Coord fh = sh;
-
- // if feature set, not set on Garmin iQue3600 ???
- if (!(FtrGet(sysFtrCreator, sysFtrNumInputAreaFlags, &ftr))) {
- if (ftr & grfFtrInputAreaFlagCollapsible) {
- UInt16 curOrientation = SysGetOrientation();
-
- if (curOrientation == sysOrientationLandscape ||
- curOrientation == sysOrientationReverseLandscape
- )
- mode = PALM_LANDSCAPE;
- else
- mode = PALM_PORTRAIT;
-
- PINSetInputTriggerState(pinInputTriggerEnabled);
- PINSetInputAreaState(pinInputAreaClosed);
- StatHide();
-
- WinGetDisplayExtent(&fw, &fh);
- fw *= 2;
- fh *= 2;
-
- StatShow();
- PINSetInputAreaState(pinInputAreaOpen);
- PINSetInputTriggerState(pinInputTriggerDisabled);
- }
- }
-
- if (stdw) *stdw = sw;
- if (stdh) *stdh = sh;
- if (fullw) *fullw = fw;
- if (fullh) *fullh = fh;
-
- return mode;
-}
-
-void PalmGetMemory(UInt32* storageMemoryP, UInt32* dynamicMemoryP, UInt32 *storageFreeP, UInt32 *dynamicFreeP) {
- UInt32 free, max;
-
- Int16 i;
- Int16 nCards;
- UInt16 cardNo;
- UInt16 heapID;
-
- UInt32 storageMemory = 0;
- UInt32 dynamicMemory = 0;
- UInt32 storageFree = 0;
- UInt32 dynamicFree = 0;
-
- // Iterate through each card to support devices with multiple cards.
- nCards = MemNumCards();
-
- for (cardNo = 0; cardNo < nCards; cardNo++) {
- // Iterate through the RAM heaps on a card (excludes ROM).
- for (i=0; i< MemNumRAMHeaps(cardNo); i++) {
- // Obtain the ID of the heap.
- heapID = MemHeapID(cardNo, i);
- // Calculate the total memory and free memory of the heap.
- MemHeapFreeBytes(heapID, &free, &max);
-
- // If the heap is dynamic, increment the dynamic memory total.
- if (MemHeapDynamic(heapID)) {
- dynamicMemory += MemHeapSize(heapID);
- dynamicFree += free;
-
- // The heap is nondynamic (storage ?).
- } else {
- storageMemory += MemHeapSize(heapID);
- storageFree += free;
- }
- }
- }
- // Reduce the stats to KB. Round the results.
- dynamicMemory = dynamicMemory / 1024L;
- storageMemory = storageMemory / 1024L;
-
- dynamicFree = dynamicFree / 1024L;
- storageFree = storageFree / 1024L;
-
- if (dynamicMemoryP) *dynamicMemoryP = dynamicMemory;
- if (storageMemoryP) *storageMemoryP = storageMemory;
- if (dynamicFreeP) *dynamicFreeP = dynamicFree;
- if (storageFreeP) *storageFreeP = storageFree;
-}
diff --git a/backends/platform/PalmOS/Src/init_sony.cpp b/backends/platform/PalmOS/Src/init_sony.cpp
deleted file mode 100644
index f6728d08b3..0000000000
--- a/backends/platform/PalmOS/Src/init_sony.cpp
+++ /dev/null
@@ -1,163 +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 <PalmOS.h>
-#include <SonyClie.h>
-#include "init_sony.h"
-
-UInt16 SilkInit(UInt32 *retVersion) {
- SonySysFtrSysInfoP sonySysFtrSysInfoP;
- UInt32 version;
- UInt16 slkRefNum;
- Err e;
-
- // Sony HiRes+
- if (!(e = FtrGet(sonySysFtrCreator, sonySysFtrNumSysInfoP, (UInt32*)&sonySysFtrSysInfoP))) {
- if (sonySysFtrSysInfoP->libr & sonySysFtrSysInfoLibrSilk) {
-
- if ((e = SysLibFind(sonySysLibNameSilk, &slkRefNum)))
- if (e == sysErrLibNotFound)
- e = SysLibLoad(sonySysFileTSilkLib, sonySysFileCSilkLib, &slkRefNum);
-
- if (!e) {
- e = FtrGet(sonySysFtrCreator, sonySysFtrNumVskVersion, &version);
- if (e) {
- // v1 = NR
- e = SilkLibOpen(slkRefNum);
- if (!e) version = vskVersionNum1;
-
- } else {
- // v2 = NX/NZ
- // v3 = UX...
- e = VskOpen(slkRefNum);
- }
- }
- } else
- e = sysErrLibNotFound;
- }
-
- if (e) {
- version = 0;
- slkRefNum = sysInvalidRefNum;
- }
-
- *retVersion = version;
- return slkRefNum;
-}
-
-void SilkRelease(UInt16 slkRefNum) {
- if (slkRefNum != sysInvalidRefNum)
- SilkLibClose(slkRefNum);
-}
-
-UInt16 SonyHRInit(UInt32 depth) {
- SonySysFtrSysInfoP sonySysFtrSysInfoP;
- Err e;
- UInt16 HRrefNum;
-
- // test if sonyHR is present
- if (!(e = FtrGet(sonySysFtrCreator, sonySysFtrNumSysInfoP, (UInt32*)&sonySysFtrSysInfoP))) {
- if (sonySysFtrSysInfoP->libr & sonySysFtrSysInfoLibrHR) { // HR available
-
- if ((e = SysLibFind(sonySysLibNameHR, &HRrefNum)))
- if (e == sysErrLibNotFound) // can't find lib
- e = SysLibLoad( 'libr', sonySysFileCHRLib, &HRrefNum);
-
- // Now we can use HR lib. Executes Open library.
- if (!e) e = HROpen(HRrefNum);
- }
- }
-
- if (e) HRrefNum = sysInvalidRefNum;
-
- if (HRrefNum != sysInvalidRefNum) {
- UInt32 width = hrWidth;
- UInt32 height = hrHeight;
- Boolean color = true;
-
- e = HRWinScreenMode(HRrefNum, winScreenModeSet, &width, &height, &depth, &color);
- // error ? release and return an invalid reference number
- if (e) {
- SonyHRRelease(HRrefNum);
- HRrefNum = sysInvalidRefNum;
- }
- }
-
- return HRrefNum;
-}
-
-void SonyHRRelease(UInt16 HRrefNum) {
- if (HRrefNum != sysInvalidRefNum) {
- HRClose(HRrefNum);
- //SysLibRemove(HRrefNum); // never call this !!
- }
-}
-
-UInt8 SonyScreenSize(UInt16 HRrefNum, Coord *stdw, Coord *stdh, Coord *fullw, Coord *fullh) {
- UInt32 version;
- UInt16 slkRefNum;
- UInt8 mode = 0;
-
- Coord sw = 160;
- Coord sh = 160;
- Coord fw = sw;
- Coord fh = sh;
-
- if (HRrefNum != sysInvalidRefNum) {
- sw = hrWidth;
- sh = hrHeight;
- fw = sw;
- fh = sh;
-
- slkRefNum = SilkInit(&version);
-
- if (slkRefNum != sysInvalidRefNum) {
- if (version == vskVersionNum1) {
- SilkLibEnableResize(slkRefNum);
- SilkLibResizeDispWin(slkRefNum, silkResizeMax);
- HRWinGetWindowExtent(HRrefNum, &fw, &fh);
- SilkLibResizeDispWin(slkRefNum, silkResizeNormal);
- SilkLibDisableResize(slkRefNum);
- mode = SONY_PORTRAIT;
-
- } else {
- VskSetState(slkRefNum, vskStateEnable, (version == vskVersionNum2 ? vskResizeVertically : vskResizeHorizontally));
- VskSetState(slkRefNum, vskStateResize, vskResizeNone);
- HRWinGetWindowExtent(HRrefNum, &fw, &fh);
- VskSetState(slkRefNum, vskStateResize, vskResizeMax);
- VskSetState(slkRefNum, vskStateEnable, vskResizeDisable);
- mode = (version == vskVersionNum3 ? SONY_LANDSCAPE : SONY_PORTRAIT);
- }
- SilkRelease(slkRefNum);
- }
- }
-
- *stdw = sw;
- *stdh = sh;
- *fullw = fw;
- *fullh = fh;
-
- return mode;
-}
diff --git a/backends/platform/PalmOS/Src/init_stuffs.cpp b/backends/platform/PalmOS/Src/init_stuffs.cpp
deleted file mode 100644
index 51bfe755eb..0000000000
--- a/backends/platform/PalmOS/Src/init_stuffs.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-#include <PalmOS.h>
-
-#ifndef DISABLE_SONY
-#include <SonyClie.h>
-#endif
-
-#include <PalmNavigator.h>
-#include <HsExtCommon.h>
-#include <HsNavCommon.h>
-#include <PalmGoLCD.h>
-
-#include "globals.h" // for OPTIONS_DEF()
-#include "init_stuffs.h"
-#include "stuffs.h"
-
-#ifndef DISABLE_TAPWAVE
-#define __TWKEYS_H__ // bad hack
-#include "tapwave.h"
-#endif
-
-#ifndef DISABLE_PA1LIB
-#include "Pa1Lib.h"
-#endif
-
-#ifndef DISABLE_LIGHTSPEED
-#include "lightspeed_public.h"
-#endif
-
-// TODO : check the depth to set correct value
-// works only for 8bit for now
-UInt32 StuffsGetPitch(Coord fullw) {
- UInt32 pitch = 0;
-
- if (OPTIONS_TST(kOptModeHiDensity)) {
- WinScreenGetAttribute(winScreenRowBytes, &pitch);
-
- // FIXME : hack for TT3 simulator (and real ?) return 28 on landscape mode
- if (pitch < fullw)
- pitch = fullw;
-
- } else {
- pitch = fullw;
- }
-
- return pitch;
-}
-
-void *StuffsForceVG() {
- // create an empty form to force the VG to be shown
- FormType *frmP = FrmNewForm(4567, NULL, 0,0,0,0, false, 0, 0, 0);
- FrmDrawForm(frmP);
- return frmP;
-}
-
-void StuffsReleaseVG(void *vg) {
- FrmDeleteForm((FormPtr)vg);
-}
-
-void StuffsGetFeatures() {
- UInt32 ulProcessorType, manufacturer, version, depth;
- Boolean color;
-
-#ifndef DISABLE_TAPWAVE
- // Tapwave Zodiac libs ?
- if (!FtrGet(sysFileCSystem, sysFtrNumOEMCompanyID, &manufacturer))
- if (manufacturer == twCreatorID) {
- OPTIONS_SET(kOptDeviceZodiac);
- OPTIONS_SET(kOpt5WayNavigatorV2);
- }
-#endif
-
- // Hi-Density present ?
- if (!FtrGet(sysFtrCreator, sysFtrNumWinVersion, &version))
- if (version >= 4)
- OPTIONS_SET(kOptModeHiDensity);
-
- // OS5 ?
- if (!FtrGet(sysFtrCreator, sysFtrNumROMVersion, &version))
- if (version >= kOS5Version)
- OPTIONS_SET(kOptDeviceOS5);
-
- // ARM ?
- if (!FtrGet(sysFileCSystem, sysFtrNumProcessorID, &ulProcessorType))
- if (sysFtrNumProcessorIsARM(ulProcessorType))
- OPTIONS_SET(kOptDeviceARM);
- else if (ulProcessorType == sysFtrNumProcessorx86)
- OPTIONS_SET(kOptDeviceProcX86);
-
- // 5Way Navigator
- if (!FtrGet(hsFtrCreator, hsFtrIDNavigationSupported, &version)) {
- if (version >= 2)
- OPTIONS_SET(kOpt5WayNavigatorV2);
-
- } else if (!FtrGet(sysFtrCreator, sysFtrNumFiveWayNavVersion, &version)) {
- if (version >= 2)
- OPTIONS_SET(kOpt5WayNavigatorV2);
- else
- OPTIONS_SET(kOpt5WayNavigatorV1);
-
- } else if (!FtrGet(navFtrCreator, navFtrVersion, &version)) {
- if (version >= 2)
- OPTIONS_SET(kOpt5WayNavigatorV2);
- else
- OPTIONS_SET(kOpt5WayNavigatorV1);
- }
-
- // Palm Sound API ?
- if (!FtrGet(sysFileCSoundMgr, sndFtrIDVersion, &version))
- if (version >= 1)
- OPTIONS_SET(kOptPalmSoundAPI);
-
-#ifndef DISABLE_PA1LIB
- // Sony Pa1 Sound API
- if (Pa1Lib_Open()) {
- OPTIONS_SET(kOptSonyPa1LibAPI);
- Pa1Lib_Close();
- }
-#endif
-
- // GoLCD
- if (!FtrGet(goLcdLibCreator, goLcdLibFtrNum, &version))
- OPTIONS_SET(kOptGoLcdAPI);
-
-#ifndef DISABLE_LIGHTSPEED
- // Lightspeed
- if (LS_Installed())
- OPTIONS_SET(kOptLightspeedAPI);
-#endif
-
- // check for 16bit mode
- if (!WinScreenMode(winScreenModeGetSupportedDepths, NULL, NULL, &depth, &color))
- OPTIONS_SET(((depth & 0x8000) ? kOptMode16Bit : kOptNone));
-
-}
diff --git a/backends/platform/PalmOS/Src/init_stuffs.h b/backends/platform/PalmOS/Src/init_stuffs.h
deleted file mode 100644
index 124510eeac..0000000000
--- a/backends/platform/PalmOS/Src/init_stuffs.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef INIT_STUFFS_H
-#define INIT_STUFFS_H
-
-#define kOS5Version sysMakeROMVersion(5,0,0,sysROMStageRelease,0)
-
-void StuffsGetFeatures();
-UInt32 StuffsGetPitch(Coord fullw);
-void *StuffsForceVG();
-void StuffsReleaseVG(void *vg);
-
-#endif
diff --git a/backends/platform/PalmOS/Src/launcher/app.cpp b/backends/platform/PalmOS/Src/launcher/app.cpp
deleted file mode 100644
index 9bb1c1479b..0000000000
--- a/backends/platform/PalmOS/Src/launcher/app.cpp
+++ /dev/null
@@ -1,360 +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 <PalmOS.h>
-#include <SonyClie.h>
-#include <SysGlue.h>
-
-#include "StarterRsc.h"
-#include "palmdefs.h"
-#include "start.h"
-#include "globals.h"
-#include "rumble.h"
-
-#include "mathlib.h"
-#include "formCards.h"
-#include "games.h"
-
-#include "modules.h"
-#include "init_mathlib.h"
-#include "init_sony.h"
-#include "init_palmos.h"
-#include "init_stuffs.h"
-
-/***********************************************************************
- *
- * FUNCTION: AppStart
- *
- * DESCRIPTION: Get the current application's preferences.
- *
- * PARAMETERS: nothing
- *
- * RETURNED: Err value 0 if nothing went wrong
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-static Err AppStartCheckHRmode()
-{
- Err e = errNone;
- UInt32 depth = (OPTIONS_TST(kOptMode16Bit) && OPTIONS_TST(kOptDeviceOS5)) ? 16 : 8;
-
- // try to init Sony HR mode then Palm HR mode
- gVars->HRrefNum = SonyHRInit(depth);
-
- if (gVars->HRrefNum == sysInvalidRefNum) {
- if (e = PalmHRInit(depth))
- FrmCustomAlert(FrmErrorAlert,"Your device doesn't seem to support Hi-Res or 256color mode.",0,0);
- } else {
- OPTIONS_SET(kOptDeviceClie);
- }
-
- return e;
-}
-
-static void AppStopHRMode() {
- if (gVars->HRrefNum != sysInvalidRefNum)
- SonyHRRelease(gVars->HRrefNum);
- else
- PalmHRRelease();
-}
-
-static Err AppStartCheckNotify() {
- UInt32 romVersion;
- Err err;
-
- err = FtrGet(sysFtrCreator, sysFtrNumNotifyMgrVersion, &romVersion);
- if (!err) {
- UInt16 cardNo;
- LocalID dbID;
-
- err = SysCurAppDatabase(&cardNo, &dbID);
- if (!err) {
- SysNotifyRegister(cardNo, dbID, sysNotifyVolumeMountedEvent, NULL, sysNotifyNormalPriority, NULL);
- SysNotifyRegister(cardNo, dbID, sysNotifyVolumeUnmountedEvent, NULL, sysNotifyNormalPriority, NULL);
- SysNotifyRegister(cardNo, dbID, sonySysNotifyMsaEnforceOpenEvent, NULL, sysNotifyNormalPriority, NULL);
- SysNotifyRegister(cardNo, dbID, sysNotifyDisplayResizedEvent, NULL, sysNotifyNormalPriority, NULL);
- }
- }
-
- return err;
-}
-
-static Err AppStartLoadSkin() {
- Err err = errNone;
-
- // if skin defined, check if the db still exists
- if (gPrefs->skin.dbID) {
- UInt32 type, creator;
-
- // check if the DB still exists
- DmSearchStateType state;
- UInt16 cardNo;
- LocalID dbID;
- Boolean found = false;
- err = DmGetNextDatabaseByTypeCreator(true, &state, 'skin', appFileCreator, false, &cardNo, &dbID);
- while (!err && dbID && !found) {
- found = (cardNo == gPrefs->skin.cardNo && dbID == gPrefs->skin.dbID);
- err = DmGetNextDatabaseByTypeCreator(false, &state, 'skin', appFileCreator, false, &cardNo, &dbID);
- }
-
- if (found) {
- // remember to check version for next revision of the skin
- err = DmDatabaseInfo (gPrefs->skin.cardNo, gPrefs->skin.dbID, gPrefs->skin.nameP, 0, 0, 0, 0, 0, 0, 0,0, &type, &creator);
- if (!err)
- if (type != 'skin' || creator != appFileCreator)
- err = dmErrInvalidParam;
- }
-
- if (!found || err)
- MemSet(&(gPrefs->skin),sizeof(SkinInfoType),0);
- }
-
- // No skin ? try to get the first one
- if (!gPrefs->skin.dbID) {
- DmSearchStateType stateInfo;
-
- err = DmGetNextDatabaseByTypeCreator(true, &stateInfo, 'skin', appFileCreator, false, &gPrefs->skin.cardNo, &gPrefs->skin.dbID);
- if (!err)
- err = DmDatabaseInfo (gPrefs->skin.cardNo, gPrefs->skin.dbID, gPrefs->skin.nameP, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- }
-
- return err;
-}
-
-static Err AppStartCheckMathLib() {
- Err e = MathlibInit();
-
- switch (e) {
- case errNone:
- break;
- case sysErrLibNotFound:
- FrmCustomAlert(FrmErrorAlert,"Can't find MathLib !",0,0);
- break;
- default:
- FrmCustomAlert(FrmErrorAlert,"Can't open MathLib !",0,0);
- break;
- }
-
- return e;
-}
-
-static void AppStopMathLib() {
- MathlibRelease();
-}
-
-static void AppStartCheckScreenSize() {
- Coord sw, sh, fw, fh;
- UInt8 mode;
-
- OPTIONS_RST(kOptCollapsible);
- OPTIONS_RST(kOptModeWide);
- OPTIONS_RST(kOptModeLandscape);
- OPTIONS_RST(kOptModeRotatable);
-
- // we are on a sony device
- if (OPTIONS_TST(kOptDeviceClie)) {
- mode = SonyScreenSize(gVars->HRrefNum, &sw, &sh, &fw, &fh);
- if (mode) {
- OPTIONS_SET(kOptModeWide);
- OPTIONS_SET((mode == SONY_LANDSCAPE) ? kOptModeLandscape : kOptNone);
- }
- } else {
- mode = PalmScreenSize(&sw, &sh, &fw, &fh);
- if (mode) {
- OPTIONS_SET(kOptCollapsible);
- OPTIONS_SET(kOptModeWide);
- OPTIONS_SET((mode == PALM_LANDSCAPE) ? kOptModeLandscape : kOptNone);
- // TODO: doesn't work with Sony
- OPTIONS_SET(SysGlueTrapExists(pinSysSetOrientation) ? kOptModeRotatable :kOptNone);
- }
- }
-
- gVars->screenWidth = sw;
- gVars->screenHeight = sh;
-
- gVars->screenFullWidth = fw;
- gVars->screenFullHeight = fh;
-}
-
-#define max(id,value) gVars->memory[id] = (gVars->memory[id] < value ? value : gVars->memory[id])
-#define min(id,value) gVars->memory[id] = (gVars->memory[id] > value ? value : gVars->memory[id])
-#define threshold 700
-
-static void AppStartSetMemory() {
- UInt32 mem, def;
- PalmGetMemory(0,0,0,&mem);
- def = (mem > threshold) ? (mem - threshold) * 1024 : 0;
- gVars->startupMemory = mem;
-}
-
-#undef threshold
-#undef min
-#undef max
-
-Err AppStart(void) {
- UInt16 dataSize, checkSize = 0;
- Err error;
-
-#ifndef _DEBUG_ENGINE
- // delete old databases
- ModDelete();
-#endif
-
- // allocate global variables space
- dataSize = sizeof(GlobalsDataType);
- gVars = (GlobalsDataType *)MemPtrNew(dataSize);
- MemSet(gVars, dataSize, 0);
-
- gVars->indicator.on = 255;
- gVars->indicator.off = 0;
- gVars->HRrefNum = sysInvalidRefNum;
- gVars->VFS.volRefNum = vfsInvalidVolRef;
- gVars->slkRefNum = sysInvalidRefNum;
- gVars->options = kOptNone;
-
- // set memory required by the differents engines
- AppStartSetMemory();
- StuffsGetFeatures();
-
- // allocate prefs space
- dataSize = sizeof(GlobalsPreferenceType);
- gPrefs = (GlobalsPreferenceType *)MemPtrNew(dataSize);
- MemSet(gPrefs, dataSize, 0);
-
- // Read the saved preferences / saved-state information.
- if (PrefGetAppPreferences(appFileCreator, appPrefID, NULL, &checkSize, true) == noPreferenceFound || checkSize != dataSize) {
- // reset all elements
- MemSet(gPrefs, dataSize, 0);
-
- gPrefs->card.volRefNum = vfsInvalidVolRef;
- gPrefs->card.cacheSize = 4096;
- gPrefs->card.useCache = true;
- gPrefs->card.showLED = true;
- gPrefs->card.autoDetect = true;
-
- gPrefs->autoOff = true;
- gPrefs->vibrator = RumbleExists();
- gPrefs->debug = false;
- gPrefs->exitLauncher = true;
- gPrefs->stdPalette = OPTIONS_TST(kOptDeviceOS5);
- gPrefs->stylusClick = true;
-
- } else {
- PrefGetAppPreferences(appFileCreator, appPrefID, gPrefs, &dataSize, true);
- }
-
- if (!OPTIONS_TST(kOptDeviceARM)) {
- error = AppStartCheckMathLib();
- if (error) return (error);
- }
-
- error = AppStartCheckHRmode();
- if (error) return (error);
-
- bDirectMode = (AppStartLoadSkin() != errNone);
-
- // if volref previously defined, check if it's a valid one
- if (gPrefs->card.volRefNum != vfsInvalidVolRef) {
- VolumeInfoType volInfo;
- Err err = VFSVolumeInfo(gPrefs->card.volRefNum, &volInfo);
- if (err)
- gPrefs->card.volRefNum = parseCards();
- }
- else
- gPrefs->card.volRefNum = parseCards();
- if (gPrefs->card.volRefNum != vfsInvalidVolRef)
- CardSlotCreateDirs();
-
- // open games database
- error = GamOpenDatabase();
- if (error) return (error);
- GamImportDatabase();
-
- AppStartCheckScreenSize();
- AppStartCheckNotify(); // not fatal error if not avalaible
-
- return error;
-}
-
-/***********************************************************************
- *
- * FUNCTION: AppStop
- *
- * DESCRIPTION: Save the current state of the application.
- *
- * PARAMETERS: nothing
- *
- * RETURNED: nothing
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-static Err AppStopCheckNotify()
-{
- UInt32 romVersion;
- Err err;
-
- err = FtrGet(sysFtrCreator, sysFtrNumNotifyMgrVersion, &romVersion);
- if (!err) {
- UInt16 cardNo;
- LocalID dbID;
-
- err = SysCurAppDatabase(&cardNo, &dbID);
- if (!err) {
- SysNotifyUnregister(cardNo, dbID, sysNotifyVolumeUnmountedEvent, sysNotifyNormalPriority);
- SysNotifyUnregister(cardNo, dbID, sysNotifyVolumeMountedEvent, sysNotifyNormalPriority);
- // sonySysNotifyMsaEnforceOpenEvent
- SysNotifyUnregister(cardNo, dbID, sysNotifyDisplayResizedEvent, sysNotifyNormalPriority);
- }
- }
-
- return err;
-}
-
-void AppStop(void) {
- // Close all the open forms.
- FrmCloseAllForms();
- WinEraseWindow();
- WinPalette(winPaletteSetToDefault, 0, 256, NULL);
-
- // Close and move Game list database
- GamCloseDatabase(false);
-
- // Write the saved preferences / saved-state information. This data
- // will saved during a HotSync backup.
- SavePrefs();
-
- // stop all
- AppStopCheckNotify();
- if (!OPTIONS_TST(kOptDeviceARM))
- AppStopMathLib();
- AppStopHRMode();
-
- if (!bLaunched)
- MemPtrFree(gVars);
-}
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formCards.cpp b/backends/platform/PalmOS/Src/launcher/forms/formCards.cpp
deleted file mode 100644
index eb4654ed10..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formCards.cpp
+++ /dev/null
@@ -1,383 +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 <PalmOS.h>
-#include <VFSMgr.h>
-#include <PmPalmOSNVFS.h>
-
-#include "start.h"
-#include "formTabs.h"
-#include "forms.h"
-#include "globals.h"
-
-typedef struct {
- UInt16 volRefNum;
- Char nameP[expCardInfoStringMaxLen+1];
-
-} CardInfoType;
-
-static TabType *myTabP;
-static UInt16 lastTab = 0;
-
-static void CardSlotFormExit(Boolean bSave);
-
-static void CardSlotFreeList() {
- MemHandle cards = NULL;
- MemHandle items = NULL;
-
- if (itemsText && itemsList) {
- cards = MemPtrRecoverHandle(itemsList);
- items = MemPtrRecoverHandle(itemsText);
-
- itemsText = NULL;
- itemsList = NULL;
- }
- itemsType = ITEM_TYPE_UNKNOWN;
-
- if (items && cards) {
- MemHandleUnlock(items);
- MemHandleUnlock(cards);
- MemHandleFree(items);
- MemHandleFree(cards);
- }
-}
-
-static UInt16 CardSlotFillList(Boolean getRefNum = false) {
- Err err;
- UInt16 index;
- UInt16 volRefNum;
- UInt32 volIterator = vfsIteratorStart|vfsIncludePrivateVolumes;
- UInt8 counter = 0;
- UInt32 other = 1;
-
- MemHandle items = NULL;
- MemHandle cards = NULL;
- CardInfoType *cardsInfo;
-
- // retreive card infos
- while (volIterator != vfsIteratorStop) {
- err = VFSVolumeEnumerate(&volRefNum, &volIterator);
-
- if (!err) {
- Char labelP[expCardInfoStringMaxLen+1];
- MemSet(labelP, expCardInfoStringMaxLen+1, 0);
- err = VFSVolumeGetLabel(volRefNum, labelP, expCardInfoStringMaxLen+1);
-
- if (err || StrLen(labelP) == 0) { // if no label try to retreive card type
- VolumeInfoType volInfo;
- err = VFSVolumeInfo(volRefNum, &volInfo);
-
- if (!err) {
- ExpCardInfoType info;
- err = ExpCardInfo(volInfo.slotRefNum, &info);
- StrCopy(labelP, info.deviceClassStr);
- }
-
- if (err) // if err default name
- StrPrintF(labelP,"Other Card %ld", other++);
- }
-
- if (!cards)
- cards = MemHandleNew(sizeof(CardInfoType));
- else
- MemHandleResize(cards, MemHandleSize(cards) + sizeof(CardInfoType));
-
- cardsInfo = (CardInfoType *)MemHandleLock(cards);
- cardsInfo[counter].volRefNum = volRefNum;
- StrCopy(cardsInfo[counter].nameP, labelP);
- MemHandleUnlock(cards);
- counter++;
- }
- }
-
- if (counter > 0) {
- // set the list items ...
- if (!getRefNum) {
- for (index = 0; index < counter; index++) {
- if (!items)
- items = MemHandleNew(sizeof(Char *));
- else
- MemHandleResize(items, MemHandleSize(items) + sizeof(Char *));
-
- itemsText = (Char **)MemHandleLock(items);
- itemsText[index] = cardsInfo[index].nameP;
- MemHandleUnlock(items);
- }
-
- // save globals
- itemsText = (Char **)MemHandleLock(items);
- itemsList = (void *)MemHandleLock(cards);
- itemsType = ITEM_TYPE_CARD;
-
- // ... or just return a default volRefNum
- } else {
- UInt16 volRefNum;
-
- cardsInfo = (CardInfoType *)MemHandleLock(cards);
- volRefNum = cardsInfo[0].volRefNum; // return the first volref
- MemHandleUnlock(cards);
- MemHandleFree(cards);
-
- return volRefNum;
- }
-
- // no card found ? free old list in any or return invalid volref
- } else {
- if (!getRefNum)
- CardSlotFreeList();
- else
- return vfsInvalidVolRef;
- }
-
- return counter;
-}
-
-static void ConfigTabInit(Boolean update = false) {
- ListPtr listP;
-
- UInt16 index;
- Int16 selected = -1;
-
- UInt16 counter = CardSlotFillList();
- listP = (ListType *)GetObjectPtr(TabCardConfigSlotList);
-
- // itemsText can be NULL if counter = 0
- LstSetListChoices (listP, itemsText, counter);
- if (counter > 0) {
- CardInfoType *cardsInfo = (CardInfoType *)itemsList;
-
- for (index = 0; index < counter; index++) {
- if (cardsInfo[index].volRefNum == gPrefs->card.volRefNum) {
- selected = index;
- break;
- }
- }
-
- LstSetSelection(listP, selected);
- }
-
- if (!update) {
- FieldType *fld1P;
- Char *cacheP;
- MemHandle cacheH;
-
- fld1P = (FieldType *)GetObjectPtr(TabCardConfigCacheSizeField);
- cacheH = MemHandleNew(FldGetMaxChars(fld1P)+1);
- cacheP = (Char *)MemHandleLock(cacheH);
- StrIToA(cacheP, gPrefs->card.cacheSize / 1024);
- MemHandleUnlock(cacheH);
-
- FldSetTextHandle(fld1P, cacheH);
- CtlSetValue((ControlType *)GetObjectPtr(TabCardConfigCacheCheckbox), gPrefs->card.useCache);
- CtlSetValue((ControlType *)GetObjectPtr(TabCardConfigLedCheckbox), gPrefs->card.showLED);
- CtlSetValue((ControlType *)GetObjectPtr(TabCardConfigDetectCheckbox), gPrefs->card.autoDetect);
- // update ? redraw the list
- } else {
- WinScreenLock(winLockCopy);
- LstDrawList(listP);
- WinScreenUnlock();
- }
-}
-
-static UInt16 ConfigTabSave() {
- ControlType *cckP[3];
- FieldType *fld1P;
- ListPtr listP;
- FormPtr frmP;
- UInt16 updateCode = frmRedrawUpdateMS;
-
- cckP[0] = (ControlType *)GetObjectPtr(TabCardConfigCacheCheckbox);
- cckP[1] = (ControlType *)GetObjectPtr(TabCardConfigLedCheckbox);
- cckP[2] = (ControlType *)GetObjectPtr(TabCardConfigDetectCheckbox);
-
- gPrefs->card.useCache = CtlGetValue(cckP[0]);
- gPrefs->card.showLED = CtlGetValue(cckP[1]);
- gPrefs->card.autoDetect = CtlGetValue(cckP[2]);
-
- fld1P = (FieldType *)GetObjectPtr(TabCardConfigCacheSizeField);
- frmP = FrmGetActiveForm();
- if (FldGetTextLength(fld1P) == 0 && CtlGetValue(cckP[0]) == 1) {
- TabSetActive(frmP, myTabP, 0);
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, TabCardConfigCacheSizeField));
- FrmCustomAlert(FrmWarnAlert,"You must specified a cache size.",0,0);
- return 0;
- }
- gPrefs->card.cacheSize = StrAToI(FldGetTextPtr(fld1P)) * 1024;
-
- Int16 selected;
- CardInfoType *cardsInfo = (CardInfoType *)itemsList;
-
- listP = (ListType *)GetObjectPtr(TabCardConfigSlotList);
- selected = LstGetSelection(listP);
- if (selected == -1) {
- gPrefs->card.volRefNum = vfsInvalidVolRef;
- } else if (gPrefs->card.volRefNum != cardsInfo[selected].volRefNum) {
- updateCode = frmRedrawUpdateMSImport;
- gPrefs->card.volRefNum = cardsInfo[selected].volRefNum;
- }
-
- CardSlotCreateDirs();
- CardSlotFreeList();
-
- return updateCode;
-}
-
-static void GameListTabInit() {
- CtlSetValue((ControlType *)GetObjectPtr(TabCardGameListMoveCheckbox), gPrefs->card.moveDB);
- CtlSetValue((ControlType *)GetObjectPtr(TabCardGameListDeleteCheckbox), gPrefs->card.deleteDB);
- CtlSetValue((ControlType *)GetObjectPtr(TabCardGameListConfirmCheckbox), gPrefs->card.confirmMoveDB);
-}
-
-static void GameListTabSave() {
- ControlType *cckP[3];
-
- cckP[0] = (ControlType *)GetObjectPtr(TabCardGameListMoveCheckbox);
- cckP[1] = (ControlType *)GetObjectPtr(TabCardGameListDeleteCheckbox);
- cckP[2] = (ControlType *)GetObjectPtr(TabCardGameListConfirmCheckbox);
-
- gPrefs->card.moveDB = CtlGetValue(cckP[0]);
- gPrefs->card.deleteDB = CtlGetValue(cckP[1]);
- gPrefs->card.confirmMoveDB = CtlGetValue(cckP[2]);
-}
-
-static void GameListTabDraw() {
- ControlType *cck1P;
- FormPtr frmP = FrmGetActiveForm();
-
- cck1P = (ControlType *)GetObjectPtr(TabCardGameListMoveCheckbox);
- if (CtlGetValue(cck1P)) {
- FrmShowObject(frmP, FrmGetObjectIndex (frmP, TabCardGameListDeleteCheckbox));
- FrmShowObject(frmP, FrmGetObjectIndex (frmP, TabCardGameListConfirmCheckbox));
- } else {
- FrmHideObject(frmP, FrmGetObjectIndex (frmP, TabCardGameListDeleteCheckbox));
- FrmHideObject(frmP, FrmGetObjectIndex (frmP, TabCardGameListConfirmCheckbox));
- }
-}
-
-static void CardSlotFormInit() {
- TabType *tabP;
- FormType *frmP = FrmGetActiveForm();
-
- tabP = TabNewTabs(2);
- TabAddContent(&frmP, tabP, "Cards", TabCardConfigForm);
- TabAddContent(&frmP, tabP, "Game List", TabCardGameListForm, GameListTabDraw);
-
- ConfigTabInit();
- GameListTabInit();
-
- FrmDrawForm(frmP);
- TabSetActive(frmP, tabP, lastTab);
-
- myTabP = tabP;
-}
-
-static void CardSlotFormSave() {
- UInt16 updateCode;
- updateCode = ConfigTabSave();
- if (!updateCode) return;
- GameListTabSave();
- CardSlotCreateDirs();
-
- TabDeleteTabs(myTabP);
- FrmReturnToMain(updateCode);
-}
-
-static void CardSlotFormCancel() {
- CardSlotFreeList();
- TabDeleteTabs(myTabP);
- FrmReturnToMain();
-}
-
-Boolean CardSlotFormHandleEvent(EventPtr eventP) {
- FormPtr frmP = FrmGetActiveForm();
- Boolean handled = false;
-
- switch (eventP->eType) {
- case frmOpenEvent:
- CardSlotFormInit();
- handled = true;
- break;
-
- case frmCloseEvent:
- CardSlotFormCancel();
- handled = true;
- break;
-
- case ctlSelectEvent:
- switch (eventP->data.ctlSelect.controlID)
- {
- case (CardSlotForm + 1) :
- case (CardSlotForm + 2) :
- lastTab = (eventP->data.ctlSelect.controlID - CardSlotForm - 1);
- TabSetActive(frmP, myTabP, lastTab);
- break;
-
- case CardSlotOkButton:
- CardSlotFormSave();
- break;
-
- case CardSlotCancelButton:
- CardSlotFormCancel();
- break;
-
- case TabCardGameListMoveCheckbox:
- GameListTabDraw();
- break;
- }
- handled = true;
- break;
-
- default:
- break;
- }
-
- return handled;
-}
-
-void CardSlotCreateDirs() {
- if (gPrefs->card.volRefNum != vfsInvalidVolRef) {
- VFSDirCreate(gPrefs->card.volRefNum, "/PALM");
- VFSDirCreate(gPrefs->card.volRefNum, "/PALM/Programs");
- VFSDirCreate(gPrefs->card.volRefNum, "/PALM/Programs/ScummVM");
- VFSDirCreate(gPrefs->card.volRefNum, "/PALM/Programs/ScummVM/Games");
- VFSDirCreate(gPrefs->card.volRefNum, "/PALM/Programs/ScummVM/Saved");
- VFSDirCreate(gPrefs->card.volRefNum, "/PALM/Programs/ScummVM/Audio");
- VFSDirCreate(gPrefs->card.volRefNum, "/PALM/Programs/ScummVM/Mods");
- VFSDirCreate(gPrefs->card.volRefNum, "/PALM/Programs/ScummVM/Themes");
- }
-}
-
-void CardSlotFormUpdate() {
- if (itemsType == ITEM_TYPE_CARD) {
- CardSlotFreeList();
- ConfigTabInit(true);
- }
-}
-
-UInt16 parseCards() {
- UInt16 volRefNum = CardSlotFillList(true);
- CardSlotFreeList();
- return volRefNum;
-}
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formEditGame.cpp b/backends/platform/PalmOS/Src/launcher/forms/formEditGame.cpp
deleted file mode 100644
index 0540c12577..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formEditGame.cpp
+++ /dev/null
@@ -1,612 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include <PalmOS.h>
-#include <VFSMgr.h>
-#include <FileBrowserLibCommon.h>
-#include <FileBrowserLib68K.h>
-
-#include "formTabs.h"
-#include "forms.h"
-
-#include "start.h"
-#include "games.h"
-#include "skin.h"
-
-#define errBadParam 0x1000
-
-static TabType *myTabP;
-static UInt16 lastTab = 0;
-
-UInt8 gFormEditMode;
-
-static void GameTabInit(GameInfoType *gameInfoP) {
- FieldType *fld1P, *fld2P, *fld3P;
- Char *nameP, *pathP, *gameP;
- MemHandle nameH, pathH, gameH;
- ListType *list1P;
-
- list1P = (ListType *)GetObjectPtr(TabGameInfoEngineList);
-
- itemsText = (Char **)MemPtrNew(ENGINE_COUNT * sizeof(Char *));
- for (int i = 0; i < ENGINE_COUNT; i++)
- itemsText[i] = (Char *)engines[i].nameP;
- LstSetListChoices(list1P, itemsText, ENGINE_COUNT);
-
- fld1P = (FieldType *)GetObjectPtr(TabGameInfoEntryNameField);
- fld2P = (FieldType *)GetObjectPtr(TabGameInfoPathField);
- fld3P = (FieldType *)GetObjectPtr(TabGameInfoGameField);
-
- nameH = MemHandleNew(FldGetMaxChars(fld1P)+1);
- pathH = MemHandleNew(FldGetMaxChars(fld2P)+1);
- gameH = MemHandleNew(FldGetMaxChars(fld3P)+1);
-
- nameP = (Char *)MemHandleLock(nameH);
- pathP = (Char *)MemHandleLock(pathH);
- gameP = (Char *)MemHandleLock(gameH);
-
- if (gameInfoP) {
- LstSetSelection(list1P, gameInfoP->engine);
- LstSetTopItem(list1P, gameInfoP->engine);
- StrCopy(nameP, gameInfoP->nameP);
- StrCopy(pathP, gameInfoP->pathP);
- StrCopy(gameP, gameInfoP->gameP);
- } else {
- LstSetSelection(list1P, 0);
- MemSet(nameP,MemHandleSize(nameH),0);
- MemSet(pathP,MemHandleSize(pathH),0);
- MemSet(gameP,MemHandleSize(gameH),0);
- }
-
- CtlSetLabel((ControlType *)GetObjectPtr(TabGameInfoEnginePopTrigger), LstGetSelectionText(list1P, LstGetSelection(list1P)));
-
- MemHandleUnlock(nameH);
- MemHandleUnlock(pathH);
- MemHandleUnlock(gameH);
-
- FldSetTextHandle(fld1P, nameH);
- FldSetTextHandle(fld2P, pathH);
- FldSetTextHandle(fld3P, gameH);
-}
-
-static Err GameTabSave(GameInfoType *gameInfoP) {
- FieldType *fld1P, *fld2P, *fld3P;
- ListType *list1P;
-
- FormType *frmP = FrmGetActiveForm();
- list1P = (ListType *)GetObjectPtr(TabGameInfoEngineList);
-
- fld1P = (FieldType *)GetObjectPtr(TabGameInfoEntryNameField);
- fld2P = (FieldType *)GetObjectPtr(TabGameInfoPathField);
- fld3P = (FieldType *)GetObjectPtr(TabGameInfoGameField);
-
- FldTrimText(fld1P);
- FldTrimText(fld2P);
- FldTrimText(fld3P);
-
- // test case
- if (!gameInfoP) {
- if (FldGetTextLength(fld1P) == 0) {
- FrmCustomAlert(FrmWarnAlert,"You must specify an entry name.",0,0);
- TabSetActive(frmP, myTabP, 0);
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, TabGameInfoEntryNameField));
- return errBadParam;
-
- } else if (FldGetTextLength(fld2P) == 0) {
- FrmCustomAlert(FrmWarnAlert,"You must specify a path.",0,0);
- TabSetActive(frmP, myTabP, 0);
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, TabGameInfoPathField));
- return errBadParam;
-
- } else if (FldGetTextLength(fld3P) == 0) {
- FrmCustomAlert(FrmWarnAlert,"You must specify a game.",0,0);
- TabSetActive(frmP, myTabP, 0);
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, TabGameInfoGameField));
- return errBadParam;
- }
-
- } else {
- gameInfoP->engine = LstGetSelection(list1P);
- StrCopy(gameInfoP->nameP, FldGetTextPtr(fld1P));
- StrCopy(gameInfoP->pathP, FldGetTextPtr(fld2P));
- StrCopy(gameInfoP->gameP, FldGetTextPtr(fld3P));
-
- if (gameInfoP->pathP[StrLen(gameInfoP->pathP)-1] != '/')
- StrCat(gameInfoP->pathP, "/");
-
- MemPtrFree(itemsText);
- itemsText = NULL;
- }
-
- return errNone;
-}
-
-static void DisplayInit(GameInfoType *gameInfoP) {
- ListType *list1P, *list2P;
-
- list1P = (ListType *)GetObjectPtr(TabGameDisplayGfxListList);
- list2P = (ListType *)GetObjectPtr(TabGameDisplayRenderList);
-
- if (gameInfoP) {
- LstSetSelection(list1P, gameInfoP->gfxMode);
- LstSetSelection(list2P, gameInfoP->renderMode);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameDisplayFilterCheckbox), gameInfoP->filter);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameDisplayFullscreenCheckbox), gameInfoP->fullscreen);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameDisplayAspectRatioCheckbox), gameInfoP->aspectRatio);
-
- } else {
- LstSetSelection(list1P, 0);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameDisplayFilterCheckbox), 0);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameDisplayFullscreenCheckbox), 0);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameDisplayAspectRatioCheckbox), 0);
- }
-
- CtlSetLabel((ControlType *)GetObjectPtr(TabGameDisplayGfxPopupPopTrigger), LstGetSelectionText(list1P, LstGetSelection(list1P)));
- CtlSetLabel((ControlType *)GetObjectPtr(TabGameDisplayRenderPopTrigger), LstGetSelectionText(list2P, LstGetSelection(list2P)));
-}
-
-static Err DisplaySave(GameInfoType *gameInfoP) {
- ListType *list1P, *list2P;
- ControlType *cck6P, *cck7P, *cck8P;
-
- FormType *frmP = FrmGetActiveForm();
-
- list1P = (ListType *)GetObjectPtr(TabGameDisplayGfxListList);
- list2P = (ListType *)GetObjectPtr(TabGameDisplayRenderList);
- cck6P = (ControlType *)GetObjectPtr(TabGameDisplayFilterCheckbox);
- cck7P = (ControlType *)GetObjectPtr(TabGameDisplayFullscreenCheckbox);
- cck8P = (ControlType *)GetObjectPtr(TabGameDisplayAspectRatioCheckbox);
-
- if (!gameInfoP) {
- } else {
- gameInfoP->gfxMode = LstGetSelection(list1P);
- gameInfoP->renderMode = LstGetSelection(list2P);
- gameInfoP->filter = CtlGetValue(cck6P);
- gameInfoP->fullscreen = CtlGetValue(cck7P);
- gameInfoP->aspectRatio = CtlGetValue(cck8P);
- }
-
- return errNone;
-}
-
-static void OptionsInit(GameInfoType *gameInfoP) {
- ListType *list2P, *list3P;
- FieldType *fld4P, *fld5P, *fld6P;
- Char *loadP, *roomP, *talkP;
- MemHandle loadH, roomH, talkH;
-
- list2P = (ListType *)GetObjectPtr(TabGameOptionsLanguageList);
- list3P = (ListType *)GetObjectPtr(TabGameOptionsPlatformList);
-
- fld4P = (FieldType *)GetObjectPtr(TabGameOptionsLoadSlotField);
- fld5P = (FieldType *)GetObjectPtr(TabGameOptionsStartRoomField);
- fld6P = (FieldType *)GetObjectPtr(TabGameOptionsTalkSpeedField);
-
- loadH = MemHandleNew(FldGetMaxChars(fld4P)+1);
- roomH = MemHandleNew(FldGetMaxChars(fld5P)+1);
- talkH = MemHandleNew(FldGetMaxChars(fld6P)+1);
-
- loadP = (Char *)MemHandleLock(loadH);
- roomP = (Char *)MemHandleLock(roomH);
- talkP = (Char *)MemHandleLock(talkH);
-
- if (gameInfoP) {
- LstSetSelection(list2P, gameInfoP->language);
- LstSetTopItem(list2P, gameInfoP->language);
- LstSetSelection(list3P, gameInfoP->platform);
- LstSetTopItem(list3P, gameInfoP->platform);
-
- StrIToA(loadP, gameInfoP->loadSlot);
- StrIToA(roomP, gameInfoP->bootValue);
- StrIToA(talkP, gameInfoP->talkValue);
-
- CtlSetValue((ControlType *)GetObjectPtr(TabGameOptionsLoadSlotCheckbox), gameInfoP->autoLoad);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameOptionsStartRoomCheckbox), gameInfoP->bootParam);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameOptionsAmigaCheckbox), gameInfoP->setPlatform);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameOptionsSubtitlesCheckbox), gameInfoP->subtitles);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameOptionsTalkSpeedCheckbox), gameInfoP->talkSpeed);
-
- } else {
- LstSetSelection(list2P, 0);
- LstSetSelection(list3P, 0);
-
- StrIToA(loadP, 0);
- StrIToA(roomP, 0);
- StrIToA(talkP, 60);
-
- CtlSetValue((ControlType *)GetObjectPtr(TabGameOptionsLoadSlotCheckbox), 0);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameOptionsStartRoomCheckbox), 0);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameOptionsAmigaCheckbox), 0);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameOptionsSubtitlesCheckbox), 1);
- CtlSetValue((ControlType *)GetObjectPtr(TabGameOptionsTalkSpeedCheckbox), 0);
- }
-
- MemHandleUnlock(loadH);
- MemHandleUnlock(roomH);
- MemHandleUnlock(talkH);
-
- FldSetTextHandle(fld4P, loadH);
- FldSetTextHandle(fld5P, roomH);
- FldSetTextHandle(fld6P, talkH);
-
- CtlSetLabel((ControlType *)GetObjectPtr(TabGameOptionsLanguagePopTrigger), LstGetSelectionText(list2P, LstGetSelection(list2P)));
- CtlSetLabel((ControlType *)GetObjectPtr(TabGameOptionsPlatformPopTrigger), LstGetSelectionText(list3P, LstGetSelection(list3P)));
-}
-
-static Err OptionsSave(GameInfoType *gameInfoP) {
- FieldType *fld4P, *fld5P, *fld6P;
- ControlType *cck1P, *cck2P, *cck3P, *cck4P, *cck5P;
- ListType *list2P, *list3P;
-
- FormType *frmP = FrmGetActiveForm();
-
- list2P = (ListType *)GetObjectPtr(TabGameOptionsLanguageList);
- list3P = (ListType *)GetObjectPtr(TabGameOptionsPlatformList);
-
- fld4P = (FieldType *)GetObjectPtr(TabGameOptionsLoadSlotField);
- fld5P = (FieldType *)GetObjectPtr(TabGameOptionsStartRoomField);
- fld6P = (FieldType *)GetObjectPtr(TabGameOptionsTalkSpeedField);
-
- cck1P = (ControlType *)GetObjectPtr(TabGameOptionsLoadSlotCheckbox);
- cck2P = (ControlType *)GetObjectPtr(TabGameOptionsStartRoomCheckbox);
- cck3P = (ControlType *)GetObjectPtr(TabGameOptionsAmigaCheckbox);
- cck4P = (ControlType *)GetObjectPtr(TabGameOptionsSubtitlesCheckbox);
- cck5P = (ControlType *)GetObjectPtr(TabGameOptionsTalkSpeedCheckbox);
-
- if (!gameInfoP) {
- if (FldGetTextLength(fld5P) == 0 && CtlGetValue(cck2P) == 1) {
- FrmCustomAlert(FrmWarnAlert,"You must specify a room number.",0,0);
- TabSetActive(frmP, myTabP, 2);
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, TabGameOptionsStartRoomField));
- return errBadParam;
-
- } else if (FldGetTextLength(fld6P) == 0 && CtlGetValue(cck5P) == 1) {
- FrmCustomAlert(FrmWarnAlert,"You must specify a talk speed.",0,0);
- TabSetActive(frmP, myTabP, 2);
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, TabGameOptionsTalkSpeedField));
- return errBadParam;
- }
- } else {
- gameInfoP->language = LstGetSelection(list2P);
- gameInfoP->platform = LstGetSelection(list3P);
-
- gameInfoP->autoLoad = CtlGetValue(cck1P);
- gameInfoP->bootParam = CtlGetValue(cck2P);
- gameInfoP->setPlatform = CtlGetValue(cck3P);
- gameInfoP->subtitles = (CtlGetValue(cck4P));
- gameInfoP->talkSpeed = CtlGetValue(cck5P);
-
- gameInfoP->loadSlot = StrAToI(FldGetTextPtr(fld4P));
- gameInfoP->bootValue = StrAToI(FldGetTextPtr(fld5P));
- gameInfoP->talkValue = StrAToI(FldGetTextPtr(fld6P));
- }
-
- return errNone;
-}
-
-static void GameManInit(UInt16 index) {
- TabType *tabP;
- FormType *frmP = FrmGetActiveForm();
- UInt16 active = lastTab;
-
- tabP = TabNewTabs(3);
- TabAddContent(&frmP, tabP, "Game", TabGameInfoForm);
- TabAddContent(&frmP, tabP, "Display", TabGameDisplayForm);
- TabAddContent(&frmP, tabP, "Options", TabGameOptionsForm);
-
- UInt16 refNum;
- if (SysLibFind(kFileBrowserLibName, &refNum))
- FrmRemoveObject(&frmP, FrmGetObjectIndex(frmP, TabGameInfoBrowsePushButton));
-
- if (index != dmMaxRecordIndex) {
- MemHandle recordH = NULL;
- GameInfoType *gameInfoP;
-
- recordH = DmQueryRecord(gameDB, index);
- gameInfoP = (GameInfoType *)MemHandleLock(recordH);
-
- GameTabInit(gameInfoP);
- DisplayInit(gameInfoP);
- OptionsInit(gameInfoP);
-
- MemHandleUnlock(recordH);
- CtlSetUsable((ControlType *)GetObjectPtr(GameEditDeleteButton),true);
- } else {
- active = 0; // new game ? start with first tab
- GameTabInit(0);
- DisplayInit(0);
- OptionsInit(0);
- CtlSetUsable((ControlType *)GetObjectPtr(GameEditDeleteButton),false);
- }
-
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, TabGameInfoEntryNameField));
- FrmDrawForm(frmP);
- TabSetActive(frmP, tabP, active);
-
- myTabP = tabP;
-}
-
-static void GameManSave(UInt16 index) {
- MemHandle recordH;
- GameInfoType *gameInfoP, newGameInfo;
-
- if (GameTabSave(0) == errBadParam) return;
- if (DisplaySave(0) == errBadParam) return;
- if (OptionsSave(0) == errBadParam) return;
-
- if (index != dmMaxRecordIndex) {
- recordH = DmGetRecord(gameDB, index);
- gameInfoP = (GameInfoType *)MemHandleLock(recordH);
- MemMove(&newGameInfo, gameInfoP, sizeof(GameInfoType));
-
- } else {
- index = dmMaxRecordIndex;
- GamUnselect();
- recordH = DmNewRecord(gameDB, &index, sizeof(GameInfoType));
- gameInfoP = (GameInfoType *)MemHandleLock(recordH);
-
- MemSet(&newGameInfo, sizeof(GameInfoType), 0);
- newGameInfo.version = curItemVersion;
- newGameInfo.icnID = 0xFFFF;
- newGameInfo.selected = true;
-
- // default sound data
- newGameInfo.musicInfo.volume.palm = 50;
- newGameInfo.musicInfo.volume.music = 192;
- newGameInfo.musicInfo.volume.sfx = 192;
- newGameInfo.musicInfo.volume.speech = 192;
- newGameInfo.musicInfo.volume.audiocd = 50;
-
- newGameInfo.musicInfo.sound.tempo = 100;
- newGameInfo.musicInfo.sound.defaultTrackLength = 10;
- newGameInfo.musicInfo.sound.firstTrack = 1;
- }
-
- GameTabSave(&newGameInfo);
- DisplaySave(&newGameInfo);
- OptionsSave(&newGameInfo);
-
- DmWrite(gameInfoP, 0, &newGameInfo, sizeof(GameInfoType));
-
- MemHandleUnlock(recordH);
- DmReleaseRecord (gameDB, index, 0);
- GamSortList();
- // update list position
- {
- RectangleType rArea;
- UInt16 posIndex, maxView;
-
- // get the sorted index
- index = GamGetSelected();
- // if new item is out of the list bounds, change current list pos
- SknGetListBounds(&rArea, NULL);
- maxView = rArea.extent.y / sknInfoListItemSize;
- posIndex = gPrefs->listPosition;
-
- // if out of the current list position
- if (!(index >= posIndex && index < (posIndex + maxView)))
- gPrefs->listPosition = index; // this value is corrected in SknUpdateList if needed
- }
-
- TabDeleteTabs(myTabP);
- FrmReturnToMain();
- SknUpdateList();
-}
-
-/***********************************************************************
- *
- * FUNCTION: EditGameFormSave
- * FUNCTION: EditGameFormInit
- * FUNCTION: EditGameFormHandleEvent
- *
- * DESCRIPTION:
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-void EditGameFormDelete(Boolean direct) {
- UInt16 index = GamGetSelected();
-
- if (index == dmMaxRecordIndex) {
- FrmCustomAlert(FrmWarnAlert, "Select an entry first.",0,0);
- return;
-
- } else if (FrmCustomAlert(FrmConfirmAlert, "Do you really want to delete this entry ?", 0, 0) == FrmConfirmYes) {
- DmRemoveRecord(gameDB, index);
- if (!direct) {
- TabDeleteTabs(myTabP);
- FrmReturnToMain();
- }
- GamSortList();
- SknUpdateList();
- }
-}
-
-static void EditGameCancel() {
- if (itemsText) {
- MemPtrFree(itemsText);
- itemsText = NULL;
- }
- TabDeleteTabs(myTabP);
- FrmReturnToMain();
-}
-
-static void EditGameBowser() {
- UInt16 refNum;
- Err e;
-
- ControlPtr butP = (ControlType *)GetObjectPtr(TabGameInfoBrowsePushButton);
- CtlSetValue(butP, 0);
-
- e = SysLibFind (kFileBrowserLibName, &refNum);
- if (!e) {
- e = FileBrowserLibOpen (refNum);
- if (!e) {
- UInt16 volRefNum = gPrefs->card.volRefNum;
- Char *textP, *pathP = (Char *)MemPtrNew(kFileBrowserLibPathBufferSize);
- pathP[0] = chrNull;
-
- if (FileBrowserLibShowOpenDialog(refNum, &volRefNum, pathP, 0, 0, 0, "Game Data Path", kFileBrowserLibFlagNoFiles)) {
- FieldPtr fldP;
- MemHandle textH;
- Int16 offset, copySize, maxSize;
-
- fldP = (FieldType *)GetObjectPtr(TabGameInfoPathField);
- maxSize = FldGetMaxChars(fldP);
- textH = FldGetTextHandle(fldP);
-
- FldSetTextHandle(fldP, NULL);
- textP = (Char *)MemHandleLock(textH);
- offset = 0;
- copySize = StrLen(pathP);
-
- if (StrNCaselessCompare(pathP, "/Palm/Programs/ScummVM/Games/", 29) == 0) {
- if (StrLen(pathP) == 29) {
- copySize = 1;
- pathP[0] = '.';
- } else {
- copySize -= 29;
- offset = 29;
- }
- }
-
- if (copySize > maxSize)
- copySize = maxSize;
- StrNCopy(textP, pathP + offset, copySize);
-
- MemHandleUnlock(textH);
- FldSetTextHandle(fldP, textH);
- FldDrawField(fldP);
- FldGrabFocus(fldP);
- }
-
- MemPtrFree(pathP);
- FileBrowserLibClose(refNum);
- }
- }
-}
-
-Boolean EditGameFormHandleEvent(EventPtr eventP) {
- FormPtr frmP = FrmGetActiveForm();
- Boolean handled = false;
-
- switch (eventP->eType) {
- case frmCloseEvent:
- EditGameCancel();
- handled = true;
- break;
-
- case frmOpenEvent:
- switch (gFormEditMode) {
- case edtModeAdd:
- GameManInit(dmMaxRecordIndex);
- break;
- case edtModeEdit:
- case edtModeParams:
- default :
- GameManInit(GamGetSelected());
- break;
- }
- handled = true;
- break;
-
- case keyDownEvent:
- switch (eventP->data.keyDown.chr) {
- case chrLineFeed:
- case chrCarriageReturn:
- return true;
- }
- break;
-
- case ctlSelectEvent:
- switch (eventP->data.ctlSelect.controlID)
- {
- case (GameEditForm + 1) :
- case (GameEditForm + 2) :
- case (GameEditForm + 3) :
- lastTab = (eventP->data.ctlSelect.controlID - GameEditForm - 1);
- TabSetActive(frmP, myTabP, lastTab);
- break;
-
- case GameEditOKButton:
- switch (gFormEditMode) {
- case edtModeAdd:
- GameManSave(dmMaxRecordIndex);
- break;
- case edtModeEdit:
- case edtModeParams:
- default :
- GameManSave(GamGetSelected());
- break;
- }
- break;
-
- case GameEditCancelButton:
- EditGameCancel();
- break;
-
- case GameEditDeleteButton:
- EditGameFormDelete(false);
- break;
-
- case TabGameInfoBrowsePushButton:
- EditGameBowser();
- break;
-
- case TabGameInfoEnginePopTrigger:
- FrmList(eventP, TabGameInfoEngineList);
- FrmHideObject(frmP, FrmGetObjectIndex(frmP, TabGameInfoEngineList));
- break;
-
- case TabGameDisplayGfxPopupPopTrigger:
- FrmList(eventP, TabGameDisplayGfxListList);
- FrmHideObject(frmP, FrmGetObjectIndex(frmP, TabGameDisplayGfxListList));
- break;
-
- case TabGameDisplayRenderPopTrigger:
- FrmList(eventP, TabGameDisplayRenderList);
- FrmHideObject(frmP, FrmGetObjectIndex(frmP, TabGameDisplayRenderList));
- break;
-
- case TabGameOptionsLanguagePopTrigger:
- FrmList(eventP, TabGameOptionsLanguageList);
- FrmHideObject(frmP, FrmGetObjectIndex(frmP, TabGameOptionsLanguageList));
- break;
-
- case TabGameOptionsPlatformPopTrigger:
- FrmList(eventP, TabGameOptionsPlatformList);
- FrmHideObject(frmP, FrmGetObjectIndex(frmP, TabGameOptionsPlatformList));
- break;
- }
- handled = true;
- break;
-
- default:
- break;
- }
-
- return handled;
-}
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formMisc.cpp b/backends/platform/PalmOS/Src/launcher/forms/formMisc.cpp
deleted file mode 100644
index 35b44486e9..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formMisc.cpp
+++ /dev/null
@@ -1,275 +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 <PalmOS.h>
-
-#include "start.h"
-#include "formTabs.h"
-#include "forms.h"
-#include "globals.h"
-
-static TabType *myTabP;
-static UInt16 lastTab = 0;
-
-static Boolean ScummVMTabSave() {
- FieldType *fld1P, *fld2P;
- ControlType *cckP[11];
- FormPtr frmP;
-
- fld1P = (FieldType *)GetObjectPtr(TabMiscScummVMDebugLevelField);
- fld2P = (FieldType *)GetObjectPtr(TabMiscScummVMAutosaveField);
-
- cckP[0] = (ControlType *)GetObjectPtr(TabMiscScummVMAutosaveCheckbox);
- cckP[3] = (ControlType *)GetObjectPtr(TabMiscScummVMDebugCheckbox);
- cckP[6] = (ControlType *)GetObjectPtr(TabMiscScummVMDemoCheckbox);
- cckP[9] = (ControlType *)GetObjectPtr(TabMiscScummVMCopyProtectionCheckbox);
- cckP[10]= (ControlType *)GetObjectPtr(TabMiscScummVMAltIntroCheckbox);
-
- frmP = FrmGetActiveForm();
- if (FldGetTextLength(fld1P) == 0 && CtlGetValue(cckP[3]) == 1) {
- TabSetActive(frmP, myTabP, 1);
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, TabMiscScummVMDebugLevelField));
- FrmCustomAlert(FrmWarnAlert,"You must specify a debug level.",0,0);
- return false;
-
- } else if (FldGetTextLength(fld2P) == 0 && CtlGetValue(cckP[0]) == 1) {
- TabSetActive(frmP, myTabP, 1);
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, TabMiscScummVMAutosaveField));
- FrmCustomAlert(FrmWarnAlert,"You must specify a period.",0,0);
- return false;
- }
-
- gPrefs->autoSave = CtlGetValue(cckP[0]);
- gPrefs->debug = CtlGetValue(cckP[3]);
- gPrefs->demoMode = CtlGetValue(cckP[6]);
- gPrefs->copyProtection = CtlGetValue(cckP[9]);
- gPrefs->altIntro = CtlGetValue(cckP[10]);
-
- gPrefs->debugLevel = StrAToI(FldGetTextPtr(fld1P));
- gPrefs->autoSavePeriod = StrAToI(FldGetTextPtr(fld2P));
-
- return true;
-}
-
-static void PalmOSTabSave() {
- ControlType *cckP[11];
-
- if (OPTIONS_TST(kOptDeviceARM) && !OPTIONS_TST(kOptDeviceZodiac)) {
- cckP[3]= (ControlType *)GetObjectPtr(TabMiscPalmOSAdvancedCheckbox);
- gPrefs->advancedMode = CtlGetValue(cckP[3]);
- }
-
- if (!OPTIONS_TST(kOptDeviceARM)) {
- cckP[2] = (ControlType *)GetObjectPtr(TabMiscPalmOSStdPaletteCheckbox);
- gPrefs->stdPalette = CtlGetValue(cckP[2]);
- }
-
- cckP[0] = (ControlType *)GetObjectPtr(TabMiscPalmOSVibratorCheckbox);
- cckP[1] = (ControlType *)GetObjectPtr(TabMiscPalmOSNoAutoOffCheckbox);
- cckP[4] = (ControlType *)GetObjectPtr(TabMiscPalmOSLargerStackCheckbox);
- cckP[5] = (ControlType *)GetObjectPtr(TabMiscPalmOSExitLauncherCheckbox);
- cckP[6] = (ControlType *)GetObjectPtr(TabMiscPalmOSStylusClickCheckbox);
- cckP[7] = (ControlType *)GetObjectPtr(TabMiscPalmOSArrowCheckbox);
-
- gPrefs->vibrator = CtlGetValue(cckP[0]);
- gPrefs->autoOff = !CtlGetValue(cckP[1]);
- gPrefs->setStack = CtlGetValue(cckP[4]);
- gPrefs->exitLauncher = CtlGetValue(cckP[5]);
- gPrefs->stylusClick = !CtlGetValue(cckP[6]);
- gPrefs->arrowKeys = CtlGetValue(cckP[7]);
-}
-
-static void ExtsTabSave() {
- ControlType *cckP[2];
-
- if (OPTIONS_TST(kOptLightspeedAPI)) {
- ListType *list1P = (ListType *)GetObjectPtr(TabMiscExtsLightspeedList);
- cckP[0] = (ControlType *)GetObjectPtr(TabMiscExtsLightspeedCheckbox);
-
- gPrefs->lightspeed.enable = CtlGetValue(cckP[0]);
- gPrefs->lightspeed.mode = LstGetSelection(list1P);
- }
- if (OPTIONS_TST(kOptGoLcdAPI)) {
- cckP[1] = (ControlType *)GetObjectPtr(TabMiscExtsGolcdCheckbox);
- gPrefs->goLCD = CtlGetValue(cckP[1]);
- }
-}
-
-static void ScummVMTabInit() {
- FieldType *fld1P, *fld2P;
- Char *levelP, *periodP;
- MemHandle levelH, periodH;
-
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscScummVMAutosaveCheckbox), gPrefs->autoSave);
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscScummVMDebugCheckbox), gPrefs->debug);
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscScummVMDemoCheckbox), gPrefs->demoMode);
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscScummVMCopyProtectionCheckbox), gPrefs->copyProtection);
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscScummVMAltIntroCheckbox), gPrefs->altIntro);
-
- fld1P = (FieldType *)GetObjectPtr(TabMiscScummVMDebugLevelField);
- fld2P = (FieldType *)GetObjectPtr(TabMiscScummVMAutosaveField);
-
- levelH = MemHandleNew(FldGetMaxChars(fld1P)+1);
- levelP = (Char *)MemHandleLock(levelH);
- StrIToA(levelP, gPrefs->debugLevel);
- MemHandleUnlock(levelH);
-
- periodH = MemHandleNew(FldGetMaxChars(fld2P)+1);
- periodP = (Char *)MemHandleLock(periodH);
- StrIToA(periodP, gPrefs->autoSavePeriod);
- MemHandleUnlock(periodH);
-
- FldSetTextHandle(fld1P, levelH);
- FldSetTextHandle(fld2P, periodH);
-}
-
-static void PalmOSTabInit() {
- if (OPTIONS_TST(kOptDeviceARM) && !OPTIONS_TST(kOptDeviceZodiac))
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscPalmOSAdvancedCheckbox), gPrefs->advancedMode);
-
- if (!OPTIONS_TST(kOptDeviceARM))
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscPalmOSStdPaletteCheckbox), gPrefs->stdPalette);
-
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscPalmOSExitLauncherCheckbox), gPrefs->exitLauncher);
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscPalmOSLargerStackCheckbox), gPrefs->setStack);
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscPalmOSVibratorCheckbox), gPrefs->vibrator);
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscPalmOSNoAutoOffCheckbox), !gPrefs->autoOff);
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscPalmOSStylusClickCheckbox), !gPrefs->stylusClick);
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscPalmOSArrowCheckbox), gPrefs->arrowKeys);
-}
-
-static void ExtsTabInit() {
- if (OPTIONS_TST(kOptLightspeedAPI)) {
- ListType *list1P = (ListType *)GetObjectPtr(TabMiscExtsLightspeedList);
- LstSetSelection(list1P, gPrefs->lightspeed.mode);
- CtlSetLabel((ControlType *)GetObjectPtr(TabMiscExtsLightspeedPopTrigger), LstGetSelectionText(list1P, LstGetSelection(list1P)));
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscExtsLightspeedCheckbox), gPrefs->lightspeed.enable);
- }
-
- if (OPTIONS_TST(kOptGoLcdAPI))
- CtlSetValue((ControlType *)GetObjectPtr(TabMiscExtsGolcdCheckbox), gPrefs->goLCD);
-}
-
-static void MiscFormSave() {
- if (!ScummVMTabSave()) return;
- PalmOSTabSave();
- ExtsTabSave();
-
- TabDeleteTabs(myTabP);
- FrmReturnToMain();
-}
-
-static void MiscFormInit() {
- TabType *tabP;
- FormType *frmP = FrmGetActiveForm();
- UInt8 extsCnt = 2;
-
- tabP = TabNewTabs(3);
- TabAddContent(&frmP, tabP, "PalmOS", TabMiscPalmOSForm);
- TabAddContent(&frmP, tabP, "ScummVM", TabMiscScummVMForm);
- TabAddContent(&frmP, tabP, "More ...", TabMiscExtsForm);
-
- if (OPTIONS_TST(kOptDeviceARM)) {
- FrmRemoveObject(&frmP, FrmGetObjectIndex(frmP, TabMiscPalmOSStdPaletteCheckbox));
- TabMoveUpObject(frmP, TabMiscPalmOSAdvancedCheckbox, 12);
- }
-
- if (!OPTIONS_TST(kOptDeviceARM) || OPTIONS_TST(kOptDeviceZodiac))
- FrmRemoveObject(&frmP, FrmGetObjectIndex(frmP, TabMiscPalmOSAdvancedCheckbox));
-
- if (!OPTIONS_TST(kOptGoLcdAPI)) {
- FrmRemoveObject(&frmP, FrmGetObjectIndex(frmP, TabMiscExtsGolcdCheckbox));
- // move lightspeed
- TabMoveUpObject(frmP, TabMiscExtsLightspeedCheckbox, 12);
- TabMoveUpObject(frmP, TabMiscExtsLightspeedPopTrigger, 12);
- TabMoveUpObject(frmP, TabMiscExtsLightspeedList, 12);
- TabMoveUpObject(frmP, TabMiscExtsNothingLabel, 12);
- extsCnt--;
- }
-
- if (!OPTIONS_TST(kOptLightspeedAPI)) {
- FrmRemoveObject(&frmP, FrmGetObjectIndex(frmP, TabMiscExtsLightspeedCheckbox));
-// FrmRemoveObject(&frmP, FrmGetObjectIndex(frmP, TabMiscExtsLightspeedList)); // cannot remove this ?
- FrmRemoveObject(&frmP, FrmGetObjectIndex(frmP, TabMiscExtsLightspeedPopTrigger));
- TabMoveUpObject(frmP, TabMiscExtsNothingLabel, 12);
- extsCnt--;
- }
-
- if (extsCnt)
- FrmRemoveObject(&frmP, FrmGetObjectIndex(frmP, TabMiscExtsNothingLabel));
-
- PalmOSTabInit();
- ScummVMTabInit();
- ExtsTabInit();
-
- FrmDrawForm(frmP);
- TabSetActive(frmP, tabP, lastTab);
-
- myTabP = tabP;
-}
-
-Boolean MiscFormHandleEvent(EventPtr eventP) {
- FormPtr frmP = FrmGetActiveForm();
- Boolean handled = false;
-
- switch (eventP->eType) {
- case frmOpenEvent:
- MiscFormInit();
- handled = true;
- break;
-
- case ctlSelectEvent:
- switch (eventP->data.ctlSelect.controlID)
- {
- case (MiscForm + 1) :
- case (MiscForm + 2) :
- case (MiscForm + 3) :
- lastTab = (eventP->data.ctlSelect.controlID - MiscForm - 1);
- TabSetActive(frmP, myTabP, lastTab);
- break;
-
- case TabMiscExtsLightspeedPopTrigger:
- FrmList(eventP, TabMiscExtsLightspeedList);
- FrmHideObject(frmP, FrmGetObjectIndex(frmP, TabMiscExtsLightspeedList));
- break;
-
- case MiscOKButton:
- MiscFormSave();
- break;
-
- case MiscCancelButton:
- TabDeleteTabs(myTabP);
- FrmReturnToMain();
- break;
- }
- handled = true;
- break;
-
- default:
- break;
- }
-
- return handled;
-}
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formSelect.cpp b/backends/platform/PalmOS/Src/launcher/forms/formSelect.cpp
deleted file mode 100644
index bb0ac894c2..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formSelect.cpp
+++ /dev/null
@@ -1,278 +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 <PalmOS.h>
-#include "StarterRsc.h"
-#include "formUtil.h"
-#include "games.h"
-#include "start.h"
-
-#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0])))
-
-static Char **items = NULL;
-Int16 selectedEngine = -1;
-
-// Supported games
-static const char *engine_agos[] = {
- "Demon in my Pocket",
- "Elvira - Mistress of the Dark",
- "Elvira II - The Jaws of Cerberus",
- "Jumble",
- "NoPatience",
- "Simon the Sorcerer I",
- "Simon the Sorcerer II",
- "Swampy Adventures",
- "The Feeble Files",
- "Waxworks"
-};
-
-static const char *engine_sky[] = {
- "Floppy, CD and Demo"
-};
-
-static const char *engine_sword1[] = {
- "The Shadow of the Templars (PC/Mac)",
- "The Shadow of the Templars (Demo)"
-};
-
-static const char *engine_sword2[] = {
- "The Smoking Mirror",
- "The Smoking Mirror (Demo)"
-};
-
-static const char *engine_cine[] = {
- "Future Wars",
- "Operation Stealth"
-};
-
-static const char *engine_queen[] = {
- "Flight of the Amazon Queen"
-};
-
-static const char *engine_lure[] = {
- "Lure of the Tempress"
-};
-
-static const char *engine_gob[] = {
- "Bargon Attack",
- "Gobliiins",
- "Gobliins 2",
- "Goblins Quest 3",
- "The Bizarre Adventures of Woodruff and the Schnibble",
- "Ween: The Prophecy",
-};
-
-static const char *engine_kyra[] = {
- "The Legend of Kyrandia",
- "The Legend of Kyrandia: The Hand of Fate",
- "The Legend of Kyrandia: Malcolm's Revenge"
-};
-
-static const char *engine_parallaction[] = {
- "Nippon Safes Inc."
-};
-
-static const char *engine_saga[] = {
- "I Have No Mouth And I Must Scream",
- "Inherit the earth"
-};
-
-static const char *engine_scumm[] = {
- "Day of the Tentacle",
- "Indiana Jones and the Fate of Atlantis",
- "Indiana Jones and the Last Crusade",
- "Loom",
- "Maniac Mansion",
- "Monkey Island 2: LeChuck's Revenge",
- "Passport to Adventure",
- "Sam & Max Hit the Road",
- "The Secret of Monkey Island"
- "Zak McKracken and the Alien Mindbenders"
-};
-
-static const char *engine_agi[] = {
- "AGI Tetris",
- "Caitlyn's Destiny",
- "Donald Duck's Playground",
- "Fanmade AGI game",
- "Gold Rush!",
- "King's Quest I: Quest for the Crown",
- "King's Quest II: Romancing the Throne",
- "King's Quest III: To Heir Is Human",
- "King's Quest IV: The Perils of Rosella",
- "Leisure Suit Larry in the Land of the Lounge Lizards",
- "Mixed-Up Mother Goose",
- "Manhunter 1: New York",
- "Manhunter 2: San Francisco",
- "Police Quest I: In Pursuit of the Death Angel",
- "Serguei's Destiny 1",
- "Serguei's Destiny 2",
- "Space Quest 0: Replicated",
- "Space Quest I: The Sarien Encounter",
- "Space Quest II: Vohaul's Revenge",
- "Space Quest X: The Lost Chapter",
- "The Black Cauldron",
- "Xmas Card"
-};
-
-static const char *engine_touche[] = {
- "Touche: The Adventures of the Fifth Musketeer"
-};
-
-static const char *engine_cruise[] = {
- "Cruise for a Corpse"
-};
-
-static const struct {
- int size;
- const char **listP;
-} supported[] = {
- { ARRAYSIZE(engine_agos), engine_agos },
- { ARRAYSIZE(engine_sky), engine_sky },
- { ARRAYSIZE(engine_sword1), engine_sword1 },
- { ARRAYSIZE(engine_sword2), engine_sword2 },
- { ARRAYSIZE(engine_cine), engine_cine },
- { ARRAYSIZE(engine_queen), engine_queen },
- { ARRAYSIZE(engine_lure), engine_lure },
- { ARRAYSIZE(engine_gob), engine_gob },
- { ARRAYSIZE(engine_kyra), engine_kyra },
- { ARRAYSIZE(engine_parallaction), engine_parallaction },
- { ARRAYSIZE(engine_saga), engine_saga },
- { ARRAYSIZE(engine_scumm), engine_scumm },
- { ARRAYSIZE(engine_agi), engine_agi },
- { ARRAYSIZE(engine_touche), engine_touche },
- { ARRAYSIZE(engine_cruise), engine_cruise }
-};
-
-static void SelectorSetList(Int16 sel) {
- ListType *listP;
- FormPtr frmP = FrmGetActiveForm();
-
- Boolean toBeDrawn = (items != NULL);
- if (items)
- MemPtrFree(items);
-
- listP = (ListType *)FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, EngineSupportedList));
- items = (Char **)MemPtrNew(supported[sel].size * sizeof(Char *));
-
- for (int i = 0; i < supported[sel].size; i++)
- items[i] = (Char *)supported[sel].listP[i];
-
- LstSetListChoices (listP, items, supported[sel].size);
- LstSetTopItem(listP, 0);
- LstSetSelection(listP, -1);
-
- if (toBeDrawn) {
- WinScreenLock(winLockCopy);
- LstDrawList(listP);
- WinScreenUnlock();
- }
-}
-
-static void SelectorFormInit() {
- ListType *listP;
- FormPtr frmP = FrmGetActiveForm();
-
- listP = (ListType *)FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, EngineListList));
- itemsText = (Char **)MemPtrNew(ENGINE_COUNT * sizeof(Char *));
-
- for (int i = 0; i < ENGINE_COUNT; i++)
- itemsText[i] = (Char *)engines[i].nameP;
-
- LstSetListChoices (listP, itemsText, ENGINE_COUNT);
- LstSetSelection(listP, 0);
-
- SelectorSetList(0);
-
- FrmDrawForm(frmP);
-}
-
-static void SelectorFormFree(bool quit) {
- items = NULL;
-
- if (!quit) {
- ListType *listP = (ListType *)GetObjectPtr(EngineListList);
- Int16 sel = LstGetSelection(listP);
-
- FrmReturnToMain();
- StartScummVM(sel);
-
- } else {
- FrmReturnToMain();
-
- if (bDirectMode) {
- // force exit if nothing selected
- EventType event;
- event.eType = keyDownEvent;
- event.data.keyDown.chr = vchrLaunch;
- event.data.keyDown.modifiers = commandKeyMask;
- EvtAddUniqueEventToQueue(&event, 0, true);
- }
- }
-}
-
-Boolean SelectorFormHandleEvent(EventPtr eventP) {
- FormPtr frmP = FrmGetActiveForm();
- Boolean handled = false;
-
- switch (eventP->eType) {
- case frmOpenEvent:
- SelectorFormInit();
- handled = true;
- break;
-
- case frmCloseEvent:
- SelectorFormFree(true);
- handled = true;
- break;
-
- case lstSelectEvent:
- if (eventP->data.lstSelect.listID == EngineSupportedList)
- LstSetSelection(eventP->data.lstSelect.pList, -1);
- else
- SelectorSetList(eventP->data.lstSelect.selection);
- handled = true;
- break;
-
- case ctlSelectEvent:
- switch (eventP->data.ctlSelect.controlID)
- {
- case EngineOkButton:
- SelectorFormFree(false);
- break;
-
- case EngineCancelButton:
- SelectorFormFree(true);
- break;
- }
- handled = true;
- break;
-
- default:
- break;
- }
-
- return handled;
-}
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp b/backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp
deleted file mode 100644
index b4c1e222d0..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-#include <PalmOS.h>
-
-#include "palmdefs.h"
-#include "start.h"
-#include "forms.h"
-#include "skin.h"
-#include "globals.h"
-
-static Int16 SkinsFormCompare(SkinInfoType *a, SkinInfoType *b, SortRecordInfoPtr, SortRecordInfoPtr, MemHandle) {
- return StrCompare(a->nameP, b->nameP);
-}
-
-static void SkinsFormInit(Boolean bDraw) {
- MemHandle skins = NULL;
- SkinInfoType *skinsInfo;
- UInt16 numSkins = 0;
-
- FormPtr frmP;
- ListType *listP;
- MemHandle items = NULL;
- ControlType *cck1P;
- DmSearchStateType stateInfo;
- UInt16 cardNo;
- LocalID dbID;
-
- Err errInfo;
- Char nameP[32];
-
- itemsText = NULL;
-
- // parse and save skins
- Err err = DmGetNextDatabaseByTypeCreator(true, &stateInfo, 'skin', appFileCreator, false, &cardNo, &dbID);
- while (!err && dbID) {
- errInfo = DmDatabaseInfo (cardNo, dbID, nameP, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- if (!errInfo)
- {
- if (!skins)
- skins = MemHandleNew(sizeof(SkinInfoType));
- else
- MemHandleResize(skins, MemHandleSize(skins) + sizeof(SkinInfoType));
-
- skinsInfo = (SkinInfoType *)MemHandleLock(skins);
- StrCopy(skinsInfo[numSkins].nameP, nameP);
- skinsInfo[numSkins].cardNo = cardNo;
- skinsInfo[numSkins].dbID = dbID;
- MemHandleUnlock(skins);
- numSkins++;
- }
- err = DmGetNextDatabaseByTypeCreator(false, &stateInfo, 'skin', appFileCreator, false, &cardNo, &dbID);
- }
-
- Int16 selected = -1;
-
- cck1P = (ControlType *)GetObjectPtr(SkinsSoundClickCheckbox);
- CtlSetValue(cck1P, gPrefs->soundClick);
-
- listP = (ListType *)GetObjectPtr(SkinsSkinList);
- skinsInfo = (SkinInfoType *)MemHandleLock(skins);
- SysQSort(skinsInfo, numSkins, sizeof(SkinInfoType), (CmpFuncPtr)SkinsFormCompare, 0);
-
- // create itemsText (TODO: create a custom draw function)
- for (UInt16 index=0; index < numSkins; index++)
- {
- if (!items)
- items = MemHandleNew(sizeof(Char *));
- else
- MemHandleResize(items, MemHandleSize(items) + sizeof(Char *));
-
- itemsText = (Char **)MemHandleLock(items);
- itemsText[index] = skinsInfo[index].nameP;
- MemHandleUnlock(items);
-
- if ( gPrefs->skin.cardNo == skinsInfo[index].cardNo &&
- gPrefs->skin.dbID == skinsInfo[index].dbID &&
- StrCompare(gPrefs->skin.nameP, skinsInfo[index].nameP) == 0)
- selected = index;
- }
- // save globals and set list
- itemsText = (Char **)MemHandleLock(items);
- itemsList = (void *)skinsInfo;
- itemsType = ITEM_TYPE_SKIN;
-
- LstSetListChoices (listP, itemsText, numSkins);
- LstSetSelection(listP, selected);
-
- // bDraw = true -> draw whole from
- // bDraw = false -> redraw list
- if (bDraw) {
- frmP = FrmGetActiveForm();
- FrmDrawForm(frmP);
- } else {
- WinScreenLock(winLockCopy);
- LstDrawList(listP);
- WinScreenUnlock();
-// LstSetSelection(listP, 0);
- }
-}
-
-static void SkinsFormExit(Boolean bSave) {
- MemHandle skins;
- MemHandle items;
- SkinInfoType *skinsInfo;
-
- ListType *listP;
- Int16 selected;
-
- listP = (ListType *)GetObjectPtr(SkinsSkinList);
- selected = LstGetSelection(listP);
-
- if (bSave && selected == -1) { // may never occured...
- FrmCustomAlert(FrmWarnAlert, "You didn't select a skin.", 0, 0);
- return;
- }
-
- skinsInfo = (SkinInfoType *)itemsList;
- skins = MemPtrRecoverHandle(skinsInfo);
- items = MemPtrRecoverHandle(itemsText);
-
- itemsText = NULL;
- itemsList = NULL;
- itemsType = ITEM_TYPE_UNKNOWN;
-
- if (bSave) {
- ControlType *cck1P;
-
- StrCopy(gPrefs->skin.nameP, skinsInfo[selected].nameP);
- gPrefs->skin.cardNo = skinsInfo[selected].cardNo;
- gPrefs->skin.dbID = skinsInfo[selected].dbID;
-
-/* DmOpenRef skinDB = SknOpenSkin();
- UInt32 depth = SknGetDepth(skinDB);
- SknCloseSkin(skinDB);
-
- if (depth != 8 && depth != 16) depth = 8;
-
- if (depth == 16 && !OPTIONS_TST(kOptMode16Bit)) {
- FrmCustomAlert(FrmInfoAlert, "You can only use 8bit skin on your device.", 0, 0);
- gPrefs->skin.cardNo = cardNo;
- gPrefs->skin.dbID = dbID;
- }
-*/
- cck1P = (ControlType *)GetObjectPtr(SkinsSoundClickCheckbox);
- gPrefs->soundClick = CtlGetValue(cck1P);
- }
-
- FrmReturnToMain();
-
- MemHandleUnlock(items);
- MemHandleUnlock(skins);
- MemHandleFree(items);
- MemHandleFree(skins);
-
- if (bSave)
- SknApplySkin();
-}
-
-static void SkinsFormBeam() {
- SkinInfoType *skinsInfo;
-
- ListType *listP;
- Int16 selected;
- Err err;
-
- listP = (ListType *)GetObjectPtr(SkinsSkinList);
- selected = LstGetSelection(listP);
-
- if (selected == -1) { // may never occured...
- FrmCustomAlert(FrmWarnAlert, "You didn't select a skin.", 0, 0);
- return;
- }
-
- skinsInfo = (SkinInfoType *)itemsList;
- err = SendDatabase(0, skinsInfo[selected].dbID, "skin.pdb", "\nScummVM Skin");
-
-// if (err)
-// FrmCustomAlert(FrmErrorAlert, "Unable to beam this skin.",0,0);
-}
-
-static void SkinsFormDelete() {
- MemHandle skins;
- MemHandle items;
- SkinInfoType *skinsInfo;
-
- ListType *listP;
- Int16 selected;
-
- listP = (ListType *)GetObjectPtr(SkinsSkinList);
- selected = LstGetSelection(listP);
-
- if (selected == -1) { // may never occured...
- FrmCustomAlert(FrmInfoAlert, "You didn't select a skin.", 0, 0);
- return;
- }
-
- skinsInfo = (SkinInfoType *)itemsList;
- skins = MemPtrRecoverHandle(skinsInfo);
- items = MemPtrRecoverHandle(itemsText);
-
- if ( gPrefs->skin.cardNo == skinsInfo[selected].cardNo &&
- gPrefs->skin.dbID == skinsInfo[selected].dbID &&
- StrCompare(gPrefs->skin.nameP, skinsInfo[selected].nameP) == 0) {
- FrmCustomAlert(FrmInfoAlert, "You cannot delete the active skin.",0,0);
- return;
-
- } else {
- Err err = DmDeleteDatabase(0, skinsInfo[selected].dbID);
- if (!err) {
-
- itemsText = NULL;
- itemsList = NULL;
- itemsType = ITEM_TYPE_UNKNOWN;
-
- MemHandleUnlock(items);
- MemHandleUnlock(skins);
- MemHandleFree(items);
- MemHandleFree(skins);
-
- SkinsFormInit(false);
- } else {
- FrmCustomAlert(FrmErrorAlert, "Skin deletion failed.",0,0);
- }
- }
-
-}
-Boolean SkinsFormHandleEvent(EventPtr eventP) {
- Boolean handled = false;
-
- switch (eventP->eType) {
-
- case frmOpenEvent:
- SkinsFormInit(true);
- handled = true;
- break;
-
- case frmCloseEvent:
- SkinsFormExit(false);
- handled = true;
- break;
-
- case ctlSelectEvent:
- switch (eventP->data.ctlSelect.controlID)
- {
- case SkinsOKButton:
- SkinsFormExit(true);
- break;
-
- case SkinsCancelButton:
- SkinsFormExit(false);
- break;
-
- case SkinsBeamButton:
- SkinsFormBeam();
- break;
-
- case SkinsDeleteButton:
- SkinsFormDelete();
- break;
- }
- handled = true;
- break;
-
- default:
- break;
- }
-
- return handled;
-}
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formUtil.cpp b/backends/platform/PalmOS/Src/launcher/forms/formUtil.cpp
deleted file mode 100644
index 6d1d55e6e2..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formUtil.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include <PalmOS.h>
-#include <TxtGlue.h>
-
-#include "forms.h"
-
-Char **itemsText = NULL;
-void *itemsList = NULL;
-Char itemsType = ITEM_TYPE_UNKNOWN;
-
-void FrmReturnToMain(UInt16 updateCode) {
- // if there is a form loaded, prevent crash on OS5
- if (FrmGetFirstForm()) {
- FrmUpdateForm(MainForm, updateCode);
- FrmReturnToForm(MainForm);
- }
-}
-
-void FldTrimText(FieldPtr fldP) {
- MemHandle tmpH;
- Char *tmpP;
-
- tmpH = FldGetTextHandle(fldP);
- FldSetTextHandle(fldP, NULL);
- tmpP = (Char *)MemHandleLock(tmpH);
- TxtGlueStripSpaces(tmpP, true, true);
- MemHandleUnlock(tmpH);
- FldSetTextHandle(fldP, tmpH);
-}
-
-/***********************************************************************
- *
- * FUNCTION: GetObjectPtr
- *
- * DESCRIPTION: This routine returns a pointer to an object in the current
- * form.
- *
- * PARAMETERS: formId - id of the form to display
- *
- * RETURNED: void *
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-void * GetObjectPtr(UInt16 objectID) {
- FormPtr frmP;
-
- frmP = FrmGetActiveForm();
- return FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, objectID));
-}
-
-void FrmList(EventPtr eventP, UInt16 objectID) {
- ListType *listP;
- UInt16 listItem;
-
- listP = (ListType *)GetObjectPtr(objectID);
- listItem = LstPopupList(listP);
- CtlSetLabel(eventP->data.ctlSelect.pControl, LstGetSelectionText(listP, LstGetSelection(listP)));
-}
-
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formUtil.h b/backends/platform/PalmOS/Src/launcher/forms/formUtil.h
deleted file mode 100644
index e9b87bc49f..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formUtil.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __FORMUTIL_H__
-#define __FORMUTIL_H__
-
-#define frmRedrawUpdateMS (frmRedrawUpdateCode + 1)
-#define frmRedrawUpdateMSImport (frmRedrawUpdateCode + 2)
-
-#define NO_ENGINE -1
-
-// form list draw
-#define ITEM_TYPE_UNKNOWN 'U'
-#define ITEM_TYPE_CARD 'C'
-#define ITEM_TYPE_SKIN 'S'
-
-extern Char **itemsText;
-extern void *itemsList;
-extern Char itemsType;
-
-void FrmReturnToMain(UInt16 updateCode = frmRedrawUpdateMS);
-void * GetObjectPtr(UInt16 objectID);
-void FldTrimText(FieldPtr fldP);
-void FrmList(EventPtr eventP, UInt16 objectID);
-
-#endif
diff --git a/backends/platform/PalmOS/Src/launcher/forms/forminfo.cpp b/backends/platform/PalmOS/Src/launcher/forms/forminfo.cpp
deleted file mode 100644
index 3f4ab1b28f..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/forminfo.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-#include <PalmOS.h>
-
-#include "start.h"
-#include "formTabs.h"
-#include "forms.h"
-
-#include "base/version.h"
-#include "globals.h"
-#include "init_palmos.h"
-
-/***********************************************************************
- *
- * FUNCTION: MiscOptionsFormSave
- * FUNCTION: MiscOptionsFormInit
- * FUNCTION: MiscOptionsFormHandleEvent
- *
- * DESCRIPTION: Misc. Options form functions
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-static TabType *myTabP;
-static UInt16 lastTab = 0;
-
-static UInt32 GetStackSize() {
- MemPtr startPP, endPP;
- SysGetStackInfo(&startPP, &endPP);
-
- return ((Char *)endPP - (Char *)startPP) / 1024L;
-}
-
-static void VersionTabDraw() {
- WinDrawChars(gScummVMVersion, StrLen(gScummVMVersion), 47, 12 + 30);
- WinDrawChars(gScummVMBuildDate, StrLen(gScummVMBuildDate), 47, 24 + 30);
-}
-
-static void SystemTabDraw() {
- Coord x;
- UInt32 dm, sm, df, sf, stack;
- Char num[10];
-
- PalmGetMemory(&sm, &dm, &sf, 0);
- stack = GetStackSize();
- df = gVars->startupMemory;
-
- WinSetTextColor(UIColorGetTableEntryIndex(UIObjectForeground));
- FntSetFont(stdFont);
-
- StrIToA(num, dm);
- x = 147 - FntCharsWidth(num, StrLen(num)) + 5;
- WinDrawChars(num, StrLen(num), x, 12 + 30);
-
- StrIToA(num, sm);
- x = 147 - FntCharsWidth(num, StrLen(num)) + 5;
- WinDrawChars(num, StrLen(num), x, 24 + 30);
-
- StrIToA(num, stack);
- x = 147 - FntCharsWidth(num, StrLen(num)) + 5;
- WinDrawChars(num, StrLen(num), x, 36 + 30);
-
- StrIToA(num, df);
- x = 107 - FntCharsWidth(num, StrLen(num)) + 5;
- WinDrawChars(num, StrLen(num), x, 12 + 30);
-
- StrIToA(num, sf);
- x = 107 - FntCharsWidth(num, StrLen(num)) + 5;
- WinDrawChars(num, StrLen(num), x, 24 + 30);
-
- StrCopy(num,"-");
- x = 107 - FntCharsWidth(num, StrLen(num)) + 5;
- WinDrawChars(num, StrLen(num), x, 36 + 30);
-}
-
-static void InfoFormSave() {
- TabDeleteTabs(myTabP);
- FrmReturnToMain();
-}
-
-static void AboutTabDraw() {
- MemHandle hTemp;
- BitmapPtr bmpTemp;
-
- hTemp = DmGetResource (bitmapRsc, 1200);
- if (hTemp) {
- bmpTemp = (BitmapType *)MemHandleLock(hTemp);
- WinDrawBitmap(bmpTemp,3,44);
- MemPtrUnlock(bmpTemp);
- DmReleaseResource(hTemp);
- }
-}
-
-static void InfoFormInit() {
- TabType *tabP;
- FormType *frmP = FrmGetActiveForm();
-
- tabP = TabNewTabs(3);
- TabAddContent(&frmP, tabP, "About", TabInfoAboutForm, AboutTabDraw);
- TabAddContent(&frmP, tabP, "Version", TabInfoVersionForm, VersionTabDraw);
- TabAddContent(&frmP, tabP, "Memory", TabInfoSystemForm, SystemTabDraw);
-
- lastTab = 0;
- FrmDrawForm(frmP);
- TabSetActive(frmP, tabP, lastTab);
-
- myTabP = tabP;
-}
-
-Boolean InfoFormHandleEvent(EventPtr eventP) {
- FormPtr frmP = FrmGetActiveForm();
- Boolean handled = false;
-
- switch (eventP->eType) {
- case frmOpenEvent:
- InfoFormInit();
- handled = true;
- break;
-
- case frmCloseEvent:
- InfoFormSave();
- handled = true;
- break;
-
- case ctlSelectEvent:
- switch (eventP->data.ctlSelect.controlID)
- {
- case (InfoForm + 1) :
- case (InfoForm + 2) :
- case (InfoForm + 3) :
- lastTab = (eventP->data.ctlSelect.controlID - InfoForm - 1);
- TabSetActive(frmP, myTabP, lastTab);
- break;
-
- case InfoOKButton:
- InfoFormSave();
- break;
- }
- handled = true;
- break;
-
- default:
- break;
- }
-
- return handled;
-}
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formmain.cpp b/backends/platform/PalmOS/Src/launcher/forms/formmain.cpp
deleted file mode 100644
index ca2e18ee6d..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formmain.cpp
+++ /dev/null
@@ -1,364 +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 <PalmOS.h>
-
-#include "StarterRsc.h"
-#include "start.h"
-#include "skin.h"
-#include "games.h"
-#include "globals.h"
-
-#include "base/version.h"
-
-#include "formEditGame.h"
-#include "formUtil.h"
-
-static UInt16 sknLastOn = skinButtonNone;
-
-static Err BeamMe() {
- UInt16 cardNo;
- LocalID dbID;
- Err err;
-
- err = SysCurAppDatabase(&cardNo, &dbID);
- if (dbID)
- err = SendDatabase(0, dbID, "ScummVM.prc", "\nPlay your favorite LucasArts games");
- else
- err = DmGetLastErr();
-
- return err;
-}
-
-/***********************************************************************
- *
- * FUNCTION: MainFormInit
- *
- * DESCRIPTION: This routine initializes the MainForm form.
- *
- * PARAMETERS: frm - pointer to the MainForm form.
- *
- * RETURNED: nothing
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-static void MainFormInit()
-{
- SknApplySkin();
-}
-
-/***********************************************************************
- *
- * FUNCTION: MainFormDoCommand
- *
- * DESCRIPTION: This routine performs the menu command specified.
- *
- * PARAMETERS: command - menu item id
- *
- * RETURNED: nothing
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-
-static Boolean MainFormDoCommand(UInt16 command)
-{
- Boolean handled = false;
-
- switch (command) {
- case MainGamesMemoryCard:
- FrmPopupForm(CardSlotForm);
- handled = true;
- break;
-
- case MainGamesNew:
- gFormEditMode = edtModeAdd;
- FrmPopupForm(GameEditForm);
- handled = true;
- break;
-
- case MainGamesEdit:
- gFormEditMode = edtModeEdit;
- FrmPopupForm(GameEditForm);
- handled = true;
- break;
-
- case MainGamesDelete:
- EditGameFormDelete(true);
- handled = true;
- break;
-
- case MainOptionsBeam:
- BeamMe();
- //if (BeamMe())
- //FrmCustomAlert(FrmErrorAlert,"Unable to beam ScummVM for PalmOS.",0,0);
- handled = true;
- break;
-
- case MainOptionsAbout:
- FrmPopupForm(InfoForm);
- handled = true;
- break;
-
- case MainGamesMusicSound:
- FrmPopupForm(MusicForm);
- handled = true;
- break;
-
- case MainOptionsSkins:
- FrmPopupForm(SkinsForm);
- handled = true;
- break;
-
- case MainOptionsMisc:
- FrmPopupForm(MiscForm);
- handled = true;
- break;
- }
-
- MenuEraseStatus(0);
- return handled;
-}
-
-/***********************************************************************
- *
- * FUNCTION: MainFormHandleEvent
- *
- * DESCRIPTION: This routine is the event handler for the
- * "MainForm" of this application.
- *
- * PARAMETERS: eventP - a pointer to an EventType structure
- *
- * RETURNED: true if the event has handle and should not be passed
- * to a higher level handler.
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-
-static Boolean PenDownRepeat() {
- Coord x,y;
- Boolean penDown, handled = false;
- EvtGetPen(&x, &y, &penDown);
-
- if (penDown && sknLastOn) {
- RectangleType r;
- DmOpenRef skinDBP;
-
- skinDBP = SknOpenSkin();
- SknGetObjectBounds(skinDBP, sknLastOn, &r);
-
- if (RctPtInRectangle(x*2, y*2, &r)) {
- if (SknGetState(skinDBP, sknLastOn) != sknStateSelected) {
- SknSetState(skinDBP, sknLastOn, sknStateSelected);
- SknShowObject(skinDBP, sknLastOn);
- }
-
- switch (sknLastOn) {
- case skinSliderUpArrow:
- case skinSliderDownArrow:
- handled = SknProcessArrowAction(sknLastOn);
- break;
- }
-
- } else {
- if (SknGetState(skinDBP, sknLastOn) != sknStateNormal) {
- SknSetState(skinDBP, sknLastOn, sknStateNormal);
- SknShowObject(skinDBP, sknLastOn);
- }
- }
-
- SknCloseSkin(skinDBP);
- }
-
- return handled;
-}
-
-
-Boolean MainFormHandleEvent(EventPtr eventP)
-{
- Boolean handled = false;
- FormPtr frmP;
- Coord x,y;
- DmOpenRef skinDBP;
-
- switch (eventP->eType) {
- case frmUpdateEvent:
- {
- RectangleType r;
- UInt16 idx;
- IndexedColorType bgColor = UIColorGetTableEntryIndex(UIFormFill);
- frmP = FrmGetFormPtr(MainForm);
-
- if (gPrefs->card.volRefNum != vfsInvalidVolRef)
- idx = FrmGetObjectIndex (frmP, MainMSBitMap);
- else
- idx = FrmGetObjectIndex (frmP, MainMSNoneBitMap);
-
- WinSetDrawMode(winPaint);
- WinSetBackColor(bgColor);
- FrmGetObjectBounds(frmP, idx, &r);
- WinEraseRectangle(&r, 0);
- FrmShowObject(frmP, idx);
-
- if (eventP->data.frmUpdate.updateCode == frmRedrawUpdateMSImport) {
- GamImportDatabase();
- SknUpdateList();
- }
- handled = true;
- break;
- }
- case menuEvent:
- handled = MainFormDoCommand(eventP->data.menu.itemID);
- break;
-
- case frmOpenEvent:
- MainFormInit();
- handled = true;
- break;
-
- case ctlSelectEvent:
- switch (eventP->data.ctlSelect.controlID)
- {
- case MainCardsButton:
- //gPrefs->card.volRefNum = parseCards(true);
- FrmPopupForm(CardSlotForm);
- break;
-
- case MainAboutButton:
- FrmPopupForm(InfoForm);
- break;
-
-// case MainListTypeSelTrigger:
-// FrmList(eventP, MainListTypeList);
-// break;
- }
- handled = true;
- break;
-
- case penUpEvent:
- x = eventP->screenX;
- y = eventP->screenY;
- lastIndex = dmMaxRecordIndex; // enable select/unselect list item
-
- if (sknLastOn != skinButtonNone) {
- RectangleType r;
- skinDBP = SknOpenSkin();
- SknGetObjectBounds(skinDBP, sknLastOn, &r);
- SknSetState(skinDBP, sknLastOn, sknStateNormal);
- SknShowObject(skinDBP, sknLastOn);
- SknCloseSkin(skinDBP);
-
- if (RctPtInRectangle(x*2, y*2, &r)) {
- switch (sknLastOn) {
- case skinButtonGameAdd:
- gFormEditMode = edtModeAdd;
- FrmPopupForm(GameEditForm);
- handled = true;
- break;
-
- case skinButtonGameAudio:
- FrmPopupForm(MusicForm);
- handled = true;
- break;
-
- case skinButtonGameEdit:
- case skinButtonGameParams:
- gFormEditMode = edtModeParams;
- FrmPopupForm(GameEditForm);
- handled = true;
- break;
-
- case skinButtonGameStart:
- if (gPrefs->card.volRefNum == vfsInvalidVolRef)
- FrmCustomAlert(FrmWarnAlert,"Please select/insert a memory card.", 0, 0);
- else if (GamGetSelected() != dmMaxRecordIndex)
- StartScummVM();
- else
- FrmPopupForm(EngineForm);
- handled = true;
- break;
-
- case skinButtonGameDelete:
- EditGameFormDelete(true);
- break;
- }
- }
- sknLastOn = skinButtonNone;
- }
- break;
-
- case penDownEvent:
- case penMoveEvent:
- if (sknLastOn == skinButtonNone) {
- x = eventP->screenX;
- y = eventP->screenY;
- skinDBP = SknOpenSkin();
-
- switch (sknLastOn = SknCheckClick(skinDBP, x,y)) {
- case skinButtonNone:
- break;
- case skinSliderUpArrow:
- case skinSliderDownArrow:
- case skinButtonGameAdd:
- case skinButtonGameEdit:
- case skinButtonGameParams:
- case skinButtonGameStart:
- case skinButtonGameDelete:
- case skinButtonGameAudio:
- SknSetState(skinDBP, sknLastOn, sknStateSelected);
- SknShowObject(skinDBP, sknLastOn);
- if (gPrefs->soundClick)
- SndPlaySystemSound(sndClick);
- handled = true;
- break;
- default:
- FrmCustomAlert(FrmWarnAlert,"Unknown button !",0,0);
- }
- SknCloseSkin(skinDBP);
- SknSelect(x, y);
- }
- break;
-
- case keyDownEvent:
- if ( (eventP->data.keyDown.chr >= 'a' && eventP->data.keyDown.chr <= 'z') ||
- (eventP->data.keyDown.chr >= 'A' && eventP->data.keyDown.chr <= 'Z')) {
- if (GamJumpTo(eventP->data.keyDown.chr)) {
- SknUpdateList();
- handled = true;
- }
- }
- break;
-
- default:
- handled = PenDownRepeat();
- }
-
- return handled;
-}
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp b/backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp
deleted file mode 100644
index 58eaa5b5fc..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp
+++ /dev/null
@@ -1,388 +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 <PalmOS.h>
-
-#include "start.h"
-#include "formTabs.h"
-#include "forms.h"
-#include "games.h"
-
-#include "globals.h"
-
-static TabType *myTabP;
-static UInt16 lastTab = 0;
-
-static GameInfoType *gameInfoP = NULL;
-
-// Music
-static Boolean MusicTabSave() {
- ControlType *cck1P, *cck2P;
- ListType *list1P, *list2P, *list3P;
- FieldType *fld1P;
- UInt16 tempo;
- FormPtr frmP;
-
- frmP = FrmGetActiveForm();
-
- cck1P = (ControlType *)GetObjectPtr(TabMusicMusicCheckbox);
- cck2P = (ControlType *)GetObjectPtr(TabMusicMultiMidiCheckbox);
-
- list1P = (ListType *)GetObjectPtr(TabMusicDriverList);
- list2P = (ListType *)GetObjectPtr(TabMusicRateList);
- list3P = (ListType *)GetObjectPtr(TabMusicQualityList);
-
- fld1P = (FieldType *)GetObjectPtr(TabMusicTempoField);
-
- tempo = StrAToI(FldGetTextPtr(fld1P));
- if (tempo < 50 || tempo > 200) {
- TabSetActive(frmP, myTabP, 0);
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, TabMusicTempoField));
- FrmCustomAlert(FrmErrorAlert, "Invalid tempo value (50...200)", 0, 0);
- return false;
- }
-
- gameInfoP->musicInfo.sound.music = CtlGetValue(cck1P);
- gameInfoP->musicInfo.sound.multiMidi = CtlGetValue(cck2P);
-
- gameInfoP->musicInfo.sound.drvMusic = LstGetSelection(list1P);
- gameInfoP->musicInfo.sound.rate = LstGetSelection(list2P);
- gameInfoP->fmQuality = LstGetSelection(list3P);
- gameInfoP->musicInfo.sound.tempo = tempo;
-
- return true;
-}
-
-static void MusicTabInit() {
- ControlType *cck1P, *cck2P;
- ListType *list1P, *list2P, *list3P;
- FieldType *fld1P;
- MemHandle tempoH;
- Char *tempoP;
-
- cck1P = (ControlType *)GetObjectPtr(TabMusicMusicCheckbox);
- cck2P = (ControlType *)GetObjectPtr(TabMusicMultiMidiCheckbox);
-
- list1P = (ListType *)GetObjectPtr(TabMusicDriverList);
- list2P = (ListType *)GetObjectPtr(TabMusicRateList);
- list3P = (ListType *)GetObjectPtr(TabMusicQualityList);
-
- fld1P = (FieldType *)GetObjectPtr(TabMusicTempoField);
-
- CtlSetValue(cck1P, gameInfoP->musicInfo.sound.music);
- CtlSetValue(cck2P, gameInfoP->musicInfo.sound.multiMidi);
-
- if (gameInfoP->musicInfo.sound.drvMusic > 5)
- gameInfoP->musicInfo.sound.drvMusic = 0;
-
-
- LstSetSelection(list1P, gameInfoP->musicInfo.sound.drvMusic);
- LstSetTopItem(list1P, gameInfoP->musicInfo.sound.drvMusic);
- CtlSetLabel((ControlType *)GetObjectPtr(TabMusicDriverPopTrigger), LstGetSelectionText(list1P, LstGetSelection(list1P)));
-
- LstSetSelection(list2P, gameInfoP->musicInfo.sound.rate);
- LstSetTopItem(list2P, gameInfoP->musicInfo.sound.rate);
- CtlSetLabel((ControlType *)GetObjectPtr(TabMusicRatePopTrigger), LstGetSelectionText(list2P, LstGetSelection(list2P)));
-
- LstSetSelection(list3P, gameInfoP->fmQuality);
- CtlSetLabel((ControlType *)GetObjectPtr(TabMusicQualityPopTrigger), LstGetSelectionText(list3P, LstGetSelection(list3P)));
-
- tempoH = MemHandleNew(FldGetMaxChars(fld1P)+1);
- tempoP = (Char *)MemHandleLock(tempoH);
- StrIToA(tempoP, gameInfoP->musicInfo.sound.tempo);
- MemHandleUnlock(tempoH);
- FldSetTextHandle(fld1P, tempoH);
-}
-
-// Audio CD
-static Boolean AudioCDTabSave() {
- ControlType *cck3P;
- FieldType *fld2P, *fld3P;
- ListType *list1P, *list2P;
- UInt16 firstTrack;
- FormPtr frmP;
-
- frmP = FrmGetActiveForm();
-
- cck3P = (ControlType *)GetObjectPtr(TabAudioCDMP3Checkbox);
- fld2P = (FieldType *)GetObjectPtr(TabAudioCDLengthSecsField);
- fld3P = (FieldType *)GetObjectPtr(TabAudioCDFirstTrackField);
- list1P = (ListType *)GetObjectPtr(TabAudioCDDriverList);
- list2P = (ListType *)GetObjectPtr(TabAudioCDFormatList);
-
- firstTrack = StrAToI(FldGetTextPtr(fld3P));
- if (firstTrack < 1 || firstTrack > 999) {
- TabSetActive(frmP, myTabP, 2);
- FrmSetFocus(frmP, FrmGetObjectIndex(frmP, TabAudioCDFirstTrackField));
- FrmCustomAlert(FrmErrorAlert, "Invalid track value (1...999)", 0, 0);
- return false;
- }
-
- gameInfoP->musicInfo.sound.CD = CtlGetValue(cck3P);
-
- gameInfoP->musicInfo.sound.drvCD = LstGetSelection(list1P);
- gameInfoP->musicInfo.sound.frtCD = LstGetSelection(list2P);
-
- gameInfoP->musicInfo.sound.defaultTrackLength = StrAToI(FldGetTextPtr(fld2P));
- gameInfoP->musicInfo.sound.firstTrack = firstTrack;
-
- return true;
-}
-
-static void AudioCDTabInit() {
- ControlType *cck3P;
- FieldType *fld2P, *fld3P;
- ListType *list1P, *list2P;
- MemHandle lengthH, firstTrackH;
- Char *lengthP, *firstTrackP;
-
- cck3P = (ControlType *)GetObjectPtr(TabAudioCDMP3Checkbox);
- fld2P = (FieldType *)GetObjectPtr(TabAudioCDLengthSecsField);
- fld3P = (FieldType *)GetObjectPtr(TabAudioCDFirstTrackField);
- list1P = (ListType *)GetObjectPtr(TabAudioCDDriverList);
- list2P = (ListType *)GetObjectPtr(TabAudioCDFormatList);
-
- LstSetSelection(list1P, gameInfoP->musicInfo.sound.drvCD);
- CtlSetLabel((ControlType *)GetObjectPtr(TabAudioCDDriverPopTrigger), LstGetSelectionText(list1P, LstGetSelection(list1P)));
-
- LstSetSelection(list2P, gameInfoP->musicInfo.sound.frtCD);
- CtlSetLabel((ControlType *)GetObjectPtr(TabAudioCDFormatPopTrigger), LstGetSelectionText(list2P, LstGetSelection(list2P)));
-
- CtlSetValue(cck3P, gameInfoP->musicInfo.sound.CD);
-
- lengthH = MemHandleNew(FldGetMaxChars(fld2P)+1);
- lengthP = (Char *)MemHandleLock(lengthH);
- StrIToA(lengthP, gameInfoP->musicInfo.sound.defaultTrackLength);
- MemHandleUnlock(lengthH);
- FldSetTextHandle(fld2P, lengthH);
-
- firstTrackH = MemHandleNew(FldGetMaxChars(fld3P)+1);
- firstTrackP = (Char *)MemHandleLock(firstTrackH);
- StrIToA(firstTrackP, gameInfoP->musicInfo.sound.firstTrack);
- MemHandleUnlock(firstTrackH);
- FldSetTextHandle(fld3P, firstTrackH);
-}
-
-// Volume
-static void VolumeTabSave() {
- SliderControlType *slid1P, *slid2P, *slid3P, *slid4P, *slid5P;
-
- slid1P = (SliderControlType *)GetObjectPtr(TabVolumePalmSliderControl);
- slid2P = (SliderControlType *)GetObjectPtr(TabVolumeMusicSliderControl);
- slid3P = (SliderControlType *)GetObjectPtr(TabVolumeSfxSliderControl);
- slid4P = (SliderControlType *)GetObjectPtr(TabVolumeSpeechSliderControl);
- slid5P = (SliderControlType *)GetObjectPtr(TabVolumeAudioCDSliderControl);
-
- CtlGetSliderValues ((ControlType *)slid1P, 0, 0, 0, &gameInfoP->musicInfo.volume.palm);
- CtlGetSliderValues ((ControlType *)slid2P, 0, 0, 0, &gameInfoP->musicInfo.volume.music);
- CtlGetSliderValues ((ControlType *)slid3P, 0, 0, 0, &gameInfoP->musicInfo.volume.sfx);
- CtlGetSliderValues ((ControlType *)slid4P, 0, 0, 0, &gameInfoP->musicInfo.volume.speech);
- CtlGetSliderValues ((ControlType *)slid5P, 0, 0, 0, &gameInfoP->musicInfo.volume.audiocd);
-}
-
-static void VolumeTabInit() {
- SliderControlType *slid1P, *slid2P, *slid3P, *slid4P, *slid5P;
- UInt16 value;
-
- slid1P = (SliderControlType *)GetObjectPtr(TabVolumePalmSliderControl);
- slid2P = (SliderControlType *)GetObjectPtr(TabVolumeMusicSliderControl);
- slid3P = (SliderControlType *)GetObjectPtr(TabVolumeSfxSliderControl);
- slid4P = (SliderControlType *)GetObjectPtr(TabVolumeSpeechSliderControl);
- slid5P = (SliderControlType *)GetObjectPtr(TabVolumeAudioCDSliderControl);
-
- value = gameInfoP->musicInfo.volume.palm;
- CtlSetSliderValues ((ControlType *)slid1P, 0, 0, 0, &value);
- value = gameInfoP->musicInfo.volume.music;
- CtlSetSliderValues ((ControlType *)slid2P, 0, 0, 0, &value);
- value = gameInfoP->musicInfo.volume.sfx;
- CtlSetSliderValues ((ControlType *)slid3P, 0, 0, 0, &value);
- value = gameInfoP->musicInfo.volume.speech;
- CtlSetSliderValues ((ControlType *)slid4P, 0, 0, 0, &value);
- value = gameInfoP->musicInfo.volume.audiocd;
- CtlSetSliderValues ((ControlType *)slid5P, 0, 0, 0, &value);
-}
-
-static void MusicFormSave(UInt16 index) {
- if (index != dmMaxRecordIndex) {
- MemHandle recordH;
- GameInfoType *ogameInfoP;
-
- if (!MusicTabSave()) return;
- if (!AudioCDTabSave()) return;
- VolumeTabSave();
-
- recordH = DmGetRecord(gameDB, index);
- ogameInfoP = (GameInfoType *)MemHandleLock(recordH);
- DmWrite(ogameInfoP, 0, gameInfoP, sizeof(GameInfoType));
- MemHandleUnlock(recordH);
- DmReleaseRecord (gameDB, index, 0);
- }
-
- MemPtrFree(gameInfoP);
- gameInfoP = NULL;
-
- TabDeleteTabs(myTabP);
- FrmReturnToMain();
-}
-static void MusicFormInit(UInt16 index) {
- TabType *tabP;
- FormType *frmP = FrmGetActiveForm();
-
- if (index != dmMaxRecordIndex) {
- MemHandle recordH = NULL;
- GameInfoType *ogameInfoP;
-
- recordH = DmQueryRecord(gameDB, index);
- ogameInfoP = (GameInfoType *)MemHandleLock(recordH);
-
- if (!ogameInfoP) {
- FrmCustomAlert(FrmErrorAlert, "An error occured.",0,0);
- return;
- }
-
- gameInfoP = (GameInfoType *)MemPtrNew(sizeof(GameInfoType));
- MemMove(gameInfoP, ogameInfoP, sizeof(GameInfoType));
- MemHandleUnlock(recordH);
-
- } else {
- FrmCustomAlert(FrmWarnAlert, "Select an entry first.",0,0);
- FrmReturnToMain();
- return;
- }
-
- tabP = TabNewTabs(3);
- TabAddContent(&frmP, tabP, "Sound", TabMusicForm);
- TabAddContent(&frmP, tabP, "Volume", TabVolumeForm);
- TabAddContent(&frmP, tabP, "Audio CD", TabAudioCDForm);
-
- MusicTabInit();
- AudioCDTabInit();
- VolumeTabInit();
-
- FrmDrawForm(frmP);
- TabSetActive(frmP, tabP, lastTab);
-
- myTabP = tabP;
-}
-
-Boolean MusicFormHandleEvent(EventPtr eventP) {
- FormPtr frmP = FrmGetActiveForm();
- Boolean handled = false;
-
- switch (eventP->eType) {
- case frmOpenEvent:
- MusicFormInit(GamGetSelected());
- handled = true;
- break;
-
- case frmCloseEvent:
- MusicFormSave(dmMaxRecordIndex);
- handled = true;
- break;
-
- case ctlSelectEvent:
- switch (eventP->data.ctlSelect.controlID)
- {
- case (MusicForm + 1) :
- case (MusicForm + 2) :
- case (MusicForm + 3) :
- lastTab = (eventP->data.ctlSelect.controlID - MusicForm - 1);
- TabSetActive(frmP, myTabP, lastTab);
- break;
-
- case TabMusicDriverPopTrigger:
- FrmList(eventP, TabMusicDriverList);
- FrmHideObject(frmP, FrmGetObjectIndex(frmP, TabMusicDriverList));
-
- if (!OPTIONS_TST(kOptDeviceZodiac) && !OPTIONS_TST(kOptSonyPa1LibAPI)) {
- ListType *list1P = (ListType *)GetObjectPtr(TabMusicDriverList);
-
- if (LstGetSelection(list1P) == 4) {
- FrmCustomAlert(FrmInfoAlert, "There is no built-in MIDI support on your device.", 0, 0);
- LstSetSelection(list1P, 0);
- CtlSetLabel((ControlType *)GetObjectPtr(TabMusicDriverPopTrigger), LstGetSelectionText(list1P, LstGetSelection(list1P)));
- }
- }
- break;
-
- case TabMusicQualityPopTrigger:
- FrmList(eventP, TabMusicQualityList);
- FrmHideObject(frmP, FrmGetObjectIndex(frmP, TabMusicQualityList));
- break;
-
- case TabMusicRatePopTrigger:
- FrmList(eventP, TabMusicRateList);
- FrmHideObject(frmP, FrmGetObjectIndex(frmP, TabMusicRateList));
-
- if (!OPTIONS_TST(kOptPalmSoundAPI)) {
- ListType *list1P = (ListType *)GetObjectPtr(TabMusicRateList);
-
- if (LstGetSelection(list1P) != 0) {
- FrmCustomAlert(FrmInfoAlert, "You cannot use this rate on your device.", 0, 0);
- LstSetSelection(list1P, 0);
- CtlSetLabel((ControlType *)GetObjectPtr(TabMusicRatePopTrigger), LstGetSelectionText(list1P, LstGetSelection(list1P)));
- }
- }
- break;
-
- case TabAudioCDFormatPopTrigger:
- FrmList(eventP, TabAudioCDFormatList);
- FrmHideObject(frmP, FrmGetObjectIndex(frmP, TabAudioCDFormatList));
-
- if (LstGetSelection((ListPtr)GetObjectPtr(TabAudioCDDriverList)) == 1) {
- ListType *list1P = (ListType *)GetObjectPtr(TabAudioCDFormatList);
- LstSetSelection(list1P, 0);
- CtlSetLabel((ControlType *)GetObjectPtr(TabAudioCDFormatPopTrigger), LstGetSelectionText(list1P, LstGetSelection(list1P)));
- }
- break;
-
- case TabAudioCDDriverPopTrigger:
- FrmList(eventP, TabAudioCDDriverList);
- FrmHideObject(frmP, FrmGetObjectIndex(frmP, TabAudioCDDriverList));
-
- if (LstGetSelection((ListPtr)GetObjectPtr(TabAudioCDDriverList)) == 1) {
- ListType *list1P = (ListType *)GetObjectPtr(TabAudioCDFormatList);
- LstSetSelection(list1P, 0);
- CtlSetLabel((ControlType *)GetObjectPtr(TabAudioCDFormatPopTrigger), LstGetSelectionText(list1P, LstGetSelection(list1P)));
- }
- break;
-
- case MusicOKButton:
- MusicFormSave(GamGetSelected());
- break;
-
- case MusicCancelButton:
- MusicFormSave(dmMaxRecordIndex);
- break;
- }
- handled = true;
- break;
-
- default:
- break;
- }
-
- return handled;
-}
diff --git a/backends/platform/PalmOS/Src/launcher/forms/forms.h b/backends/platform/PalmOS/Src/launcher/forms/forms.h
deleted file mode 100644
index ca0089d8c1..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/forms.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __FORMS_H__
-#define __FORMS_H__
-
-#include "StarterRsc.h"
-#include "formUtil.h"
-
-#include "formEditGame.h"
-#include "formCards.h"
-
-
-#define HANDLER(x) Boolean x##FormHandleEvent(EventPtr eventP);
-
-HANDLER(Main)
-HANDLER(EditGame)
-HANDLER(SystemInfo)
-HANDLER(Misc)
-HANDLER(CardSlot)
-HANDLER(Skins)
-HANDLER(Music)
-HANDLER(Info)
-HANDLER(Selector)
-
-#endif
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formtabs.cpp b/backends/platform/PalmOS/Src/launcher/forms/formtabs.cpp
deleted file mode 100644
index d3f18e39d7..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formtabs.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-#include <PalmOS.h>
-#include <CtlGlue.h>
-#include <FrmGlue.h>
-#include <LstGlue.h>
-
-#include "globals.h"
-#include "formTabs.h"
-
-TabType *TabNewTabs(UInt16 cnt) {
- TabType *newP = new TabType;
-
- newP->count = 0;
- newP->width = 0;
- newP->tabs = new TabDataType[cnt];
-
- return newP;
-}
-
-void TabMoveUpObject(FormType *frmP, UInt16 objID, Coord amount) {
- Coord x, y;
- FrmGetObjectPosition(frmP, FrmGetObjectIndex(frmP, objID), &x, &y);
- FrmSetObjectPosition(frmP, FrmGetObjectIndex(frmP, objID), x, y - amount);
-}
-
-void TabDeleteTabs(TabType *tabP) {
- UInt16 cnt, num;
- num = MemPtrSize(tabP->tabs) / sizeof(TabDataType);
-
- for (cnt = 0; cnt < num; cnt++)
- FrmDeleteForm(tabP->tabs[cnt].srcP);
-
- delete tabP->tabs;
- delete tabP;
-}
-
-Err TabAddContent(FormType **frmP, TabType *tabP, const Char *nameP, UInt16 rscID, TabProc *drawFunc) {
- FormType *srcP;
- UInt16 cnt;
- void *objP, **dstP;
- UInt16 objNum;
- Coord x, y, w, h;
- UInt16 id;
- RectangleType r;
-
- dstP = (void **)frmP;
- srcP = FrmInitForm(rscID);
-
- objNum = FrmGetNumberOfObjects(srcP);
-
- // save tab data
-
- // it's required to keep to source forms active
- // while the tab form is not close for list data ptr (items text)
- // TODO : fix this !
- tabP->tabs[tabP->count].srcP = srcP;
- tabP->tabs[tabP->count].first = FrmGetObjectId(srcP, 0);
- tabP->tabs[tabP->count].last = FrmGetObjectId(srcP, objNum - 1);
- tabP->tabs[tabP->count].drawFunc= drawFunc;
- tabP->count++;
- tabP->active = tabP->count;
-
- // create tab
- FntSetFont(stdFont);
- x = 4 + tabP->width;
- y = 16;
- w = FntCharsWidth(nameP, StrLen(nameP)) + 6;
- h = 12;
- ControlType *addP = CtlNewControl(dstP, (FrmGetFormId(*frmP) + tabP->count), buttonCtl, nameP, x, y, w, h, stdFont, 0, true);
- CtlGlueSetFrameStyle(addP, noButtonFrame);
- tabP->width += w + 3;
-
- // create tab content
- for (cnt = 0; cnt < objNum; cnt++) {
- objP = FrmGetObjectPtr(srcP, cnt);
- id = FrmGetObjectId(srcP, cnt);
- FrmGetObjectBounds(srcP, cnt, &r);
- x = r.topLeft.x - 2;
- y = r.topLeft.y + 30;
- w = r.extent.x;
- h = r.extent.y;
-
- FrmSetObjectPosition(srcP, cnt, x, y);
-
- switch (FrmGetObjectType(srcP, cnt)) {
- case frmListObj: {
- // HOWTO : to auto link the list to a popup trigger the listID must be popupID + 1 if popup id
- // desn't exist the triggerID will be 0 and the list will be shown, but take care to not define
- // ListID - 1 object if you want to show the list.
- ListType *newP;
- Char **itemsP = LstGlueGetItemsText((ListType *)objP);
- FontID font = LstGlueGetFont((ListType *)objP);
- UInt16 visible = LstGetVisibleItems((ListType *)objP);
- UInt16 items = LstGetNumberOfItems((ListType *)objP);
- UInt16 trigger = id - 1;
- trigger = (FrmGetObjectIndex((FormType *)*dstP, trigger) != frmInvalidObjectId) ? trigger : 0;
-
- LstNewList(dstP, id, x, y, w, h, font, visible, trigger);
- newP = (ListType *)FrmGetObjectPtr((FormType *)*dstP, FrmGetObjectIndex((FormType *)*dstP, id));
- LstSetListChoices(newP, itemsP, items);
- FrmHideObject((FormType *)*dstP, FrmGetObjectIndex((FormType *)*dstP, id));
- break;
- }
- case frmFieldObj: {
- FieldAttrType attr;
- FontID font = FldGetFont((FieldType *)objP);
- UInt16 maxChars = FldGetMaxChars((FieldType *)objP);
- FldGetAttributes((FieldType *)objP, &attr);
- FldNewField(dstP, id, x, y, w, h, font, maxChars, attr.editable, attr.underlined, attr.singleLine, attr.dynamicSize, (JustificationType)attr.justification, attr.autoShift, attr.hasScrollBar, attr.numeric);
- FrmHideObject((FormType *)*dstP, FrmGetObjectIndex((FormType *)*dstP, id));
- break;
- }
- case frmControlObj: {
- const Char *textP = CtlGetLabel((ControlType *)objP);
- ControlStyleType style = CtlGlueGetControlStyle((ControlType *)objP);
- FontID font = CtlGlueGetFont((ControlType *)objP);
- ControlType *newP = CtlNewControl(dstP, id, style, textP, x, y, w, h, font, 0, true);
- FrmHideObject((FormType *)*dstP, FrmGetObjectIndex((FormType *)*dstP, id));
- switch (style) {
- case sliderCtl:
- {
- UInt16 min, max, page, val;
- CtlGetSliderValues((ControlType *)objP, &min, &max, &page, &val);
- CtlSetSliderValues(newP, &min, &max, &page, &val);
- break;
- }
- }
- break;
- }
- case frmLabelObj: {
- const Char *textP = FrmGetLabel(srcP, id);
- FontID font = FrmGlueGetLabelFont(srcP, id);
- FrmNewLabel((FormType **)dstP, id, textP, x, y, font);
- FrmHideObject((FormType *)*dstP, FrmGetObjectIndex((FormType *)*dstP, id));
- break;
- }
-
- case frmBitmapObj: {
-/* UInt16 family = id + 1;
- FrmNewBitmap((FormType **)dstP, id, id, x, y);
- //FrmHideObject((FormType *)*dstP, FrmGetObjectIndex((FormType *)*dstP, id));
-*/ break;
- }
- }
- }
-
- frmP = (FormType **)dstP; // save new form ptr
- return errNone;
-}
-
-void TabSetActive(FormType *frmP, TabType *tabP, UInt16 num) {
- UInt16 cnt, idx;
- RectangleType r;
- TabDataPtr dataP;
-
- if (tabP->active == num)
- return;
-
- dataP = &tabP->tabs[tabP->active];
-
- // hide active tab objects
- if (tabP->active != tabP->count) {
- for (cnt = dataP->first; cnt <= dataP->last; cnt++) {
- if ((idx = FrmGetObjectIndex(frmP, cnt)) != frmInvalidObjectId)
- FrmHideObject(frmP, idx);
- }
- }
-
- // save active tab
- tabP->active = num;
- dataP = &tabP->tabs[num];
-
- // draw tab limit
- WinSetForeColor(UIColorGetTableEntryIndex(UIFormFill));
- WinDrawLine(1, 14, 154,14);
- WinDrawLine(1, 15, 154,15);
- RctSetRectangle(&r, 1, 30, 154, 100);
- WinDrawRectangle(&r, 0);
- WinSetForeColor(UIColorGetTableEntryIndex(UIObjectFrame));
- WinDrawLine(1, 28, 154,28);
-
- // set tabs size
- for (cnt = 0; cnt < tabP->count; cnt++) {
- idx = FrmGetObjectIndex (frmP, (FrmGetFormId(frmP) + cnt + 1));
-
- if (idx != frmInvalidObjectId) {
- FrmGetObjectBounds(frmP, idx, &r);
- r.topLeft.y = (num == cnt) ? 17 : 17;
- r.extent.y = (num == cnt) ? 12 : 11;
- FrmSetObjectBounds(frmP, idx, &r);
-
- if (num == cnt) {
- RGBColorType yellow = {0,255,192,0};
-
- UInt8 line = /*(UIColorGetTableEntryIndex(UIFormFill) == UIColorGetTableEntryIndex(UIFieldTextHighlightBackground)) ?
- WinRGBToIndex(&yellow) :*/
- UIColorGetTableEntryIndex(UIFieldTextHighlightBackground);
-
- r.topLeft.y -= 1;
- WinSetForeColor(UIColorGetTableEntryIndex(UIObjectFrame));
- WinDrawRectangleFrame(simpleFrame, &r);
- WinSetForeColor(line);
- WinDrawLine(r.topLeft.x, r.topLeft.y, r.topLeft.x + r.extent.x - 1, r.topLeft.y);
- FrmShowObject(frmP, idx);
-
- } else {
- UInt8 frame = UIColorGetTableEntryIndex(UIObjectFrame);
- RGBColorType light;
- WinIndexToRGB(frame, &light);
- light.r = (255 - light.r) > 72 ? light.r + 72 : 255;
- light.g = (255 - light.g) > 72 ? light.g + 72 : 255;
- light.b = (255 - light.b) > 72 ? light.b + 72 : 255;
-
- WinSetForeColor(WinRGBToIndex(&light));
- WinDrawRectangleFrame(simpleFrame, &r);
- WinSetForeColor(frame);
- WinDrawLine(r.topLeft.x - 1, r.topLeft.y + r.extent.y, r.topLeft.x + r.extent.x, r.topLeft.y + r.extent.y);
- }
-
- // round corner
- WinSetForeColor(UIColorGetTableEntryIndex(UIFormFill));
- if (OPTIONS_TST(kOptModeHiDensity)) {
- WinSetCoordinateSystem(kCoordinatesNative);
- WinDrawPixel((r.topLeft.x - 1) * 2, (r.topLeft.y - 1) * 2);
- WinDrawPixel((r.topLeft.x + r.extent.x) * 2 + 1, (r.topLeft.y - 1) * 2);
- WinSetCoordinateSystem(kCoordinatesStandard);
-
- } else {
- // TODO
- }
- }
- }
-
- // show objects
- for (cnt = dataP->first; cnt <= dataP->last; cnt++) {
- if ((idx = FrmGetObjectIndex(frmP, cnt)) != frmInvalidObjectId)
- FrmShowObject(frmP, idx);
- }
-
- // post draw function
- if (dataP->drawFunc)
- (dataP->drawFunc)();
-}
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formtabs.h b/backends/platform/PalmOS/Src/launcher/forms/formtabs.h
deleted file mode 100644
index f14c2ff4e4..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formtabs.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef __FORMTABS_H__
-#define __FORMTABS_H__
-
-typedef void (TabProc)();
-
-typedef struct {
- FormPtr srcP;
- UInt16 first;
- UInt16 last;
- TabProc *drawFunc;
-} TabDataType, *TabDataPtr;
-
-typedef struct {
- UInt16 count, active;
- Coord width;
- TabDataPtr tabs;
-} TabType, *TabPtr;
-
-TabType *TabNewTabs (UInt16 cnt);
-void TabDeleteTabs (TabType *tabP);
-Err TabAddContent (FormType **frmP, TabType *tabP, const Char *nameP, UInt16 rscID, TabProc *drawFunc = 0);
-void TabSetActive (FormType *frmP, TabType *tabP, UInt16 num);
-void TabMoveUpObject (FormType *frmP, UInt16 objID, Coord amount);
-#endif
diff --git a/backends/platform/PalmOS/Src/launcher/games.cpp b/backends/platform/PalmOS/Src/launcher/games.cpp
deleted file mode 100644
index c3f7ef3e4a..0000000000
--- a/backends/platform/PalmOS/Src/launcher/games.cpp
+++ /dev/null
@@ -1,548 +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 <PalmOS.h>
-#include <VFSMgr.h>
-#include <ctype.h>
-
-#include "globals.h"
-#include "palmdefs.h"
-#include "start.h"
-#include "games.h"
-#include "skin.h"
-
-#include "StarterRsc.h"
-
-DmOpenRef gameDB = NULL;
-
-static Err GamUpdateList() {
- if (gameDB) {
- UInt16 numRecs = DmNumRecords(gameDB);
-
- if (numRecs > 0) {
- MemHandle tmpH;
- UInt32 version, size;
- UInt32 *versionP;
-
- // get record size and version
- tmpH = DmQueryRecord(gameDB, 0);
- size = MemHandleSize(tmpH);
- versionP = (UInt32 *)MemHandleLock(tmpH);
- version = *versionP;
- MemHandleUnlock(tmpH);
-
- // check record
- if (version != curItemVersion || size != sizeof(GameInfoType)) {
- UInt16 index;
- GameInfoType gitCur;
- void *tmpP;
- FormPtr ofmP, frmP;
-
- // show dialog
- ofmP = FrmGetActiveForm();
- frmP = FrmInitForm(ConvertForm);
- FrmSetActiveForm(frmP);
- FrmDrawForm(frmP);
- SysTaskDelay(1 * SysTicksPerSecond());
-
- MemSet(&gitCur, sizeof(GameInfoType), 0);
-
- if (version == itemVersion_357 ||
- version == itemVersion_356 ||
- version == itemVersion_355 ||
- version == itemVersion_354 ||
- version == itemVersion_353 ||
- version == itemVersion_352 ||
- version == itemVersion_351 ||
- version == itemVersion_350 ||
- version == itemVersion_340 ||
- version == itemVersion_330 ||
- version == itemVersion_320 ||
- version == itemVersion_310 ||
- version == itemVersion_300 ||
- version == itemVersion_270 ||
- version == itemVersion_260 ||
- version == itemVersion_250) {
- for (index = 0; index < numRecs; index++) {
- // get old data
- tmpH = DmQueryRecord(gameDB, index);
- tmpP = MemHandleLock(tmpH);
- MemMove(&gitCur, tmpP, MemHandleSize(tmpH));
- MemHandleUnlock(tmpH);
-
- // new format
- gitCur.version = curItemVersion;
-
- if (version < itemVersion_300) {
- gitCur.musicInfo.volume.palm = 50;
- gitCur.musicInfo.volume.music = 192;
- gitCur.musicInfo.volume.sfx = 192;
- gitCur.musicInfo.volume.speech = 192;
- gitCur.musicInfo.volume.audiocd = 50;
-
- gitCur.musicInfo.sound.tempo = 100;
- gitCur.musicInfo.sound.defaultTrackLength = 10;
- gitCur.musicInfo.sound.firstTrack = 1;
- }
-
- if (version < itemVersion_310)
- gitCur.engine = 0;
-
- if (version < itemVersion_320)
- gitCur.renderMode = 0;
-
- if (version <= itemVersion_330) {
- gitCur.fmQuality = 0;
- gitCur.gfxMode = (gitCur.gfxMode == 3 ? 1 : 0); // v3.4 only 2 modes
-
- if (gitCur.engine == 0) gitCur.engine = 8;
- else if (gitCur.engine == 1) gitCur.engine = 7;
- else if (gitCur.engine == 2) gitCur.engine = 3;
- else if (gitCur.engine == 3) gitCur.engine = 1;
- else if (gitCur.engine == 4) gitCur.engine = 0;
- else if (gitCur.engine == 5) gitCur.engine = 6;
- else if (gitCur.engine == 6) gitCur.engine = 4;
- else if (gitCur.engine == 7) gitCur.engine = 5;
- else if (gitCur.engine == 8) gitCur.engine = 2;
-
- if (gitCur.renderMode == 1) gitCur.renderMode = 4;
- else if (gitCur.renderMode == 2) gitCur.renderMode = 5;
- else if (gitCur.renderMode == 3) gitCur.renderMode = 2;
- else if (gitCur.renderMode == 4) gitCur.renderMode = 3;
- else if (gitCur.renderMode == 5) gitCur.renderMode = 1;
-
- if (gitCur.platform == 2) gitCur.platform = 6;
- else if (gitCur.platform == 5) gitCur.platform = 8;
- else if (gitCur.platform == 6) gitCur.platform = 2;
-
- if (gitCur.language == 1) gitCur.language = 4;
- else if (gitCur.language == 2) gitCur.language = 6;
- else if (gitCur.language == 3) gitCur.language = 5;
- else if (gitCur.language == 4) gitCur.language = 8;
- else if (gitCur.language == 5) gitCur.language = 11;
- else if (gitCur.language == 6) gitCur.language = 13;
- else if (gitCur.language == 7) gitCur.language = 9;
- else if (gitCur.language == 8) gitCur.language = 1;
- else if (gitCur.language == 9) gitCur.language = 10;
- else if (gitCur.language == 10) gitCur.language = 7;
- else if (gitCur.language == 11) gitCur.language = 12;
- else if (gitCur.language == 12) gitCur.language = 2;
- else if (gitCur.language == 13) gitCur.language = 3;
-
- if (gitCur.musicInfo.sound.drvMusic == 1) gitCur.musicInfo.sound.drvMusic = 4;
- else if (gitCur.musicInfo.sound.drvMusic == 2) gitCur.musicInfo.sound.drvMusic = 5;
- else if (gitCur.musicInfo.sound.drvMusic == 4) gitCur.musicInfo.sound.drvMusic = 2;
- else if (gitCur.musicInfo.sound.drvMusic == 5) gitCur.musicInfo.sound.drvMusic = 1;
- }
-
- if (version <= itemVersion_340) {
- gitCur.platform++;
-
- if (gitCur.language == 3)
- gitCur.language = 0;
- else if (gitCur.language >= 11)
- gitCur.language++;
- }
-
- if (version <= itemVersion_350)
- if (gitCur.platform >= 9)
- gitCur.platform++;
-
- if (version <= itemVersion_351) {
- if (gitCur.engine >= ENGINE_LURE) // newly added engine
- gitCur.engine++;
-
- if (gitCur.engine == ENGINE_SCUMM) // reorder
- gitCur.engine = ENGINE_AGOS;
- else if (gitCur.engine == ENGINE_AGOS)
- gitCur.engine = ENGINE_SCUMM;
- }
-
- if (version <= itemVersion_352) {
- if (gitCur.engine >= ENGINE_CINE) // newly added engine
- gitCur.engine++;
-
- gitCur.platform++;
- }
-
- if (version <= itemVersion_353)
- gitCur.musicInfo.sound.drvMusic++;
-
- if (version <= itemVersion_354)
- if (gitCur.engine >= ENGINE_AGI) // newly added engine
- gitCur.engine++;
-
- if (version <= itemVersion_355) {
- gitCur.engine++; // renamed Simon -> AGOS
- if (gitCur.engine == ENGINE_COUNT)
- gitCur.engine = ENGINE_AGOS;
- }
-
- if (version <= itemVersion_356) {
- if (gitCur.platform >= 3)
- gitCur.platform++;
- }
-
- if (version <= itemVersion_357)
- if (gitCur.engine >= ENGINE_PARALLACTION) // newly added engine
- gitCur.engine++;
-
- if (gitCur.musicInfo.volume.palm > 100)
- gitCur.musicInfo.volume.palm = 50;
-
- // simply resize the old record
- tmpH = DmResizeRecord(gameDB, index, sizeof(GameInfoType)); // TODO : check error on resize tmpH==NULL
- tmpP = MemHandleLock(tmpH);
- DmWrite(tmpP, 0, &gitCur, sizeof(GameInfoType));
- MemPtrUnlock(tmpP);
- }
-
- } else if (version == itemVersion_200) {
- // need conversion from V2 -> V3.5.2
- GameInfoTypeV2 git0;
-
- for (index = 0; index < numRecs; index++) {
-
- // get old data
- tmpH = DmQueryRecord(gameDB, index);
- tmpP = MemHandleLock(tmpH);
- MemMove(&git0, tmpP, sizeof(GameInfoTypeV2));
- MemHandleUnlock(tmpH);
-
- // convert to new format
- gitCur.version = curItemVersion;
- gitCur.icnID = 0xFFFF;
- gitCur.selected = git0.selected;
- StrCopy(gitCur.nameP, git0.nameP);
- StrCopy(gitCur.pathP, git0.pathP);
- StrCopy(gitCur.gameP, git0.gameP);
- gitCur.gfxMode = (git0.gfxMode == 3 ? 1 : 0); // v3.4 only 2 modes
-
- gitCur.autoLoad = git0.autoLoad;
- gitCur.bootParam = git0.bootParam;
- gitCur.setPlatform = git0.setPlatform;
- gitCur.subtitles = git0.subtitles;
- gitCur.talkSpeed = git0.talkSpeed;
-
- gitCur.loadSlot = git0.loadSlot;
- gitCur.bootValue = git0.bootValue;
- gitCur.talkValue = git0.talkValue;
- gitCur.platform = git0.platform;
- gitCur.language = git0.language;
-
- gitCur.musicInfo.volume.palm = 50;
- gitCur.musicInfo.volume.music = 192;
- gitCur.musicInfo.volume.sfx = 192;
- gitCur.musicInfo.volume.speech = 192;
- gitCur.musicInfo.volume.audiocd = 50;
-
- gitCur.musicInfo.sound.tempo = 100;
- gitCur.musicInfo.sound.defaultTrackLength = 10;
- gitCur.musicInfo.sound.firstTrack = 1;
-
- // to V3.4
- if (gitCur.platform == 2) gitCur.platform = 6;
- else if (gitCur.platform == 5) gitCur.platform = 8;
- else if (gitCur.platform == 6) gitCur.platform = 2;
-
- if (gitCur.language == 1) gitCur.language = 4;
- else if (gitCur.language == 2) gitCur.language = 6;
- else if (gitCur.language == 3) gitCur.language = 5;
- else if (gitCur.language == 4) gitCur.language = 8;
- else if (gitCur.language == 5) gitCur.language = 11;
- else if (gitCur.language == 6) gitCur.language = 13;
- else if (gitCur.language == 7) gitCur.language = 9;
- else if (gitCur.language == 8) gitCur.language = 1;
- else if (gitCur.language == 9) gitCur.language = 10;
- else if (gitCur.language == 10) gitCur.language = 7;
- else if (gitCur.language == 11) gitCur.language = 12;
- else if (gitCur.language == 12) gitCur.language = 2;
- else if (gitCur.language == 13) gitCur.language = 3;
-
- if (gitCur.musicInfo.sound.drvMusic == 1) gitCur.musicInfo.sound.drvMusic = 4;
- else if (gitCur.musicInfo.sound.drvMusic == 2) gitCur.musicInfo.sound.drvMusic = 5;
- else if (gitCur.musicInfo.sound.drvMusic == 4) gitCur.musicInfo.sound.drvMusic = 2;
- else if (gitCur.musicInfo.sound.drvMusic == 5) gitCur.musicInfo.sound.drvMusic = 1;
-
- // to V3.5
- gitCur.platform++;
-
- if (gitCur.language == 3)
- gitCur.language = 0;
- else if (gitCur.language >= 11)
- gitCur.language++;
-
- // to V3.5.1
- if (gitCur.platform >= 9)
- gitCur.platform++;
-
- //to V3.5.3
- gitCur.musicInfo.sound.drvMusic++;
-
- // -----
- gitCur.engine = ENGINE_SCUMM;
-
- tmpH = DmResizeRecord(gameDB, index, sizeof(GameInfoType)); // TODO : check error on resize tmpH==NULL
- tmpP = MemHandleLock(tmpH);
- DmWrite(tmpP, 0, &gitCur, sizeof(GameInfoType));
- MemPtrUnlock(tmpP);
- }
- } else {
- // need conversion from V0 -> V3.5.2
- GameInfoTypeV0 git0;
-
- for (index = 0; index < numRecs; index++) {
-
- // get old data
- tmpH = DmQueryRecord(gameDB, index);
- tmpP = MemHandleLock(tmpH);
- MemMove(&git0, tmpP, sizeof(GameInfoTypeV0));
- MemHandleUnlock(tmpH);
-
- // convert to new format
- gitCur.version = curItemVersion;
- gitCur.icnID = 0xFFFF;
- gitCur.selected = git0.selected;
- StrCopy(gitCur.nameP, git0.nameP);
- StrCopy(gitCur.pathP, git0.pathP);
- StrCopy(gitCur.gameP, git0.gameP);
- gitCur.gfxMode = (git0.gfxMode == 3 ? 1 : 0); // v3.4 only 2 modes
-
- gitCur.autoLoad = git0.autoLoad;
- gitCur.bootParam = git0.bootParam;
- gitCur.setPlatform = git0.amiga; // amiga become platform amiga/atari-st/machintosh
- gitCur.platform = 1;
- gitCur.subtitles = git0.subtitles;
- gitCur.talkSpeed = git0.talkSpeed;
-
- gitCur.loadSlot = git0.loadSlot;
- gitCur.bootValue = git0.bootValue;
- gitCur.talkValue = git0.talkValue;
- gitCur.platform = 2; // default to amiga
- gitCur.language = git0.language;
-
- gitCur.musicInfo.volume.palm = 50;
- gitCur.musicInfo.volume.music = 192;
- gitCur.musicInfo.volume.sfx = 192;
- gitCur.musicInfo.volume.speech = 192;
- gitCur.musicInfo.volume.audiocd = 50;
-
- gitCur.musicInfo.sound.tempo = 100;
- gitCur.musicInfo.sound.defaultTrackLength = 10;
- gitCur.musicInfo.sound.firstTrack = 1;
-
- gitCur.engine = ENGINE_SCUMM;
-
- tmpH = DmResizeRecord(gameDB, index, sizeof(GameInfoType)); // TODO : check error on resize tmpH==NULL
- tmpP = MemHandleLock(tmpH);
- DmWrite(tmpP, 0, &gitCur, sizeof(GameInfoType));
- MemPtrUnlock(tmpP);
- }
- }
-
- FrmEraseForm(frmP);
- FrmDeleteForm(frmP);
- if (ofmP)
- FrmSetActiveForm(ofmP);
- }
- }
- }
-
- return errNone;
-}
-
-Err GamOpenDatabase() {
- Err err = errNone;
-
- gameDB = DmOpenDatabaseByTypeCreator( 'DATA', appFileCreator, dmModeReadWrite);
-
- if (!gameDB) {
- err = DmCreateDatabase(0, "ScummVM-Data", appFileCreator, 'DATA', false);
- if (!err) {
- gameDB = DmOpenDatabaseByTypeCreator( 'DATA', appFileCreator, dmModeReadWrite);
-
- if (!gameDB)
- err = DmGetLastErr();
- }
- }
-
- if (err)
- FrmCustomAlert(FrmErrorAlert,"Cannot open/create games list DB !",0,0);
- else
- err = GamUpdateList();
-
- return err;
-}
-
-void GamImportDatabase() {
- if (gPrefs->card.volRefNum != vfsInvalidVolRef && gPrefs->card.moveDB) {
- FileRef file;
- Err e;
-
- e = VFSFileOpen(gPrefs->card.volRefNum, "/Palm/Programs/ScummVM/listdata.pdb", vfsModeRead, &file);
- if (!e) {
- UInt16 oCardNo, nCardNo;
- LocalID oDbID, nDbID;
-
- VFSFileClose(file);
- if (gPrefs->card.confirmMoveDB)
- if (FrmCustomAlert(FrmConfirmAlert, "Do you want to import games database from memory card ?", 0, 0) == FrmConfirmNo) {
- // prevent to replace the file on memory card
- gPrefs->card.moveDB = false;
- return;
- }
-
- // get current db info and rename it
- DmOpenDatabaseInfo(gameDB, &oDbID, 0, 0, &oCardNo, 0);
- GamCloseDatabase(true);
- e = DmDeleteDatabase(oCardNo, oDbID);
-
- if (!e)
- if (e = VFSImportDatabaseFromFile(gPrefs->card.volRefNum, "/Palm/Programs/ScummVM/listdata.pdb", &nCardNo, &nDbID))
- FrmCustomAlert(FrmErrorAlert, "Failed to import games database from memory card.", 0, 0);
-
- GamOpenDatabase();
- }
- }
-}
-
-void GamCloseDatabase(Boolean ignoreCardParams) {
- if (gameDB) {
- LocalID dbID;
- UInt16 cardNo;
-
- DmOpenDatabaseInfo(gameDB, &dbID, 0, 0, &cardNo, 0);
- DmCloseDatabase(gameDB);
-
- if (!ignoreCardParams) {
- if (gPrefs->card.moveDB && gPrefs->card.volRefNum != vfsInvalidVolRef) {
- VFSFileRename(gPrefs->card.volRefNum, "/Palm/Programs/ScummVM/listdata.pdb", "listdata-old.pdb");
- Err e = VFSExportDatabaseToFile(gPrefs->card.volRefNum, "/Palm/Programs/ScummVM/listdata.pdb", cardNo, dbID);
- if (!e) {
- VFSFileDelete(gPrefs->card.volRefNum, "/Palm/Programs/ScummVM/listdata-old.pdb");
- if (gPrefs->card.deleteDB)
- DmDeleteDatabase(cardNo, dbID);
- } else {
- VFSFileRename(gPrefs->card.volRefNum, "/Palm/Programs/ScummVM/listdata-old.pdb", "listdata.pdb");
- }
- }
- }
- }
- gameDB = NULL;
-}
-
-static Int16 GamCompare(GameInfoType *a, GameInfoType *b, SortRecordInfoPtr, SortRecordInfoPtr, MemHandle) {
- return StrCaselessCompare(a->nameP, b->nameP);
-}
-
-Err GamSortList() {
- return DmQuickSort (gameDB, (DmComparF *)GamCompare, 0);
-}
-
-void GamUnselect() {
- GameInfoType *game;
-
- MemHandle recordH;
- UInt16 index;
-
- index = GamGetSelected();
-
- if (index != dmMaxRecordIndex) {
- Boolean newValue;
-
- recordH = DmGetRecord(gameDB, index);
- game = (GameInfoType *)MemHandleLock(recordH);
-
- newValue = false;
- DmWrite(game, OffsetOf(GameInfoType,selected), &newValue, sizeof(Boolean));
-
- MemHandleUnlock(recordH);
- DmReleaseRecord (gameDB, index, 0);
- }
-}
-
-UInt16 GamGetSelected() {
- MemHandle record;
- GameInfoType *game;
- Boolean selected;
- UInt16 index = DmNumRecords(gameDB)-1;
-
- while (index != (UInt16)-1) {
- record = DmQueryRecord(gameDB, index);
- game = (GameInfoType *)MemHandleLock(record);
- selected = game->selected;
- MemHandleUnlock(record);
-
- if (selected)
- return index;
-
- index--;
- }
-
- return dmMaxRecordIndex;
-}
-
-Boolean GamJumpTo(Char letter) {
- MemHandle record;
- GameInfoType *game;
- Boolean found = false;
- UInt16 index = 0;
- UInt16 maxIndex = DmNumRecords(gameDB);
- UInt16 active = GamGetSelected();
-
- while (index < maxIndex) {
- record = DmGetRecord(gameDB, index);
- game = (GameInfoType *)MemHandleLock(record);
-
- if (tolower(game->nameP[0]) == tolower(letter)) {
- found = true;
-
- if (index != active) {
- RectangleType rArea;
- UInt16 maxView;
- Boolean newValue = true;
-
- SknGetListBounds(&rArea, NULL);
- maxView = rArea.extent.y / sknInfoListItemSize;
-
- GamUnselect();
- DmWrite(game, OffsetOf(GameInfoType,selected), &newValue, sizeof(Boolean));
-
- if (index < gPrefs->listPosition || index >= (gPrefs->listPosition + maxView))
- gPrefs->listPosition = index;
- }
- }
-
- MemHandleUnlock(record);
- DmReleaseRecord (gameDB, index, 0);
-
- index++;
-
- if (found)
- return found;
- }
-
- return found;
-}
diff --git a/backends/platform/PalmOS/Src/launcher/games.h b/backends/platform/PalmOS/Src/launcher/games.h
deleted file mode 100644
index 7c381a40f4..0000000000
--- a/backends/platform/PalmOS/Src/launcher/games.h
+++ /dev/null
@@ -1,212 +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$
- *
- */
-
-#ifndef __GAMES_H__
-#define __GAMES_H__
-
-#define curItemVersion sysMakeROMVersion(3,5,8,0,0) // Parallaction engine
-
-
-#define itemVersion_357 sysMakeROMVersion(3,5,7,0,0) // Added : Apple IIgs
-#define itemVersion_356 sysMakeROMVersion(3,5,6,0,0) // Changed : Simon -> AGOS
-#define itemVersion_355 sysMakeROMVersion(3,5,5,0,0) // Added : AGI engine
-#define itemVersion_354 sysMakeROMVersion(3,5,4,0,0) // Added : Default/Auto music driver
-#define itemVersion_353 sysMakeROMVersion(3,5,3,0,0) // Added : CinE engine and 3DO platform
-#define itemVersion_352 sysMakeROMVersion(3,5,2,0,0) // Added : Lure engine
-#define itemVersion_351 sysMakeROMVersion(3,5,1,0,0) // Added : Sega CD platform
-#define itemVersion_350 sysMakeROMVersion(3,5,0,0,0)
-#define itemVersion_340 sysMakeROMVersion(3,4,0,0,0)
-#define itemVersion_330 sysMakeROMVersion(3,3,0,0,0)
-#define itemVersion_320 sysMakeROMVersion(3,2,0,0,0)
-#define itemVersion_310 sysMakeROMVersion(3,1,0,0,0)
-#define itemVersion_300 sysMakeROMVersion(3,0,0,0,0)
-#define itemVersion_270 sysMakeROMVersion(2,7,0,0,0)
-#define itemVersion_260 sysMakeROMVersion(2,6,0,0,0)
-#define itemVersion_250 sysMakeROMVersion(2,5,0,0,0)
-#define itemVersion_200 sysMakeROMVersion(2,0,0,0,0)
-
-// old config structs
-typedef struct {
- UInt32 version;
- UInt16 icnID; // icon to display on the list
- Boolean selected;
-
- Char nameP[50]; // game name to display in list
- Char pathP[150]; // path to the game files
- Char gameP[10]; // scumm name of the game
- UInt16 gfxMode;
-
- Boolean autoLoad;
- UInt16 loadSlot;
- Boolean bootParam;
- UInt16 bootValue;
- Boolean amiga;
- Boolean subtitles;
- Boolean talkSpeed;
- UInt16 talkValue;
- UInt8 language;
-
-} GameInfoTypeV0;
-
-typedef struct {
- UInt32 version;
- UInt16 icnID; // icon to display on the list
- Boolean selected;
-
- Char nameP[50]; // game name to display in list
- Char pathP[150]; // path to the game files
- Char gameP[10]; // scumm name of the game
- UInt16 gfxMode;
-
- Boolean autoLoad;
- Boolean bootParam;
- Boolean setPlatform;
- Boolean subtitles;
- Boolean talkSpeed;
-
- UInt16 loadSlot;
- UInt16 bootValue;
- UInt16 talkValue;
- UInt8 platform;
- UInt8 language;
-
-} GameInfoTypeV2;
-
-
-// Current config
-typedef struct {
- struct {
- UInt16 palm;
- UInt16 music;
- UInt16 sfx; // TODO : remove
- UInt16 speech;
- UInt16 audiocd;
- } volume;
-
- struct {
- // midi
- Boolean multiMidi;
- Boolean music; // TODO : rename this, it is enable audio option
- UInt8 drvMusic;
- UInt8 tempo;
- // sound FX
- Boolean sfx; // TODO : remove this
- UInt8 rate;
- // CD audio
- Boolean CD;
- UInt8 drvCD, frtCD;
- UInt16 defaultTrackLength;
- UInt16 firstTrack;
- } sound;
-} MusicInfoType;
-
-typedef struct {
- UInt32 version;
- UInt16 icnID; // icon to display on the list
- Boolean selected;
-
- Char nameP[50]; // game name to display in list
- Char pathP[150]; // path to the game files
- Char gameP[15]; // scumm name of the game
- UInt16 gfxMode;
-
- Boolean autoLoad;
- Boolean bootParam;
- Boolean setPlatform;
- Boolean subtitles;
- Boolean talkSpeed;
-
- UInt16 loadSlot;
- UInt16 bootValue;
- UInt16 talkValue;
- UInt8 platform;
- UInt8 language; // |- v2.5
-
- Boolean filter; // v2.6
- Boolean fullscreen; // |
- Boolean aspectRatio; // |- v2.7
-
- MusicInfoType musicInfo;// v3.0
-
- UInt8 engine; // |- v3.1
- UInt8 renderMode; // |- v3.2
-// Boolean use16Bit; // |- v3.3 // removed
- UInt8 fmQuality; // |- v3.4 // replace use16Bit
-} GameInfoType;
-
-enum {
- ENGINE_AGOS = 0,
- ENGINE_SKY,
- ENGINE_SWORD1,
- ENGINE_SWORD2,
- ENGINE_CINE,
- ENGINE_QUEEN,
- ENGINE_LURE,
- ENGINE_GOB,
- ENGINE_KYRA,
- ENGINE_PARALLACTION,
- ENGINE_SAGA,
- ENGINE_SCUMM,
- ENGINE_AGI,
- ENGINE_TOUCHE,
- ENGINE_CRUISE,
- ENGINE_DRASCULA,
- ENGINE_COUNT
-};
-
-static const struct {
- const char *fileP;
- const char *nameP;
-} engines[] = {
- { "agos", "AGOS Engine" },
- { "sky", "Beneath a Steel Sky" },
- { "sword1", "Broken Sword I" },
- { "sword2", "Broken Sword II" },
- { "cine", "Delphine Cinematique v1.0" },
- { "queen", "Flight of the Amazon Queen" },
- { "lure", "Lure of the Tempress" },
- { "gob", "Gobliiins, Bargon Attack and more" },
- { "kyra", "Kyrandia" },
- { "parallaction", "Parallaction" },
- { "saga", "SAGA Engine" },
- { "scumm", "Scumm Games" },
- { "agi", "Sierra AGI" },
- { "touche", "Touche: The Adventures of the Fifth Musketeer" },
- { "cruise", "Beta -> Cruise for a Corpse" },
- { "drascula", "Beta -> Drascula" },
-};
-
-// protos
-Err GamOpenDatabase ();
-void GamImportDatabase ();
-void GamCloseDatabase (Boolean ignoreCardParams);
-Err GamSortList ();
-UInt16 GamGetSelected ();
-void GamUnselect ();
-Boolean GamJumpTo (Char letter);
-
-extern DmOpenRef gameDB;
-
-#endif
diff --git a/backends/platform/PalmOS/Src/launcher/launch.cpp b/backends/platform/PalmOS/Src/launcher/launch.cpp
deleted file mode 100644
index cb2d52b20e..0000000000
--- a/backends/platform/PalmOS/Src/launcher/launch.cpp
+++ /dev/null
@@ -1,512 +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 <PalmOS.h>
-#include <PmPalmOSNVFS.h>
-#include "StarterRsc.h"
-
-#include "games.h"
-#include "start.h"
-#include "rumble.h"
-#include "globals.h"
-#include "features.h"
-#include "formUtil.h"
-#include "formCards.h"
-#include "palmdefs.h"
-
-#include "init_palmos.h"
-#include "init_stuffs.h"
-
-#include "modules.h"
-#include "args.h"
-
-
-#define BUILD_ERROR(m) \
- { StrCopy(msg, m); \
- StrCat(msg, "\n\nPlease check that all required files are installed on your card, and you have enough free storage memory."); \
- goto onError; }
-
-#define BUILD_FILE(h,m) \
- StrCopy(filename, "/Palm/Programs/ScummVM/Mods/"); \
- StrCat(filename, h); \
- StrCat(filename, m);
-
-#define FIND_FILE() \
- if (*volRefNum == vfsInvalidVolRef) \
- *volRefNum = ModFind(filename);
-
-
-#define CHECK_FILE(m) \
- e = VFSFileOpen(*volRefNum, filename, vfsModeRead, &file); \
- if (e) \
- BUILD_ERROR(m) \
- else \
- VFSFileClose(file);
-
-#define IMPRT_FILE(m) \
- e = VFSImportDatabaseFromFile(*volRefNum, filename, &cardNo, &dbID); \
- if (e) \
- BUILD_ERROR(m)
-
-#define DELET_FILE(f) \
- del_dbID = DmFindDatabase(0, f); \
- if (del_dbID) \
- DmDeleteDatabase(0, del_dbID);
-
-void ModDelete() {
- LocalID del_dbID;
-
- DELET_FILE("Glbs::Common");
- DELET_FILE("Glbs::Engine");
- DELET_FILE("ScummVM-Engine");
-}
-
-UInt16 ModFind(const Char *f) {
- Err e;
- UInt16 volRefNum;
- FileRef r;
- UInt32 volIterator = vfsIteratorStart|vfsIncludePrivateVolumes;
- while (volIterator != vfsIteratorStop) {
- e = VFSVolumeEnumerate(&volRefNum, &volIterator);
-
- if (!e) e = VFSFileOpen(volRefNum, f, vfsModeRead, &r);
- if (!e) e = VFSFileClose(r);
- if (!e) break;
- }
-
- return volRefNum;
-}
-
-static void ModSetStack(UInt32 newSize, UInt16 cardNo, LocalID dbID) {
- DmOpenRef dbRef = DmOpenDatabase(cardNo, dbID, dmModeReadWrite);
-
- if (dbRef) {
- MemHandle pref = DmGetResource('pref',0);
- UInt32 size = 0;
-
- if (pref) {
- SysAppPrefsType *data = (SysAppPrefsType *)MemHandleLock(pref);
- size = data->stackSize;
-
- if (newSize) {
- SysAppPrefsType newData;
- MemMove(&newData, data, sizeof(SysAppPrefsType));
- newData.stackSize = newSize;
- DmWrite(data, 0, &newData, sizeof(SysAppPrefsType));
- }
-
- MemPtrUnlock(data);
- DmReleaseResource(pref);
- }
-
- DmCloseDatabase(dbRef);
- }
-}
-
-static Err ModImport(UInt16 *volRefNum, UInt8 engine, Boolean *armP) {
-#ifndef _DEBUG_ENGINE
- char filename[256];
- UInt16 cardNo;
- LocalID dbID;
- UInt32 result;
- FileRef file;
-#endif
- char msg[256];
- FormPtr ofmP, frmP;
- Err e = errNone;
-
- ofmP = FrmGetActiveForm();
- frmP = FrmInitForm(ImportForm);
- FrmSetActiveForm(frmP);
- FrmDrawForm(frmP);
-
- // In debug mode, the engine files are directly uploaded to the simulator
-#ifndef _DEBUG_ENGINE
- // engine file ?
- BUILD_FILE(engines[engine].fileP, ".engine");
- FIND_FILE ();
- CHECK_FILE("ScummVM engine file was not found !");
- IMPRT_FILE("Cannot import engine file !");
-
- // need more files ?
- dbID = DmFindDatabase(0, "ScummVM-Engine"); // be sure to have the correct dbID
- e = SysAppLaunch(cardNo, dbID, 0, sysAppLaunchCustomEngineGetInfo, 0, &result);
- *armP = ((result & GET_MODEARM) == GET_MODEARM);
-
-/* ARM ONLY FOR NOW, NOT REQUIRED
- // common file ?
- if (!e && (result & GET_DATACOMMON)) {
- BUILD_FILE("common", ".data");
- CHECK_FILE("Common data file was not found !");
- IMPRT_FILE("Cannot import common data file !");
- }
- // data file ?
- if (!e && (result & GET_DATAENGINE)) {
- BUILD_FILE(engines[engine].fileP, ".data");
- CHECK_FILE("Engine data file was not found !");
- IMPRT_FILE("Cannot import engine data file !");
- }
-*/
-#endif
- // if error, cleanup
- if (e) ModDelete();
-
-onError:
- FrmEraseForm(frmP);
- FrmDeleteForm(frmP);
- if (e) {
- if (ofmP) FrmSetActiveForm(ofmP);
- FrmCustomAlert(FrmErrorAlert, msg, 0, 0);
- }
-
- return e;
-}
-
-#undef DELET_FILE
-#undef CHECK_FILE
-#undef BUILD_FILE
-
-Boolean StartScummVM(Int16 engine) {
- Char **argvP;
- UInt8 lightspeed, argc = 0;
- UInt32 stackSize;
- Boolean toLauncher, direct, isARM;
- Char num[6];
-
- argvP = ArgsInit();
- direct = false;
-
- // start command line (exec name)
- ArgsAdd(&argvP[argc], "-", NULL, &argc);
- // standard path
- ArgsAdd(&argvP[argc], "--themepath=", "/PALM/Programs/ScummVM/Themes", &argc);
-
- UInt16 index = GamGetSelected();
- // no game selected
- if (index == dmMaxRecordIndex) {
- if (engine == NO_ENGINE) {
- // free args
- ArgsFree(argvP);
- return false;
- }
-
- // default values
- if (bDirectMode)
- gPrefs->card.volRefNum = parseCards(); // always use the first removable card available (?)
-
- gVars->filter = true;
- gVars->palmVolume = 50;
- gVars->fmQuality = FM_QUALITY_INI;
- direct = true;
-
- // somthing selected
- } else {
- Char pathP[256];
- MemHandle recordH;
- GameInfoType *gameInfoP;
-
- recordH = DmQueryRecord(gameDB,index);
- gameInfoP = (GameInfoType *)MemHandleLock(recordH);
- engine = gameInfoP->engine;
-
- // build path
- StrCopy(pathP,"/Palm/Programs/ScummVM/Games/");
- if (gameInfoP->pathP[0] == '/')
- StrCopy(pathP, gameInfoP->pathP);
- else if (!(gameInfoP->pathP[0] == '.' && StrLen(gameInfoP->pathP) == 1))
- StrCat(pathP, gameInfoP->pathP);
-
- // path
- ArgsAdd(&argvP[argc], "-p", pathP, &argc);
-
- // language
- if (gameInfoP->language > 0) {
- const Char *lang = "zh\0cz\0gb\0en\0fr\0de\0hb\0it\0jp\0kr\0pl\0pt\0ru\0es\0se\0";
- ArgsAdd(&argvP[argc], "-q", (lang + (gameInfoP->language - 1) * 3), &argc);
- }
-
- // fullscreen ?
- if (gameInfoP->fullscreen)
- ArgsAdd(&argvP[argc], "-f", NULL, &argc);
-
- // aspect-ratio ?
- ArgsAdd(&argvP[argc], (gameInfoP->aspectRatio ? "--aspect-ratio" : "--no-aspect-ratio"), NULL, &argc);
-
- // gfx mode
- gVars->filter = gameInfoP->filter;
-
- switch (gameInfoP->renderMode) {
- case 1:
- ArgsAdd(&argvP[argc], "--render-mode=", "amiga", &argc);
- break;
- case 2:
- ArgsAdd(&argvP[argc], "--render-mode=", "cga", &argc);
- break;
- case 3:
- ArgsAdd(&argvP[argc], "--render-mode=", "ega", &argc);
- break;
- case 4:
- ArgsAdd(&argvP[argc], "--render-mode=", "hercAmber", &argc);
- break;
- case 5:
- ArgsAdd(&argvP[argc], "--render-mode=", "hercGreen", &argc);
- break;
- }
-
- switch (gameInfoP->gfxMode) {
- case 1:
- ArgsAdd(&argvP[argc], "-g", "wide", &argc);
- break;
- default:
- ArgsAdd(&argvP[argc], "-g", "1x", &argc);
- break;
- }
-
- // load state
- if (gameInfoP->autoLoad) {
- StrIToA(num, gameInfoP->loadSlot);
- ArgsAdd(&argvP[argc], "-x", num, &argc);
- }
- // boot script parameter
- if (gameInfoP->bootParam) {
- StrIToA(num, gameInfoP->bootValue);
- ArgsAdd(&argvP[argc], "-b", num, &argc);
- }
- // not a PC version
- if (gameInfoP->setPlatform) {
- static const char *platform[] = {
- "3do",
- "acorn",
- "amiga",
- "2gs",
- "atari",
- "c64",
- "pc",
- "fmtowns",
- "linux",
- "mac",
- "nes",
- "segacd",
- "windows"
- };
- ArgsAdd(&argvP[argc], "--platform=", platform[gameInfoP->platform], &argc);
- }
-
- // subtitles
- if (gameInfoP->subtitles)
- ArgsAdd(&argvP[argc], "-n", NULL, &argc);
-
- // multi midi ?
- if (gameInfoP->musicInfo.sound.multiMidi)
- ArgsAdd(&argvP[argc], "--multi-midi", NULL, &argc);
-
- if (engine == ENGINE_SCUMM) {
- // music tempo
- StrIToA(num, gameInfoP->musicInfo.sound.tempo);
- ArgsAdd(&argvP[argc], "--tempo=", num, &argc);
- }
-
- // talk speed
- if (gameInfoP->talkSpeed) {
- StrIToA(num, gameInfoP->talkValue);
- ArgsAdd(&argvP[argc], "--talkspeed=", num, &argc);
- }
-
- // music driver
- if (gameInfoP->musicInfo.sound.music) {
- static char *drv[] = {
- "auto",
- "null",
- "adlib",
- "towns",
- "pcjr",
- "native",
- "pcspk"
- };
-
- if (StrCompare(drv[gameInfoP->musicInfo.sound.drvMusic], "native") == 0) {
- if (OPTIONS_TST(kOptDeviceZodiac))
- ArgsAdd(&argvP[argc], "-e", "zodiac", &argc); // Tapwave Zodiac
- else if (OPTIONS_TST(kOptSonyPa1LibAPI))
- ArgsAdd(&argvP[argc], "-e", "ypa1", &argc); // Pa1Lib devices
- else
- ArgsAdd(&argvP[argc], "-e", "auto", &argc); // no driver, switch to auto
- } else {
- ArgsAdd(&argvP[argc], "-e", drv[gameInfoP->musicInfo.sound.drvMusic], &argc);
- }
-
- // output rate
- UInt32 rates[] = {4000, 8000, 11025, 22050, 44100};
- StrIToA(num, rates[gameInfoP->musicInfo.sound.rate]);
- ArgsAdd(&argvP[argc], "--output-rate=", num, &argc);
-
- // FM quality
- gVars->fmQuality = gameInfoP->fmQuality;
-
- } else {
- ArgsAdd(&argvP[argc], "-e", "null", &argc);
- }
-
- // volume control
- StrIToA(num, gameInfoP->musicInfo.volume.sfx);
- ArgsAdd(&argvP[argc], "-s", num, &argc);
- StrIToA(num, gameInfoP->musicInfo.volume.music);
- ArgsAdd(&argvP[argc], "-m", num, &argc);
- StrIToA(num, gameInfoP->musicInfo.volume.speech);
- ArgsAdd(&argvP[argc], "-r", num, &argc);
-
- // game name
- ArgsAdd(&argvP[argc], gameInfoP->gameP, NULL, &argc);
-
- gVars->palmVolume = gameInfoP->musicInfo.sound.music ? gameInfoP->musicInfo.volume.palm : 0;
-
- MemHandleUnlock(recordH);
- } // end no game / game selected
-
- // common command line options
-
- // debug level
- if (gPrefs->debug) {
- StrIToA(num, gPrefs->debugLevel);
- ArgsAdd(&argvP[argc], "-d", num, &argc);
- }
-
- if (engine == ENGINE_QUEEN || engine == ENGINE_SKY) {
- // alternative intro ?
- if (gPrefs->altIntro)
- ArgsAdd(&argvP[argc], "--alt-intro", NULL, &argc);
- }
-
- if (engine == ENGINE_SCUMM) {
- // demo mode ?
- if (gPrefs->demoMode)
- ArgsAdd(&argvP[argc], "--demo-mode", NULL, &argc);
- }
-
- // copy protection ?
- if (gPrefs->copyProtection)
- ArgsAdd(&argvP[argc], "--copy-protection", NULL, &argc);
-
- // exceed max args ?
- if (argc > MAX_ARG)
- FrmCustomAlert(FrmErrorAlert, "Too many parameters.",0,0);
-
- // set some common options
- stackSize = (gPrefs->setStack ? STACK_LARGER : STACK_DEFAULT);
- lightspeed= (gPrefs->lightspeed.enable ? gPrefs->lightspeed.mode : 255);
- toLauncher= (gPrefs->exitLauncher);
-
- // gVars values
- // (gVars->HRrefNum defined in checkHRmode on Clie)
-#ifndef _DEBUG_ENGINE
- gVars->VFS.volRefNum = (gPrefs->card.autoDetect ? vfsInvalidVolRef : gPrefs->card.volRefNum);
-#else
- gVars->VFS.volRefNum = gPrefs->card.volRefNum;
-#endif
- gVars->vibrator = gPrefs->vibrator;
- gVars->stdPalette = gPrefs->stdPalette;
- gVars->VFS.cacheSize = (gPrefs->card.useCache ? gPrefs->card.cacheSize : 0);
- gVars->indicator.showLED= gPrefs->card.showLED;
- gVars->stylusClick = gPrefs->stylusClick;
- gVars->autoSave = (gPrefs->autoSave ? gPrefs->autoSavePeriod : -1);
- gVars->advancedMode = gPrefs->advancedMode;
- gVars->arrowKeys = gPrefs->arrowKeys;
-
- // user params
- HWR_RSTALL();
-
- if (gPrefs->goLCD)
- HWR_SET(INIT_GOLCD);
- else
- OPTIONS_RST(kOptGoLcdAPI);
-
- if (!gPrefs->autoOff)
- HWR_SET(INIT_AUTOOFF);
-
- if (gVars->vibrator)
- HWR_SET(INIT_VIBRATOR);
-/* ????
- if ( musicDriver == 1 ||
- musicDriver == 3 ||
- musicDriver == 4 ||
- musicDriver == sysInvalidRefNum) {
- HWR_SET(INIT_PA1LIB);
- }
-*/
- if (ModImport(&gVars->VFS.volRefNum, engine, &isARM) != errNone) {
- if (bDirectMode) {
- // and force exit if nothing selected
- EventType event;
- event.eType = keyDownEvent;
- event.data.keyDown.chr = vchrLaunch;
- event.data.keyDown.modifiers = commandKeyMask;
- EvtAddUniqueEventToQueue(&event, 0, true);
- }
- ArgsFree(argvP);
- return false;
- }
-
- // reset mode if screen rotation occured (DIA only)
- if (!direct && OPTIONS_TST(kOptCollapsible)) {
- UInt8 mode = PalmScreenSize(0,0, &(gVars->screenFullWidth), &(gVars->screenFullHeight));
- OPTIONS_RST(kOptModeLandscape);
- OPTIONS_SET((mode == PALM_LANDSCAPE) ? kOptModeLandscape : kOptNone);
- }
-
- // free and save globals pref memory
- GamCloseDatabase(false);
- FrmCloseAllForms();
- SavePrefs();
-
- {
- UInt16 cardNo;
- UInt32 dbID;
-
- LaunchParamType *cmdPBP = (LaunchParamType *)MemPtrNew(sizeof(LaunchParamType));
-
- MemPtrSetOwner(cmdPBP, 0);
- MemPtrSetOwner(gVars, 0);
- ArgsSetOwner(argvP, 0);
-
- cardNo = 0;
- dbID = DmFindDatabase(0, "ScummVM-Engine");
-
- if (isARM)
- FtrSet(appFileCreator, ftrStack , (stackSize * 4));
- else
- ModSetStack(stackSize, cardNo, dbID);
-
- cmdPBP->args.argc = argc;
- cmdPBP->args.argv = argvP;
- cmdPBP->gVars = gVars;
- cmdPBP->lightspeed = lightspeed;
- cmdPBP->exitLauncher = toLauncher;
-
- SysUIAppSwitch(cardNo, dbID, sysAppLaunchCmdNormalLaunch, cmdPBP);
- bLaunched = true;
- }
-
- return false;
-}
diff --git a/backends/platform/PalmOS/Src/launcher/skin.cpp b/backends/platform/PalmOS/Src/launcher/skin.cpp
deleted file mode 100644
index 4c3f722aa1..0000000000
--- a/backends/platform/PalmOS/Src/launcher/skin.cpp
+++ /dev/null
@@ -1,612 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include <PalmOS.h>
-#include <PalmOSGlue.h>
-#include <SonyClie.h>
-
-#include "start.h"
-#include "games.h"
-#include "globals.h"
-#include "skin.h"
-#include "StarterRsc.h"
-
-UInt16 lastIndex = dmMaxRecordIndex; // last select index in the list to prevent flash
-static WinHandle winLockH = NULL;
-
-MemPtr SknScreenLock(WinLockInitType initMode) {
- Err e;
- RectangleType r;
-
- WinGetBounds(WinGetDisplayWindow(), &r);
- winLockH = WinCreateOffscreenWindow(r.extent.x, r.extent.y, nativeFormat, &e);
- WinSetDrawWindow(winLockH);
-
- if (initMode == winLockCopy)
- WinCopyRectangle(WinGetDisplayWindow(), winLockH, &r, 0, 0, winPaint);
-
- return BmpGetBits(WinGetBitmap(winLockH));
-}
-
-void SknScreenUnlock() {
- RectangleType r;
-
- WinGetBounds(winLockH, &r);
- WinCopyRectangle(winLockH, WinGetDisplayWindow(), &r, 0, 0, winPaint);
- WinSetDrawWindow(WinGetDisplayWindow());
- WinDeleteWindow(winLockH, false);
- winLockH = NULL;
-}
-
-static void SknGetListColors(DmOpenRef skinDBP, UInt8 *text, UInt8 *selected, UInt8 *background) {
- UInt16 colIndex;
- MemHandle colH;
- UInt8 *colTemp;
-
- // default
- *text = UIColorGetTableEntryIndex (UIMenuForeground);
- *selected = UIColorGetTableEntryIndex (UIMenuSelectedForeground);
- *background = UIColorGetTableEntryIndex (UIMenuSelectedFill);
-
- if (skinDBP) {
- colIndex = DmFindResource (skinDBP, sknColorsRsc, skinColors, NULL);
-
- if (colIndex != (UInt16)-1) {
- colH = DmGetResourceIndex(skinDBP, colIndex);
-
- if (colH) {
- colTemp = (UInt8 *)MemHandleLock(colH);
-
- *text = colTemp[0];
- *selected = colTemp[1];
- *background = colTemp[2];
-
- MemPtrUnlock(colTemp);
- DmReleaseResource(colH);
- }
- }
- }
-}
-
-static void SknCopyBits(DmOpenRef skinDBP, DmResID bitmapID, const RectangleType *srcRect, Coord destX, Coord destY) {
- MemHandle hTemp;
- BitmapPtr bmpTemp;
- UInt16 index;
-
- Coord cx, cy, cw, ch, bw, bh;
- RectangleType copy, old;
-
- if (skinDBP) {
- // find the bitmap
- index = DmFindResource (skinDBP, bitmapRsc, bitmapID, NULL);
-
- if (index != (UInt16)-1) {
- hTemp = DmGetResourceIndex(skinDBP,index);
-
- if (hTemp) {
- bmpTemp = (BitmapType *)MemHandleLock(hTemp);
- BmpGlueGetDimensions(bmpTemp, &bw, &bh, 0);
-
- if (!srcRect) {
- cx = 0;
- cy = 0;
- cw = bw;
- ch = bh;
- } else {
- cx = srcRect->topLeft.x;
- cy = srcRect->topLeft.y;
- cw = srcRect->extent.x;
- ch = srcRect->extent.y;
- }
-
- if (ch) {
- WinGetClip(&old);
- if (OPTIONS_TST(kOptModeHiDensity)) {
- Err e;
- BitmapTypeV3 *bmp2P;
-
- // create an uncompressed version of the bitmap
- WinHandle win = WinCreateOffscreenWindow(bw, bh, screenFormat, &e);
- WinHandle old = WinGetDrawWindow();
- WinSetDrawWindow(win);
- WinDrawBitmap(bmpTemp, 0, 0);
- WinSetDrawWindow(old);
-
- bmp2P = BmpCreateBitmapV3(WinGetBitmap(win), kDensityDouble, BmpGetBits(WinGetBitmap(win)), NULL);
-
- copy.topLeft.x = destX / 2;
- copy.topLeft.y = destY / 2;
- copy.extent.x = cw / 2;
- copy.extent.y = ch / 2;
-
- WinSetClip(&copy);
- WinDrawBitmap((BitmapPtr)bmp2P, (destX - cx) / 2, (destY - cy) / 2);
- BmpDelete((BitmapPtr)bmp2P);
- WinDeleteWindow(win, false);
-
- } else {
- copy.topLeft.x = destX;
- copy.topLeft.y = destY;
- copy.extent.x = cw;
- copy.extent.y = ch;
-
- HRWinSetClip(gVars->HRrefNum, &copy);
- HRWinDrawBitmap(gVars->HRrefNum, bmpTemp, destX - cx, destY - cy);
- }
- WinSetClip(&old);
- }
-
- MemPtrUnlock(bmpTemp);
- DmReleaseResource(hTemp);
- }
- }
- }
-}
-
-void SknApplySkin() {
- DmOpenRef skinDBP;
- RectangleType r;
- FormPtr frmP = FrmGetActiveForm();
-
- // draw skin
- FrmDrawForm(frmP);
- SknScreenLock(winLockCopy);
-
- skinDBP = SknOpenSkin();
-
- if (gPrefs->card.volRefNum != vfsInvalidVolRef)
- FrmShowObject(frmP, FrmGetObjectIndex (frmP, MainMSBitMap));
- else
- FrmShowObject(frmP, FrmGetObjectIndex (frmP, MainMSNoneBitMap));
-
- WinSetForeColor(255);
- WinSetDrawMode(winPaint);
- WinDrawLine (0, 14, 159, 14);
- WinDrawLine (0, 13, 159, 13);
-
- SknGetObjectBounds(skinDBP, skinBackgroundImageTop, &r);
- SknCopyBits(skinDBP, skinBackgroundImageTop, 0, r.topLeft.x, r.topLeft.y);
- SknGetObjectBounds(skinDBP, skinBackgroundImageBottom, &r);
- SknCopyBits(skinDBP, skinBackgroundImageBottom, 0, r.topLeft.x, r.topLeft.y);
-
- for (UInt16 resID = 1100; resID <= 7000; resID += 100) {
- SknSetState(skinDBP, resID, sknStateNormal);
- SknShowObject(skinDBP, resID);
- }
-
- SknCloseSkin(skinDBP);
- SknScreenUnlock();
- SknUpdateList();
-}
-
-void SknGetObjectBounds(DmOpenRef skinDBP, DmResID resID, RectangleType *rP) {
-
- UInt16 bmpIndex, strIndex;
- MemHandle hBmp, hStr;
- BitmapType *bmpTemp;
- UInt8 *strTemp;
-
- RctSetRectangle(rP, 0, 0, 0, 0);
-
- if (skinDBP) {
- bmpIndex = DmFindResource (skinDBP, bitmapRsc, resID, NULL);
-
- if (bmpIndex != (UInt16)-1) { // if bmp exists
- strIndex = DmFindResource (skinDBP, sknPosRsc, resID, NULL);
-
- if (strIndex != (UInt16)-1) { // if params exist
- hBmp = DmGetResourceIndex(skinDBP,bmpIndex);
-
- if (hBmp) {
- hStr = DmGetResourceIndex(skinDBP,strIndex);
-
- if (hStr) {
- // buttons : state|x|y|w/h slider|draw mode|x1/y1 keep|x2/y2 keep slider
- // list (160mode) : state|x|y|w|h|
- bmpTemp = (BitmapType *)MemHandleLock(hBmp);
- strTemp = (UInt8 *)MemHandleLock(hStr);
-
- BmpGlueGetDimensions(bmpTemp, &(rP->extent.x), &(rP->extent.y), 0);
- rP->topLeft.x = strTemp[sknInfoPosX] * 2;
- rP->topLeft.y = strTemp[sknInfoPosY] * 2;
-
- MemPtrUnlock(strTemp);
- DmReleaseResource(hStr);
- }
-
- MemPtrUnlock(bmpTemp);
- DmReleaseResource(hBmp);
- }
- }
- }
- }
-}
-
-DmOpenRef SknOpenSkin() {
- return DmOpenDatabase(gPrefs->skin.cardNo, gPrefs->skin.dbID, dmModeReadOnly);
-}
-
-void SknCloseSkin(DmOpenRef skinDBP) {
- if (skinDBP)
- DmCloseDatabase(skinDBP);
-}
-
-UInt8 SknSetState(DmOpenRef skinDBP, DmResID resID, UInt8 newState) {
-
- UInt16 index;
- MemHandle hStr;
- UInt8 *strTemp;
- UInt8 oldState = 0;
-
- if (skinDBP) {
- index = DmFindResource (skinDBP, sknPosRsc, resID, NULL);
-
- if (index != (UInt16)-1) {
- hStr = DmGetResourceIndex(skinDBP, index);
-
- if (hStr) {
- strTemp = (UInt8 *)MemHandleLock(hStr);
- oldState = strTemp[sknInfoState];
-
- if (oldState != newState) {
- DmWrite(strTemp, 0, &newState, 1);
- }
-
- MemPtrUnlock(strTemp);
- DmReleaseResource(hStr);
- }
- }
- }
-
- return oldState;
-}
-
-UInt8 SknGetDepth(DmOpenRef skinDBP) {
- UInt16 index;
- MemHandle hStr;
- UInt8 *strTemp;
- UInt8 depth = 8;
-
- if (skinDBP) {
- index = DmFindResource (skinDBP, sknDepthRsc, skinDepth, NULL);
-
- if (index != (UInt16)-1) {
- hStr = DmGetResourceIndex(skinDBP, index);
-
- if (hStr) {
- strTemp = (UInt8 *)MemHandleLock(hStr);
- depth = *strTemp;
- MemPtrUnlock(strTemp);
- DmReleaseResource(hStr);
- }
- }
- }
-
- return depth;
-}
-
-UInt8 SknGetState(DmOpenRef skinDBP, DmResID resID) {
- UInt16 index;
- MemHandle hStr;
- UInt8 *strTemp;
- UInt8 oldState = sknStateDisabled;
-
- if (skinDBP) {
- index = DmFindResource (skinDBP, sknPosRsc, resID, NULL);
-
- if (index != (UInt16)-1) {
- hStr = DmGetResourceIndex(skinDBP, index);
-
- if (hStr) {
- strTemp = (UInt8 *)MemHandleLock(hStr);
- oldState = strTemp[sknInfoState];
- MemPtrUnlock(strTemp);
- DmReleaseResource(hStr);
- }
- }
- }
-
- return oldState;
-}
-
-void SknShowObject(DmOpenRef skinDBP, DmResID resID) {
- RectangleType r;
- UInt8 state = SknGetState(skinDBP, resID);
- SknGetObjectBounds(skinDBP, resID, &r);
- SknCopyBits(skinDBP, resID + state, NULL, r.topLeft.x, r.topLeft.y);
-}
-
-void SknGetListBounds(RectangleType *rAreaP, RectangleType *rArea2xP) {
- DmOpenRef skinDBP;
- UInt16 strIndex;
- MemHandle hStr;
- UInt8 *strTemp;
- UInt16 x,y,w,h;
-
- skinDBP = DmOpenDatabase(gPrefs->skin.cardNo, gPrefs->skin.dbID, dmModeReadOnly);
- if (skinDBP) {
- strIndex = DmFindResource (skinDBP, sknPosRsc, skinList, NULL);
-
- if (strIndex != 0xFFFF) { // if params exist
- hStr = DmGetResourceIndex(skinDBP,strIndex);
- if (hStr) {
- strTemp = (UInt8 *)MemHandleLock(hStr);
-
- x = strTemp[sknInfoPosX];
- y = strTemp[sknInfoPosY];
- w = strTemp[sknInfoListWidth];
- h = strTemp[sknInfoListSize] * sknInfoListItemSize;
-
- if (rAreaP)
- RctSetRectangle(rAreaP ,x, y, w, h);
- if (rArea2xP)
- RctSetRectangle(rArea2xP, x+x, y+y, w+w, h+h);
-
- MemHandleUnlock(hStr);
- DmReleaseResource(hStr);
- }
- }
-
- DmCloseDatabase(skinDBP);
- }
-}
-
-static void SknRedrawTools(DmOpenRef skinDBP) {
- if (GamGetSelected() == dmMaxRecordIndex) {
- if (SknGetState(skinDBP, skinButtonGameDelete) == sknStateNormal) {
- SknSetState(skinDBP, skinButtonGameDelete,sknStateDisabled);
- SknShowObject(skinDBP, skinButtonGameDelete);
- }
- if (SknGetState(skinDBP, skinButtonGameEdit) == sknStateNormal) {
- SknSetState(skinDBP, skinButtonGameEdit,sknStateDisabled);
- SknShowObject(skinDBP, skinButtonGameEdit);
- }
- if (SknGetState(skinDBP, skinButtonGameAudio) == sknStateNormal) {
- SknSetState(skinDBP, skinButtonGameAudio,sknStateDisabled);
- SknShowObject(skinDBP, skinButtonGameAudio);
- }
-
- } else {
- if (SknGetState(skinDBP, skinButtonGameDelete) == sknStateDisabled) {
- SknSetState(skinDBP, skinButtonGameDelete,sknStateNormal);
- SknShowObject(skinDBP, skinButtonGameDelete);
- }
- if (SknGetState(skinDBP, skinButtonGameEdit) == sknStateDisabled) {
- SknSetState(skinDBP, skinButtonGameEdit,sknStateNormal);
- SknShowObject(skinDBP, skinButtonGameEdit);
- }
- if (SknGetState(skinDBP, skinButtonGameAudio) == sknStateDisabled) {
- SknSetState(skinDBP, skinButtonGameAudio,sknStateNormal);
- SknShowObject(skinDBP, skinButtonGameAudio);
- }
- }
-}
-
-static void SknRedrawSlider(DmOpenRef skinDBP, UInt16 index, UInt16 maxIndex, UInt16 perPage) {
- if (maxIndex <= perPage) {
- if (SknGetState(skinDBP,skinSliderUpArrow) != sknStateDisabled) {
- SknSetState(skinDBP,skinSliderUpArrow,sknStateDisabled);
- SknShowObject(skinDBP,skinSliderUpArrow);
- }
- if (SknGetState(skinDBP,skinSliderDownArrow) != sknStateDisabled) {
- SknSetState(skinDBP,skinSliderDownArrow,sknStateDisabled);
- SknShowObject(skinDBP,skinSliderDownArrow);
- }
-
- } else {
- if (SknGetState(skinDBP,skinSliderUpArrow) == sknStateDisabled) {
- SknSetState(skinDBP,skinSliderUpArrow,sknStateNormal);
- SknShowObject(skinDBP,skinSliderUpArrow);
- }
- if (SknGetState(skinDBP,skinSliderDownArrow) == sknStateDisabled) {
- SknSetState(skinDBP,skinSliderDownArrow,sknStateNormal);
- SknShowObject(skinDBP,skinSliderDownArrow);
- }
- }
-}
-
-void SknUpdateList() {
- MemHandle record;
- Int32 index, maxIndex, maxView;
- GameInfoType *game;
- RectangleType rArea, rField, rCopy, rArea2x;
- DmOpenRef skinDBP;
-
- UInt8 txtColor, norColor, selColor, bkgColor;
- UInt16 x,y;
-
- SknScreenLock(winLockCopy);
-
- SknGetListBounds(&rArea, &rArea2x);
- skinDBP = SknOpenSkin();
- // set default bg
- WinSetForeColor(UIColorGetTableEntryIndex (UIFormFill));
- WinDrawRectangle(&rArea,0);
- // copy top bg
- SknGetObjectBounds(skinDBP, skinBackgroundImageTop, &rField);
- RctGetIntersection(&rArea2x, &rField, &rCopy);
- x = rCopy.topLeft.x;
- y = rCopy.topLeft.y;
- rCopy.topLeft.x -= rField.topLeft.x;
- rCopy.topLeft.y -= rField.topLeft.y;
- SknCopyBits(skinDBP, skinBackgroundImageTop, &rCopy, x, y);
- // copy bottom bg
- SknGetObjectBounds(skinDBP, skinBackgroundImageBottom, &rField);
- RctGetIntersection(&rArea2x, &rField, &rCopy);
- x = rCopy.topLeft.x;
- y = rCopy.topLeft.y;
- rCopy.topLeft.x -= rField.topLeft.x;
- rCopy.topLeft.y -= rField.topLeft.y;
- SknCopyBits(skinDBP, skinBackgroundImageBottom, &rCopy, x, y);
-
- FntSetFont(stdFont);
-
- index = gPrefs->listPosition;
- maxIndex = DmNumRecords(gameDB);
- maxView = rArea.extent.y / sknInfoListItemSize;
-
- if (index > 0 && (index + maxView) > maxIndex)
- index -= (index + maxView) - maxIndex;
-
- if (index < 0)
- index = 0;
-
- gPrefs->listPosition = index;
-
- SknRedrawSlider(skinDBP, index, maxIndex, maxView);
- SknRedrawTools(skinDBP);
- SknGetListColors(skinDBP, &norColor, &selColor, &bkgColor);
-
- SknCloseSkin(skinDBP);
-
- while (index < (gPrefs->listPosition + maxView) && index < maxIndex) {
- record = DmQueryRecord(gameDB, index);
- game = (GameInfoType *)MemHandleLock(record);
-
- // text box
- RctSetRectangle(&rField, rArea.topLeft.x, (rArea.topLeft.y + sknInfoListItemSize * (index - gPrefs->listPosition)), rArea.extent.x, sknInfoListItemSize);
- WinSetClip(&rField);
-
- if (game->selected) {
- WinSetDrawMode(winPaint);
- WinSetForeColor(bkgColor);
- WinDrawRectangle(&rField,0);
- txtColor = selColor;
- }
- else
- txtColor = norColor;
-
- // clipping
- rField.topLeft.x += 2;
- rField.extent.x -= 4;
- WinSetClip(&rField);
- // draw text mask
- WinSetTextColor(255);
- WinSetDrawMode(winMask);
- WinPaintChars(game->nameP, StrLen(game->nameP), rField.topLeft.x, rField.topLeft.y);
- // draw text
- if (txtColor) {
- WinSetTextColor(txtColor);
- WinSetDrawMode(winOverlay);
- WinPaintChars(game->nameP, StrLen(game->nameP), rField.topLeft.x, rField.topLeft.y);
- }
-
- MemHandleUnlock(record);
- index++;
- }
-
- RctSetRectangle(&rArea,0,0,160,160);
- WinSetClip(&rArea);
- SknScreenUnlock();
-}
-
-UInt16 SknCheckClick(DmOpenRef skinDBP, Coord mx, Coord my) {
- UInt16 resID;
- RectangleType r;
-
- mx *= 2;
- my *= 2;
-
- if (skinDBP) {
- for (resID = 1100; resID <= 7000; resID += 100) {
- if (SknGetState(skinDBP, resID) != sknStateDisabled) {
- SknGetObjectBounds(skinDBP, resID, &r);
- if (RctPtInRectangle(mx, my, &r)) {
- return resID;
- }
- }
- }
- }
-
- return 0;
-}
-
-void SknSelect(Coord x, Coord y) {
- RectangleType rArea;
- SknGetListBounds(&rArea,0);
-
- if (RctPtInRectangle(x, y, &rArea)) {
- UInt16 index;
- MemHandle record;
- GameInfoType *game;
- UInt16 oldIndex;
-
- index = (y - rArea.topLeft.y) / sknInfoListItemSize + gPrefs->listPosition;
-
- if (index == lastIndex)
- return;
-
- if (index < DmNumRecords(gameDB)) {
- Boolean newValue;
-
- oldIndex = GamGetSelected();
-
- if (oldIndex != index && oldIndex != dmMaxRecordIndex)
- GamUnselect();
-
- record = DmGetRecord(gameDB, index);
- game = (GameInfoType *)MemHandleLock(record);
-
- newValue = !game->selected;
- DmWrite(game, OffsetOf(GameInfoType,selected), &newValue, sizeof(Boolean));
-
- MemHandleUnlock(record);
- DmReleaseRecord (gameDB, index, 0);
-
- lastIndex = index;
- SknUpdateList();
- }
- }
-}
-
-Boolean SknProcessArrowAction(UInt16 button) {
- Boolean handled = false;
-
- switch (button) {
- case skinSliderUpArrow:
- if (gPrefs->listPosition > 0) {
- gPrefs->listPosition--;
- SknUpdateList();
- }
- handled = true;
- break;
-
- case skinSliderDownArrow:
- RectangleType rArea;
- UInt16 maxView;
-
- SknGetListBounds(&rArea, 0);
- maxView = rArea.extent.y / sknInfoListItemSize;
-
- if (gPrefs->listPosition < DmNumRecords(gameDB)-maxView) {
- gPrefs->listPosition++;
- SknUpdateList();
- }
- handled = true;
- break;
- }
-
- return handled;
-}
diff --git a/backends/platform/PalmOS/Src/launcher/skin.h b/backends/platform/PalmOS/Src/launcher/skin.h
deleted file mode 100644
index e8a81e7e2d..0000000000
--- a/backends/platform/PalmOS/Src/launcher/skin.h
+++ /dev/null
@@ -1,131 +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$
- *
- */
-
-#ifndef __SKIN_H__
-#define __SKIN_H__
-
-// skin
-#define sknInfoState 0
-#define sknInfoPosX 1
-#define sknInfoPosY 2
-
-#define sknInfoMaxWOrH 3
-#define sknInfoDrawMode 4
-#define sknInfoKeepXOrY1 5
-#define sknInfoKeepXOrY2 7
-
-#define sknInfoListWidth sknInfoMaxWOrH
-#define sknInfoListHeight sknInfoDrawMode
-#define sknInfoListSize sknInfoListHeight
-#define sknInfoListItemSize 12
-
-#define sknPosRsc 'sPos'
-#define sknColorsRsc 'sCol'
-#define sknDepthRsc 'sDep'
-
-#define sknStateNormal 0
-#define sknStateSelected 10
-#define sknStateDisabled 20
-
-#define sknSelectedState(bmp) (bmp + sknStateSelected)
-#define sknDisabledState(bmp) (bmp + sknStateDisabled)
-
-// skin elements
-#define skinList 500
-#define skinColors 600
-#define skinDepth 700
-
-#define skinButtonNone 0
-
-#define skinSliderUpArrow 2000
-#define skinSliderDownArrow 2100
-
-#define skinButtonGameParams 3000
-#define skinButtonGameAdd 3100
-#define skinButtonGameEdit 3200
-#define skinButtonGameAudio 3300
-#define skinButtonGameDelete 4000
-#define skinButtonGameStart 7000
-
-#define skinBackgroundImageTop 1000
-#define skinBackgroundImageBottom 1010
-///
-
-
-#define skinToolsBackground 1100
-
-#define skinListUpArrowNormal 1500
-#define skinListUpArrowOver 1510
-#define skinListUpArrowDisabled 1540
-
-#define skinListDownArrowNormal 1800
-#define skinListDownArrowOver 1810
-#define skinListDownArrowDisabled 1840
-
-#define skinButtonGameInfoNormal 2000
-#define skinButtonGameInfoOver 2010
-#define skinButtonGameInfoDisabled 2040
-
-#define skinButtonGameParamNormal 3000
-#define skinButtonGameParamOver 3010
-
-#define skinButtonGameDeleteNormal 4000
-#define skinButtonGameDeleteOver 4010
-#define skinButtonGameDeleteDisabled 4040
-
-#define skinButtonVibratorNormal 5000
-#define skinButtonVibratorOver 5010
-#define skinButtonVibratorSelected 5020
-#define skinButtonVibratorSelectedOver 5030
-#define skinButtonVibratorDisabled 5040
-
-
-#define skinButtonSleepNormal 6000
-#define skinButtonSleepOver 6010
-#define skinButtonSleepSelected 6020
-#define skinButtonSleepSelectedOver 9030
-
-#define skinButtonPlayNormal 7000
-#define skinButtonPlayOver 7010
-#define skinButtonPlayDisabled 7040
-
-// protos
-void SknApplySkin();
-void SknGetObjectBounds(DmOpenRef skinDBP, DmResID resID, RectangleType *rP);
-DmOpenRef SknOpenSkin();
-void SknCloseSkin(DmOpenRef skinDBP);
-UInt8 SknSetState(DmOpenRef skinDBP, DmResID resID, UInt8 newState);
-void SknShowObject(DmOpenRef skinDBP, DmResID resID);
-UInt8 SknGetState(DmOpenRef skinDBP, DmResID resID);
-void SknUpdateList();
-void SknGetListBounds(RectangleType *rAreaP, RectangleType *rArea2xP);
-UInt16 SknCheckClick(DmOpenRef skinDBP, Coord mx, Coord my);
-void SknSelect(Coord x, Coord y);
-Boolean SknProcessArrowAction(UInt16 button);
-UInt8 SknGetDepth(DmOpenRef skinDBP);
-
-extern UInt16 lastIndex;
-
-#endif
diff --git a/backends/platform/PalmOS/Src/launcher/start.cpp b/backends/platform/PalmOS/Src/launcher/start.cpp
deleted file mode 100644
index b5e8f24884..0000000000
--- a/backends/platform/PalmOS/Src/launcher/start.cpp
+++ /dev/null
@@ -1,367 +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 <PalmOS.h>
-#include <SonyClie.h>
-
-#include "palmdefs.h"
-#include "start.h"
-#include "games.h"
-#include "globals.h"
-#include "modules.h"
-#include "skin.h"
-
-#include "forms.h"
-
-/***********************************************************************
- *
- * Global variables
- *
- ***********************************************************************/
-GlobalsPreferencePtr gPrefs;
-GlobalsDataPtr gVars;
-
-Boolean bDirectMode = false;
-Boolean bLaunched = false;
-
-/***********************************************************************
- *
- * Internal Constants
- *
- ***********************************************************************/
-
-// Define the minimum OS version we support (3.5 for now).
-#define kOurMinVersion sysMakeROMVersion(3,5,0,sysROMStageRelease,0)
-#define kPalmOS10Version sysMakeROMVersion(1,0,0,sysROMStageRelease,0)
-
-/***********************************************************************
- *
- * Internal Functions
- *
- ***********************************************************************/
-
-// Callback for ExgDBWrite to send data with Exchange Manager
-static Err WriteDBData(const void* dataP, UInt32* sizeP, void* userDataP) {
- Err err;
- *sizeP = ExgSend((ExgSocketPtr)userDataP, (void*)dataP, *sizeP, &err);
- return err;
-}
-
-Err SendDatabase (UInt16 cardNo, LocalID dbID, Char *nameP, Char *descriptionP) {
- ExgSocketType exgSocket;
- Err err;
-
- // Create exgSocket structure
- MemSet(&exgSocket, sizeof(exgSocket), 0);
- exgSocket.description = descriptionP;
- exgSocket.name = nameP;
-
- // Start an exchange put operation
- err = ExgPut(&exgSocket);
- if (!err) {
- err = ExgDBWrite(WriteDBData, &exgSocket, NULL, dbID, cardNo);
- err = ExgDisconnect(&exgSocket, err);
- }
-
- return err;
-}
-
-
-/***********************************************************************
- *
- * FUNCTION: RomVersionCompatible
- *
- * DESCRIPTION: This routine checks that a ROM version is meet your
- * minimum requirement.
- *
- * PARAMETERS: requiredVersion - minimum rom version required
- * (see sysFtrNumROMVersion in SystemMgr.h
- * for format)
- * launchFlags - flags that indicate if the application
- * UI is initialized.
- *
- * RETURNED: error code or zero if rom is compatible
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-static Err RomVersionCompatible(UInt32 requiredVersion, UInt16 launchFlags) {
- UInt32 romVersion;
-
- // See if we're on in minimum required version of the ROM or later.
- FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
- if (romVersion < requiredVersion) {
- if ((launchFlags & (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) ==
- (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) {
-
- FrmAlert (RomIncompatibleAlert);
-
- // Palm OS 1.0 will continuously relaunch this app unless we switch to
- // another safe one.
- if (romVersion <= kPalmOS10Version)
- AppLaunchWithCommand(sysFileCDefaultApp, sysAppLaunchCmdNormalLaunch, NULL);
-
- }
- return sysErrRomIncompatible;
- }
-
- return errNone;
-}
-
-///////////////////////////////////////////////////////////////////////
-
-
-void SavePrefs() {
- if (gPrefs) {
- PrefSetAppPreferences(appFileCreator, appPrefID, appPrefVersionNum, gPrefs, sizeof (GlobalsPreferenceType), true);
- MemPtrFree(gPrefs);
- gPrefs = NULL;
- }
-}
-
-/***********************************************************************
- *
- * FUNCTION: AppHandleEvent
- *
- * DESCRIPTION: This routine loads form resources and set the event
- * handler for the form loaded.
- *
- * PARAMETERS: event - a pointer to an EventType structure
- *
- * RETURNED: true if the event has handle and should not be passed
- * to a higher level handler.
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-static Boolean AppHandleEvent(EventPtr eventP) {
- UInt16 formId;
- FormPtr frmP;
-
- if (eventP->eType == frmLoadEvent) {
- // Load the form resource.
- formId = eventP->data.frmLoad.formID;
- frmP = FrmInitForm(formId);
- FrmSetActiveForm(frmP);
-
- // Set the event handler for the form. The handler of the currently
- // active form is called by FrmHandleEvent each time is receives an
- // event.
- switch (formId) {
- case MainForm:
- FrmSetEventHandler(frmP, MainFormHandleEvent);
- break;
-
- case SkinsForm:
- FrmSetEventHandler(frmP, SkinsFormHandleEvent);
- break;
-
- case GameEditForm:
- FrmSetEventHandler(frmP, EditGameFormHandleEvent);
- break;
-
- case MiscForm:
- FrmSetEventHandler(frmP, MiscFormHandleEvent);
- break;
-
- case CardSlotForm:
- FrmSetEventHandler(frmP, CardSlotFormHandleEvent);
- break;
-
- case MusicForm:
- FrmSetEventHandler(frmP, MusicFormHandleEvent);
- break;
-
- case InfoForm:
- FrmSetEventHandler(frmP, InfoFormHandleEvent);
- break;
-
- case EngineForm:
- FrmSetEventHandler(frmP, SelectorFormHandleEvent);
- break;
-
- default:
-// ErrFatalDisplay("Invalid Form Load Event");
- break;
- }
- return true;
- }
-
- return false;
-}
-
-/***********************************************************************
- *
- * FUNCTION: AppEventLoop
- *
- * DESCRIPTION: This routine is the event loop for the application.
- *
- * PARAMETERS: nothing
- *
- * RETURNED: nothing
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-static void AppEventLoop(void) {
- UInt16 error;
- EventType event;
-
- do {
- EvtGetEvent(&event, evtNoWait);
-
- if (! SysHandleEvent(&event))
- if (! MenuHandleEvent(0, &event, &error))
- if (! AppHandleEvent(&event))
- FrmDispatchEvent(&event);
-
- } while (event.eType != appStopEvent);
-}
-
-/***********************************************************************
- *
- * FUNCTION: ScummVMPalmMain
- *
- * DESCRIPTION: This is the main entry point for the application.
- *
- * PARAMETERS: cmd - word value specifying the launch code.
- * cmdPB - pointer to a structure that is associated with the launch code.
- * launchFlags - word value providing extra information about the launch.
- *
- * RETURNED: Result of launch
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-static void AppLaunchCmdNotify(UInt16 LaunchFlags, SysNotifyParamType * pData) {
- switch (pData->notifyType) {
- case sysNotifyVolumeMountedEvent:
- pData->handled = true; // don't switch
-
- if (gPrefs) { // gPrefs exists ? so we are in the palm selector
- CardSlotFormUpdate(); // redraw card list if needed
-
- if (gPrefs->card.volRefNum == vfsInvalidVolRef) {
- VFSAnyMountParamType *notifyDetailsP = (VFSAnyMountParamType *)pData->notifyDetailsP;
- gPrefs->card.volRefNum = notifyDetailsP->volRefNum;
-
- if (FrmGetFormPtr(MainForm) == FrmGetActiveForm())
- if (gPrefs->card.volRefNum != vfsInvalidVolRef) {
- CardSlotCreateDirs();
- FrmUpdateForm(MainForm, frmRedrawUpdateMSImport);
- }
- }
- }
- break;
-
- case sysNotifyVolumeUnmountedEvent:
- if (gPrefs) {
- CardSlotFormUpdate();
-
- if (gPrefs->card.volRefNum == (UInt16)pData->notifyDetailsP) {
- gPrefs->card.volRefNum = vfsInvalidVolRef;
-
- if (FrmGetFormPtr(MainForm) == FrmGetActiveForm())
- FrmUpdateForm(MainForm, frmRedrawUpdateMS);
- }
- }
- break;
-
- case sysNotifyDisplayResizedEvent:
- if (gVars)
- if (FrmGetFormPtr(MainForm) == FrmGetActiveForm())
- SknApplySkin();
- break;
-
- case sonySysNotifyMsaEnforceOpenEvent:
- // what am i supposed to do here ???
- break;
- }
-}
-
-static UInt32 ScummVMPalmMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) {
- Err error;
-
- error = RomVersionCompatible (kOurMinVersion, launchFlags);
- if (error) return (error);
-
- switch (cmd) {
- case sysAppLaunchCmdNotify:
- AppLaunchCmdNotify(launchFlags, (SysNotifyParamType *) cmdPBP);
- break;
-
- case sysAppLaunchCustomEngineDelete:
-#ifndef _DEBUG_ENGINE
- ModDelete();
-#endif
- break;
-
- case sysAppLaunchCmdNormalLaunch:
- error = AppStart();
- if (error)
- goto end;
-
- if (!bDirectMode) {
- FrmGotoForm(MainForm);
- }else {
- GamUnselect();
- FrmGotoForm(EngineForm);
- }
-
- AppEventLoop();
-end:
- AppStop();
- break;
-
- default:
- break;
-
- }
- return error;
-}
-
-/***********************************************************************
- *
- * FUNCTION: PilotMain
- *
- * DESCRIPTION: This is the main entry point for the application.
- *
- * PARAMETERS: cmd - word value specifying the launch code.
- * cmdPB - pointer to a structure that is associated with the launch code.
- * launchFlags - word value providing extra information about the launch.
- * RETURNED: Result of launch
- *
- * REVISION HISTORY:
- *
- *
- ***********************************************************************/
-
-UInt32 PilotMain( UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) {
- return ScummVMPalmMain(cmd, cmdPBP, launchFlags);
-}
diff --git a/backends/platform/PalmOS/Src/launcher/start.h b/backends/platform/PalmOS/Src/launcher/start.h
deleted file mode 100644
index 3ed52b465b..0000000000
--- a/backends/platform/PalmOS/Src/launcher/start.h
+++ /dev/null
@@ -1,98 +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$
- *
- */
-
-#ifndef __START_H__
-#define __START_H__
-
-typedef struct {
- Char nameP[32];
- UInt16 cardNo;
- LocalID dbID;
-} SkinInfoType, *SkinInfoPtr;
-
-typedef struct {
-
- //skin params
- SkinInfoType skin; // card where is located the skin
- Boolean soundClick;
-
- Boolean vibrator;
- Boolean autoOff;
- Boolean setStack;
- Boolean exitLauncher;
- Boolean goLCD;
- Boolean stylusClick;
- Boolean arrowKeys;
-
- UInt16 listPosition;
- UInt16 autoSavePeriod;
-
- struct {
- UInt16 volRefNum;
- UInt32 cacheSize;
- Boolean useCache;
- Boolean showLED;
- Boolean autoDetect;
- Boolean moveDB;
- Boolean deleteDB;
- Boolean confirmMoveDB;
- } card;
-
- Boolean debug;
- UInt16 debugLevel;
- Boolean stdPalette;
- Boolean demoMode;
- Boolean copyProtection;
- Boolean oldarm;// TODO : free slot...
- Boolean altIntro;
- Boolean autoSave;
- Boolean advancedMode;
-
- struct {
- Boolean enable;
- UInt8 mode;
- } lightspeed;
-
-} GlobalsPreferenceType, *GlobalsPreferencePtr;
-
-extern GlobalsPreferencePtr gPrefs;
-
-extern Boolean bDirectMode;
-extern Boolean bLaunched;
-
-#define appPrefID 0x00
-#define appVersionNum 0x01
-#define appPrefVersionNum 0x02
-
-#define STACK_DEFAULT 8192
-#define STACK_LARGER 16384
-#define STACK_GET 0
-
-Err AppStart(void);
-void AppStop(void);
-Boolean StartScummVM(Int16 engine = -1);
-void SavePrefs();
-Err SendDatabase (UInt16 cardNo, LocalID dbID, Char *nameP, Char *descriptionP);
-#endif
diff --git a/backends/platform/PalmOS/Src/modules.cpp b/backends/platform/PalmOS/Src/modules.cpp
deleted file mode 100644
index b16e2cf7d5..0000000000
--- a/backends/platform/PalmOS/Src/modules.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-#include <PalmOS.h>
-
-#include "palmdefs.h"
-#include "args.h"
-#include "globals.h"
-#include "modules.h"
-#include "features.h"
-
-#include "rumble.h"
-#include "init_mathlib.h"
-#include "init_pa1lib.h"
-#include "init_palmos.h"
-#include "init_stuffs.h"
-#include "init_sony.h"
-#include "init_golcd.h"
-
-#ifndef DISABLE_LIGHTSPEED
-#include "lightspeed_public.h"
-#endif
-
-GlobalsDataPtr gVars;
-
-#include "endianutils.h"
-#include <PNOLoader.h>
-
-#ifdef COMPILE_ZODIAC
-# include <tapwave.h>
-# include <TwRuntime.h>
-#endif
-
-void run(int argc, char *argv[]) {
- // init args
- ArgsExportInit(argv, argc, true);
-
- // init system
- PalmHRInit(16);
- PalmInit(HWR_GET());
- void *__ptr = StuffsForceVG();
-
- gVars->screenPitch = StuffsGetPitch(gVars->screenFullWidth);
-
- // export global struct to ARM
- VARS_EXPORT();
- DO_VARS(_4B, 32, 0);
- DO_VARS(_2B, 16, (gVars->_4B * sizeof(UInt32)));
- FtrSet(appFileCreator, ftrVars , (UInt32)gVars);
-
- // run the module
-#ifdef COMPILE_ZODIAC
- NativeFuncType *entry;
- TwLoadModule(0, 0, 0, 1, twLoadFlagTNA|twLoadFlagQuickRun, &entry);
-#else
- PnoDescriptor pno;
- PnoLoadFromResources(&pno, 'ARMC', 1, appFileCreator, 1);
- PnoCall(&pno, 0);
- PnoUnload(&pno);
-#endif
-
- // reset globals
- DO_VARS(_4B, 32, 0);
- DO_VARS(_2B, 16, (gVars->_4B * sizeof(UInt32)));
-
- // release
- StuffsReleaseVG(__ptr);
- PalmRelease(HWR_GET());
- PalmHRRelease();
-
- // free args
- ArgsExportRelease(true);
- ArgsFree(argv);
-
- // release global struct
- FtrUnregister(appFileCreator, ftrVars);
- FtrUnregister(appFileCreator, ftrStack);
- MemPtrFree(gVars);
-
- // reset the palette if needed
- WinPalette(winPaletteSetToDefault, 0, 256, NULL);
-}
-
-static UInt32 ModulesPalmMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
-{
- UInt32 result = 0;
-
- switch (cmd) {
- case sysAppLaunchCustomEngineGetInfo: {
-#ifdef PALMOS_NATIVE
- result = GET_MODEARM;
-#else
-# if defined(ENABLE_SCUMM) || \
- defined(ENABLE_AGOS) || \
- defined(ENABLE_SWORD1)
- result = GET_DATACOMMON|GET_DATAENGINE|GET_MODE68K;
-# else
- result = GET_DATACOMMON|GET_MODE68K;
-# endif
-#endif
- break;
- }
-
- case sysAppLaunchCmdNormalLaunch: {
- if (cmdPBP) {
- Char **argvP;
- UInt16 cardNo;
- LocalID dbID;
-
- LaunchParamType *lp = (LaunchParamType *)cmdPBP;
-
- gVars = lp->gVars;
- argvP = lp->args.argv;
-
- // get the free memory on the dynamic heap
- PalmGetMemory(0,0,0, &(gVars->startupMemory));
-
-#ifndef DISABLE_LIGHTSPEED
- switch (lp->lightspeed) {
- case 0:
- LS_SetCPUSpeedHigh();
- break;
- case 1:
- LS_SetCPUSpeedNormal();
- break;
- case 2:
- LS_SetCPUSpeedLow();
- break;
- }
-#endif
- // MemPtrSetOwner(gVars, ownerID);
- // ArgsSetOwner(argvP, ownerID); // will be freed by main(...)
- // MemPtrFree(lp); // will be freed by the system on exit
-
- run(lp->args.argc, argvP);
-
- cardNo = 0;
- dbID = DmFindDatabase(0, "ScummVM");
- if (dbID) {
- if (lp->exitLauncher)
- SysUIAppSwitch(cardNo, dbID, sysAppLaunchCustomEngineDelete,0);
- else
- SysUIAppSwitch(cardNo, dbID, sysAppLaunchCmdNormalLaunch,0);
- }
- }
- break;
- }
-
- default:
- break;
-
- }
-
- return result;
-}
-
-UInt32 PilotMain( UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) {
- return ModulesPalmMain(cmd, cmdPBP, launchFlags);
-}
diff --git a/backends/platform/PalmOS/Src/modules.h b/backends/platform/PalmOS/Src/modules.h
deleted file mode 100644
index d172ad11c2..0000000000
--- a/backends/platform/PalmOS/Src/modules.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef MODULES_H
-#define MODULES_H
-
-#include "globals.h"
-
-#define sysAppLaunchCode_SVMRunEngine (sysAppLaunchCmdCustomBase + 0)
-
-void ModDelete();
-
-typedef struct {
- UInt8 lightspeed;
- Boolean exitLauncher;
-
- struct {
- UInt8 argc;
- Char **argv;
- } args;
-
- GlobalsDataPtr gVars;
-} LaunchParamType;
-
-#endif
diff --git a/backends/platform/PalmOS/Src/native/oscalls.cpp b/backends/platform/PalmOS/Src/native/oscalls.cpp
deleted file mode 100644
index 9bfd01393f..0000000000
--- a/backends/platform/PalmOS/Src/native/oscalls.cpp
+++ /dev/null
@@ -1,92 +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 <PenInputMgr.h>
-#include "pace.h"
-
-GlobalsType global;
-
-
-PACE_CLASS_WRAPPER(Err)
- __68k_StatShow(void) {
- PACE_PIN_EXEC_NP(pinStatShow, Err)
-}
-
-PACE_CLASS_WRAPPER(Err)
- __68k_StatHide(void) {
- PACE_PIN_EXEC_NP(pinStatHide, Err)
-}
-
-PACE_CLASS_WRAPPER(Err)
- __68k_PINSetInputAreaState(UInt16 state) {
- PACE_PARAMS_INIT()
- PACE_PARAMS_ADD16(state)
- PACE_PARAMS_END()
- PACE_PIN_EXEC(pinPINSetInputAreaState, Err)
-}
-
-PACE_CLASS_WRAPPER(UInt16)
- __68k_PINGetInputAreaState(void) {
- PACE_PIN_EXEC_NP(pinPINGetInputAreaState, UInt16)
-}
-
-PACE_CLASS_WRAPPER(Err)
- __68k_PINSetInputTriggerState(UInt16 state) {
- PACE_PARAMS_INIT()
- PACE_PARAMS_ADD16(state)
- PACE_PARAMS_END()
- PACE_PIN_EXEC(pinPINSetInputTriggerState, Err)
-}
-
-PACE_CLASS_WRAPPER(UInt16)
- __68k_PINGetInputTriggerState(void) {
- PACE_PIN_EXEC_NP(pinPINGetInputTriggerState, UInt16)
-}
-
-PACE_CLASS_WRAPPER(Err)
- __68k_SysSetOrientation(UInt16 orientation) {
- PACE_PARAMS_INIT()
- PACE_PARAMS_ADD16(orientation)
- PACE_PARAMS_END()
- PACE_PIN_EXEC(pinSysSetOrientation, Err)
-}
-
-PACE_CLASS_WRAPPER(UInt16)
- __68k_SysGetOrientation(void) {
- PACE_PIN_EXEC_NP(pinSysGetOrientation, UInt16)
-}
-
-PACE_CLASS_WRAPPER(Err)
- __68k_SysSetOrientationTriggerState(UInt16 triggerState) {
- PACE_PARAMS_INIT()
- PACE_PARAMS_ADD16(triggerState)
- PACE_PARAMS_END()
- PACE_PIN_EXEC(pinSysSetOrientationTriggerState, Err)
-}
-
-PACE_CLASS_WRAPPER(UInt16)
- __68k_SysGetOrientationTriggerState(void) {
- PACE_PIN_EXEC_NP(pinSysGetOrientationTriggerState, UInt16)
-}
diff --git a/backends/platform/PalmOS/Src/native/pace.h b/backends/platform/PalmOS/Src/native/pace.h
deleted file mode 100644
index 37b903b2c3..0000000000
--- a/backends/platform/PalmOS/Src/native/pace.h
+++ /dev/null
@@ -1,103 +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$
- *
- */
-
-#ifndef PACE_H
-#define PACE_H
-
-#include <PceNativeCall.h>
-//#include "endianutils.h"
-
-// local definition of the emulation state structure
-typedef struct {
- UInt32 instr;
- UInt32 regData[8];
- UInt32 regAddress[8];
- UInt32 regPC;
-} EmulStateType;
-
-typedef struct {
- EmulStateType *emulStateP;
- Call68KFuncType *call68KFuncP;
-} GlobalsType;
-
-extern GlobalsType global;
-
-// TODO : check this, already defined in ARMlet_Runtime
-//extern EmulStateType *g_emulStateP;
-//extern Call68KFuncType *g_call68KFuncP;
-#define g_emulStateP global.emulStateP
-#define g_call68KFuncP global.call68KFuncP
-
-
-#ifdef __cplusplus
-# define PACE_CLASS_WRAPPER(rv) extern "C" rv
-#else
-# define PACE_CLASS_WRAPPER(rv) rv
-#endif
-#define PACE_CALLBACK_PTR g_call68KFuncP
-#define PACE_EMULSTATE g_emulStateP
-
-#define ALIGN_4BYTE(addr) (((UInt32)(addr) + 3) & 0xFFFFFFFC)
-
-/****** TAKEN FROM PACEInteface.cpp (ARMlet_Runtime) ******/
-// local definition of the emulation state structure
-
-#define PACE_PARAMS_INIT() \
- UInt8 params[] = {
-
-#define PACE_PARAMS_ADD8(param) \
- (UInt8)(param), \
- 0,
-
-#define PACE_PARAMS_ADD16(param) \
- (UInt8)((UInt16)(param) >> 8), \
- (UInt8)(param),
-
-#define PACE_PARAMS_ADD32(param) \
- (UInt8)((UInt32)(param) >> 24), \
- (UInt8)((UInt32)(param) >> 16), \
- (UInt8)((UInt32)(param) >> 8), \
- (UInt8)(param),
-
-#define PACE_PARAMS_END() \
- };
-
-// PIN
-#define PACE_PIN_EXEC_NP(pinTrap, returnType) \
- PACE_EMULSTATE->regData[2] = pinTrap; \
- return ((returnType)((PACE_CALLBACK_PTR)( \
- static_cast<void *>(PACE_EMULSTATE), \
- PceNativeTrapNo(sysTrapPinsDispatch), \
- NULL, 0)));
-
-#define PACE_PIN_EXEC(pinTrap, returnType) \
- PACE_EMULSTATE->regData[2] = pinTrap; \
- return ((returnType)((PACE_CALLBACK_PTR)( \
- static_cast<void *>(PACE_EMULSTATE), \
- PceNativeTrapNo(sysTrapPinsDispatch), \
- &params, \
- sizeof(params))));
-
-#endif
diff --git a/backends/platform/PalmOS/Src/native/pnoARM.c b/backends/platform/PalmOS/Src/native/pnoARM.c
deleted file mode 100644
index 48c4fee972..0000000000
--- a/backends/platform/PalmOS/Src/native/pnoARM.c
+++ /dev/null
@@ -1,60 +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$
- *
- */
-
-#ifdef COMPILE_OS5
-
-#include <PalmOS.h>
-#include <stdlib.h>
-#include "pace.h"
-
-// Linker still looks for ARMlet_Main as entry point, but the
-// "ARMlet" name is now officially discouraged. Compare an
-// contrast to "PilotMain" for 68K applications.
-#define PNO_Main ARMlet_Main
-
-/* Prepare static initializers */
-extern long __sinit__[];
-extern void __ARMlet_Startup__();
-
-/* simple function pointer */
-typedef void (*StaticInitializer)(void);
-
-unsigned long PNO_Main(const void *emulStateP, void *userData68KP, Call68KFuncType *call68KFuncP) {
- global.emulStateP = (EmulStateType *)emulStateP;
- global.call68KFuncP = call68KFuncP;
-
- // handle static initializers
- if (__sinit__) {
- long base = (long)__ARMlet_Startup__;
- long s, *p;
-
- for (p = __sinit__; p && (s = *p) != 0; p++)
- ((StaticInitializer)(s + base))();
- }
-
- return PilotMain(sysAppLaunchCmdNormalLaunch, userData68KP, 0);
-}
-
-#endif
diff --git a/backends/platform/PalmOS/Src/native/pnoStartup.c b/backends/platform/PalmOS/Src/native/pnoStartup.c
deleted file mode 100644
index b76cac3024..0000000000
--- a/backends/platform/PalmOS/Src/native/pnoStartup.c
+++ /dev/null
@@ -1,28 +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$
- *
- */
-
-#ifdef COMPILE_OS5
-# include "(Source)/ARMlet_Startup.c"
-#endif
diff --git a/backends/platform/PalmOS/Src/native/zodiacARM.cpp b/backends/platform/PalmOS/Src/native/zodiacARM.cpp
deleted file mode 100644
index 7323bb6d69..0000000000
--- a/backends/platform/PalmOS/Src/native/zodiacARM.cpp
+++ /dev/null
@@ -1,150 +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 "PalmVersion.h"
-#include <MSL_PalmOS.h>
-
-#include "globals.h"
-#include "args.h"
-#include "palmdefs.h"
-
-#include "rumble.h"
-
-
-//#include <AdnDebugMgr.h>
-//#define DEBUG_ARM
-
-#include "base/main.h"
-#ifdef COMPILE_ZODIAC
-# include "be_zodiac.h"
-#endif
-#include "be_os5ex.h"
-
-GlobalsDataType g_vars;
-GlobalsDataPtr gVars = &g_vars;
-UInt32 g_stackSize;
-
-extern "C" void __destroy_global_chain(void);
-extern void DrawStatus(Boolean show);
-
-static void palm_main(int argc, char **argvP) {
-#ifdef COMPILE_OS5
- if (gVars->advancedMode)
- g_system = new OSystem_PalmOS5Ex();
- else
- g_system = new OSystem_PalmOS5();
-#elif defined(COMPILE_ZODIAC)
- g_system = new OSystem_PalmZodiac();
-#else
- #error "No target defined."
-#endif
-
- assert(g_system);
-
- scummvm_main(argc, argvP);
-
- g_system->quit(); // TODO: Consider removing / replacing this!
-}
-
-static void Go() {
- void *tmp;
- char **argvP;
- int argc;
-
-#ifdef DEBUG_ARM
-// Tell the debugger we want to enable full debugging
- UInt32 flags = AdnDebugEnableGet();
- flags |= kAdnEnableMasterSwitch | kAdnEnableFullDebugging;
- AdnDebugEnableSet(flags);
-// Tell the debugger where our code lives in memory:
- AdnDebugNativeRegister(sysFileTApplication, appFileCreator, 'ARMC', 1);
-#endif
-
- // get global struct
- FtrGet(appFileCreator, ftrVars, (UInt32 *)&tmp);
- MemMove(gVars, tmp, sizeof(GlobalsDataType));
-
- // init STDIO
- stdio_set_cache(0);
- stdio_init(gVars->VFS.volRefNum, "/PALM/Programs/ScummVM/scumm.log");
- if (gVars->indicator.showLED)
- stdio_set_led(DrawStatus);
- stdio_set_cache(gVars->VFS.cacheSize);
-
- // get args
- FtrGet(appFileCreator, ftrArgsData, (UInt32 *)&argvP);
- FtrGet(appFileCreator, ftrArgsCount, (UInt32 *)&argc);
-
- // init system
- WinSetDrawWindow(WinGetDisplayWindow());
- if (HWR_INIT(INIT_VIBRATOR)) gVars->vibrator = RumbleInit();
-
- // run ...
- DO_EXIT ( palm_main(argc, argvP); )
-
- // release
- if (HWR_INIT(INIT_VIBRATOR)) RumbleRelease();
- stdio_release();
-
-#ifdef DEBUG_ARM
- AdnDebugNativeUnregister();
-#endif
-}
-
-/* Stack size */
-
-Int8 *g_newStack, *g_newStackPos;
-void *g_oldStack;
-
-static asm void *StkSwap(void *newStack ,void *dummy) {
- mov r1, r13
- mov r13, r0
- mov r0, r1
- bx lr
-}
-
-extern UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) {
- if (cmd == sysAppLaunchCmdNormalLaunch) {
- FtrGet(appFileCreator, ftrStack, &g_stackSize);
- if (!g_stackSize)
- g_stackSize = 32 * 1024;
-
- g_newStack = (Int8 *)malloc(g_stackSize + 8);
- g_newStackPos = (g_newStack + g_stackSize);
- g_newStackPos -= ((UInt32)g_newStackPos & 7);
-
- g_oldStack = StkSwap(g_newStackPos, 0);
-
- Go();
-
- StkSwap(g_oldStack, 0);
- free(g_newStack);
- }
-
- // Destroy all constructed global objects
- __destroy_global_chain();
-
- return 0;
-}
diff --git a/backends/platform/PalmOS/Src/native/zodiacStartup.cpp b/backends/platform/PalmOS/Src/native/zodiacStartup.cpp
deleted file mode 100644
index 7f6264c1ac..0000000000
--- a/backends/platform/PalmOS/Src/native/zodiacStartup.cpp
+++ /dev/null
@@ -1,161 +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$
- *
- */
-
-#ifdef COMPILE_ZODIAC
-
-#include <TapWave.h>
-
-#ifndef __PALMOS_ARMLET__
-#error "__PALMOS_ARMLET__ is not defined!!!"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * This variable holds the Tapwave Native Application interface
- * dispatch table. General ARM API calls will go through this table.
- */
-struct TwGlue* twGlue;
-const void* twEmulState;
-Call68KFuncType* twCall68KFunc;
-
-#ifdef __MWERKS__
-
-#if __PALMOS_ARMLET__ < 0x120
-#error "You must use CodeWarrior for Palm OS 9.3 or later!!!"
-#endif
-
-
-UInt32 __ARMlet_Startup__(const void*, void*, Call68KFuncType*);
-
-/*
- * These symbols aren't real, but are linker-generated symbols that
- * mark the start and end of the various data sections.
- */
-extern long __DataStart__[];
-extern long __sinit__[];
-extern long __RODataStart__[];
-extern long __BSSStart__[];
-extern long __BSSEnd__[];
-extern long __CodeRelocStart__[];
-extern long __CodeRelocEnd__[];
-extern long __DataRelocStart__[];
-extern long __DataRelocEnd__[];
-
-/* simple function pointer */
-typedef void (*StaticInitializer)(void);
-
-/*
- * This function performs relocation for Tapwave Native Application.
- */
-static void relocate(void)
-{
- // this symbol points to the very beginning of current application
- long base = (long) __ARMlet_Startup__;
- long *cur, *end;
-
- // handle static initializers
- if (__sinit__) {
- long s, *p;
-
- for (p = __sinit__; p && (s = *p) != 0; p++)
- ((StaticInitializer)(s + base))();
- }
-
- // handle code-to-data relocation
- cur = __CodeRelocStart__;
- end = __CodeRelocEnd__;
- for (; cur < end; cur++) {
- *(long*)(base + *cur) += base;
- }
-
- // handle data-to-data relocation
- cur = __DataRelocStart__;
- end = __DataRelocEnd__;
- for (; cur < end; cur++) {
- *(long*)(base + *cur) += base;
- }
-}
-
-/*
- * This is the real entrypoint for Tapwave Native Application. It
- * depends on various CodeWarrior 9.2 compiler/linker/runtime features.
- */
-static SYSTEM_CALLBACK UInt32
-Startup(const void *emulStateP, void *userData68KP, Call68KFuncType *call68KFuncP)
-{
- if (emulStateP) {
- twEmulState = emulStateP;
- twCall68KFunc = call68KFuncP;
- // COMMENT: normal pace native object launch
- return PilotMain(sysAppLaunchCmdNormalLaunch, userData68KP, 0);
- } else {
- // Setup TNA interface dispatch table
- twGlue = (struct TwGlue*) userData68KP;
-
- // OPTIONAL: relocate data segment
- relocate();
-
- // OPTIONAL: initialize the floating-point library
- // _fp_init();
-
- return 0;
- }
-}
-
-#pragma PIC off
-asm UInt32
-__ARMlet_Startup__(const void *emulStateP, void *userData68KP, Call68KFuncType *call68KFuncP)
-{
- b Startup // 0 forwarding call
- nop // 4
- nop // 8
- nop // 12
- nop // 16
- nop // 20
- nop // 24
- dcd 'TWNA' // 28 Tapwave Native Application
- dcd 1 // 32 version 1
- dcd 'cdwr' // 36 make this section the same as the __ARMlet_Startup__
- dcd __DataStart__ // 40 used by CodeWarrior 9.2
- dcd __RODataStart__ // 44
- dcd __BSSStart__ // 48
- dcd __BSSEnd__ // 52
- dcd __CodeRelocStart__ // 56
- dcd __CodeRelocEnd__ // 60
- dcd __DataRelocStart__ // 64
- dcd __DataRelocEnd__ // 68
-}
-#pragma PIC reset
-
-#endif // __MWERKS__
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif
diff --git a/backends/platform/PalmOS/Src/os5_event.cpp b/backends/platform/PalmOS/Src/os5_event.cpp
deleted file mode 100644
index 534c2eb4f9..0000000000
--- a/backends/platform/PalmOS/Src/os5_event.cpp
+++ /dev/null
@@ -1,82 +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 "be_os5.h"
-
-void OSystem_PalmOS5::get_coordinates(EventPtr ev, Coord &x, Coord &y) {
- Boolean dummy;
- EvtGetPenNative(WinGetDisplayWindow(), &ev->screenX, &ev->screenY, &dummy);
-
- x = (ev->screenX - _screenOffset.x);
- y = (ev->screenY - _screenOffset.y);
-
- if (_stretched) {
- x = (x * _screenWidth) / _screenDest.w;
- y = (y * _screenHeight) / _screenDest.h;
- }
-}
-
-bool OSystem_PalmOS5::check_event(Common::Event &event, EventPtr ev) {
- if (ev->eType == keyUpEvent) {
- switch (ev->data.keyUp.chr) {
- case vchrHard3:
- case vchrHard4:
- // will be handled by hard keys
- return true;
- }
-
- } else if (ev->eType == keyDownEvent) {
- switch (ev->data.keyDown.chr) {
-
- // hot swap gfx
-// case 0x1B04:
- case vchrHard1:
- if (OPTIONS_TST(kOptCollapsible))
- hotswap_gfx_mode(_mode == GFX_WIDE ? GFX_NORMAL: GFX_WIDE);
- return false; // not a key
-
-// case 0x1B05:
- case vchrHard2:
- setFeatureState(kFeatureAspectRatioCorrection, 0);
- return false; // not a key
-
- case vchrHard3:
- _keyExtraPressed |= _keyExtra.bitActionA;
- event.type = Common::EVENT_LBUTTONDOWN;
- event.mouse.x = _mouseCurState.x;
- event.mouse.y = _mouseCurState.y;
- return true;
-
- case vchrHard4:
- _keyExtraPressed |= _keyExtra.bitActionB;
- event.type = Common::EVENT_RBUTTONDOWN;
- event.mouse.x = _mouseCurState.x;
- event.mouse.y = _mouseCurState.y;
- return true;
- }
- }
-
- return false;
-}
diff --git a/backends/platform/PalmOS/Src/os5_gfx.cpp b/backends/platform/PalmOS/Src/os5_gfx.cpp
deleted file mode 100644
index 6a7b21e100..0000000000
--- a/backends/platform/PalmOS/Src/os5_gfx.cpp
+++ /dev/null
@@ -1,309 +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 "be_os5.h"
-#include "graphics/surface.h"
-#include "common/config-manager.h"
-#include <PenInputMgr.h>
-#include <palmOneResources.h>
-
-#include "oscalls.h"
-
-void OSystem_PalmOS5::int_initSize(uint w, uint h) {
-}
-
-WinHandle OSystem_PalmOS5::alloc_screen(Coord w, Coord h) {
- Err e;
- WinHandle winH;
- UInt16 old = WinSetCoordinateSystem(kCoordinatesNative);
- winH = WinCreateOffscreenWindow(w, h, nativeFormat, &e);
- WinSetCoordinateSystem(old);
-
- return winH;
-}
-
-void OSystem_PalmOS5::load_gfx_mode() {
- Err e;
-
- if (_gfxLoaded)
- return;
- _gfxLoaded = true;
-
- // get command line config
-// _fullscreen = ConfMan.getBool("fullscreen"); // TODO : (NORMAL mode)
- _ratio.adjustAspect = ConfMan.getBool("aspect_ratio") ? kRatioHeight : kRatioNone;
-
- // precalc ratio (WIDE mode)
- _ratio.width = (gVars->screenFullHeight * _screenWidth / _screenHeight);
- _ratio.height = (gVars->screenFullWidth * _screenHeight / _screenWidth);
-
- _offScreenP = (byte *)malloc(_screenWidth * _screenHeight);
-
- MemSet(_offScreenP, _screenWidth * _screenHeight, 0);
- MemSet(_nativePal, sizeof(_nativePal), 0);
- MemSet(_currentPalette, sizeof(_currentPalette), 0);
-
- UInt32 depth = 16;
- WinScreenMode(winScreenModeSet, NULL, NULL, &depth, NULL);
- clear_screen();
-
- if (OPTIONS_TST(kOptModeRotatable)) {
- _sysOldOrientation = __68K(SysGetOrientation());
- _sysOldTriggerState = __68K(PINGetInputTriggerState());
- __68K(SysSetOrientation(sysOrientationLandscape));
- __68K(SysSetOrientationTriggerState(sysOrientationTriggerDisabled));
- __68K(PINSetInputTriggerState(pinInputTriggerDisabled));
- }
-
- gVars->indicator.on = Graphics::RGBToColor<Graphics::ColorMasks<565> >(0,255,0);
- gVars->indicator.off = Graphics::RGBToColor<Graphics::ColorMasks<565> >(0,0,0);
-
- _overlayH = alloc_screen(_screenWidth, _screenHeight);
- _overlayP = (OverlayColor *)(BmpGetBits(WinGetBitmap(_overlayH)));
-
- _screenH = WinGetDisplayWindow();
- _screenP = (byte *)(BmpGetBits(WinGetBitmap(_screenH)));
-
- _isSwitchable = OPTIONS_TST(kOptModeLandscape) && OPTIONS_TST(kOptCollapsible);
- if (!_isSwitchable)
- _mode = GFX_NORMAL;
-
- hotswap_gfx_mode(_mode);
-}
-
-void OSystem_PalmOS5::hotswap_gfx_mode(int mode) {
- Err e;
-
- if (_mode != GFX_NORMAL && !_isSwitchable)
- return;
-
- if (_workScreenH)
- WinDeleteWindow(_workScreenH, false);
- _workScreenH = NULL;
-
- _screenDest.w = _screenWidth;
- _screenDest.h = _screenHeight;
-
- // prevent bad DIA redraw (Stat part)
- if (mode == GFX_NORMAL) {
- _redawOSD = true;
- _stretched = (_screenWidth > gVars->screenWidth);
-
- if (OPTIONS_TST(kOptCollapsible)) {
- //AiaSetInputAreaState(aiaInputAreaShow); // For T3 ??
- __68K(StatShow());
- __68K(PINSetInputAreaState(pinInputAreaOpen));
- }
-
- if (_stretched) {
- calc_rect(false);
- } else {
- // offsets
- _screenOffset.x = (gVars->screenWidth - _screenWidth) / 2;
- _screenOffset.y = (gVars->screenHeight - _screenHeight) / 2;
- }
-
- } else {
- _redawOSD = false;
- _stretched = true;
-
- if (OPTIONS_TST(kOptCollapsible)) {
- // T3 DIA library is 68k base, there is no possible native call
- //AiaSetInputAreaState(aiaInputAreaFullScreen);
- __68K(PINSetInputAreaState(pinInputAreaClosed));
- __68K(StatHide());
- }
-
- calc_rect(true);
- }
-
- if (_stretched) {
- OPTIONS_SET(kOptDisableOnScrDisp);
- if (_screenHeight == 200 && _screenDest.h == 300) {
- _render = &OSystem_PalmOS5::render_landscape15x;
- } else {
- _render = &OSystem_PalmOS5::render_landscapeAny;
- calc_scale();
- }
- } else {
- OPTIONS_RST(kOptDisableOnScrDisp);
- _render = &OSystem_PalmOS5::render_1x;
- }
-
- _workScreenH = alloc_screen(_screenDest.w, _screenDest.h);
- _workScreenP = (uint16 *)(BmpGetBits(WinGetBitmap(_workScreenH)));
- MemSet(_workScreenP, _screenDest.w * _screenDest.h * 2, 0);
-
- _mode = mode;
- clear_screen();
-}
-
-void OSystem_PalmOS5::unload_gfx_mode() {
- if (!_gfxLoaded)
- return;
- _gfxLoaded = false;
-
- // mouse data freed in quit()
- free(_offScreenP);
-
- if (_workScreenH)
- WinDeleteWindow(_workScreenH, false);
- if (_overlayH)
- WinDeleteWindow(_overlayH, false);
-
- _workScreenH = NULL;
- _overlayH = NULL;
-
- UInt32 depth = 8;
- WinScreenMode(winScreenModeSet, NULL, NULL, &depth, NULL);
- clear_screen();
-
- if (OPTIONS_TST(kOptModeRotatable)) {
- __68K(PINSetInputTriggerState(_sysOldTriggerState));
- __68K(SysSetOrientation(_sysOldOrientation));
- }
-
- WinSetCoordinateSystem(_sysOldCoord);
-}
-
-void OSystem_PalmOS5::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
- // Clip the coordinates
- if (x < 0) {
- w += x;
- buf -= x;
- x = 0;
- }
-
- if (y < 0) {
- h += y;
- buf -= y * pitch;
- y = 0;
- }
-
- if (w > _screenWidth - x)
- w = _screenWidth - x;
-
- if (h > _screenHeight - y)
- h = _screenHeight - y;
-
- if (w <= 0 || h <= 0)
- return;
-
- byte *dst = _offScreenP + y * _screenWidth + x;
-
- if (w == pitch && w == _screenWidth) {
- MemMove(dst, buf, w * h);
- } else {
- do {
- MemMove(dst, buf, w);
- dst += _screenWidth;
- buf += pitch;
- } while (--h);
- }
-}
-
-Graphics::Surface *OSystem_PalmOS5::lockScreen() {
- _framebuffer.pixels = _offScreenP;
- _framebuffer.w = _screenWidth;
- _framebuffer.h = _screenHeight;
- _framebuffer.pitch = _screenWidth;
- _framebuffer.bytesPerPixel = 1;
-
- return &_framebuffer;
-}
-
-void OSystem_PalmOS5::unlockScreen() {
- // The screen is always completely update anyway, so we don't have to force a full update here.
-}
-
-void OSystem_PalmOS5::int_updateScreen() {
- RectangleType r;
- PointType p;
-
- draw_mouse();
- ((this)->*(_render))(r, p);
-
- _sysOldCoord = WinSetCoordinateSystem(kCoordinatesNative);
- WinCopyRectangle(_workScreenH, _screenH, &r, p.x, p.y, winPaint);
- WinSetCoordinateSystem(_sysOldCoord);
- undraw_mouse();
-}
-
-void OSystem_PalmOS5::clear_screen() {
- RGBColorType rgb = { 0,0,0,0 };
- WinSetDrawWindow(WinGetDisplayWindow());
- WinSetBackColorRGB(&rgb, 0);
- WinEraseWindow();
-}
-
-void OSystem_PalmOS5::extras_palette(uint8 index, uint8 r, uint8 g, uint8 b) {
- _nativePal[index] = gfxMakeDisplayRGB(r, g, b);
-}
-
-void OSystem_PalmOS5::draw_osd(UInt16 id, Int32 x, Int32 y, Boolean show, UInt8 color) {
- if (_mode != GFX_NORMAL)
- return;
-// MemHandle hTemp = DmGetResource(bitmapRsc, id);
- MemHandle hTemp = DmGetResource('abmp', id + 100);
-
- if (hTemp) {
- RGBColorType oldRGB;
- static const RGBColorType pal[4] = {
- {0,0,255,0},
- {0,255,255,0},
- {0,255,0,0},
- {0,0,0,0}
- };
-
- BitmapType *bmTemp;
- bmTemp = (BitmapType *)MemHandleLock(hTemp);
-
- Coord w, h;
- BmpGetDimensions(bmTemp, &w, &h, 0);
-
- PointType dst = { _screenOffset.x + x, _screenOffset.y + y };
- RectangleType c, r = { dst.x, dst.y, w, h };
-
- UInt16 old = WinSetCoordinateSystem(kCoordinatesNative);
- WinSetDrawWindow(_screenH);
- WinGetClip(&c);
- WinResetClip();
-
- if (show) {
- WinSetForeColorRGB(&pal[3], &oldRGB);
- WinSetBackColorRGB(&pal[color], &oldRGB);
- WinDrawBitmap(bmTemp, dst.x, dst.y);
- } else {
- WinSetBackColorRGB(&pal[3], &oldRGB);
- WinFillRectangle(&r, 0);
- }
-
- WinSetClip(&c);
- WinSetCoordinateSystem(old);
-
- MemPtrUnlock(bmTemp);
- DmReleaseResource(hTemp);
- }
-}
diff --git a/backends/platform/PalmOS/Src/os5_mouse.cpp b/backends/platform/PalmOS/Src/os5_mouse.cpp
deleted file mode 100644
index c019e1607d..0000000000
--- a/backends/platform/PalmOS/Src/os5_mouse.cpp
+++ /dev/null
@@ -1,157 +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 "be_os5.h"
-
-void OSystem_PalmOS5::setCursorPalette(const byte *colors, uint start, uint num) {
- for (uint i = 0; i < num; i++) {
- _mousePal[i + start] = gfxMakeDisplayRGB(colors[0], colors[1], colors[2]);
- colors += 4;
- }
-
- _cursorPaletteDisabled = false;
-}
-
-void OSystem_PalmOS5::disableCursorPalette(bool disable) {
- _cursorPaletteDisabled = disable;
-}
-
-// TODO: this code is almost the same as Zodiac version.
-void OSystem_PalmOS5::draw_mouse() {
- if (!_mouseDataP || _mouseDrawn || !_mouseVisible)
- return;
-
- byte *src = _mouseDataP;
-
- int x = _mouseCurState.x - _mouseHotspotX;
- int y = _mouseCurState.y - _mouseHotspotY;
- int w = _mouseCurState.w;
- int h = _mouseCurState.h;
-
- // clip the mouse rect
- if (y < 0) {
- src -= y * w;
- h += y;
- y = 0;
- }
- if (x < 0) {
- src -= x;
- w += x;
- x = 0;
- }
-
- if (h > _screenHeight - y)
- h = _screenHeight - y;
- if (w > _screenWidth - x)
- w = _screenWidth - x;
-
- if (w <= 0 || h <= 0)
- return;
-
- // store the bounding box so that undraw mouse can restore the area the
- // mouse currently covers to its original content
- _mouseOldState.x = x;
- _mouseOldState.y = y;
- _mouseOldState.w = w;
- _mouseOldState.h = h;
-
- byte color;
- int ww;
-
- if (_overlayVisible) {
- uint16 *bak = (uint16 *)_mouseBackupP;
- uint16 *pal = _cursorPaletteDisabled ? _nativePal : _mousePal;
- uint16 *dst = _overlayP + y * _screenWidth + x;
-
- do {
- ww = w;
- do {
- *bak++ = *dst;
- color = *src++;
-
- // transparent, don't draw
- if (color != _mouseKeyColor)
- *dst = pal[color];
- dst++;
- } while (--ww);
-
- src += _mouseCurState.w - w;
- dst += _screenWidth - w;
- } while (--h);
-
- } else {
- byte *bak = _mouseBackupP;
- byte *dst =_offScreenP + y * _screenWidth + x;
-
- do {
- ww = w;
- do {
- *bak++ = *dst;
- color = *src++;
-
- // transparent, don't draw
- if (color != _mouseKeyColor)
- *dst = color;
- dst++;
- } while (--ww);
-
- src += _mouseCurState.w - w;
- dst += _screenWidth - w;
- } while (--h);
- }
-
- _mouseDrawn = true;
-}
-
-void OSystem_PalmOS5::undraw_mouse() {
- if (!_mouseDrawn)
- return;
-
- int h = _mouseOldState.h;
-
- // no need to do clipping here, since draw_mouse() did that already
- if (_overlayVisible) {
- uint16 *dst = _overlayP + _mouseOldState.y * _screenWidth + _mouseOldState.x;
- uint16 *bak = (uint16 *)_mouseBackupP;
-
- do {
- MemMove(dst, bak, _mouseOldState.w * 2);
- dst += _screenWidth;
- bak += _mouseOldState.w;
- } while (--h);
-
- } else {
- byte *dst = _offScreenP + _mouseOldState.y * _screenWidth + _mouseOldState.x;
- byte *bak = _mouseBackupP;
-
- do {
- MemMove(dst, bak, _mouseOldState.w);
- dst += _screenWidth;
- bak += _mouseOldState.w;
- } while (--h);
- }
-
- _mouseDrawn = false;
-}
diff --git a/backends/platform/PalmOS/Src/os5_overlay.cpp b/backends/platform/PalmOS/Src/os5_overlay.cpp
deleted file mode 100644
index 7e16a6b7b9..0000000000
--- a/backends/platform/PalmOS/Src/os5_overlay.cpp
+++ /dev/null
@@ -1,76 +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 "be_os5.h"
-#include "common/endian.h"
-
-void OSystem_PalmOS5::showOverlay() {
- // hide fight indicator
- draw_osd(kDrawFight, _screenDest.w - 34, _screenDest.h + 2, false);
-
- undraw_mouse();
- _overlayVisible = true;
- clearOverlay();
-}
-
-void OSystem_PalmOS5::hideOverlay() {
- undraw_mouse();
- _overlayVisible = false;
- _redawOSD = true;
-}
-
-void OSystem_PalmOS5::clearOverlay() {
- if (!_overlayVisible)
- return;
-
- byte *src = _offScreenP;
- uint16 *dst = _overlayP;
- int cnt = _screenWidth * _screenHeight;
- do {
- *dst++ = _nativePal[*src++];
- } while (--cnt);
-}
-
-void OSystem_PalmOS5::grabOverlay(OverlayColor *buf, int pitch) {
- OverlayColor *src = _overlayP;
- int h = _screenHeight;
- do {
- memcpy(buf, src, _screenWidth * 2);
- src += _screenWidth;
- buf += pitch;
- } while (--h);
-}
-
-void OSystem_PalmOS5::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
- if (w == 0 || h == 0)
- return;
-
- OverlayColor *dst = _overlayP + x + y * _screenWidth;
- do {
- memcpy(dst, buf, w * 2);
- dst += _screenWidth;
- buf += pitch;
- } while (--h);
-}
diff --git a/backends/platform/PalmOS/Src/os5_renderer.cpp b/backends/platform/PalmOS/Src/os5_renderer.cpp
deleted file mode 100644
index fea3ec28d7..0000000000
--- a/backends/platform/PalmOS/Src/os5_renderer.cpp
+++ /dev/null
@@ -1,118 +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 "be_os5.h"
-
-void OSystem_PalmOS5::render_1x(RectangleType &r, PointType &p) {
- Coord o = 0;
-
- if (_overlayVisible) {
- uint16 *src = _overlayP;
- uint16 *dst = _workScreenP;
- MemMove(dst, src, _screenWidth * _screenHeight * 2);
-
- } else {
- byte *src = _offScreenP;
- uint16 *dst = _workScreenP;
- int cnt = _screenWidth * _screenHeight;
- o = _current_shake_pos;
-
- do {
- *dst++ = _nativePal[*src++];
- } while (--cnt);
- }
-
- p.x = _screenOffset.x;
- p.y = _screenOffset.y + o;
- RctSetRectangle(&r, 0, 0, _screenWidth, _screenHeight - o);
-}
-
-void OSystem_PalmOS5::render_landscapeAny(RectangleType &r, PointType &p) {
- Coord x, y, o = 0;
- uint16 *dst = _workScreenP;
-
- if (_overlayVisible) {
- for (y = 0; y < _screenDest.h; y++) {
- uint16 *src = _overlayP + *(_scaleTableY + y);
- for (x = 0; x < _screenDest.w; x++) {
- *dst++ = *(src + *(_scaleTableX + x));
- }
- }
-
- } else {
- o = _current_shake_pos;
-
- for (y = 0; y < _screenDest.h; y++) {
- byte *src = _offScreenP + *(_scaleTableY + y);
- for (x = 0; x < _screenDest.w; x++) {
- *dst++ = *(_nativePal + *(src + *(_scaleTableX + x)));
- }
- }
- }
-
- p.x = _screenOffset.x;
- p.y = _screenOffset.y + o;
- RctSetRectangle(&r, 0, 0, _screenDest.w, _screenDest.h - o);
-}
-
-void OSystem_PalmOS5::render_landscape15x(RectangleType &r, PointType &p) {
- Coord x, y, o = 0;
- uint16 *dst = _workScreenP;
-
- if (_overlayVisible) {
- uint16 *src = _overlayP;
-
- for (y = 0; y < 100; y++) {
- // draw 2 lines
- for (x = 0; x < 320; x++) {
- *dst++ = *src++;
- *dst++ = *src;
- *dst++ = *src++;
- }
- // copy the second to the next line
- MemMove(dst, dst - 480, 480 * 2);
- dst += 480;
- }
- } else {
- byte *src = _offScreenP;
- o = _current_shake_pos;
-
- for (y = 0; y < 100; y++) {
- // draw 2 lines
- for (x = 0; x < 320; x++) {
- *dst++ = _nativePal[*src++];
- *dst++ = _nativePal[*src];
- *dst++ = _nativePal[*src++];
- }
- // copy the second to the next line
- MemMove(dst, dst - 480, 480 * 2);
- dst += 480;
- }
- }
-
- p.x = _screenOffset.x;
- p.y = _screenOffset.y + o;
- RctSetRectangle(&r, 0, 0, 480, 300 - o);
-}
diff --git a/backends/platform/PalmOS/Src/os5_sound.cpp b/backends/platform/PalmOS/Src/os5_sound.cpp
deleted file mode 100644
index 73ab64c0d5..0000000000
--- a/backends/platform/PalmOS/Src/os5_sound.cpp
+++ /dev/null
@@ -1,156 +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 "be_os5.h"
-#include "common/config-manager.h"
-#include "sound/mixer_intern.h"
-
-
-#ifdef PALMOS_ARM
-# ifdef COMPILE_ZODIAC
-# define SAMPLES_PER_SEC 44100
-# else
-# define SAMPLES_PER_SEC 22050
-# endif
-#else
-# define SAMPLES_PER_SEC 8000
-#endif
-
-
-SoundExType _soundEx;
-
-static Err sndCallback(void* UserDataP, SndStreamRef stream, void* bufferP, UInt32 *bufferSizeP) {
- SoundExType *_soundEx = (SoundExType *)UserDataP;
- SoundType *_sound = _soundEx->sound;
-
- if (_soundEx->set && _soundEx->size) {
- MemMove(bufferP, _soundEx->dataP, _soundEx->size);
- *bufferSizeP = _soundEx->size;
- _soundEx->set = false;
-
- } else {
- _soundEx->size = *bufferSizeP;
- MemSet(bufferP, 128, 0);
- *bufferSizeP = 128;
- }
-
- return errNone;
-}
-
-void OSystem_PalmOS5::sound_handler() {
- if (_sound.active) {
- if (_soundEx.size && !_soundEx.set) {
- if (!_soundEx.dataP)
- _soundEx.dataP = MemPtrNew(_soundEx.size);
-
- _mixerMgr->mixCallback((byte *)_soundEx.dataP, _soundEx.size);
- _soundEx.set = true;
- }
- }// TODO : no Sound API case
-}
-
-SndStreamVariableBufferCallback OSystem_PalmOS5::sound_callback() {
- return sndCallback;
-}
-
-bool OSystem_PalmOS5::setupMixer() {
- Err e;
- Boolean success = false;
-
- uint32 samplesPerSec;
- if (ConfMan.hasKey("output_rate"))
- samplesPerSec = ConfMan.getInt("output_rate");
- else
- samplesPerSec = SAMPLES_PER_SEC;
-
- _mixerMgr = new Audio::MixerImpl(this, samplesPerSec);
-
- if (!_sound.active) {
- if (gVars->fmQuality != FM_QUALITY_INI) {
- ConfMan.setBool("FM_medium_quality", (gVars->fmQuality == FM_QUALITY_MED));
- ConfMan.setBool("FM_high_quality", (gVars->fmQuality == FM_QUALITY_HI));
- }
-
-#if defined (COMPILE_OS5)
- CALLBACK_INIT(_soundEx);
-#endif
- _sound.proc = 0;
- _sound.param = _mixerMgr;
- _sound.active = true; // always true when we call this function, false when sound is off
-
- _soundEx.handle = 0;
- _soundEx.size = 0; // set by the callback
- _soundEx.set = false;
- _soundEx.dataP = NULL; // set by the handler
-
- // try to create sound stream
- if (OPTIONS_TST(kOptPalmSoundAPI)) {
- e = SndStreamCreateExtended(
- &_soundEx.handle,
- sndOutput,
- sndFormatPCM,
- samplesPerSec,
- sndInt16Little,
- sndStereo,
- sound_callback(),
- &_soundEx,
- 8192
-#ifdef COMPILE_OS5
- ,true
-#endif
- );
-
- e = e ? e : SndStreamStart(_soundEx.handle);
- e = e ? e : SndStreamSetVolume(_soundEx.handle, 1024L * gVars->palmVolume / 100);
- success = (e == errNone);
-
- // no Sound API
- } else {
- _soundEx.size = 512;
- _soundEx.dataP = MemPtrNew(_soundEx.size);
- }
- }
- // if not true some scenes (indy3 256,...) may freeze (ESC to skip)
-
- _mixerMgr->setReady(true);
-
- return true;
-}
-
-void OSystem_PalmOS5::clearSoundCallback() {
- if (_sound.active) {
- if (OPTIONS_TST(kOptPalmSoundAPI)) {
- SndStreamStop(_soundEx.handle);
- SndStreamDelete(_soundEx.handle);
- }
-
- if (_soundEx.dataP)
- MemPtrFree(_soundEx.dataP);
- }
-
- _sound.active = false;
- _soundEx.handle = NULL;
- _soundEx.dataP = NULL;
-}
diff --git a/backends/platform/PalmOS/Src/os5ex_sound.cpp b/backends/platform/PalmOS/Src/os5ex_sound.cpp
deleted file mode 100644
index f27f5a202d..0000000000
--- a/backends/platform/PalmOS/Src/os5ex_sound.cpp
+++ /dev/null
@@ -1,43 +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 "be_os5ex.h"
-#include "sound/mixer_intern.h"
-
-static SYSTEM_CALLBACK Err sndCallbackEx(void* UserDataP, SndStreamRef stream, void* bufferP, UInt32 *bufferSizeP) {
- CALLBACK_PROLOGUE
- SoundType *_sound = ((SoundExType *)UserDataP)->sound;
-// ((SoundProc)_sound->proc)(_sound->param, (byte *)bufferP, *bufferSizeP);
-
- Audio::MixerImpl *_mixerMgr = ( Audio::MixerImpl *)_sound->param;
- _mixerMgr->mixCallback((byte *)bufferP, *bufferSizeP);
-
- CALLBACK_EPILOGUE
- return errNone;
-}
-
-SndStreamVariableBufferCallback OSystem_PalmOS5Ex::sound_callback() {
- return sndCallbackEx;
-}
diff --git a/backends/platform/PalmOS/Src/palmdefs.h b/backends/platform/PalmOS/Src/palmdefs.h
deleted file mode 100644
index d37b533a21..0000000000
--- a/backends/platform/PalmOS/Src/palmdefs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef PALMDEFS_H
-#define PALMDEFS_H
-
-#define appFileCreator 'ScVM'
-#define sysAppLaunchCustomEngineDelete (sysAppLaunchCmdCustomBase + 0)
-#define sysAppLaunchCustomEngineGetInfo (sysAppLaunchCmdCustomBase + 1)
-
-enum {
- GET_NONE = 0,
- GET_DATACOMMON = 1 << 1,
- GET_DATAENGINE = 1 << 2,
-
- GET_MODE68K = 1 << 14,
- GET_MODEARM = 1 << 15,
-};
-
-SysAppInfoPtr SysGetAppInfo(SysAppInfoPtr *uiAppPP, SysAppInfoPtr *actionCodeAppPP)
- SYS_TRAP(sysTrapSysGetAppInfo);
-
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/compile.h b/backends/platform/PalmOS/Src/prefixes/compile.h
deleted file mode 100644
index bb7230187a..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/compile.h
+++ /dev/null
@@ -1,76 +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$
- *
- */
-
-#ifndef __COMPILE_H__
-#define __COMPILE_H__
-
-#undef ENABLE_SCUMM
-#undef ENABLE_SCUMM_7_8
-#undef ENABLE_HE
-
-#undef ENABLE_AGOS
-#undef ENABLE_SKY
-#undef ENABLE_SWORD1
-#undef ENABLE_SWORD2
-#undef ENABLE_QUEEN
-#undef ENABLE_SAGA
-#undef ENABLE_KYRA
-#undef ENABLE_AWE
-#undef ENABLE_GOB
-#undef ENABLE_LURE
-#undef ENABLE_CINE
-#undef ENABLE_AGI
-#undef ENABLE_TOUCHE
-#undef ENABLE_PARALLACTION
-#undef ENABLE_CRUISE
-#undef ENABLE_DRASCULA
-
-// ScummVM
-#define USE_SCALERS
-#define DISABLE_FANCY_THEMES
-//#define CT_NO_TRANSPARENCY
-//#define REDUCE_MEMORY_USAGE
-
-#include "compile_base.h"
-
-//#define DISABLE_ADLIB
-//#define DISABLE_LIGHTSPEED
-
-#ifdef COMPILE_ZODIAC
-# undef DISABLE_FANCY_THEMES
-# define USE_ZLIB
-// set an external ZLIB since save/load implementation
-// doesn't support built-in zodiac version which is 1.1.4
-// (seen inflateInit2 which err on "MAX_WBITS + 32")
-# define USE_ZLIB_EXTERNAL
-# define DISABLE_SONY
-#endif
-
-#ifdef COMPILE_OS5
-# define DISABLE_TAPWAVE
-# define USE_ZLIB
-#endif
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_agi.h b/backends/platform/PalmOS/Src/prefixes/native_agi.h
deleted file mode 100644
index f3feee8c70..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_agi.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_AGI STATIC_PLUGIN
-
-#undef USE_MAD
-#undef USE_VORBIS
-#undef USE_TREMOR
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_agos.h b/backends/platform/PalmOS/Src/prefixes/native_agos.h
deleted file mode 100644
index 8a804e3116..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_agos.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_AGOS STATIC_PLUGIN
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_cine.h b/backends/platform/PalmOS/Src/prefixes/native_cine.h
deleted file mode 100644
index 3d19d9c557..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_cine.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_CINE STATIC_PLUGIN
-#define _DEBUG
-
-#undef USE_MAD
-#undef USE_VORBIS
-#undef USE_TREMOR
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_common.h b/backends/platform/PalmOS/Src/prefixes/native_common.h
deleted file mode 100644
index af4db70932..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_common.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef ZNATIVE_COMMON_H
-#define ZNATIVE_COMMON_H
-
-#include "compile.h"
-
-#define __TWNEW_H__
-
-#define PALMOS_ARM
-#define DISABLE_LIGHTSPEED
-
-#define USE_MAD
-#define USE_TREMOR
-#define USE_VORBIS
-//#define USE_MPEG2
-
-// enable assert
-//#define _DEBUG
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_cruise.h b/backends/platform/PalmOS/Src/prefixes/native_cruise.h
deleted file mode 100644
index 89e6e65a70..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_cruise.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_CRUISE STATIC_PLUGIN
-
-#undef USE_MAD
-#undef USE_VORBIS
-#undef USE_TREMOR
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_drascula.h b/backends/platform/PalmOS/Src/prefixes/native_drascula.h
deleted file mode 100644
index 35bc381af4..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_drascula.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_DRASCULA STATIC_PLUGIN
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_gob.h b/backends/platform/PalmOS/Src/prefixes/native_gob.h
deleted file mode 100644
index 9cb34099d0..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_gob.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_GOB STATIC_PLUGIN
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_kyra.h b/backends/platform/PalmOS/Src/prefixes/native_kyra.h
deleted file mode 100644
index 3b09c63a6f..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_kyra.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_KYRA STATIC_PLUGIN
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_lure.h b/backends/platform/PalmOS/Src/prefixes/native_lure.h
deleted file mode 100644
index 71835ee644..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_lure.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_LURE STATIC_PLUGIN
-
-#undef USE_MAD
-#undef USE_VORBIS
-#undef USE_TREMOR
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_m4.h b/backends/platform/PalmOS/Src/prefixes/native_m4.h
deleted file mode 100644
index 3bf85460a6..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_m4.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_M4 STATIC_PLUGIN
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_made.h b/backends/platform/PalmOS/Src/prefixes/native_made.h
deleted file mode 100644
index fd439ed181..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_made.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_MADE STATIC_PLUGIN
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_parallaction.h b/backends/platform/PalmOS/Src/prefixes/native_parallaction.h
deleted file mode 100644
index e8d46cc382..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_parallaction.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_PARALLACTION STATIC_PLUGIN
-
-#undef USE_MAD
-#undef USE_VORBIS
-#undef USE_TREMOR
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_queen.h b/backends/platform/PalmOS/Src/prefixes/native_queen.h
deleted file mode 100644
index 85bb5a0a04..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_queen.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_QUEEN STATIC_PLUGIN
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_saga.h b/backends/platform/PalmOS/Src/prefixes/native_saga.h
deleted file mode 100644
index 19db05b633..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_saga.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_SAGA STATIC_PLUGIN
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_scumm.h b/backends/platform/PalmOS/Src/prefixes/native_scumm.h
deleted file mode 100644
index b8433a3fa8..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_scumm.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_SCUMM STATIC_PLUGIN
-#define ENABLE_SCUMM_7_8
-#define ENABLE_HE
-
-#define USE_ARM_GFX_ASM
-#define USE_ARM_SMUSH_ASM
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_sky.h b/backends/platform/PalmOS/Src/prefixes/native_sky.h
deleted file mode 100644
index 49b157471f..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_sky.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_SKY STATIC_PLUGIN
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_sword1.h b/backends/platform/PalmOS/Src/prefixes/native_sword1.h
deleted file mode 100644
index 6ae7bb9050..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_sword1.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_SWORD1 STATIC_PLUGIN
-#define USE_MPEG2
-#define USE_VORBIS
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_sword2.h b/backends/platform/PalmOS/Src/prefixes/native_sword2.h
deleted file mode 100644
index 5e9c45b047..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_sword2.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_SWORD2 STATIC_PLUGIN
-#undef _DEBUG
-#define USE_MPEG2
-#define USE_VORBIS
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/native_touche.h b/backends/platform/PalmOS/Src/prefixes/native_touche.h
deleted file mode 100644
index acf50e2787..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/native_touche.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#include "native_common.h"
-#define ENABLE_TOUCHE STATIC_PLUGIN
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/prefix_frontend.h b/backends/platform/PalmOS/Src/prefixes/prefix_frontend.h
deleted file mode 100644
index 8473214746..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/prefix_frontend.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-#define PALMOS_68K
-#define PALMOS_MODE
-
-//#define _DEBUG_ENGINE
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/prefix_os5.h b/backends/platform/PalmOS/Src/prefixes/prefix_os5.h
deleted file mode 100644
index 6d84c543af..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/prefix_os5.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-// PalmOS
-#define PALMOS_MODE
-#define PALMOS_68K
-#define PALMOS_NATIVE
-
-#define COMPILE_OS5
-#define DISABLE_SONY
-#define DISABLE_PA1LIB
-
-#endif
diff --git a/backends/platform/PalmOS/Src/prefixes/prefix_zodiac.h b/backends/platform/PalmOS/Src/prefixes/prefix_zodiac.h
deleted file mode 100644
index 49331d356f..0000000000
--- a/backends/platform/PalmOS/Src/prefixes/prefix_zodiac.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef PREFIX_H
-#define PREFIX_H
-
-// PalmOS
-#define PALMOS_MODE
-#define PALMOS_68K
-#define PALMOS_NATIVE
-
-#define COMPILE_ZODIAC
-#define DISABLE_SONY
-#define DISABLE_PA1LIB
-
-#endif
diff --git a/backends/platform/PalmOS/Src/rumble.cpp b/backends/platform/PalmOS/Src/rumble.cpp
deleted file mode 100644
index 513152f49c..0000000000
--- a/backends/platform/PalmOS/Src/rumble.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include <PalmOS.h>
-#include "globals.h"
-#include "vibrate.h"
-#include "rumble.h"
-
-#ifndef DISABLE_TAPWAVE
-#include "tapwave.h"
-
-TwDeviceHandle hRumble;
-#endif
-
-Boolean RumbleExists() {
- Boolean exists = false;
- Err e;
-
-#ifndef DISABLE_TAPWAVE
- if (OPTIONS_TST(kOptDeviceZodiac)) {
- e = TwDeviceOpen(&hRumble, "vibrator0", "w");
- if (!e) {
- exists = true;
- TwDeviceClose(hRumble);
- }
-
- } else
-#endif
- {
-#ifndef PALMOS_ARM
-
- UInt32 romVersion;
-
- e = FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
- if (!e) {
- if (romVersion >= sysMakeROMVersion(4,0,0,sysROMStageRelease,0)) {
- Boolean active = false;
- e = HwrVibrateAttributes(0, kHwrVibrateActive, &active);
- exists = (!e) ? true : exists;
- }
- }
-#endif
- }
-
-
- return exists;
-}
-
-void RumbleRun(Boolean active) {
-#ifndef DISABLE_TAPWAVE
- if (OPTIONS_TST(kOptDeviceZodiac)) {
- if (active) {
- UInt8 buf[] = { '\64', '\100' };
- TwDeviceControl(hRumble, 'play', buf, sizeof(buf));
- } else {
- TwDeviceControl(hRumble, 'stop', 0, 0);
- }
-
- } else
-#endif
- {
-#ifndef PALMOS_ARM
- UInt32 pattern = active ? 0xFF000000 : 0x00000000;
-
- HwrVibrateAttributes(1, kHwrVibratePattern, &pattern);
- HwrVibrateAttributes(1, kHwrVibrateActive, &active);
-#endif
- }
-
-}
-
-Boolean RumbleInit() {
- Boolean done = false;
-
-#ifndef DISABLE_TAPWAVE
- if (OPTIONS_TST(kOptDeviceZodiac)) {
- Err e = TwDeviceOpen(&hRumble, "vibrator0", "w");
- done = (!e);
-
- } else
-#endif
- {
-#ifndef PALMOS_ARM
- if (RumbleExists()) {
- UInt16 cycle = (SysTicksPerSecond())/2;
- UInt32 pattern = 0xFF000000;
- UInt16 delay = 1;
- UInt16 repeat = 1;
-
- HwrVibrateAttributes(1, kHwrVibrateRate, &cycle);
- HwrVibrateAttributes(1, kHwrVibratePattern, &pattern);
- HwrVibrateAttributes(1, kHwrVibrateDelay, &delay);
- HwrVibrateAttributes(1, kHwrVibrateRepeatCount, &repeat);
-
- done = true;
- }
-#endif
- }
- return done;
-}
-
-void RumbleRelease() {
-#ifndef DISABLE_TAPWAVE
- if (OPTIONS_TST(kOptDeviceZodiac)) {
- TwDeviceClose(hRumble);
-
- } else
-#endif
- {
-#ifndef PALMOS_ARM
- UInt32 pattern = 0x00000000;
- Boolean active = false;
-
- HwrVibrateAttributes(1, kHwrVibratePattern, &pattern);
- HwrVibrateAttributes(1, kHwrVibrateActive, &active);
-#endif
- }
-}
diff --git a/backends/platform/PalmOS/Src/rumble.h b/backends/platform/PalmOS/Src/rumble.h
deleted file mode 100644
index 680c0eb164..0000000000
--- a/backends/platform/PalmOS/Src/rumble.h
+++ /dev/null
@@ -1,34 +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$
- *
- */
-
-#ifndef __RUMBLE_H__
-#define __RUMBLE_H__
-
-Boolean RumbleExists ();
-void RumbleRun (Boolean active);
-Boolean RumbleInit ();
-void RumbleRelease ();
-
-#endif
diff --git a/backends/platform/PalmOS/Src/snd_pa1.cpp b/backends/platform/PalmOS/Src/snd_pa1.cpp
deleted file mode 100644
index ddaf6495f6..0000000000
--- a/backends/platform/PalmOS/Src/snd_pa1.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-#include <stdlib.h>
-
-#include "native.h"
-#include "globals.h"
-
-#ifdef COMPILE_PA1SND
-# include <endianutils.h>
-#endif
-
-
-static Int32 diffLookup[16] = {
- 1,3,5,7,9,11,13,15,
- -1,-3,-5,-7,-9,-11,-13,-15,
-};
-
-static Int32 indexScale[16] = {
- 0x0e6, 0x0e6, 0x0e6, 0x0e6, 0x133, 0x199, 0x200, 0x266,
- 0x0e6, 0x0e6, 0x0e6, 0x0e6, 0x133, 0x199, 0x200, 0x266 /* same value for speedup */
-};
-
-static int limit(int val,int min,int max) {
- if (val<min) return min;
- else if (val>max) return max;
- else return val;
-}
-
-void pcm2adpcm(Int16 *src, UInt8 *dst, UInt32 length) {
-#ifndef COMPILE_PA1SND
-/*
- if (OPTIONS_TST(kOptDeviceARM)) {
- PnoDescriptor pno;
- ARMPa1SndType userData = {src, dst, length};
-
- MemPtr armP = _PnoInit(ARM_PA1SND, &pno);
- _PnoCall(&pno, &userData);
- _PnoFree(&pno, armP);
-
- return;
- }
-*/
- int data,val,diff;
- int signal,step;
-#else
- long chan1, chan2;
- long data,val,diff;
- long signal,step;
-#endif
-
- signal = 0;
- step = 0x7F;
- length >>= 3; // 16bit stereo -> 4bit mono
-
- do {
-
- // high nibble
-#ifdef COMPILE_PA1SND
- chan1 = ByteSwap16(*src);
- src++;
- chan2 = ByteSwap16(*src);
- src++;
-
- diff = ((chan1 + chan2) >> 1) - signal;
-#else
- diff = ((*src++ + *src++) >> 1) - signal;
-#endif
- diff <<= 3;
- diff /= step;
-
- val = abs(diff) >> 1;
-
- if (val > 7) val = 7;
- if (diff < 0) val+= 8;
-
- signal+= (step * diffLookup[val]) >> 3;
- signal = limit(signal, -32768, 32767);
-
- step = (step * indexScale[val]) >> 8;
- step = limit(step, 0x7F, 0x6000);
-
- data = val;
-
- // low nibble
-#ifdef COMPILE_PA1SND
- chan1 = ByteSwap16(*src);
- src++;
- chan2 = ByteSwap16(*src);
- src++;
-
- diff = ((chan1 + chan2) >> 1) - signal;
-#else
- diff = ((*src++ + *src++) >> 1) - signal;
-#endif
- diff <<= 3;
- diff /= step;
-
- val = abs(diff) >> 1;
-
- if (val > 7) val = 7;
- if (diff < 0) val+= 8;
-
- signal+= (step * diffLookup[val]) >> 3;
- signal = limit(signal, -32768, 32767);
-
- step = (step * indexScale[val]) >> 8;
- step = limit(step, 0x7F, 0x6000);
-
- data |= val << 4;
-
- *dst++ = (UInt8)data;
-
- } while (--length);
-
-}
diff --git a/backends/platform/PalmOS/Src/stuffs.h b/backends/platform/PalmOS/Src/stuffs.h
deleted file mode 100644
index 25bf17c8c6..0000000000
--- a/backends/platform/PalmOS/Src/stuffs.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef STUFFS_H
-#define STUFFS_H
-
-enum {
- kOptNone = 0,
- kOptDeviceARM = 1 << 0x00,
- kOptDeviceOS5 = 1 << 0x01,
- kOptDeviceClie = 1 << 0x02,
- kOptDeviceZodiac = 1 << 0x03,
- kOptModeWide = 1 << 0x04,
- kOptModeLandscape = 1 << 0x05,
- kOptMode16Bit = 1 << 0x06,
- kOptModeHiDensity = 1 << 0x07,
- kOptCollapsible = 1 << 0x08,
- kOptDisableOnScrDisp = 1 << 0x09,
- kOpt5WayNavigatorV1 = 1 << 0x0A,
- kOpt5WayNavigatorV2 = 1 << 0x0B,
- kOptPalmSoundAPI = 1 << 0x0C,
- kOptSonyPa1LibAPI = 1 << 0x0D,
- kOptGoLcdAPI = 1 << 0x0E,
- kOptLightspeedAPI = 1 << 0x0F,
- kOptModeRotatable = 1 << 0x10,
-
- kOptDeviceProcX86 = 1 << 0x1F // DEBUG only
-};
-
-// WARNING : you need to define OPTIONS_DEF()
-#define OPTIONS_TST(x) (OPTIONS_DEF() & (x))
-#define OPTIONS_SET(x) OPTIONS_DEF() |= (x)
-#define OPTIONS_RST(x) OPTIONS_DEF() &= ~(x)
-
-#endif
diff --git a/backends/platform/PalmOS/Src/vibrate.h b/backends/platform/PalmOS/Src/vibrate.h
deleted file mode 100644
index 37604be5b7..0000000000
--- a/backends/platform/PalmOS/Src/vibrate.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/**********************************************************************
-** **
-** vibrate.h **
-** **
-** Definitions for setting/retrieving the state of the vibrator on **
-** PalmOS 4.x devices. These calls are not officially supported by **
-** Palm Inc and subsidiaries. It is not guaranteed that these calls **
-** will work at all or at least the same on every device. YOU ARE **
-** USING THESE ENTIRELY ON YOUR VERY OWN RISK ! **
-** **
-** Please send corrections to dseifert@dseifert.com **
-**********************************************************************/
-
-#include <PalmOS.h>
-
-/* HwrVibrateAttributes takes three arguments:
-** Boolean set Should the setting be set (1) or retrieved (0)
-** UInt32 setting what should be set
-** void* value pointer to the value to set, or to store the
-** retrieved setting
-*/
-
-Err HwrVibrateAttributes(Boolean set, UInt32 setting, void *value)
- SYS_TRAP(sysTrapHwrVibrateAttributes);
-
-/* to determine whether the vibrator is supported on a specific device, you
-** need to make sure that you are running on PalmOS 4.x (so that the
-** trap exists), that the attention manager exists and you need to check
-** whether HwrVibrateAttributes(0, 1, &active) returns an error code of
-** 0. ('active' is a Boolean).
-*/
-
-
-/***************************************************************/
-/* For the second parameter, the following defines can be used */
-/***************************************************************/
-
-/* *value points to a Boolean stating the state of the vibrator */
-#define kHwrVibrateActive 1
-
-/* *value points to a UInt16, specifying the length of one cycle.
-** value is in ticks (1/100 seconds) */
-#define kHwrVibrateRate 2
-
-/* *value points to a UInt32, specifying the pattern of vibrating
-**
-** example:
-** 0xFFFFFFFF stay on, no vibrating
-** 0x0F0F0F0F vibrate four times in equal intervals
-** 0xAAAAAAAA vibrate really fast (not recommended)
-** 0x0F0F0000 vibrate twice, then pause
-*/
-#define kHwrVibratePattern 3
-
-/* *value points to a UInt16, specifying the delay between two
-** cycles in ticks */
-#define kHwrVibrateDelay 4
-
-/* *value points to a UInt16 specifying the amount of repeats. */
-#define kHwrVibrateRepeatCount 5
-
diff --git a/backends/platform/PalmOS/Src/zodiac_event.cpp b/backends/platform/PalmOS/Src/zodiac_event.cpp
deleted file mode 100644
index f629c4cbd6..0000000000
--- a/backends/platform/PalmOS/Src/zodiac_event.cpp
+++ /dev/null
@@ -1,100 +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 "be_zodiac.h"
-
-bool OSystem_PalmZodiac::check_event(Common::Event &event, EventPtr ev) {
- if (ev->eType == keyUpEvent) {
- switch (ev->data.keyDown.chr) {
- case vchrActionLeft:
- event.type = Common::EVENT_LBUTTONUP;
- event.mouse.x = _mouseCurState.x;
- event.mouse.y = _mouseCurState.y;
- return true;
-
- case vchrActionRight:
- event.type = Common::EVENT_RBUTTONUP;
- event.mouse.x = _mouseCurState.x;
- event.mouse.y = _mouseCurState.y;
- return true;
- }
-
- } else if (ev->eType == keyDownEvent) {
- switch (ev->data.keyDown.chr) {
- // F5 = menu
- case vchrThumbWheelBack:
- event.type = Common::EVENT_KEYDOWN;
- event.kbd.keycode = Common::KEYCODE_F5;
- event.kbd.ascii = Common::ASCII_F5;
- event.kbd.flags = 0;
- return true;
-
- case vchrTriggerLeft:
- hotswap_gfx_mode(_mode == GFX_WIDE ? GFX_NORMAL: GFX_WIDE);
- return false; // not a key
-
- case vchrTriggerRight:
- setFeatureState(kFeatureAspectRatioCorrection, 0);
- return false; // not a key
-
- case vchrActionLeft:
- event.type = Common::EVENT_LBUTTONDOWN;
- event.mouse.x = _mouseCurState.x;
- event.mouse.y = _mouseCurState.y;
- return true;
-
- case vchrActionRight:
- event.type = Common::EVENT_RBUTTONDOWN;
- event.mouse.x = _mouseCurState.x;
- event.mouse.y = _mouseCurState.y;
- return true;
-
- // skip text
- case vchrActionDown:
- event.type = Common::EVENT_KEYDOWN;
- event.kbd.keycode = Common::KEYCODE_PERIOD;
- event.kbd.ascii = '.';
- event.kbd.flags = 0;
- return true;
-
- // trun off
- case vchrAutoOff:
- case vchrPowerOff:
- // pause the sound thread if any
- if (_sound.active)
- SndStreamPause(_soundEx.handle, true);
- break;
-
- case vchrLateWakeup:
- // resume the sound thread if any
- if (_sound.active)
- SndStreamPause(_soundEx.handle, false);
- break;
- }
-
- }
-
- return false;
-}
diff --git a/backends/platform/PalmOS/Src/zodiac_gfx.cpp b/backends/platform/PalmOS/Src/zodiac_gfx.cpp
deleted file mode 100644
index 98c563e101..0000000000
--- a/backends/platform/PalmOS/Src/zodiac_gfx.cpp
+++ /dev/null
@@ -1,309 +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 "be_zodiac.h"
-#include "common/config-manager.h"
-#include "rumble.h"
-
-static asm Err _TwGfxOpen(void **aResult, void *aInfoResult) {
- stmfd sp!, {r4-r11,lr}
- ldr r9, [r9]
- ldr r9, [r9]
- sub sp, sp, #0x24
- mov r6, r0
- mov r7, r1
- ldr pc, =0x200995F0
-}
-
-int OSystem_PalmZodiac::getDefaultGraphicsMode() const {
- return GFX_WIDE;
-}
-
-void OSystem_PalmZodiac::load_gfx_mode() {
- Err e;
-
- if (_gfxLoaded)
- return;
- _gfxLoaded = true;
-
- // get command line config
- _fullscreen = ConfMan.getBool("fullscreen"); // TODO : (NORMAL mode)
- _ratio.adjustAspect = ConfMan.getBool("aspect_ratio") ? kRatioHeight : kRatioNone;
-
- // precalc ratio (WIDE mode)
- _ratio.width = (gVars->screenFullHeight * _screenWidth / _screenHeight);
- _ratio.height = (gVars->screenFullWidth * _screenHeight / _screenWidth);
-
- _offScreenP = (byte *)MemPtrNew(_screenWidth * _screenHeight);
-
- MemSet(_offScreenP, _screenWidth * _screenHeight, 0);
- MemSet(_nativePal, sizeof(_nativePal), 0);
- MemSet(_currentPalette, sizeof(_currentPalette), 0);
-
- UInt32 depth = 16;
- WinScreenMode(winScreenModeSet, NULL, NULL, &depth, NULL);
-
- _sysOldOrientation = SysGetOrientation();
- _sysOldTriggerState = PINGetInputTriggerState();
- SysSetOrientation(sysOrientationLandscape);
- SysSetOrientationTriggerState(sysOrientationTriggerDisabled);
- PINSetInputTriggerState(pinInputTriggerDisabled);
-
- gVars->indicator.on = Graphics::RGBToColor<Graphics::ColorMasks<565> >(0,255,0);
- gVars->indicator.off = Graphics::RGBToColor<Graphics::ColorMasks<565> >(0,0,0);
-
- _screenH = WinGetDisplayWindow();
- _screenP = (byte *)BmpGetBits(WinGetBitmap(_screenH));
-
- e = _TwGfxOpen((void **)&_gfxH, 0);
- e = TwGfxGetPalmDisplaySurface(_gfxH, &_palmScreenP);
-
- // overlay buffer
- TwGfxSurfaceInfoType nfo = {
- sizeof(TwGfxSurfaceInfoType),
- _screenWidth, _screenHeight, _screenWidth * 2,
- twGfxLocationAcceleratorMemory,
- twGfxPixelFormatRGB565_LE
- };
- e = TwGfxAllocSurface(_gfxH, &_overlayP, &nfo);
-
- // prepare main bitmap
- _srcBmp.size = sizeof(TwGfxBitmapType);
- _srcBmp.width = _screenWidth;
- _srcBmp.height = _screenHeight;
- _srcBmp.rowBytes = _screenWidth;
- _srcBmp.pixelFormat = twGfxPixelFormat8bpp;
- _srcBmp.data = _offScreenP;
- _srcBmp.palette = (UInt16 *)_nativePal;
-
- _srcRect.x = 0;
- _srcRect.y = 0;
- _srcRect.w = _screenWidth;
- _srcRect.h = _screenHeight;
-
- hotswap_gfx_mode(_mode);
-}
-
-void OSystem_PalmZodiac::hotswap_gfx_mode(int mode) {
- Err e;
- TwGfxSetClip(_palmScreenP, 0);
- WinSetDrawWindow(_screenH);
-
- _screenDest.w = _screenWidth;
- _screenDest.h = _screenHeight;
-
- // prevent bad DIA redraw (Stat part)
- if (mode == GFX_NORMAL) {
- _redawOSD = true;
- _stretched = (_screenWidth > gVars->screenWidth);
- StatShow();
- PINSetInputAreaState(pinInputAreaOpen);
-
- if (_stretched) {
- calc_rect(false);
- } else {
- // offsets
- _screenOffset.x = (gVars->screenWidth - _screenWidth) / 2;
- _screenOffset.y = (gVars->screenHeight - _screenHeight) / 2;
-
- // clip Tapwave API
- TwGfxRectType rt = { _screenOffset.x, _screenOffset.y, _screenWidth, _screenHeight };
- TwGfxSetClip(_palmScreenP, &rt);
- }
-
- } else {
- _redawOSD = false;
- _stretched = true;
- PINSetInputAreaState(pinInputAreaClosed);
- StatHide();
-
- calc_rect(true);
- }
-
- if (_stretched) {
- OPTIONS_SET(kOptDisableOnScrDisp);
- TwGfxSetClip(_palmScreenP, &_dstRect);
-
- if (!_tmpScreenP) {
- // wide buffer
- TwGfxSurfaceInfoType nfo = {
- sizeof(TwGfxSurfaceInfoType),
- _screenWidth, _screenHeight, _screenWidth * 2,
- twGfxLocationAcceleratorMemory,
- twGfxPixelFormatRGB565_LE
- };
- e = TwGfxAllocSurface(_gfxH, &_tmpScreenP, &nfo);
- }
- } else {
- OPTIONS_RST(kOptDisableOnScrDisp);
- if (_tmpScreenP) {
- e = TwGfxFreeSurface(_tmpScreenP);
- _tmpScreenP = NULL;
- }
- }
-
- _mode = mode;
- _srcPos.x = _screenOffset.x;
- _srcPos.y = _screenOffset.y;
- clear_screen();
-// updateScreen();
-}
-
-void OSystem_PalmZodiac::unload_gfx_mode() {
- Err e;
-
- if (!_gfxLoaded)
- return;
- _gfxLoaded = false;
-
- if (_tmpScreenP) {
- e = TwGfxFreeSurface(_tmpScreenP);
- _tmpScreenP = NULL;
- }
-
- e = TwGfxFreeSurface(_overlayP);
- e = TwGfxClose(_gfxH);
-
- UInt32 depth = 8;
- WinScreenMode(winScreenModeSet, NULL, NULL, &depth, NULL);
- clear_screen();
-
- MemPtrFree(_offScreenP);
-
- PINSetInputTriggerState(_sysOldTriggerState);
- SysSetOrientation(_sysOldOrientation);
- StatShow();
- PINSetInputAreaState(pinInputAreaOpen);
-}
-
-static void rumblePack(Boolean active) {
- if (!gVars->vibrator)
- return;
-
- RumbleRun(active);
-}
-
-void OSystem_PalmZodiac::int_setShakePos(int shakeOffset) {
- if (shakeOffset == 0)
- rumblePack(false);
-}
-
-void OSystem_PalmZodiac::updateScreen() {
- Err e;
-
- // draw the mouse pointer
- draw_mouse();
-
- // update the screen
- if (_overlayVisible) {
- if (_stretched) {
- TwGfxRectType dst = {_dstRect.x, _dstRect.y, _dstRect.w, _dstRect.h};
- e = TwGfxStretchBlt2(_palmScreenP, &dst, _overlayP, &_srcRect, twGfxStretchFast| (gVars->filter ? twGfxStretchSmooth : 0));
- } else {
- e = TwGfxBitBlt(_palmScreenP, &_srcPos, _overlayP, &_srcRect);
- }
-
- } else {
- if (_stretched) {
- TwGfxPointType pos = {0, 0};
- TwGfxRectType dst = {_dstRect.x, _dstRect.y, _dstRect.w, _dstRect.h};
-
- if (_new_shake_pos != _current_shake_pos) {
- TwGfxRectType r = { _screenOffset.x, _screenOffset.y, _dstRect.w, _new_shake_pos };
-
- if (_new_shake_pos != 0) {
- TwGfxFillRect(_palmScreenP, &r, 0);
- rumblePack(_new_shake_pos >= 3);
- }
- r.y += dst.h;
- r.h = _current_shake_pos;
- TwGfxFillRect(_palmScreenP, &r, 0);
-
- _current_shake_pos = _new_shake_pos;
- dst.y += _new_shake_pos;
- }
- e = TwGfxDrawBitmap(_tmpScreenP, &pos, &_srcBmp);
- e = TwGfxWaitForVBlank(_gfxH);
- e = TwGfxStretchBlt2(_palmScreenP, &dst, _tmpScreenP, &_srcRect, twGfxStretchFast| (gVars->filter ? twGfxStretchSmooth : 0));
-
- } else {
- TwGfxPointType pos = {_srcPos.x, _srcPos.y};
-
- if (_new_shake_pos != _current_shake_pos) {
- if (_new_shake_pos != 0) {
- TwGfxRectType r = { _screenOffset.x, _screenOffset.y, _screenWidth, _new_shake_pos };
- TwGfxFillRect(_palmScreenP, &r, 0);
- rumblePack(_new_shake_pos >= 3);
- }
- _current_shake_pos = _new_shake_pos;
- pos.y += _new_shake_pos;
- }
- e = TwGfxDrawBitmap(_palmScreenP, &pos, &_srcBmp);
- }
- }
-
- // undraw the mouse
- undraw_mouse();
-}
-
-void OSystem_PalmZodiac::draw_osd(UInt16 id, Int32 x, Int32 y, Boolean show, UInt8 color) {
- if (_mode != GFX_NORMAL)
- return;
- MemHandle hTemp = DmGetResource(bitmapRsc, id + 100);
-
- if (hTemp) {
- RGBColorType oldRGB;
- static const RGBColorType pal[4] = {
- {0,0,255,0},
- {0,255,255,0},
- {0,255,0,0},
- {0,0,0,0}
- };
-
- BitmapType *bmTemp;
- bmTemp = (BitmapType *)MemHandleLock(hTemp);
-
- Coord w, h;
- WinGetBitmapDimensions(bmTemp, &w, &h); // return the size of the low density bmp
-
- PointType dst = { _screenOffset.x + x, _screenOffset.y + y };
- RectangleType c, r = { dst.x, dst.y, w * 2, h * 2 };
-
- UInt16 old = WinSetCoordinateSystem(kCoordinatesNative);
- WinSetDrawWindow(_screenH);
- if (show) {
- WinSetForeColorRGB(&pal[3], &oldRGB);
- WinSetBackColorRGB(&pal[color], &oldRGB);
- WinPaintBitmap(bmTemp, dst.x, dst.y);
- } else {
- WinSetBackColorRGB(&pal[3], &oldRGB);
- WinFillRectangle(&r, 0);
- }
- WinSetCoordinateSystem(old);
-
- MemPtrUnlock(bmTemp);
- DmReleaseResource(hTemp);
- }
-}
diff --git a/backends/platform/PalmOS/Src/zodiac_mouse.cpp b/backends/platform/PalmOS/Src/zodiac_mouse.cpp
deleted file mode 100644
index 39a789aaa1..0000000000
--- a/backends/platform/PalmOS/Src/zodiac_mouse.cpp
+++ /dev/null
@@ -1,153 +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 "be_zodiac.h"
-
-void OSystem_PalmZodiac::draw_mouse() {
- if (!_mouseDataP || _mouseDrawn || !_mouseVisible)
- return;
-
- byte *src = _mouseDataP;
-
- int x = _mouseCurState.x - _mouseHotspotX;
- int y = _mouseCurState.y - _mouseHotspotY;
- int w = _mouseCurState.w;
- int h = _mouseCurState.h;
-
- // clip the mouse rect
- if (y < 0) {
- src -= y * w;
- h += y;
- y = 0;
- }
- if (x < 0) {
- src -= x;
- w += x;
- x = 0;
- }
-
- if (h > _screenHeight - y)
- h = _screenHeight - y;
- if (w > _screenWidth - x)
- w = _screenWidth - x;
-
- if (w <= 0 || h <= 0)
- return;
-
- // store the bounding box so that undraw mouse can restore the area the
- // mouse currently covers to its original content
- _mouseOldState.x = x;
- _mouseOldState.y = y;
- _mouseOldState.w = w;
- _mouseOldState.h = h;
-
- byte color;
- int ww;
-
- if (_overlayVisible) {
- uint16 *bak = (uint16 *)_mouseBackupP;
- uint16 *pal = _cursorPaletteDisabled ? _nativePal : _mousePal;
- uint16 *dst;
-
- TwGfxLockSurface(_overlayP, (void **)&dst);
- dst += y * _screenWidth + x;
-
- do {
- ww = w;
- do {
- *bak++ = *dst;
- color = *src++;
-
- // transparent, don't draw
- if (color != _mouseKeyColor)
- *dst = pal[color];
- dst++;
- } while (--ww);
-
- src += _mouseCurState.w - w;
- dst += _screenWidth - w;
- } while (--h);
-
- TwGfxUnlockSurface(_overlayP, true);
-
- } else {
- byte *bak = _mouseBackupP;
- byte *dst =_offScreenP + y * _screenWidth + x;
-
- do {
- ww = w;
- do {
- *bak++ = *dst;
- color = *src++;
-
- // transparent, don't draw
- if (color != _mouseKeyColor)
- *dst = color;
- dst++;
- } while (--ww);
-
- src += _mouseCurState.w - w;
- dst += _screenWidth - w;
- } while (--h);
- }
-
- _mouseDrawn = true;
-}
-
-void OSystem_PalmZodiac::undraw_mouse() {
- if (!_mouseDrawn)
- return;
-
- int h = _mouseOldState.h;
-
- // no need to do clipping here, since draw_mouse() did that already
- if (_overlayVisible) {
- uint16 *dst;
- uint16 *bak = (uint16 *)_mouseBackupP;
-
- TwGfxLockSurface(_overlayP, (void **)&dst);
- dst += _mouseOldState.y * _screenWidth + _mouseOldState.x;
-
- do {
- MemMove(dst, bak, _mouseOldState.w * 2);
- dst += _screenWidth;
- bak += _mouseOldState.w;
- } while (--h);
-
- TwGfxUnlockSurface(_overlayP, true);
-
- } else {
- byte *dst = _offScreenP + _mouseOldState.y * _screenWidth + _mouseOldState.x;
- byte *bak = _mouseBackupP;
-
- do {
- MemMove(dst, bak, _mouseOldState.w);
- dst += _screenWidth;
- bak += _mouseOldState.w;
- } while (--h);
- }
-
- _mouseDrawn = false;
-}
diff --git a/backends/platform/PalmOS/Src/zodiac_overlay.cpp b/backends/platform/PalmOS/Src/zodiac_overlay.cpp
deleted file mode 100644
index f8322e8fa5..0000000000
--- a/backends/platform/PalmOS/Src/zodiac_overlay.cpp
+++ /dev/null
@@ -1,67 +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 "be_zodiac.h"
-#include "common/endian.h"
-
-void OSystem_PalmZodiac::clearOverlay() {
- if (!_overlayVisible)
- return;
-
- Err e;
- TwGfxPointType pos = {0, 0};
- TwGfxBitmapType bmp = {
- sizeof(TwGfxBitmapType),
- _screenWidth, _screenHeight, _screenWidth, twGfxPixelFormat8bpp,
- (void *)_offScreenP, (UInt16 *)_nativePal
- };
- e = TwGfxDrawBitmap(_overlayP, &pos, &bmp);
-}
-
-void OSystem_PalmZodiac::grabOverlay(OverlayColor *buf, int pitch) {
- Err e;
- OverlayColor *src;
-
- e = TwGfxLockSurface(_overlayP, (void **)&src);
- int h = _screenHeight;
- do {
- memcpy(buf, src, _screenWidth * 2);
- src += _screenWidth;
- buf += pitch;
- } while (--h);
-
- e = TwGfxUnlockSurface(_overlayP, 0);
-}
-
-void OSystem_PalmZodiac::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
- Err e;
- TwGfxPointType pos = {x, y};
- TwGfxBitmapType bmp = {
- sizeof(TwGfxBitmapType),
- w, h, pitch * 2 , twGfxPixelFormatRGB565_LE,
- (void *)buf, 0
- };
- e = TwGfxDrawBitmap(_overlayP, &pos, &bmp);
-}
diff --git a/backends/platform/PalmOS/arm.bat b/backends/platform/PalmOS/arm.bat
deleted file mode 100755
index 547ae391fe..0000000000
--- a/backends/platform/PalmOS/arm.bat
+++ /dev/null
@@ -1,3 +0,0 @@
-as.exe --defsym PALMOS_MODE=1 ../../../sound/rate_arm_asm.s -o Obj/rate_arm_asm.o
-as.exe --defsym PALMOS_MODE=1 ../../../engines/scumm/gfxARM.s -o Obj/gfxARM.o
-as.exe --defsym PALMOS_MODE=1 ../../../engines/scumm/smush/codec47ARM.s -o Obj/codec47ARM.o
diff --git a/backends/platform/PalmOS/scummvm.mcp b/backends/platform/PalmOS/scummvm.mcp
deleted file mode 100644
index a01967d059..0000000000
--- a/backends/platform/PalmOS/scummvm.mcp
+++ /dev/null
Binary files differ
diff --git a/backends/platform/android/README.build b/backends/platform/android/README.build
new file mode 100644
index 0000000000..1c407bd469
--- /dev/null
+++ b/backends/platform/android/README.build
@@ -0,0 +1,91 @@
+Building the ScummVM Android port
+=================================
+
+You will need these things to build:
+1. Android SDK
+2. An arm-oe-linux-androideabi GCC toolchain(*)
+
+In the example commands, we are going to build against the Android 1.5
+native ABI (but using the Android 1.6 SDK tools). Other version
+combinations might/should be possible with a bit of tweaking.
+
+(*) Any other sane Android toolchain should be easy to use, but this
+is the toolchain prefix that is used by default. You can trivially
+find and modify the single location where it appears in ./configure if
+you have some other prefix variation.
+
+
+In detail:
+
+1. Android SDK
+
+Download the SDK from http://developer.android.com/ and install
+somewhere. You will need both the API level 8 (aka Android 2.2) and
+API level 3 (aka Android 1.5) platforms.
+
+2. arm-*-linux-androideabi GCC toolchain
+
+You have several choices for toolchains:
+
+ - Use Google arm-eabi prebuilt toolchain.
+
+This is shipped with both the Android source release and Android NDK.
+The problem is that "arm-eabi-gcc" can't actually link anything
+successfully without extra command line flags. To use this with the
+ScummVM configure/build environment you will need to create a family
+of shell wrapper scripts that convert "arm-oe-linux-androideabi-foo" to
+"arm-eabi-foo -mandroid".
+
+For example, I use this script:
+ #!/bin/sh
+ exec arm-eabi-${0##*-} -mandroid -DANDROID "$@"
+
+... and create a family of symlinks/hardlinks pointing to it called
+arm-oe-android-linuxeabi-gcc, arm-oe-android-linuxeabi-g++, etc. For
+tools that don't take a "-mandroid" argument - like arm-eabi-strip - I
+bypass the shell wrapper and just create an arm-oe-android-linuxeabi-strip
+symlink to the tool directly.
+
+In practice you will probably need significant linker command line
+massaging in order to get the crtbegin/end and libraries all linked in
+the right way. It's not hard to do manually, but it is annoying to
+script in a general purpose way.
+
+ - Build your own arm-*-linux-androideabi toolchain from GCC source.
+
+This is lots of fun, but will become significantly easier once gcc-4.6
+is released. In the interim, I suggest using my precompiled Android
+openembedded-based toolchain:
+ wget http://commondatastorage.googleapis.com/anr/sdk/android-2.2-i686-linux-armv5te-linux-androideabi-toolchain-android.tar.bz2
+ sudo tar jxf android-2.2-i686-linux-armv5te-linux-androideabi-toolchain-android.tar.bz2 -C /
+ . /usr/local/android/arm/environment-setup
+
+Alternatively, do a websearch - there are several other cross-compile
+toolchains around.
+
+
+Building ScummVM
+================
+
+(Optionally) compress scummmodern.zip:
+(ScummVM usually ships it uncompressed, but Android can read it more
+efficiently if it is compressed *before* adding it to the apk)
+
+ ( cd gui/themes/scummmodern && zip -f ../scummmodern.zip )
+
+Then build ScummVM:
+
+ export ANDROID_SDK=<root of Android SDK>
+
+ PATH=$ANDROID_SDK/platforms/android-1.6/tools:$ANDROID_SDK/tools:$PATH
+ # You also want to ensure your arm-oe-linux-androideabi toolchain is in $PATH
+
+ export ANDROID_TOP=<root of built Android source>
+
+ ./configure --backend=android --host=android --enable-zlib #and any other flags
+ make scummvm.apk
+
+This will build a "monolithic" ScummVM package, with the engines
+statically linked in. If you want to build separate engine packages,
+like on the market, add "--enable-plugins --default-dynamic" to
+configure and also make scummvm-engine-scumm.apk, etc.
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
new file mode 100644
index 0000000000..f6af0fcff5
--- /dev/null
+++ b/backends/platform/android/android.cpp
@@ -0,0 +1,1412 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/base-backend.h"
+#include "base/main.h"
+#include "graphics/surface.h"
+
+#include "backends/platform/android/video.h"
+
+#if defined(ANDROID_BACKEND)
+
+#include <jni.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <android/log.h>
+
+#include "common/archive.h"
+#include "common/util.h"
+#include "common/rect.h"
+#include "common/queue.h"
+#include "common/mutex.h"
+#include "common/events.h"
+#include "common/config-manager.h"
+
+#include "backends/fs/posix/posix-fs-factory.h"
+#include "backends/keymapper/keymapper.h"
+#include "backends/saves/default/default-saves.h"
+#include "backends/timer/default/default-timer.h"
+#include "backends/plugins/posix/posix-provider.h"
+#include "sound/mixer_intern.h"
+
+#include "backends/platform/android/asset-archive.h"
+
+#undef LOG_TAG
+#define LOG_TAG "ScummVM"
+
+#if 0
+#define ENTER(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, args)
+#else
+#define ENTER(args...) /**/
+#endif
+
+// Fix JNIEXPORT declaration to actually do something useful
+#undef JNIEXPORT
+#define JNIEXPORT __attribute__ ((visibility("default")))
+
+// This replaces the bionic libc assert message with something that
+// actually prints the assertion failure before aborting.
+extern "C"
+void __assert(const char *file, int line, const char *expr) {
+ __android_log_assert(expr, LOG_TAG, "%s:%d: Assertion failure: %s",
+ file, line, expr);
+}
+
+static JavaVM *cached_jvm;
+static jfieldID FID_Event_type;
+static jfieldID FID_Event_synthetic;
+static jfieldID FID_Event_kbd_keycode;
+static jfieldID FID_Event_kbd_ascii;
+static jfieldID FID_Event_kbd_flags;
+static jfieldID FID_Event_mouse_x;
+static jfieldID FID_Event_mouse_y;
+static jfieldID FID_Event_mouse_relative;
+static jfieldID FID_ScummVM_nativeScummVM;
+static jmethodID MID_Object_wait;
+
+JNIEnv* JNU_GetEnv() {
+ JNIEnv* env;
+ bool version_unsupported =
+ cached_jvm->GetEnv((void**)&env, JNI_VERSION_1_2);
+ assert(! version_unsupported);
+ return env;
+}
+
+static void JNU_ThrowByName(JNIEnv* env, const char* name, const char* msg) {
+ jclass cls = env->FindClass(name);
+ // if cls is NULL, an exception has already been thrown
+ if (cls != NULL)
+ env->ThrowNew(cls, msg);
+ env->DeleteLocalRef(cls);
+}
+
+// floating point. use sparingly.
+template <class T>
+static inline T scalef(T in, float numerator, float denominator) {
+ return static_cast<float>(in) * numerator / denominator;
+}
+
+static inline GLfixed xdiv(int numerator, int denominator) {
+ assert(numerator < (1<<16));
+ return (numerator << 16) / denominator;
+}
+
+#ifdef DYNAMIC_MODULES
+class AndroidPluginProvider : public POSIXPluginProvider {
+protected:
+ virtual void addCustomDirectories(Common::FSList &dirs) const;
+};
+#endif
+
+
+#if 0
+#define CHECK_GL_ERROR() checkGlError(__FILE__, __LINE__)
+static const char* getGlErrStr(GLenum error) {
+ switch (error) {
+ case GL_NO_ERROR: return "GL_NO_ERROR";
+ case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
+ case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
+ case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
+ case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
+ case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
+ }
+
+ static char buf[40];
+ snprintf(buf, sizeof(buf), "(Unknown GL error code 0x%x)", error);
+ return buf;
+}
+static void checkGlError(const char* file, int line) {
+ GLenum error = glGetError();
+ if (error != GL_NO_ERROR)
+ warning("%s:%d: GL error: %s", file, line, getGlErrStr(error));
+}
+#else
+#define CHECK_GL_ERROR() do {} while (false)
+#endif
+
+class OSystem_Android : public BaseBackend {
+private:
+ jobject _back_ptr; // back pointer to (java) peer instance
+ jmethodID MID_displayMessageOnOSD;
+ jmethodID MID_setWindowCaption;
+ jmethodID MID_initBackend;
+ jmethodID MID_audioSampleRate;
+ jmethodID MID_showVirtualKeyboard;
+ jmethodID MID_getSysArchives;
+ jmethodID MID_getPluginDirectories;
+ jmethodID MID_setupScummVMSurface;
+ jmethodID MID_destroyScummVMSurface;
+ jmethodID MID_swapBuffers;
+
+ int _screen_changeid;
+ int _egl_surface_width;
+ int _egl_surface_height;
+
+ bool _force_redraw;
+
+ // Game layer
+ GLESPaletteTexture* _game_texture;
+ int _shake_offset;
+ Common::Rect _focus_rect;
+ bool _full_screen_dirty;
+
+ // Overlay layer
+ GLES4444Texture* _overlay_texture;
+ bool _show_overlay;
+
+ // Mouse layer
+ GLESPaletteATexture* _mouse_texture;
+ Common::Point _mouse_hotspot;
+ int _mouse_targetscale;
+ bool _show_mouse;
+ bool _use_mouse_palette;
+
+ Common::Queue<Common::Event> _event_queue;
+ MutexRef _event_queue_lock;
+
+ bool _timer_thread_exit;
+ pthread_t _timer_thread;
+ static void* timerThreadFunc(void* arg);
+
+ bool _enable_zoning;
+ bool _virtkeybd_on;
+
+ Common::SaveFileManager *_savefile;
+ Audio::MixerImpl *_mixer;
+ Common::TimerManager *_timer;
+ FilesystemFactory *_fsFactory;
+ Common::Archive *_asset_archive;
+ timeval _startTime;
+
+ void setupScummVMSurface();
+ void destroyScummVMSurface();
+ void setupKeymapper();
+ void _setCursorPalette(const byte *colors, uint start, uint num);
+
+public:
+ OSystem_Android(jobject am);
+ virtual ~OSystem_Android();
+ bool initJavaHooks(JNIEnv* env, jobject self);
+
+ static OSystem_Android* fromJavaObject(JNIEnv* env, jobject obj);
+ virtual void initBackend();
+ void addPluginDirectories(Common::FSList &dirs) const;
+ void enableZoning(bool enable) { _enable_zoning = enable; }
+ void setSurfaceSize(int width, int height) {
+ _egl_surface_width = width;
+ _egl_surface_height = height;
+ }
+
+ virtual bool hasFeature(Feature f);
+ virtual void setFeatureState(Feature f, bool enable);
+ virtual bool getFeatureState(Feature f);
+ virtual const GraphicsMode *getSupportedGraphicsModes() const;
+ virtual int getDefaultGraphicsMode() const;
+ bool setGraphicsMode(const char *name);
+ virtual bool setGraphicsMode(int mode);
+ virtual int getGraphicsMode() const;
+ virtual void initSize(uint width, uint height,
+ const Graphics::PixelFormat *format);
+ virtual int getScreenChangeID() const { return _screen_changeid; }
+ virtual int16 getHeight();
+ virtual int16 getWidth();
+ virtual void setPalette(const byte *colors, uint start, uint num);
+ virtual void grabPalette(byte *colors, uint start, uint num);
+ virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
+ virtual void updateScreen();
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
+ virtual void setShakePos(int shakeOffset);
+ virtual void fillScreen(uint32 col);
+ virtual void setFocusRectangle(const Common::Rect& rect);
+ virtual void clearFocusRectangle();
+
+ virtual void showOverlay();
+ virtual void hideOverlay();
+ virtual void clearOverlay();
+ virtual void grabOverlay(OverlayColor *buf, int pitch);
+ virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
+ virtual int16 getOverlayHeight();
+ virtual int16 getOverlayWidth();
+ virtual Graphics::PixelFormat getOverlayFormat() const {
+ // RGBA 4444
+ Graphics::PixelFormat format;
+ format.bytesPerPixel = 2;
+ format.rLoss = 8 - 4;
+ format.gLoss = 8 - 4;
+ format.bLoss = 8 - 4;
+ format.aLoss = 8 - 4;
+ format.rShift = 3*4;
+ format.gShift = 2*4;
+ format.bShift = 1*4;
+ format.aShift = 0*4;
+ return format;
+ }
+
+ virtual bool showMouse(bool visible);
+
+ virtual void warpMouse(int x, int y);
+ virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format);
+ virtual void setCursorPalette(const byte *colors, uint start, uint num);
+ virtual void disableCursorPalette(bool disable);
+
+ virtual bool pollEvent(Common::Event &event);
+ void pushEvent(const Common::Event& event);
+ virtual uint32 getMillis();
+ virtual void delayMillis(uint msecs);
+
+ virtual MutexRef createMutex(void);
+ virtual void lockMutex(MutexRef mutex);
+ virtual void unlockMutex(MutexRef mutex);
+ virtual void deleteMutex(MutexRef mutex);
+
+ virtual void quit();
+
+ virtual void setWindowCaption(const char *caption);
+ virtual void displayMessageOnOSD(const char *msg);
+ virtual void showVirtualKeyboard(bool enable);
+
+ virtual Common::SaveFileManager *getSavefileManager();
+ virtual Audio::Mixer *getMixer();
+ virtual void getTimeAndDate(TimeDate &t) const;
+ virtual Common::TimerManager *getTimerManager();
+ virtual FilesystemFactory *getFilesystemFactory();
+ virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
+};
+
+OSystem_Android::OSystem_Android(jobject am)
+ : _back_ptr(0),
+ _screen_changeid(0),
+ _force_redraw(false),
+ _game_texture(NULL),
+ _overlay_texture(NULL),
+ _mouse_texture(NULL),
+ _use_mouse_palette(false),
+ _show_mouse(false),
+ _show_overlay(false),
+ _enable_zoning(false),
+ _savefile(0),
+ _mixer(0),
+ _timer(0),
+ _fsFactory(new POSIXFilesystemFactory()),
+ _asset_archive(new AndroidAssetArchive(am)),
+ _shake_offset(0),
+ _full_screen_dirty(false),
+ _event_queue_lock(createMutex()) {
+}
+
+OSystem_Android::~OSystem_Android() {
+ ENTER("~OSystem_Android()");
+ delete _game_texture;
+ delete _overlay_texture;
+ delete _mouse_texture;
+ destroyScummVMSurface();
+ JNIEnv* env = JNU_GetEnv();
+ //env->DeleteWeakGlobalRef(_back_ptr);
+ env->DeleteGlobalRef(_back_ptr);
+ delete _savefile;
+ delete _mixer;
+ delete _timer;
+ delete _fsFactory;
+ delete _asset_archive;
+ deleteMutex(_event_queue_lock);
+}
+
+OSystem_Android* OSystem_Android::fromJavaObject(JNIEnv* env, jobject obj) {
+ jlong peer = env->GetLongField(obj, FID_ScummVM_nativeScummVM);
+ return (OSystem_Android*)peer;
+}
+
+bool OSystem_Android::initJavaHooks(JNIEnv* env, jobject self) {
+ // weak global ref to allow class to be unloaded
+ // ... except dalvik doesn't implement NewWeakGlobalRef (yet)
+ //_back_ptr = env->NewWeakGlobalRef(self);
+ _back_ptr = env->NewGlobalRef(self);
+
+ jclass cls = env->GetObjectClass(_back_ptr);
+
+#define FIND_METHOD(name, signature) do { \
+ MID_ ## name = env->GetMethodID(cls, #name, signature); \
+ if (MID_ ## name == NULL) \
+ return false; \
+ } while (0)
+
+ FIND_METHOD(setWindowCaption, "(Ljava/lang/String;)V");
+ FIND_METHOD(displayMessageOnOSD, "(Ljava/lang/String;)V");
+ FIND_METHOD(initBackend, "()V");
+ FIND_METHOD(audioSampleRate, "()I");
+ FIND_METHOD(showVirtualKeyboard, "(Z)V");
+ FIND_METHOD(getSysArchives, "()[Ljava/lang/String;");
+ FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
+ FIND_METHOD(setupScummVMSurface, "()V");
+ FIND_METHOD(destroyScummVMSurface, "()V");
+ FIND_METHOD(swapBuffers, "()Z");
+
+#undef FIND_METHOD
+
+ return true;
+}
+
+static void ScummVM_create(JNIEnv* env, jobject self, jobject am) {
+ OSystem_Android* cpp_obj = new OSystem_Android(am);
+ if (!cpp_obj->initJavaHooks(env, self))
+ // Exception already thrown by initJavaHooks
+ return;
+
+ env->SetLongField(self, FID_ScummVM_nativeScummVM, (jlong)cpp_obj);
+
+#ifdef DYNAMIC_MODULES
+ PluginManager::instance().addPluginProvider(new AndroidPluginProvider());
+#endif
+}
+
+static void ScummVM_nativeDestroy(JNIEnv* env, jobject self) {
+ OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
+ delete cpp_obj;
+}
+
+static void ScummVM_audioMixCallback(JNIEnv* env, jobject self,
+ jbyteArray jbuf) {
+ OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
+ jsize len = env->GetArrayLength(jbuf);
+ jbyte* buf = env->GetByteArrayElements(jbuf, NULL);
+ if (buf == NULL) {
+ warning("Unable to get Java audio byte array. Skipping.");
+ return;
+ }
+ Audio::MixerImpl* mixer =
+ static_cast<Audio::MixerImpl*>(cpp_obj->getMixer());
+ assert(mixer);
+ mixer->mixCallback(reinterpret_cast<byte*>(buf), len);
+ env->ReleaseByteArrayElements(jbuf, buf, 0);
+}
+
+static void ScummVM_setConfManInt(JNIEnv* env, jclass cls,
+ jstring key_obj, jint value) {
+ ENTER("setConfManInt(%p, %d)", key_obj, (int)value);
+ const char* key = env->GetStringUTFChars(key_obj, NULL);
+ if (key == NULL)
+ return;
+ ConfMan.setInt(key, value);
+ env->ReleaseStringUTFChars(key_obj, key);
+}
+
+static void ScummVM_setConfManString(JNIEnv* env, jclass cls, jstring key_obj,
+ jstring value_obj) {
+ ENTER("setConfManStr(%p, %p)", key_obj, value_obj);
+ const char* key = env->GetStringUTFChars(key_obj, NULL);
+ if (key == NULL)
+ return;
+ const char* value = env->GetStringUTFChars(value_obj, NULL);
+ if (value == NULL) {
+ env->ReleaseStringUTFChars(key_obj, key);
+ return;
+ }
+ ConfMan.set(key, value);
+ env->ReleaseStringUTFChars(value_obj, value);
+ env->ReleaseStringUTFChars(key_obj, key);
+}
+
+void* OSystem_Android::timerThreadFunc(void* arg) {
+ OSystem_Android* system = (OSystem_Android*)arg;
+ DefaultTimerManager* timer = (DefaultTimerManager*)(system->_timer);
+
+ struct timespec tv;
+ tv.tv_sec = 0;
+ tv.tv_nsec = 100 * 1000 * 1000; // 100ms
+
+ while (!system->_timer_thread_exit) {
+ timer->handler();
+ nanosleep(&tv, NULL);
+ }
+
+ return NULL;
+}
+
+void OSystem_Android::initBackend() {
+ ENTER("initBackend()");
+ JNIEnv* env = JNU_GetEnv();
+
+ ConfMan.setInt("autosave_period", 0);
+ ConfMan.setInt("FM_medium_quality", true);
+
+ // must happen before creating TimerManager to avoid race in
+ // creating EventManager
+ setupKeymapper();
+
+ // BUG: "transient" ConfMan settings get nuked by the options
+ // screen. Passing the savepath in this way makes it stick
+ // (via ConfMan.registerDefault)
+ _savefile = new DefaultSaveFileManager(ConfMan.get("savepath"));
+ _timer = new DefaultTimerManager();
+
+ gettimeofday(&_startTime, NULL);
+
+ jint sample_rate = env->CallIntMethod(_back_ptr, MID_audioSampleRate);
+ if (env->ExceptionCheck()) {
+ warning("Error finding audio sample rate - assuming 11025HZ");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ sample_rate = 11025;
+ }
+ _mixer = new Audio::MixerImpl(this, sample_rate);
+ _mixer->setReady(true);
+
+ env->CallVoidMethod(_back_ptr, MID_initBackend);
+ if (env->ExceptionCheck()) {
+ error("Error in Java initBackend");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ _timer_thread_exit = false;
+ pthread_create(&_timer_thread, NULL, timerThreadFunc, this);
+
+ OSystem::initBackend();
+
+ setupScummVMSurface();
+}
+
+void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
+ ENTER("OSystem_Android::addPluginDirectories()");
+ JNIEnv* env = JNU_GetEnv();
+
+ jobjectArray array =
+ (jobjectArray)env->CallObjectMethod(_back_ptr, MID_getPluginDirectories);
+ if (env->ExceptionCheck()) {
+ warning("Error finding plugin directories");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return;
+ }
+
+ jsize size = env->GetArrayLength(array);
+ for (jsize i = 0; i < size; ++i) {
+ jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
+ if (path_obj == NULL)
+ continue;
+ const char* path = env->GetStringUTFChars(path_obj, NULL);
+ if (path == NULL) {
+ warning("Error getting string characters from plugin directory");
+ env->ExceptionClear();
+ env->DeleteLocalRef(path_obj);
+ continue;
+ }
+ dirs.push_back(Common::FSNode(path));
+ env->ReleaseStringUTFChars(path_obj, path);
+ env->DeleteLocalRef(path_obj);
+ }
+}
+
+bool OSystem_Android::hasFeature(Feature f) {
+ return (f == kFeatureCursorHasPalette ||
+ f == kFeatureVirtualKeyboard ||
+ f == kFeatureOverlaySupportsAlpha);
+}
+
+void OSystem_Android::setFeatureState(Feature f, bool enable) {
+ ENTER("setFeatureState(%d, %d)", f, enable);
+ switch (f) {
+ case kFeatureVirtualKeyboard:
+ _virtkeybd_on = enable;
+ showVirtualKeyboard(enable);
+ break;
+ default:
+ break;
+ }
+}
+
+bool OSystem_Android::getFeatureState(Feature f) {
+ switch (f) {
+ case kFeatureVirtualKeyboard:
+ return _virtkeybd_on;
+ default:
+ return false;
+ }
+}
+
+const OSystem::GraphicsMode* OSystem_Android::getSupportedGraphicsModes() const {
+ static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
+ {"default", "Default", 1},
+ {0, 0, 0},
+ };
+ return s_supportedGraphicsModes;
+}
+
+
+int OSystem_Android::getDefaultGraphicsMode() const {
+ return 1;
+}
+
+bool OSystem_Android::setGraphicsMode(const char *mode) {
+ ENTER("setGraphicsMode(%s)", mode);
+ return true;
+}
+
+bool OSystem_Android::setGraphicsMode(int mode) {
+ ENTER("setGraphicsMode(%d)", mode);
+ return true;
+}
+
+int OSystem_Android::getGraphicsMode() const {
+ return 1;
+}
+
+void OSystem_Android::setupScummVMSurface() {
+ ENTER("setupScummVMSurface");
+ JNIEnv* env = JNU_GetEnv();
+ env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface);
+ if (env->ExceptionCheck())
+ return;
+
+ // EGL set up with a new surface. Initialise OpenGLES context.
+
+ GLESTexture::initGLExtensions();
+
+ // Turn off anything that looks like 3D ;)
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_FOG);
+ glDisable(GL_DITHER);
+ glShadeModel(GL_FLAT);
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glEnable(GL_TEXTURE_2D);
+
+ if (!_game_texture)
+ _game_texture = new GLESPaletteTexture();
+ else
+ _game_texture->reinitGL();
+
+ if (!_overlay_texture)
+ _overlay_texture = new GLES4444Texture();
+ else
+ _overlay_texture->reinitGL();
+
+ if (!_mouse_texture)
+ _mouse_texture = new GLESPaletteATexture();
+ else
+ _mouse_texture->reinitGL();
+
+ glViewport(0, 0, _egl_surface_width, _egl_surface_height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ clearFocusRectangle();
+ CHECK_GL_ERROR();
+}
+
+void OSystem_Android::destroyScummVMSurface() {
+ JNIEnv* env = JNU_GetEnv();
+ env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface);
+ // Can't use OpenGLES functions after this
+}
+
+void OSystem_Android::initSize(uint width, uint height,
+ const Graphics::PixelFormat *format) {
+ ENTER("initSize(%d,%d,%p)", width, height, format);
+
+ _game_texture->allocBuffer(width, height);
+
+ // Cap at 320x200 or the ScummVM themes abort :/
+ GLuint overlay_width = MIN(_egl_surface_width, 320);
+ GLuint overlay_height = MIN(_egl_surface_height, 200);
+ _overlay_texture->allocBuffer(overlay_width, overlay_height);
+
+ // Don't know mouse size yet - it gets reallocated in
+ // setMouseCursor. We need the palette allocated before
+ // setMouseCursor however, so just take a guess at the desired
+ // size (it's small).
+ _mouse_texture->allocBuffer(20, 20);
+}
+
+int16 OSystem_Android::getHeight() {
+ return _game_texture->height();
+}
+
+int16 OSystem_Android::getWidth() {
+ return _game_texture->width();
+}
+
+void OSystem_Android::setPalette(const byte* colors, uint start, uint num) {
+ ENTER("setPalette(%p, %u, %u)", colors, start, num);
+
+ if (!_use_mouse_palette)
+ _setCursorPalette(colors, start, num);
+
+ byte* palette = _game_texture->palette() + start*3;
+ do {
+ for (int i = 0; i < 3; ++i)
+ palette[i] = colors[i];
+ palette += 3;
+ colors += 4;
+ } while (--num);
+}
+
+void OSystem_Android::grabPalette(byte *colors, uint start, uint num) {
+ ENTER("grabPalette(%p, %u, %u)", colors, start, num);
+ const byte* palette = _game_texture->palette_const() + start*3;
+ do {
+ for (int i = 0; i < 3; ++i)
+ colors[i] = palette[i];
+ colors[3] = 0xff; // alpha
+
+ palette += 3;
+ colors += 4;
+ } while (--num);
+}
+
+void OSystem_Android::copyRectToScreen(const byte *buf, int pitch,
+ int x, int y, int w, int h) {
+ ENTER("copyRectToScreen(%p, %d, %d, %d, %d, %d)",
+ buf, pitch, x, y, w, h);
+
+ _game_texture->updateBuffer(x, y, w, h, buf, pitch);
+}
+
+void OSystem_Android::updateScreen() {
+ //ENTER("updateScreen()");
+
+ if (!_force_redraw &&
+ !_game_texture->dirty() &&
+ !_overlay_texture->dirty() &&
+ !_mouse_texture->dirty())
+ return;
+
+ _force_redraw = false;
+
+ glPushMatrix();
+
+ if (_shake_offset != 0 ||
+ (!_focus_rect.isEmpty() &&
+ !Common::Rect(_game_texture->width(),
+ _game_texture->height()).contains(_focus_rect))) {
+ // These are the only cases where _game_texture doesn't
+ // cover the entire screen.
+ glClearColorx(0, 0, 0, 1 << 16);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // Move everything up by _shake_offset (game) pixels
+ glTranslatex(0, -_shake_offset << 16, 0);
+ }
+
+ if (_focus_rect.isEmpty()) {
+ _game_texture->drawTexture(0, 0,
+ _egl_surface_width, _egl_surface_height);
+ } else {
+ glPushMatrix();
+ glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
+ xdiv(_egl_surface_height, _focus_rect.height()),
+ 1 << 16);
+ glTranslatex(-_focus_rect.left << 16, -_focus_rect.top << 16, 0);
+ glScalex(xdiv(_game_texture->width(), _egl_surface_width),
+ xdiv(_game_texture->height(), _egl_surface_height),
+ 1 << 16);
+ _game_texture->drawTexture(0, 0,
+ _egl_surface_width, _egl_surface_height);
+ glPopMatrix();
+ }
+
+ CHECK_GL_ERROR();
+
+ if (_show_overlay) {
+ _overlay_texture->drawTexture(0, 0,
+ _egl_surface_width,
+ _egl_surface_height);
+ CHECK_GL_ERROR();
+ }
+
+ if (_show_mouse) {
+ glPushMatrix();
+
+ glTranslatex(-_mouse_hotspot.x << 16,
+ -_mouse_hotspot.y << 16,
+ 0);
+
+ // Scale up ScummVM -> OpenGL (pixel) coordinates
+ int texwidth, texheight;
+ if (_show_overlay) {
+ texwidth = getOverlayWidth();
+ texheight = getOverlayHeight();
+ } else {
+ texwidth = getWidth();
+ texheight = getHeight();
+ }
+ glScalex(xdiv(_egl_surface_width, texwidth),
+ xdiv(_egl_surface_height, texheight),
+ 1 << 16);
+
+ // Note the extra half texel to position the mouse in
+ // the middle of the x,y square:
+ const Common::Point& mouse = getEventManager()->getMousePos();
+ glTranslatex((mouse.x << 16) | 1 << 15,
+ (mouse.y << 16) | 1 << 15, 0);
+
+ // Mouse targetscale just seems to make the cursor way
+ // too big :/
+ //glScalex(_mouse_targetscale << 16, _mouse_targetscale << 16,
+ // 1 << 16);
+
+ _mouse_texture->drawTexture();
+
+ glPopMatrix();
+ }
+
+ glPopMatrix();
+
+ CHECK_GL_ERROR();
+
+ JNIEnv* env = JNU_GetEnv();
+ if (!env->CallBooleanMethod(_back_ptr, MID_swapBuffers)) {
+ // Context lost -> need to reinit GL
+ destroyScummVMSurface();
+ setupScummVMSurface();
+ }
+}
+
+Graphics::Surface *OSystem_Android::lockScreen() {
+ ENTER("lockScreen()");
+ Graphics::Surface* surface = _game_texture->surface();
+ assert(surface->pixels);
+ return surface;
+}
+
+void OSystem_Android::unlockScreen() {
+ ENTER("unlockScreen()");
+ assert(_game_texture->dirty());
+}
+
+void OSystem_Android::setShakePos(int shake_offset) {
+ ENTER("setShakePos(%d)", shake_offset);
+ if (_shake_offset != shake_offset) {
+ _shake_offset = shake_offset;
+ _force_redraw = true;
+ }
+}
+
+void OSystem_Android::fillScreen(uint32 col) {
+ ENTER("fillScreen(%u)", col);
+ assert(col < 256);
+ _game_texture->fillBuffer(col);
+}
+
+void OSystem_Android::setFocusRectangle(const Common::Rect& rect) {
+ ENTER("setFocusRectangle(%d,%d,%d,%d)",
+ rect.left, rect.top, rect.right, rect.bottom);
+ if (_enable_zoning) {
+ _focus_rect = rect;
+ _force_redraw = true;
+ }
+}
+
+void OSystem_Android::clearFocusRectangle() {
+ ENTER("clearFocusRectangle()");
+ if (_enable_zoning) {
+ _focus_rect = Common::Rect();
+ _force_redraw = true;
+ }
+}
+
+void OSystem_Android::showOverlay() {
+ ENTER("showOverlay()");
+ _show_overlay = true;
+ _force_redraw = true;
+}
+
+void OSystem_Android::hideOverlay() {
+ ENTER("hideOverlay()");
+ _show_overlay = false;
+ _force_redraw = true;
+}
+
+void OSystem_Android::clearOverlay() {
+ ENTER("clearOverlay()");
+ _overlay_texture->fillBuffer(0);
+}
+
+void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) {
+ ENTER("grabOverlay(%p, %d)", buf, pitch);
+ // We support overlay alpha blending, so the pixel data here
+ // shouldn't actually be used. Let's fill it with zeros, I'm sure
+ // it will be fine...
+ const Graphics::Surface* surface = _overlay_texture->surface_const();
+ assert(surface->bytesPerPixel == sizeof(buf[0]));
+ int h = surface->h;
+ do {
+ memset(buf, 0, surface->w * sizeof(buf[0]));
+ buf += pitch; // This 'pitch' is pixels not bytes
+ } while (--h);
+}
+
+void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch,
+ int x, int y, int w, int h) {
+ ENTER("copyRectToOverlay(%p, %d, %d, %d, %d, %d)",
+ buf, pitch, x, y, w, h);
+ const Graphics::Surface* surface = _overlay_texture->surface_const();
+ assert(surface->bytesPerPixel == sizeof(buf[0]));
+
+ // This 'pitch' is pixels not bytes
+ _overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0]));
+}
+
+int16 OSystem_Android::getOverlayHeight() {
+ return _overlay_texture->height();
+}
+
+int16 OSystem_Android::getOverlayWidth() {
+ return _overlay_texture->width();
+}
+
+bool OSystem_Android::showMouse(bool visible) {
+ ENTER("showMouse(%d)", visible);
+ _show_mouse = visible;
+ return true;
+}
+
+void OSystem_Android::warpMouse(int x, int y) {
+ ENTER("warpMouse(%d, %d)", x, y);
+ // We use only the eventmanager's idea of the current mouse
+ // position, so there is nothing extra to do here.
+}
+
+void OSystem_Android::setMouseCursor(const byte *buf, uint w, uint h,
+ int hotspotX, int hotspotY,
+ uint32 keycolor, int cursorTargetScale,
+ const Graphics::PixelFormat *format) {
+ ENTER("setMouseCursor(%p, %u, %u, %d, %d, %d, %d, %p)",
+ buf, w, h, hotspotX, hotspotY, (int)keycolor, cursorTargetScale,
+ format);
+
+ assert(keycolor < 256);
+
+ _mouse_texture->allocBuffer(w, h);
+
+ // Update palette alpha based on keycolor
+ byte* palette = _mouse_texture->palette();
+ int i = 256;
+ do {
+ palette[3] = 0xff;
+ palette += 4;
+ } while (--i);
+ palette = _mouse_texture->palette();
+ palette[keycolor*4 + 3] = 0x00;
+ _mouse_texture->updateBuffer(0, 0, w, h, buf, w);
+
+ _mouse_hotspot = Common::Point(hotspotX, hotspotY);
+ _mouse_targetscale = cursorTargetScale;
+}
+
+void OSystem_Android::_setCursorPalette(const byte *colors,
+ uint start, uint num) {
+ byte* palette = _mouse_texture->palette() + start*4;
+ do {
+ for (int i = 0; i < 3; ++i)
+ palette[i] = colors[i];
+ // Leave alpha untouched to preserve keycolor
+
+ palette += 4;
+ colors += 4;
+ } while (--num);
+}
+
+void OSystem_Android::setCursorPalette(const byte *colors,
+ uint start, uint num) {
+ ENTER("setCursorPalette(%p, %u, %u)", colors, start, num);
+ _setCursorPalette(colors, start, num);
+ _use_mouse_palette = true;
+}
+
+void OSystem_Android::disableCursorPalette(bool disable) {
+ ENTER("disableCursorPalette(%d)", disable);
+ _use_mouse_palette = !disable;
+}
+
+void OSystem_Android::setupKeymapper() {
+#ifdef ENABLE_KEYMAPPER
+ using namespace Common;
+
+ Keymapper *mapper = getEventManager()->getKeymapper();
+
+ HardwareKeySet *keySet = new HardwareKeySet();
+ keySet->addHardwareKey(
+ new HardwareKey("n", KeyState(KEYCODE_n), "n (vk)",
+ kTriggerLeftKeyType,
+ kVirtualKeyboardActionType));
+ mapper->registerHardwareKeySet(keySet);
+
+ Keymap *globalMap = new Keymap("global");
+ Action *act;
+
+ act = new Action(globalMap, "VIRT", "Display keyboard",
+ kVirtualKeyboardActionType);
+ act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0));
+
+ mapper->addGlobalKeymap(globalMap);
+
+ mapper->pushKeymap("global");
+#endif
+}
+
+bool OSystem_Android::pollEvent(Common::Event &event) {
+ //ENTER("pollEvent()");
+ lockMutex(_event_queue_lock);
+ if (_event_queue.empty()) {
+ unlockMutex(_event_queue_lock);
+ return false;
+ }
+ event = _event_queue.pop();
+ unlockMutex(_event_queue_lock);
+
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ // TODO: only dirty/redraw move bounds
+ _force_redraw = true;
+ // fallthrough
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONDOWN:
+ case Common::EVENT_RBUTTONUP:
+ case Common::EVENT_WHEELUP:
+ case Common::EVENT_WHEELDOWN:
+ case Common::EVENT_MBUTTONDOWN:
+ case Common::EVENT_MBUTTONUP: {
+ if (event.kbd.flags == 1) { // relative mouse hack
+ // Relative (trackball) mouse hack.
+ const Common::Point& mouse_pos =
+ getEventManager()->getMousePos();
+ event.mouse.x += mouse_pos.x;
+ event.mouse.y += mouse_pos.y;
+ event.mouse.x = CLIP(event.mouse.x, (int16)0, _show_overlay ?
+ getOverlayWidth() : getWidth());
+ event.mouse.y = CLIP(event.mouse.y, (int16)0, _show_overlay ?
+ getOverlayHeight() : getHeight());
+ } else {
+ // Touchscreen events need to be converted
+ // from device to game coords first.
+ const GLESTexture* tex = _show_overlay
+ ? static_cast<GLESTexture*>(_overlay_texture)
+ : static_cast<GLESTexture*>(_game_texture);
+ event.mouse.x = scalef(event.mouse.x, tex->width(),
+ _egl_surface_width);
+ event.mouse.y = scalef(event.mouse.y, tex->height(),
+ _egl_surface_height);
+ event.mouse.x -= _shake_offset;
+ }
+ break;
+ }
+ case Common::EVENT_SCREEN_CHANGED:
+ debug("EVENT_SCREEN_CHANGED");
+ _screen_changeid++;
+ destroyScummVMSurface();
+ setupScummVMSurface();
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void OSystem_Android::pushEvent(const Common::Event& event) {
+ lockMutex(_event_queue_lock);
+
+ // Try to combine multiple queued mouse move events
+ if (event.type == Common::EVENT_MOUSEMOVE &&
+ !_event_queue.empty() &&
+ _event_queue.back().type == Common::EVENT_MOUSEMOVE) {
+ Common::Event tail = _event_queue.back();
+ if (event.kbd.flags) {
+ // relative movement hack
+ tail.mouse.x += event.mouse.x;
+ tail.mouse.y += event.mouse.y;
+ } else {
+ // absolute position
+ tail.kbd.flags = 0; // clear relative flag
+ tail.mouse.x = event.mouse.x;
+ tail.mouse.y = event.mouse.y;
+ }
+ }
+ else
+ _event_queue.push(event);
+
+ unlockMutex(_event_queue_lock);
+}
+
+static void ScummVM_pushEvent(JNIEnv* env, jobject self, jobject java_event) {
+ OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
+
+ Common::Event event;
+ event.type = (Common::EventType)env->GetIntField(java_event,
+ FID_Event_type);
+ event.synthetic =
+ env->GetBooleanField(java_event, FID_Event_synthetic);
+
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ case Common::EVENT_KEYUP:
+ event.kbd.keycode = (Common::KeyCode)env->GetIntField(
+ java_event, FID_Event_kbd_keycode);
+ event.kbd.ascii = static_cast<int>(env->GetIntField(
+ java_event, FID_Event_kbd_ascii));
+ event.kbd.flags = static_cast<int>(env->GetIntField(
+ java_event, FID_Event_kbd_flags));
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONDOWN:
+ case Common::EVENT_RBUTTONUP:
+ case Common::EVENT_WHEELUP:
+ case Common::EVENT_WHEELDOWN:
+ case Common::EVENT_MBUTTONDOWN:
+ case Common::EVENT_MBUTTONUP:
+ event.mouse.x =
+ env->GetIntField(java_event, FID_Event_mouse_x);
+ event.mouse.y =
+ env->GetIntField(java_event, FID_Event_mouse_y);
+ // This is a terrible hack. We stash "relativeness"
+ // in the kbd.flags field until pollEvent() can work
+ // it out.
+ event.kbd.flags = env->GetBooleanField(
+ java_event, FID_Event_mouse_relative) ? 1 : 0;
+ break;
+ default:
+ break;
+ }
+
+ cpp_obj->pushEvent(event);
+}
+
+uint32 OSystem_Android::getMillis() {
+ timeval curTime;
+ gettimeofday(&curTime, NULL);
+ return (uint32)(((curTime.tv_sec - _startTime.tv_sec) * 1000) + \
+ ((curTime.tv_usec - _startTime.tv_usec) / 1000));
+}
+
+void OSystem_Android::delayMillis(uint msecs) {
+ usleep(msecs * 1000);
+}
+
+OSystem::MutexRef OSystem_Android::createMutex() {
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+
+ pthread_mutex_t *mutex = new pthread_mutex_t;
+ if (pthread_mutex_init(mutex, &attr) != 0) {
+ warning("pthread_mutex_init() failed!");
+ delete mutex;
+ return NULL;
+ }
+ return (MutexRef)mutex;
+}
+
+void OSystem_Android::lockMutex(MutexRef mutex) {
+ if (pthread_mutex_lock((pthread_mutex_t*)mutex) != 0)
+ warning("pthread_mutex_lock() failed!");
+}
+
+void OSystem_Android::unlockMutex(MutexRef mutex) {
+ if (pthread_mutex_unlock((pthread_mutex_t*)mutex) != 0)
+ warning("pthread_mutex_unlock() failed!");
+}
+
+void OSystem_Android::deleteMutex(MutexRef mutex) {
+ pthread_mutex_t* m = (pthread_mutex_t*)mutex;
+ if (pthread_mutex_destroy(m) != 0)
+ warning("pthread_mutex_destroy() failed!");
+ else
+ delete m;
+}
+
+void OSystem_Android::quit() {
+ ENTER("quit()");
+
+ _timer_thread_exit = true;
+ pthread_join(_timer_thread, NULL);
+}
+
+void OSystem_Android::setWindowCaption(const char *caption) {
+ ENTER("setWindowCaption(%s)", caption);
+ JNIEnv* env = JNU_GetEnv();
+ jstring java_caption = env->NewStringUTF(caption);
+ env->CallVoidMethod(_back_ptr, MID_setWindowCaption, java_caption);
+ if (env->ExceptionCheck()) {
+ warning("Failed to set window caption");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ env->DeleteLocalRef(java_caption);
+}
+
+void OSystem_Android::displayMessageOnOSD(const char *msg) {
+ ENTER("displayMessageOnOSD(%s)", msg);
+ JNIEnv* env = JNU_GetEnv();
+ jstring java_msg = env->NewStringUTF(msg);
+ env->CallVoidMethod(_back_ptr, MID_displayMessageOnOSD, java_msg);
+ if (env->ExceptionCheck()) {
+ warning("Failed to display OSD message");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ env->DeleteLocalRef(java_msg);
+}
+
+void OSystem_Android::showVirtualKeyboard(bool enable) {
+ ENTER("showVirtualKeyboard(%d)", enable);
+ JNIEnv* env = JNU_GetEnv();
+ env->CallVoidMethod(_back_ptr, MID_showVirtualKeyboard, enable);
+ if (env->ExceptionCheck()) {
+ error("Error trying to show virtual keyboard");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+}
+
+Common::SaveFileManager *OSystem_Android::getSavefileManager() {
+ assert(_savefile);
+ return _savefile;
+}
+
+Audio::Mixer *OSystem_Android::getMixer() {
+ assert(_mixer);
+ return _mixer;
+}
+
+Common::TimerManager *OSystem_Android::getTimerManager() {
+ assert(_timer);
+ return _timer;
+}
+
+void OSystem_Android::getTimeAndDate(TimeDate &td) const {
+ struct tm tm;
+ const time_t curTime = time(NULL);
+ localtime_r(&curTime, &tm);
+ td.tm_sec = tm.tm_sec;
+ td.tm_min = tm.tm_min;
+ td.tm_hour = tm.tm_hour;
+ td.tm_mday = tm.tm_mday;
+ td.tm_mon = tm.tm_mon;
+ td.tm_year = tm.tm_year;
+}
+
+FilesystemFactory *OSystem_Android::getFilesystemFactory() {
+ return _fsFactory;
+}
+
+void OSystem_Android::addSysArchivesToSearchSet(Common::SearchSet &s,
+ int priority) {
+ s.add("ASSET", _asset_archive, priority, false);
+
+ JNIEnv* env = JNU_GetEnv();
+
+ jobjectArray array =
+ (jobjectArray)env->CallObjectMethod(_back_ptr, MID_getSysArchives);
+ if (env->ExceptionCheck()) {
+ warning("Error finding system archive path");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return;
+ }
+
+ jsize size = env->GetArrayLength(array);
+ for (jsize i = 0; i < size; ++i) {
+ jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
+ const char* path = env->GetStringUTFChars(path_obj, NULL);
+ if (path != NULL) {
+ s.addDirectory(path, path, priority);
+ env->ReleaseStringUTFChars(path_obj, path);
+ }
+ env->DeleteLocalRef(path_obj);
+ }
+}
+
+
+static jint ScummVM_scummVMMain(JNIEnv* env, jobject self, jobjectArray args) {
+ OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
+
+ const int MAX_NARGS = 32;
+ int res = -1;
+
+ int argc = env->GetArrayLength(args);
+ if (argc > MAX_NARGS) {
+ JNU_ThrowByName(env, "java/lang/IllegalArgumentException",
+ "too many arguments");
+ return 0;
+ }
+
+ char* argv[MAX_NARGS];
+ int nargs; // note use in cleanup loop below
+ for (nargs = 0; nargs < argc; ++nargs) {
+ jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
+ if (arg == NULL) {
+ argv[nargs] = NULL;
+ } else {
+ const char* cstr = env->GetStringUTFChars(arg, NULL);
+ argv[nargs] = const_cast<char*>(cstr);
+ if (cstr == NULL)
+ goto cleanup; // exception already thrown
+ }
+ env->DeleteLocalRef(arg);
+ }
+
+ g_system = cpp_obj;
+ assert(g_system);
+ __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
+ "Entering scummvm_main with %d args", argc);
+ res = scummvm_main(argc, argv);
+ __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Exiting scummvm_main");
+ g_system->quit();
+
+cleanup:
+ nargs--;
+ for (int i = 0; i < nargs; ++i) {
+ if (argv[i] == NULL)
+ continue;
+ jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
+ if (arg == NULL)
+ // Exception already thrown
+ return res;
+ env->ReleaseStringUTFChars(arg, argv[i]);
+ env->DeleteLocalRef(arg);
+ }
+
+ return res;
+}
+
+#ifdef DYNAMIC_MODULES
+void AndroidPluginProvider::addCustomDirectories(Common::FSList &dirs) const {
+ OSystem_Android* g_system_android = (OSystem_Android*)g_system;
+ g_system_android->addPluginDirectories(dirs);
+}
+#endif
+
+static void ScummVM_enableZoning(JNIEnv* env, jobject self, jboolean enable) {
+ OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
+ cpp_obj->enableZoning(enable);
+}
+
+static void ScummVM_setSurfaceSize(JNIEnv* env, jobject self,
+ jint width, jint height) {
+ OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
+ cpp_obj->setSurfaceSize(width, height);
+}
+
+const static JNINativeMethod gMethods[] = {
+ { "create", "(Landroid/content/res/AssetManager;)V",
+ (void*)ScummVM_create },
+ { "nativeDestroy", "()V", (void*)ScummVM_nativeDestroy },
+ { "scummVMMain", "([Ljava/lang/String;)I",
+ (void*)ScummVM_scummVMMain },
+ { "pushEvent", "(Lorg/inodes/gus/scummvm/Event;)V",
+ (void*)ScummVM_pushEvent },
+ { "audioMixCallback", "([B)V",
+ (void*)ScummVM_audioMixCallback },
+ { "setConfMan", "(Ljava/lang/String;I)V",
+ (void*)ScummVM_setConfManInt },
+ { "setConfMan", "(Ljava/lang/String;Ljava/lang/String;)V",
+ (void*)ScummVM_setConfManString },
+ { "enableZoning", "(Z)V",
+ (void*)ScummVM_enableZoning },
+ { "setSurfaceSize", "(II)V",
+ (void*)ScummVM_setSurfaceSize },
+};
+
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM* jvm, void* reserved) {
+ cached_jvm = jvm;
+
+ JNIEnv* env;
+ if (jvm->GetEnv((void**)&env, JNI_VERSION_1_2))
+ return JNI_ERR;
+
+ jclass cls = env->FindClass("org/inodes/gus/scummvm/ScummVM");
+ if (cls == NULL)
+ return JNI_ERR;
+ if (env->RegisterNatives(cls, gMethods, ARRAYSIZE(gMethods)) < 0)
+ return JNI_ERR;
+
+ FID_ScummVM_nativeScummVM = env->GetFieldID(cls, "nativeScummVM", "J");
+ if (FID_ScummVM_nativeScummVM == NULL)
+ return JNI_ERR;
+
+ jclass event = env->FindClass("org/inodes/gus/scummvm/Event");
+ if (event == NULL)
+ return JNI_ERR;
+ FID_Event_type = env->GetFieldID(event, "type", "I");
+ if (FID_Event_type == NULL)
+ return JNI_ERR;
+ FID_Event_synthetic = env->GetFieldID(event, "synthetic", "Z");
+ if (FID_Event_synthetic == NULL)
+ return JNI_ERR;
+ FID_Event_kbd_keycode = env->GetFieldID(event, "kbd_keycode", "I");
+ if (FID_Event_kbd_keycode == NULL)
+ return JNI_ERR;
+ FID_Event_kbd_ascii = env->GetFieldID(event, "kbd_ascii", "I");
+ if (FID_Event_kbd_ascii == NULL)
+ return JNI_ERR;
+ FID_Event_kbd_flags = env->GetFieldID(event, "kbd_flags", "I");
+ if (FID_Event_kbd_flags == NULL)
+ return JNI_ERR;
+ FID_Event_mouse_x = env->GetFieldID(event, "mouse_x", "I");
+ if (FID_Event_mouse_x == NULL)
+ return JNI_ERR;
+ FID_Event_mouse_y = env->GetFieldID(event, "mouse_y", "I");
+ if (FID_Event_mouse_y == NULL)
+ return JNI_ERR;
+ FID_Event_mouse_relative = env->GetFieldID(event, "mouse_relative", "Z");
+ if (FID_Event_mouse_relative == NULL)
+ return JNI_ERR;
+
+ cls = env->FindClass("java/lang/Object");
+ if (cls == NULL)
+ return JNI_ERR;
+ MID_Object_wait = env->GetMethodID(cls, "wait", "()V");
+ if (MID_Object_wait == NULL)
+ return JNI_ERR;
+
+ return JNI_VERSION_1_2;
+}
+
+#endif
diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk
new file mode 100644
index 0000000000..95e848e0d9
--- /dev/null
+++ b/backends/platform/android/android.mk
@@ -0,0 +1,59 @@
+# Android specific build targets
+
+AAPT = aapt
+DX = dx
+APKBUILDER = apkbuilder
+ADB = adb -e
+JAVAC ?= javac
+JAVACFLAGS = -source 1.5 -target 1.5
+
+# FIXME: find/mark plugin entry points and add all this back again:
+#LDFLAGS += -Wl,--gc-sections
+#CXXFLAGS += -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden
+
+resources.ap_: $(srcdir)/dists/android/AndroidManifest.xml $(RESOURCES) $(ASSETS) $(ANDROID_JAR8) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA)
+ $(INSTALL) -d build.tmp/assets/
+ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) build.tmp/assets/
+ $(AAPT) package -f -M $< -S $(srcdir)/dists/android/res -A build.tmp/assets -I $(ANDROID_JAR8) -F $@
+
+build.tmp/%/resources.ap_: build.tmp/%/AndroidManifest.xml build.stage/%/res/values/strings.xml build.stage/%/res/drawable/scummvm.png $(ANDROID_JAR8)
+ $(AAPT) package -f -M $< -S build.stage/$*/res -I $(ANDROID_JAR8) -F $@
+
+scummvm.apk: build.tmp/libscummvm.so resources.ap_ classes.dex
+ # Package installer won't delete old libscummvm.so on upgrade so
+ # replace it with a zero size file
+ $(INSTALL) -d build.stage/common/lib/armeabi
+ touch build.stage/common/lib/armeabi/libscummvm.so
+ # We now handle the library unpacking ourselves from mylib/
+ $(INSTALL) -d build.stage/common/mylib/armeabi
+ $(INSTALL) -c -m 644 build.tmp/libscummvm.so build.stage/common/mylib/armeabi/
+ $(STRIP) build.stage/common/mylib/armeabi/libscummvm.so
+ # "-nf lib/armeabi/libscummvm.so" builds bogus paths?
+ $(APKBUILDER) $@ -z resources.ap_ -f classes.dex -rf build.stage/common || { $(RM) $@; exit 1; }
+
+scummvm-engine-%.apk: plugins/lib%.so build.tmp/%/resources.ap_ build.tmp/plugins/classes.dex
+ $(INSTALL) -d build.stage/$*/apk/mylib/armeabi/
+ $(INSTALL) -c -m 644 plugins/lib$*.so build.stage/$*/apk/mylib/armeabi/
+ $(STRIP) build.stage/$*/apk/mylib/armeabi/lib$*.so
+ $(APKBUILDER) $@ -z build.tmp/$*/resources.ap_ -f build.tmp/plugins/classes.dex -rf build.stage/$*/apk || { $(RM) $@; exit 1; }
+
+release/%.apk: %.apk
+ @$(MKDIR) -p $(@D)
+ @$(RM) $@
+ $(CP) $< $@.tmp
+ # remove debugging signature
+ zip -d $@.tmp META-INF/\*
+ jarsigner $(JARSIGNER_FLAGS) $@.tmp release
+ zipalign 4 $@.tmp $@
+ $(RM) $@.tmp
+
+androidrelease: release/scummvm.apk $(patsubst plugins/lib%.so,release/scummvm-engine-%.apk,$(PLUGINS))
+
+androidtest: scummvm.apk scummvm-engine-scumm.apk scummvm-engine-kyra.apk
+ @set -e; for apk in $^; do \
+ echo $(ADB) install -r $$apk; \
+ $(ADB) install -r $$apk; \
+ done
+ $(ADB) shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n org.inodes.gus.scummvm/.Unpacker
+
+.PHONY: androidrelease androidtest
diff --git a/backends/platform/android/asset-archive.cpp b/backends/platform/android/asset-archive.cpp
new file mode 100644
index 0000000000..20c6a653c0
--- /dev/null
+++ b/backends/platform/android/asset-archive.cpp
@@ -0,0 +1,414 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(ANDROID)
+
+#include <jni.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "common/str.h"
+#include "common/stream.h"
+#include "common/util.h"
+#include "common/archive.h"
+#include "common/debug.h"
+
+#include "backends/platform/android/asset-archive.h"
+
+extern JNIEnv* JNU_GetEnv();
+
+// Must match android.content.res.AssetManager.ACCESS_*
+const jint ACCESS_UNKNOWN = 0;
+const jint ACCESS_RANDOM = 1;
+
+// This might be useful to someone else. Assumes markSupported() == true.
+class JavaInputStream : public Common::SeekableReadStream {
+public:
+ JavaInputStream(JNIEnv* env, jobject is);
+ virtual ~JavaInputStream();
+ virtual bool eos() const { return _eos; }
+ virtual bool err() const { return _err; }
+ virtual void clearErr() { _eos = _err = false; }
+ virtual uint32 read(void *dataPtr, uint32 dataSize);
+ virtual int32 pos() const { return _pos; }
+ virtual int32 size() const { return _len; }
+ virtual bool seek(int32 offset, int whence = SEEK_SET);
+private:
+ void close(JNIEnv* env);
+ jmethodID MID_mark;
+ jmethodID MID_available;
+ jmethodID MID_close;
+ jmethodID MID_read;
+ jmethodID MID_reset;
+ jmethodID MID_skip;
+ jobject _input_stream;
+ jsize _buflen;
+ jbyteArray _buf;
+ uint32 _pos;
+ jint _len;
+ bool _eos;
+ bool _err;
+};
+
+JavaInputStream::JavaInputStream(JNIEnv* env, jobject is) :
+ _eos(false), _err(false), _pos(0)
+{
+ _input_stream = env->NewGlobalRef(is);
+ _buflen = 8192;
+ _buf = static_cast<jbyteArray>(env->NewGlobalRef(env->NewByteArray(_buflen)));
+
+ jclass cls = env->GetObjectClass(_input_stream);
+ MID_mark = env->GetMethodID(cls, "mark", "(I)V");
+ assert(MID_mark);
+ MID_available = env->GetMethodID(cls, "available", "()I");
+ assert(MID_mark);
+ MID_close = env->GetMethodID(cls, "close", "()V");
+ assert(MID_close);
+ MID_read = env->GetMethodID(cls, "read", "([BII)I");
+ assert(MID_read);
+ MID_reset = env->GetMethodID(cls, "reset", "()V");
+ assert(MID_reset);
+ MID_skip = env->GetMethodID(cls, "skip", "(J)J");
+ assert(MID_skip);
+
+ // Mark start of stream, so we can reset back to it.
+ // readlimit is set to something bigger than anything we might
+ // want to seek within.
+ env->CallVoidMethod(_input_stream, MID_mark, 10*1024*1024);
+ _len = env->CallIntMethod(_input_stream, MID_available);
+}
+
+JavaInputStream::~JavaInputStream() {
+ JNIEnv* env = JNU_GetEnv();
+ close(env);
+ env->DeleteGlobalRef(_buf);
+ env->DeleteGlobalRef(_input_stream);
+}
+
+void JavaInputStream::close(JNIEnv* env) {
+ env->CallVoidMethod(_input_stream, MID_close);
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+}
+
+uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) {
+ JNIEnv* env = JNU_GetEnv();
+
+ if (_buflen < dataSize) {
+ _buflen = dataSize;
+ env->DeleteGlobalRef(_buf);
+ _buf = static_cast<jbyteArray>(env->NewGlobalRef(env->NewByteArray(_buflen)));
+ }
+
+ jint ret = env->CallIntMethod(_input_stream, MID_read, _buf, 0, dataSize);
+ if (env->ExceptionCheck()) {
+ warning("Exception during JavaInputStream::read(%p, %d)",
+ dataPtr, dataSize);
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ _err = true;
+ ret = -1;
+ } else if (ret == -1) {
+ _eos = true;
+ ret = 0;
+ } else {
+ env->GetByteArrayRegion(_buf, 0, ret, static_cast<jbyte*>(dataPtr));
+ _pos += ret;
+ }
+ return ret;
+}
+
+bool JavaInputStream::seek(int32 offset, int whence) {
+ JNIEnv* env = JNU_GetEnv();
+ uint32 newpos;
+ switch (whence) {
+ case SEEK_SET:
+ newpos = offset;
+ break;
+ case SEEK_CUR:
+ newpos = _pos + offset;
+ break;
+ case SEEK_END:
+ newpos = _len + offset;
+ break;
+ default:
+ debug("Unknown 'whence' arg %d", whence);
+ return false;
+ }
+
+ jlong skip_bytes;
+ if (newpos > _pos) {
+ skip_bytes = newpos - _pos;
+ } else {
+ // Can't skip backwards, so jump back to start and skip from there.
+ env->CallVoidMethod(_input_stream, MID_reset);
+ if (env->ExceptionCheck()) {
+ warning("Failed to rewind to start of asset stream");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return false;
+ }
+ _pos = 0;
+ skip_bytes = newpos;
+ }
+
+ while (skip_bytes > 0) {
+ jlong ret = env->CallLongMethod(_input_stream, MID_skip, skip_bytes);
+ if (env->ExceptionCheck()) {
+ warning("Failed to skip %ld bytes into asset stream",
+ static_cast<long>(skip_bytes));
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return false;
+ } else if (ret == 0) {
+ warning("InputStream->skip(%ld) didn't skip any bytes. Aborting seek.",
+ static_cast<long>(skip_bytes));
+ return false; // No point looping forever...
+ }
+ _pos += ret;
+ skip_bytes -= ret;
+ }
+ _eos = false;
+ return true;
+}
+
+
+// Must match android.content.res.AssetFileDescriptor.UNKNOWN_LENGTH
+const jlong UNKNOWN_LENGTH = -1;
+
+// Reading directly from a fd is so much more efficient, that it is
+// worth optimising for.
+class AssetFdReadStream : public Common::SeekableReadStream {
+public:
+ AssetFdReadStream(JNIEnv* env, jobject assetfd);
+ virtual ~AssetFdReadStream();
+ virtual bool eos() const { return _eos; }
+ virtual bool err() const { return _err; }
+ virtual void clearErr() { _eos = _err = false; }
+ virtual uint32 read(void *dataPtr, uint32 dataSize);
+ virtual int32 pos() const { return _pos; }
+ virtual int32 size() const { return _declared_len; }
+ virtual bool seek(int32 offset, int whence = SEEK_SET);
+private:
+ void close(JNIEnv* env);
+ int _fd;
+ jmethodID MID_close;
+ jobject _assetfd;
+ jlong _start_off;
+ jlong _declared_len;
+ uint32 _pos;
+ bool _eos;
+ bool _err;
+};
+
+AssetFdReadStream::AssetFdReadStream(JNIEnv* env, jobject assetfd) :
+ _eos(false), _err(false), _pos(0)
+{
+ _assetfd = env->NewGlobalRef(assetfd);
+
+ jclass cls = env->GetObjectClass(_assetfd);
+ MID_close = env->GetMethodID(cls, "close", "()V");
+ assert(MID_close);
+
+ jmethodID MID_getStartOffset =
+ env->GetMethodID(cls, "getStartOffset", "()J");
+ assert(MID_getStartOffset);
+ _start_off = env->CallLongMethod(_assetfd, MID_getStartOffset);
+
+ jmethodID MID_getDeclaredLength =
+ env->GetMethodID(cls, "getDeclaredLength", "()J");
+ assert(MID_getDeclaredLength);
+ _declared_len = env->CallLongMethod(_assetfd, MID_getDeclaredLength);
+
+ jmethodID MID_getFileDescriptor =
+ env->GetMethodID(cls, "getFileDescriptor", "()Ljava/io/FileDescriptor;");
+ assert(MID_getFileDescriptor);
+ jobject javafd = env->CallObjectMethod(_assetfd, MID_getFileDescriptor);
+ assert(javafd);
+ jclass fd_cls = env->GetObjectClass(javafd);
+ jfieldID FID_descriptor = env->GetFieldID(fd_cls, "descriptor", "I");
+ assert(FID_descriptor);
+ _fd = env->GetIntField(javafd, FID_descriptor);
+}
+
+AssetFdReadStream::~AssetFdReadStream() {
+ JNIEnv* env = JNU_GetEnv();
+ env->CallVoidMethod(_assetfd, MID_close);
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+ env->DeleteGlobalRef(_assetfd);
+}
+
+uint32 AssetFdReadStream::read(void *dataPtr, uint32 dataSize) {
+ if (_declared_len != UNKNOWN_LENGTH) {
+ jlong cap = _declared_len - _pos;
+ if (dataSize > cap)
+ dataSize = cap;
+ }
+ int ret = ::read(_fd, dataPtr, dataSize);
+ if (ret == 0)
+ _eos = true;
+ else if (ret == -1)
+ _err = true;
+ else
+ _pos += ret;
+ return ret;
+}
+
+bool AssetFdReadStream::seek(int32 offset, int whence) {
+ if (whence == SEEK_SET) {
+ if (_declared_len != UNKNOWN_LENGTH && offset > _declared_len)
+ offset = _declared_len;
+ offset += _start_off;
+ } else if (whence == SEEK_END && _declared_len != UNKNOWN_LENGTH) {
+ whence = SEEK_SET;
+ offset = _start_off + _declared_len + offset;
+ }
+ int ret = lseek(_fd, offset, whence);
+ if (ret == -1)
+ return false;
+ _pos = ret - _start_off;
+ _eos = false;
+ return true;
+}
+
+AndroidAssetArchive::AndroidAssetArchive(jobject am) {
+ JNIEnv* env = JNU_GetEnv();
+ _am = env->NewGlobalRef(am);
+
+ jclass cls = env->GetObjectClass(_am);
+ MID_open = env->GetMethodID(cls, "open",
+ "(Ljava/lang/String;I)Ljava/io/InputStream;");
+ assert(MID_open);
+ MID_openFd = env->GetMethodID(cls, "openFd",
+ "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
+ assert(MID_openFd);
+ MID_list = env->GetMethodID(cls, "list",
+ "(Ljava/lang/String;)[Ljava/lang/String;");
+ assert(MID_list);
+}
+
+AndroidAssetArchive::~AndroidAssetArchive() {
+ JNIEnv* env = JNU_GetEnv();
+ env->DeleteGlobalRef(_am);
+}
+
+bool AndroidAssetArchive::hasFile(const Common::String &name) {
+ JNIEnv* env = JNU_GetEnv();
+ jstring path = env->NewStringUTF(name.c_str());
+ jobject result = env->CallObjectMethod(_am, MID_open, path, ACCESS_UNKNOWN);
+ if (env->ExceptionCheck()) {
+ // Assume FileNotFoundException
+ //warning("Error while calling AssetManager->open(%s)", name.c_str());
+ //env->ExceptionDescribe();
+ env->ExceptionClear();
+ env->DeleteLocalRef(path);
+ return false;
+ }
+ env->DeleteLocalRef(result);
+ env->DeleteLocalRef(path);
+ return true;
+}
+
+int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) {
+ JNIEnv* env = JNU_GetEnv();
+ Common::List<Common::String> dirlist;
+ dirlist.push_back("");
+
+ int count = 0;
+ while (!dirlist.empty()) {
+ const Common::String dir = dirlist.back();
+ dirlist.pop_back();
+
+ jstring jpath = env->NewStringUTF(dir.c_str());
+ jobjectArray jpathlist = static_cast<jobjectArray>(env->CallObjectMethod(_am, MID_list, jpath));
+ if (env->ExceptionCheck()) {
+ warning("Error while calling AssetManager->list(%s). Ignoring.",
+ dir.c_str());
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ continue; // May as well keep going ...
+ }
+ env->DeleteLocalRef(jpath);
+
+ for (jsize i = 0; i < env->GetArrayLength(jpathlist); ++i) {
+ jstring elem = (jstring)env->GetObjectArrayElement(jpathlist, i);
+ const char* p = env->GetStringUTFChars(elem, NULL);
+ Common::String thispath = dir;
+ if (!thispath.empty())
+ thispath += "/";
+ thispath += p;
+
+ // Assume files have a . in them, and directories don't
+ if (strchr(p, '.')) {
+ member_list.push_back(getMember(thispath));
+ ++count;
+ } else
+ dirlist.push_back(thispath);
+
+ env->ReleaseStringUTFChars(elem, p);
+ env->DeleteLocalRef(elem);
+ }
+
+ env->DeleteLocalRef(jpathlist);
+ }
+
+ return count;
+}
+
+Common::ArchiveMemberPtr AndroidAssetArchive::getMember(const Common::String &name) {
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const Common::String &path) const {
+ JNIEnv* env = JNU_GetEnv();
+ jstring jpath = env->NewStringUTF(path.c_str());
+
+ // Try openFd() first ...
+ jobject afd = env->CallObjectMethod(_am, MID_openFd, jpath);
+ if (env->ExceptionCheck())
+ env->ExceptionClear();
+ else if (afd != NULL) {
+ // success :)
+ env->DeleteLocalRef(jpath);
+ return new AssetFdReadStream(env, afd);
+ }
+
+ // ... and fallback to normal open() if that doesn't work
+ jobject is = env->CallObjectMethod(_am, MID_open, jpath, ACCESS_RANDOM);
+ if (env->ExceptionCheck()) {
+ // Assume FileNotFoundException
+ //warning("Error opening %s", path.c_str());
+ //env->ExceptionDescribe();
+ env->ExceptionClear();
+ env->DeleteLocalRef(jpath);
+ return NULL;
+ }
+
+ return new JavaInputStream(env, is);
+}
+
+#endif
diff --git a/backends/platform/PalmOS/Src/cd_msa.h b/backends/platform/android/asset-archive.h
index 223bc0efcf..b3f6993c50 100644
--- a/backends/platform/PalmOS/Src/cd_msa.h
+++ b/backends/platform/android/asset-archive.h
@@ -23,46 +23,31 @@
*
*/
-#ifndef CD_MSA_H
-#define CD_MSA_H
+#if defined(ANDROID)
-#include "cdaudio.h"
+#include <jni.h>
-class MsaCDPlayer : public CDAudio {
-public:
- MsaCDPlayer(OSystem *sys);
-
- bool init();
- void release();
-
- bool poll();
- void update();
- void play(int track, int num_loops, int start_frame, int duration);
- void stop();
-
- void setVolume(int volume);
+#include "common/str.h"
+#include "common/stream.h"
+#include "common/util.h"
+#include "common/archive.h"
- private:
- void initInternal();
-
- OSystem *_sys;
- UInt16 _msaRefNum;
-
- UInt32 _volumeLLimit;
- UInt32 _volumeRLimit;
-
- // cdrom
- AlbumInfoType _msaAlbum;
- UInt16 _msaLoops;
+class AndroidAssetArchive : public Common::Archive {
+public:
+ AndroidAssetArchive(jobject am);
+ virtual ~AndroidAssetArchive();
- UInt32 _msaStopTime;
+ virtual bool hasFile(const Common::String &name);
+ virtual int listMembers(Common::ArchiveMemberList &list);
+ virtual Common::ArchiveMemberPtr getMember(const Common::String &name);
+ virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
- UInt32 _msaStartFrame;
- UInt32 _msaDuration;
+private:
+ jmethodID MID_open;
+ jmethodID MID_openFd;
+ jmethodID MID_list;
- UInt16 _msaTrack;
- UInt32 _msaTrackStartSu, _msaTrackEndSu;
- UInt32 _msaTrackLength;
+ jobject _am;
};
#endif
diff --git a/backends/platform/android/module.mk b/backends/platform/android/module.mk
new file mode 100644
index 0000000000..b457b388b1
--- /dev/null
+++ b/backends/platform/android/module.mk
@@ -0,0 +1,84 @@
+MODULE := backends/platform/android
+
+MODULE_OBJS := \
+ android.o asset-archive.o video.o
+
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
+
+JAVA_SRC = \
+ $(MODULE)/org/inodes/gus/scummvm/ScummVM.java \
+ $(MODULE)/org/inodes/gus/scummvm/ScummVMApplication.java \
+ $(MODULE)/org/inodes/gus/scummvm/ScummVMActivity.java \
+ $(MODULE)/org/inodes/gus/scummvm/EditableSurfaceView.java \
+ $(MODULE)/org/inodes/gus/scummvm/Unpacker.java \
+ $(MODULE)/org/inodes/gus/scummvm/Manifest.java \
+ $(MODULE)/org/inodes/gus/scummvm/R.java
+
+JAVA_PLUGIN_SRC = \
+ $(MODULE)/org/inodes/gus/scummvm/PluginProvider.java
+
+RESOURCES = \
+ $(srcdir)/dists/android/res/values/strings.xml \
+ $(srcdir)/dists/android/res/layout/main.xml \
+ $(srcdir)/dists/android/res/layout/splash.xml \
+ $(srcdir)/dists/android/res/drawable/gradient.xml \
+ $(srcdir)/dists/android/res/drawable/scummvm.png \
+ $(srcdir)/dists/android/res/drawable/scummvm_big.png
+
+ASSETS = $(DIST_FILES_ENGINEDATA) $(DIST_FILES_THEMES)
+
+PLUGIN_RESOURCES = \
+ $(srcdir)/dists/android/res/values/strings.xml \
+ $(srcdir)/dists/android/res/drawable/scummvm.png
+
+# These must be incremented for each market upload
+#ANDROID_VERSIONCODE = 6 Specified in dists/android/AndroidManifest.xml.in
+ANDROID_PLUGIN_VERSIONCODE = 6
+
+# This is a bit silly. I want to compile against the 1.6 android.jar,
+# to make the compiler check that I don't use something that requires
+# a newer Android. However, in order to use android:installLocation,
+# we need to give aapt a version >=8 android.jar - even though the
+# result will work ok on 1.5+.
+ANDROID_JAR = $(ANDROID_SDK)/platforms/android-1.5/android.jar
+ANDROID_JAR8 = $(ANDROID_SDK)/platforms/android-8/android.jar
+
+# This library contains scummvm proper
+build.tmp/libscummvm.so: $(OBJS)
+ @$(MKDIR) -p $(@D)
+ $(QUIET_LINK)$(CXX) -shared $(LDFLAGS) -Wl,-Bsymbolic -Wl,-soname,$(@F) -Wl,--no-undefined -o $@ $(PRE_OBJS_FLAGS) $(OBJS) $(POST_OBJS_FLAGS) $(LIBS)
+
+
+backends/platform/android/org/inodes/gus/scummvm/R.java backends/platform/android/org/inodes/gus/scummvm/Manifest.java: $(srcdir)/dists/android/AndroidManifest.xml $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR8)
+ $(AAPT) package -m -J backends/platform/android -M $< -S $(srcdir)/dists/android/res -I $(ANDROID_JAR8)
+
+build.tmp/classes/%.class: $(srcdir)/backends/platform/android/%.java $(srcdir)/backends/platform/android/org/inodes/gus/scummvm/R.java
+ @$(MKDIR) -p $(@D)
+ $(JAVAC) $(JAVACFLAGS) -cp $(srcdir)/backends/platform/android -d build.tmp/classes -bootclasspath $(ANDROID_JAR) $<
+
+build.tmp/classes.plugin/%.class: $(srcdir)/backends/platform/android/%.java
+ @$(MKDIR) -p $(@D)
+ $(JAVAC) $(JAVACFLAGS) -cp $(srcdir)/backends/platform/android -d build.tmp/classes.plugin -bootclasspath $(ANDROID_JAR) $<
+
+classes.dex: $(JAVA_SRC:backends/platform/android/%.java=build.tmp/classes/%.class)
+ $(DX) --dex --output=$@ build.tmp/classes
+
+build.tmp/plugins/classes.dex: $(JAVA_PLUGIN_SRC:backends/platform/android/%.java=build.tmp/classes.plugin/%.class)
+ @$(MKDIR) -p $(@D)
+ $(DX) --dex --output=$@ build.tmp/classes.plugin
+
+build.tmp/%/AndroidManifest.xml build.stage/%/res/values/strings.xml: dists/android/mkmanifest.pl configure dists/android/AndroidManifest.xml
+ dists/android/mkmanifest.pl --id=$* --configure=configure \
+ --version-name=$(VERSION) \
+ --version-code=$(ANDROID_PLUGIN_VERSIONCODE) \
+ --stringres=build.stage/$*/res/values/strings.xml \
+ --manifest=build.tmp/$*/AndroidManifest.xml \
+ --master-manifest=dists/android/AndroidManifest.xml \
+ --unpacklib=mylib/armeabi/lib$*.so
+
+build.stage/%/res/drawable/scummvm.png: dists/android/res/drawable/scummvm.png
+ @$(MKDIR) -p $(@D)
+ $(CP) $< $@
diff --git a/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
new file mode 100644
index 0000000000..5b71d4a3a5
--- /dev/null
+++ b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
@@ -0,0 +1,59 @@
+package org.inodes.gus.scummvm;
+
+import android.content.Context;
+import android.text.InputType;
+import android.util.AttributeSet;
+import android.view.SurfaceView;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
+
+public class EditableSurfaceView extends SurfaceView {
+ public EditableSurfaceView(Context context) {
+ super(context);
+ }
+
+ public EditableSurfaceView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public EditableSurfaceView(Context context, AttributeSet attrs,
+ int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ public boolean onCheckIsTextEditor() {
+ return true;
+ }
+
+ private class MyInputConnection extends BaseInputConnection {
+ public MyInputConnection() {
+ super(EditableSurfaceView.this, false);
+ }
+
+ @Override
+ public boolean performEditorAction(int actionCode) {
+ if (actionCode == EditorInfo.IME_ACTION_DONE) {
+ InputMethodManager imm = (InputMethodManager)
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(getWindowToken(), 0);
+ }
+ return super.performEditorAction(actionCode); // Sends enter key
+ }
+ }
+
+ @Override
+ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+ outAttrs.initialCapsMode = 0;
+ outAttrs.initialSelEnd = outAttrs.initialSelStart = -1;
+ outAttrs.inputType = (InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_NORMAL |
+ InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
+ outAttrs.imeOptions = (EditorInfo.IME_ACTION_DONE |
+ EditorInfo.IME_FLAG_NO_EXTRACT_UI);
+
+ return new MyInputConnection();
+ }
+}
diff --git a/backends/platform/android/org/inodes/gus/scummvm/Event.java b/backends/platform/android/org/inodes/gus/scummvm/Event.java
new file mode 100644
index 0000000000..f9c7aba93b
--- /dev/null
+++ b/backends/platform/android/org/inodes/gus/scummvm/Event.java
@@ -0,0 +1,330 @@
+package org.inodes.gus.scummvm;
+
+import android.view.KeyEvent;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Event {
+ // Common::EventType enum.
+ // Must be kept in sync with common/events.h
+ public final static int EVENT_INVALID = 0;
+ public final static int EVENT_KEYDOWN = 1;
+ public final static int EVENT_KEYUP = 2;
+ public final static int EVENT_MOUSEMOVE = 3;
+ public final static int EVENT_LBUTTONDOWN = 4;
+ public final static int EVENT_LBUTTONUP = 5;
+ public final static int EVENT_RBUTTONDOWN = 6;
+ public final static int EVENT_RBUTTONUP = 7;
+ public final static int EVENT_WHEELUP = 8;
+ public final static int EVENT_WHEELDOWN = 9;
+ public final static int EVENT_QUIT = 10;
+ public final static int EVENT_SCREEN_CHANGED = 11;
+ public final static int EVENT_PREDICTIVE_DIALOG = 12;
+ public final static int EVENT_MBUTTONDOWN = 13;
+ public final static int EVENT_MBUTTONUP = 14;
+ public final static int EVENT_MAINMENU = 15;
+ public final static int EVENT_RTL = 16;
+
+ // common/keyboard.h
+ public final static int ASCII_F1 = 315;
+ public final static int ASCII_F2 = 316;
+ public final static int ASCII_F3 = 317;
+ public final static int ASCII_F4 = 318;
+ public final static int ASCII_F5 = 319;
+ public final static int ASCII_F6 = 320;
+ public final static int ASCII_F7 = 321;
+ public final static int ASCII_F8 = 322;
+ public final static int ASCII_F9 = 323;
+ public final static int ASCII_F10 = 324;
+ public final static int ASCII_F11 = 325;
+ public final static int ASCII_F12 = 326;
+ public final static int KBD_CTRL = 1 << 0;
+ public final static int KBD_ALT = 1 << 1;
+ public final static int KBD_SHIFT = 1 << 2;
+
+ public final static int KEYCODE_INVALID = 0;
+ public final static int KEYCODE_BACKSPACE = 8;
+ public final static int KEYCODE_TAB = 9;
+ public final static int KEYCODE_CLEAR = 12;
+ public final static int KEYCODE_RETURN = 13;
+ public final static int KEYCODE_PAUSE = 19;
+ public final static int KEYCODE_ESCAPE = 27;
+ public final static int KEYCODE_SPACE = 32;
+ public final static int KEYCODE_EXCLAIM = 33;
+ public final static int KEYCODE_QUOTEDBL = 34;
+ public final static int KEYCODE_HASH = 35;
+ public final static int KEYCODE_DOLLAR = 36;
+ public final static int KEYCODE_AMPERSAND = 38;
+ public final static int KEYCODE_QUOTE = 39;
+ public final static int KEYCODE_LEFTPAREN = 40;
+ public final static int KEYCODE_RIGHTPAREN = 41;
+ public final static int KEYCODE_ASTERISK = 42;
+ public final static int KEYCODE_PLUS = 43;
+ public final static int KEYCODE_COMMA = 44;
+ public final static int KEYCODE_MINUS = 45;
+ public final static int KEYCODE_PERIOD = 46;
+ public final static int KEYCODE_SLASH = 47;
+ public final static int KEYCODE_0 = 48;
+ public final static int KEYCODE_1 = 49;
+ public final static int KEYCODE_2 = 50;
+ public final static int KEYCODE_3 = 51;
+ public final static int KEYCODE_4 = 52;
+ public final static int KEYCODE_5 = 53;
+ public final static int KEYCODE_6 = 54;
+ public final static int KEYCODE_7 = 55;
+ public final static int KEYCODE_8 = 56;
+ public final static int KEYCODE_9 = 57;
+ public final static int KEYCODE_COLON = 58;
+ public final static int KEYCODE_SEMICOLON = 59;
+ public final static int KEYCODE_LESS = 60;
+ public final static int KEYCODE_EQUALS = 61;
+ public final static int KEYCODE_GREATER = 62;
+ public final static int KEYCODE_QUESTION = 63;
+ public final static int KEYCODE_AT = 64;
+ public final static int KEYCODE_LEFTBRACKET = 91;
+ public final static int KEYCODE_BACKSLASH = 92;
+ public final static int KEYCODE_RIGHTBRACKET = 93;
+ public final static int KEYCODE_CARET = 94;
+ public final static int KEYCODE_UNDERSCORE = 95;
+ public final static int KEYCODE_BACKQUOTE = 96;
+ public final static int KEYCODE_a = 97;
+ public final static int KEYCODE_b = 98;
+ public final static int KEYCODE_c = 99;
+ public final static int KEYCODE_d = 100;
+ public final static int KEYCODE_e = 101;
+ public final static int KEYCODE_f = 102;
+ public final static int KEYCODE_g = 103;
+ public final static int KEYCODE_h = 104;
+ public final static int KEYCODE_i = 105;
+ public final static int KEYCODE_j = 106;
+ public final static int KEYCODE_k = 107;
+ public final static int KEYCODE_l = 108;
+ public final static int KEYCODE_m = 109;
+ public final static int KEYCODE_n = 110;
+ public final static int KEYCODE_o = 111;
+ public final static int KEYCODE_p = 112;
+ public final static int KEYCODE_q = 113;
+ public final static int KEYCODE_r = 114;
+ public final static int KEYCODE_s = 115;
+ public final static int KEYCODE_t = 116;
+ public final static int KEYCODE_u = 117;
+ public final static int KEYCODE_v = 118;
+ public final static int KEYCODE_w = 119;
+ public final static int KEYCODE_x = 120;
+ public final static int KEYCODE_y = 121;
+ public final static int KEYCODE_z = 122;
+ public final static int KEYCODE_DELETE = 127;
+ // Numeric keypad
+ public final static int KEYCODE_KP0 = 256;
+ public final static int KEYCODE_KP1 = 257;
+ public final static int KEYCODE_KP2 = 258;
+ public final static int KEYCODE_KP3 = 259;
+ public final static int KEYCODE_KP4 = 260;
+ public final static int KEYCODE_KP5 = 261;
+ public final static int KEYCODE_KP6 = 262;
+ public final static int KEYCODE_KP7 = 263;
+ public final static int KEYCODE_KP8 = 264;
+ public final static int KEYCODE_KP9 = 265;
+ public final static int KEYCODE_KP_PERIOD = 266;
+ public final static int KEYCODE_KP_DIVIDE = 267;
+ public final static int KEYCODE_KP_MULTIPLY = 268;
+ public final static int KEYCODE_KP_MINUS = 269;
+ public final static int KEYCODE_KP_PLUS = 270;
+ public final static int KEYCODE_KP_ENTER = 271;
+ public final static int KEYCODE_KP_EQUALS = 272;
+ // Arrows + Home/End pad
+ public final static int KEYCODE_UP = 273;
+ public final static int KEYCODE_DOWN = 274;
+ public final static int KEYCODE_RIGHT = 275;
+ public final static int KEYCODE_LEFT = 276;
+ public final static int KEYCODE_INSERT = 277;
+ public final static int KEYCODE_HOME = 278;
+ public final static int KEYCODE_END = 279;
+ public final static int KEYCODE_PAGEUP = 280;
+ public final static int KEYCODE_PAGEDOWN = 281;
+ // Function keys
+ public final static int KEYCODE_F1 = 282;
+ public final static int KEYCODE_F2 = 283;
+ public final static int KEYCODE_F3 = 284;
+ public final static int KEYCODE_F4 = 285;
+ public final static int KEYCODE_F5 = 286;
+ public final static int KEYCODE_F6 = 287;
+ public final static int KEYCODE_F7 = 288;
+ public final static int KEYCODE_F8 = 289;
+ public final static int KEYCODE_F9 = 290;
+ public final static int KEYCODE_F10 = 291;
+ public final static int KEYCODE_F11 = 292;
+ public final static int KEYCODE_F12 = 293;
+ public final static int KEYCODE_F13 = 294;
+ public final static int KEYCODE_F14 = 295;
+ public final static int KEYCODE_F15 = 296;
+ // Key state modifier keys
+ public final static int KEYCODE_NUMLOCK = 300;
+ public final static int KEYCODE_CAPSLOCK = 301;
+ public final static int KEYCODE_SCROLLOCK = 302;
+ public final static int KEYCODE_RSHIFT = 303;
+ public final static int KEYCODE_LSHIFT = 304;
+ public final static int KEYCODE_RCTRL = 305;
+ public final static int KEYCODE_LCTRL = 306;
+ public final static int KEYCODE_RALT = 307;
+ public final static int KEYCODE_LALT = 308;
+ public final static int KEYCODE_RMETA = 309;
+ public final static int KEYCODE_LMETA = 310;
+ public final static int KEYCODE_LSUPER = 311; // Left "Windows" key
+ public final static int KEYCODE_RSUPER = 312; // Right "Windows" key
+ public final static int KEYCODE_MODE = 313; // "Alt Gr" key
+ public final static int KEYCODE_COMPOSE = 314; // Multi-key compose key
+ // Miscellaneous function keys
+ public final static int KEYCODE_HELP = 315;
+ public final static int KEYCODE_PRINT = 316;
+ public final static int KEYCODE_SYSREQ = 317;
+ public final static int KEYCODE_BREAK = 318;
+ public final static int KEYCODE_MENU = 319;
+ public final static int KEYCODE_POWER = 320; // Power Macintosh power key
+ public final static int KEYCODE_EURO = 321; // Some european keyboards
+ public final static int KEYCODE_UNDO = 322; // Atari keyboard has Undo
+
+ // Android KeyEvent keycode -> ScummVM keycode
+ public final static Map<Integer, Integer> androidKeyMap;
+ static {
+ Map<Integer, Integer> map = new HashMap<Integer, Integer>();
+
+ map.put(KeyEvent.KEYCODE_DEL, KEYCODE_BACKSPACE);
+ map.put(KeyEvent.KEYCODE_TAB, KEYCODE_TAB);
+ map.put(KeyEvent.KEYCODE_CLEAR, KEYCODE_CLEAR);
+ map.put(KeyEvent.KEYCODE_ENTER, KEYCODE_RETURN);
+ //map.put(??, KEYCODE_PAUSE);
+ map.put(KeyEvent.KEYCODE_BACK, KEYCODE_ESCAPE);
+ map.put(KeyEvent.KEYCODE_SPACE, KEYCODE_SPACE);
+ //map.put(??, KEYCODE_EXCLAIM);
+ //map.put(??, KEYCODE_QUOTEDBL);
+ map.put(KeyEvent.KEYCODE_POUND, KEYCODE_HASH);
+ //map.put(??, KEYCODE_DOLLAR);
+ //map.put(??, KEYCODE_AMPERSAND);
+ map.put(KeyEvent.KEYCODE_APOSTROPHE, KEYCODE_QUOTE);
+ //map.put(??, KEYCODE_LEFTPAREN);
+ //map.put(??, KEYCODE_RIGHTPAREN);
+ //map.put(??, KEYCODE_ASTERISK);
+ map.put(KeyEvent.KEYCODE_PLUS, KEYCODE_PLUS);
+ map.put(KeyEvent.KEYCODE_COMMA, KEYCODE_COMMA);
+ map.put(KeyEvent.KEYCODE_MINUS, KEYCODE_MINUS);
+ map.put(KeyEvent.KEYCODE_PERIOD, KEYCODE_PERIOD);
+ map.put(KeyEvent.KEYCODE_SLASH, KEYCODE_SLASH);
+ map.put(KeyEvent.KEYCODE_0, KEYCODE_0);
+ map.put(KeyEvent.KEYCODE_1, KEYCODE_1);
+ map.put(KeyEvent.KEYCODE_2, KEYCODE_2);
+ map.put(KeyEvent.KEYCODE_3, KEYCODE_3);
+ map.put(KeyEvent.KEYCODE_4, KEYCODE_4);
+ map.put(KeyEvent.KEYCODE_5, KEYCODE_5);
+ map.put(KeyEvent.KEYCODE_6, KEYCODE_6);
+ map.put(KeyEvent.KEYCODE_7, KEYCODE_7);
+ map.put(KeyEvent.KEYCODE_8, KEYCODE_8);
+ map.put(KeyEvent.KEYCODE_9, KEYCODE_9);
+ //map.put(??, KEYCODE_COLON);
+ map.put(KeyEvent.KEYCODE_SEMICOLON, KEYCODE_SEMICOLON);
+ //map.put(??, KEYCODE_LESS);
+ map.put(KeyEvent.KEYCODE_EQUALS, KEYCODE_EQUALS);
+ //map.put(??, KEYCODE_GREATER);
+ //map.put(??, KEYCODE_QUESTION);
+ map.put(KeyEvent.KEYCODE_AT, KEYCODE_AT);
+ map.put(KeyEvent.KEYCODE_LEFT_BRACKET, KEYCODE_LEFTBRACKET);
+ map.put(KeyEvent.KEYCODE_BACKSLASH, KEYCODE_BACKSLASH);
+ map.put(KeyEvent.KEYCODE_RIGHT_BRACKET, KEYCODE_RIGHTBRACKET);
+ //map.put(??, KEYCODE_CARET);
+ //map.put(??, KEYCODE_UNDERSCORE);
+ //map.put(??, KEYCODE_BACKQUOTE);
+ map.put(KeyEvent.KEYCODE_A, KEYCODE_a);
+ map.put(KeyEvent.KEYCODE_B, KEYCODE_b);
+ map.put(KeyEvent.KEYCODE_C, KEYCODE_c);
+ map.put(KeyEvent.KEYCODE_D, KEYCODE_d);
+ map.put(KeyEvent.KEYCODE_E, KEYCODE_e);
+ map.put(KeyEvent.KEYCODE_F, KEYCODE_f);
+ map.put(KeyEvent.KEYCODE_G, KEYCODE_g);
+ map.put(KeyEvent.KEYCODE_H, KEYCODE_h);
+ map.put(KeyEvent.KEYCODE_I, KEYCODE_i);
+ map.put(KeyEvent.KEYCODE_J, KEYCODE_j);
+ map.put(KeyEvent.KEYCODE_K, KEYCODE_k);
+ map.put(KeyEvent.KEYCODE_L, KEYCODE_l);
+ map.put(KeyEvent.KEYCODE_M, KEYCODE_m);
+ map.put(KeyEvent.KEYCODE_N, KEYCODE_n);
+ map.put(KeyEvent.KEYCODE_O, KEYCODE_o);
+ map.put(KeyEvent.KEYCODE_P, KEYCODE_p);
+ map.put(KeyEvent.KEYCODE_Q, KEYCODE_q);
+ map.put(KeyEvent.KEYCODE_R, KEYCODE_r);
+ map.put(KeyEvent.KEYCODE_S, KEYCODE_s);
+ map.put(KeyEvent.KEYCODE_T, KEYCODE_t);
+ map.put(KeyEvent.KEYCODE_U, KEYCODE_u);
+ map.put(KeyEvent.KEYCODE_V, KEYCODE_v);
+ map.put(KeyEvent.KEYCODE_W, KEYCODE_w);
+ map.put(KeyEvent.KEYCODE_X, KEYCODE_x);
+ map.put(KeyEvent.KEYCODE_Y, KEYCODE_y);
+ map.put(KeyEvent.KEYCODE_Z, KEYCODE_z);
+ //map.put(KeyEvent.KEYCODE_DEL, KEYCODE_DELETE); use BACKSPACE instead
+ //map.put(??, KEYCODE_KP_*);
+ map.put(KeyEvent.KEYCODE_DPAD_UP, KEYCODE_UP);
+ map.put(KeyEvent.KEYCODE_DPAD_DOWN, KEYCODE_DOWN);
+ map.put(KeyEvent.KEYCODE_DPAD_RIGHT, KEYCODE_RIGHT);
+ map.put(KeyEvent.KEYCODE_DPAD_LEFT, KEYCODE_LEFT);
+ //map.put(??, KEYCODE_INSERT);
+ //map.put(??, KEYCODE_HOME);
+ //map.put(??, KEYCODE_END);
+ //map.put(??, KEYCODE_PAGEUP);
+ //map.put(??, KEYCODE_PAGEDOWN);
+ //map.put(??, KEYCODE_F{1-15});
+ map.put(KeyEvent.KEYCODE_NUM, KEYCODE_NUMLOCK);
+ //map.put(??, KEYCODE_CAPSLOCK);
+ //map.put(??, KEYCODE_SCROLLLOCK);
+ map.put(KeyEvent.KEYCODE_SHIFT_RIGHT, KEYCODE_RSHIFT);
+ map.put(KeyEvent.KEYCODE_SHIFT_LEFT, KEYCODE_LSHIFT);
+ //map.put(??, KEYCODE_RCTRL);
+ //map.put(??, KEYCODE_LCTRL);
+ map.put(KeyEvent.KEYCODE_ALT_RIGHT, KEYCODE_RALT);
+ map.put(KeyEvent.KEYCODE_ALT_LEFT, KEYCODE_LALT);
+ // ?? META, SUPER
+ // ?? MODE, COMPOSE
+ // ?? HELP, PRINT, SYSREQ, BREAK, EURO, UNDO
+ map.put(KeyEvent.KEYCODE_MENU, KEYCODE_MENU);
+ map.put(KeyEvent.KEYCODE_POWER, KEYCODE_POWER);
+
+ androidKeyMap = Collections.unmodifiableMap(map);
+ }
+
+ public int type;
+ public boolean synthetic;
+ public int kbd_keycode;
+ public int kbd_ascii;
+ public int kbd_flags;
+ public int mouse_x;
+ public int mouse_y;
+ public boolean mouse_relative; // Used for trackball events
+
+ public Event() {
+ type = EVENT_INVALID;
+ synthetic = false;
+ }
+
+ public Event(int type) {
+ this.type = type;
+ synthetic = false;
+ }
+
+ public static Event KeyboardEvent(int type, int keycode, int ascii,
+ int flags) {
+ Event e = new Event();
+ e.type = type;
+ e.kbd_keycode = keycode;
+ e.kbd_ascii = ascii;
+ e.kbd_flags = flags;
+ return e;
+ }
+
+ public static Event MouseEvent(int type, int x, int y) {
+ Event e = new Event();
+ e.type = type;
+ e.mouse_x = x;
+ e.mouse_y = y;
+ return e;
+ }
+}
diff --git a/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java b/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
new file mode 100644
index 0000000000..840f3440d5
--- /dev/null
+++ b/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
@@ -0,0 +1,52 @@
+package org.inodes.gus.scummvm;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+public class PluginProvider extends BroadcastReceiver {
+ public final static String META_UNPACK_LIB =
+ "org.inodes.gus.scummvm.meta.UNPACK_LIB";
+
+ public void onReceive(Context context, Intent intent) {
+ if (!intent.getAction().equals(ScummVMApplication.ACTION_PLUGIN_QUERY))
+ return;
+
+ Bundle extras = getResultExtras(true);
+
+ final ActivityInfo info;
+ try {
+ info = context.getPackageManager()
+ .getReceiverInfo(new ComponentName(context, this.getClass()),
+ PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(this.toString(), "Error finding my own info?", e);
+ return;
+ }
+
+ String mylib = info.metaData.getString(META_UNPACK_LIB);
+ if (mylib != null) {
+ ArrayList<String> all_libs =
+ extras.getStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS);
+
+ all_libs.add(new Uri.Builder()
+ .scheme("plugin")
+ .authority(context.getPackageName())
+ .path(mylib)
+ .toString());
+
+ extras.putStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS,
+ all_libs);
+ }
+
+ setResultExtras(extras);
+ }
+}
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
new file mode 100644
index 0000000000..d39aa363ef
--- /dev/null
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
@@ -0,0 +1,353 @@
+package org.inodes.gus.scummvm;
+
+import android.content.Context;
+import android.content.res.AssetManager;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Process;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+
+import javax.microedition.khronos.opengles.GL;
+import javax.microedition.khronos.opengles.GL10;
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGL11;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+
+import java.io.File;
+import java.util.concurrent.Semaphore;
+
+
+// At least in Android 2.1, eglCreateWindowSurface() requires an
+// EGLNativeWindowSurface object, which is hidden deep in the bowels
+// of libui. Until EGL is properly exposed, it's probably safer to
+// use the Java versions of most EGL functions :(
+
+public class ScummVM implements SurfaceHolder.Callback {
+ private final static String LOG_TAG = "ScummVM.java";
+
+ private final int AUDIO_FRAME_SIZE = 2 * 2; // bytes. 16bit audio * stereo
+ public static class AudioSetupException extends Exception {}
+
+ private long nativeScummVM; // native code hangs itself here
+ boolean scummVMRunning = false;
+
+ private native void create(AssetManager am);
+
+ public ScummVM(Context context) {
+ create(context.getAssets()); // Init C++ code, set nativeScummVM
+ }
+
+ private native void nativeDestroy();
+
+ public synchronized void destroy() {
+ if (nativeScummVM != 0) {
+ nativeDestroy();
+ nativeScummVM = 0;
+ }
+ }
+ protected void finalize() {
+ destroy();
+ }
+
+ // Surface creation:
+ // GUI thread: create surface, release lock
+ // ScummVM thread: acquire lock (block), read surface
+ //
+ // Surface deletion:
+ // GUI thread: post event, acquire lock (block), return
+ // ScummVM thread: read event, free surface, release lock
+ //
+ // In other words, ScummVM thread does this:
+ // acquire lock
+ // setup surface
+ // when SCREEN_CHANGED arrives:
+ // destroy surface
+ // release lock
+ // back to acquire lock
+ static final int configSpec[] = {
+ EGL10.EGL_RED_SIZE, 5,
+ EGL10.EGL_GREEN_SIZE, 5,
+ EGL10.EGL_BLUE_SIZE, 5,
+ EGL10.EGL_DEPTH_SIZE, 0,
+ EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
+ EGL10.EGL_NONE,
+ };
+ EGL10 egl;
+ EGLDisplay eglDisplay = EGL10.EGL_NO_DISPLAY;
+ EGLConfig eglConfig;
+ EGLContext eglContext = EGL10.EGL_NO_CONTEXT;
+ EGLSurface eglSurface = EGL10.EGL_NO_SURFACE;
+ Semaphore surfaceLock = new Semaphore(0, true);
+ SurfaceHolder nativeSurface;
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ nativeSurface = holder;
+ surfaceLock.release();
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format,
+ int width, int height) {
+ // Disabled while I debug GL problems
+ //pushEvent(new Event(Event.EVENT_SCREEN_CHANGED));
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ pushEvent(new Event(Event.EVENT_SCREEN_CHANGED));
+ try {
+ surfaceLock.acquire();
+ } catch (InterruptedException e) {
+ Log.e(this.toString(),
+ "Interrupted while waiting for surface lock", e);
+ }
+ }
+
+ // Called by ScummVM thread (from initBackend)
+ private void createScummVMGLContext() {
+ egl = (EGL10)EGLContext.getEGL();
+ eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+ int[] version = new int[2];
+ egl.eglInitialize(eglDisplay, version);
+ int[] num_config = new int[1];
+ egl.eglChooseConfig(eglDisplay, configSpec, null, 0, num_config);
+
+ final int numConfigs = num_config[0];
+ if (numConfigs <= 0)
+ throw new IllegalArgumentException("No configs match configSpec");
+
+ EGLConfig[] configs = new EGLConfig[numConfigs];
+ egl.eglChooseConfig(eglDisplay, configSpec, configs, numConfigs,
+ num_config);
+ eglConfig = configs[0];
+
+ eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
+ EGL10.EGL_NO_CONTEXT, null);
+ }
+
+ // Called by ScummVM thread
+ static private boolean _log_version = true;
+ protected void setupScummVMSurface() {
+ try {
+ surfaceLock.acquire();
+ } catch (InterruptedException e) {
+ Log.e(this.toString(),
+ "Interrupted while waiting for surface lock", e);
+ return;
+ }
+ eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
+ nativeSurface, null);
+ egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
+
+ GL10 gl = (GL10)eglContext.getGL();
+
+ if (_log_version) {
+ Log.i(LOG_TAG, String.format("Using EGL %s (%s); GL %s/%s (%s)",
+ egl.eglQueryString(eglDisplay, EGL10.EGL_VERSION),
+ egl.eglQueryString(eglDisplay, EGL10.EGL_VENDOR),
+ gl.glGetString(GL10.GL_VERSION),
+ gl.glGetString(GL10.GL_RENDERER),
+ gl.glGetString(GL10.GL_VENDOR)));
+ _log_version = false; // only log this once
+ }
+
+ int[] value = new int[1];
+ egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, value);
+ int width = value[0];
+ egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, value);
+ int height = value[0];
+ Log.i(LOG_TAG, String.format("New surface is %dx%d", width, height));
+ setSurfaceSize(width, height);
+ }
+
+ // Called by ScummVM thread
+ protected void destroyScummVMSurface() {
+ if (eglSurface != null) {
+ egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+ egl.eglDestroySurface(eglDisplay, eglSurface);
+ eglSurface = EGL10.EGL_NO_SURFACE;
+ }
+
+ surfaceLock.release();
+ }
+
+ public void setSurface(SurfaceHolder holder) {
+ holder.addCallback(this);
+ }
+
+ final public boolean swapBuffers() {
+ if (!egl.eglSwapBuffers(eglDisplay, eglSurface)) {
+ int error = egl.eglGetError();
+ Log.w(LOG_TAG, String.format("eglSwapBuffers exited with error 0x%x", error));
+ if (error == EGL11.EGL_CONTEXT_LOST)
+ return false;
+ }
+ return true;
+ }
+
+ // Set scummvm config options
+ final public native static void loadConfigFile(String path);
+ final public native static void setConfMan(String key, int value);
+ final public native static void setConfMan(String key, String value);
+ final public native void enableZoning(boolean enable);
+ final public native void setSurfaceSize(int width, int height);
+
+ // Feed an event to ScummVM. Safe to call from other threads.
+ final public native void pushEvent(Event e);
+
+ final private native void audioMixCallback(byte[] buf);
+
+ // Runs the actual ScummVM program and returns when it does.
+ // This should not be called from multiple threads simultaneously...
+ final public native int scummVMMain(String[] argv);
+
+ // Callbacks from C++ peer instance
+ //protected GraphicsMode[] getSupportedGraphicsModes() {}
+ protected void displayMessageOnOSD(String msg) {}
+ protected void setWindowCaption(String caption) {}
+ protected void showVirtualKeyboard(boolean enable) {}
+ protected String[] getSysArchives() { return new String[0]; }
+ protected String[] getPluginDirectories() { return new String[0]; }
+ protected void initBackend() throws AudioSetupException {
+ createScummVMGLContext();
+ initAudio();
+ }
+
+ private static class AudioThread extends Thread {
+ final private int buf_size;
+ private boolean is_paused = false;
+ final private ScummVM scummvm;
+ final private AudioTrack audio_track;
+
+ AudioThread(ScummVM scummvm, AudioTrack audio_track, int buf_size) {
+ super("AudioThread");
+ this.scummvm = scummvm;
+ this.audio_track = audio_track;
+ this.buf_size = buf_size;
+ setPriority(Thread.MAX_PRIORITY);
+ setDaemon(true);
+ }
+
+ public void pauseAudio() {
+ synchronized (this) {
+ is_paused = true;
+ }
+ audio_track.pause();
+ }
+
+ public void resumeAudio() {
+ synchronized (this) {
+ is_paused = false;
+ notifyAll();
+ }
+ audio_track.play();
+ }
+
+ public void run() {
+ byte[] buf = new byte[buf_size];
+ audio_track.play();
+ int offset = 0;
+ try {
+ while (true) {
+ synchronized (this) {
+ while (is_paused)
+ wait();
+ }
+
+ if (offset == buf.length) {
+ // Grab new audio data
+ scummvm.audioMixCallback(buf);
+ offset = 0;
+ }
+ int len = buf.length - offset;
+ int ret = audio_track.write(buf, offset, len);
+ if (ret < 0) {
+ Log.w(LOG_TAG, String.format(
+ "AudioTrack.write(%dB) returned error %d",
+ buf.length, ret));
+ break;
+ } else if (ret != len) {
+ Log.w(LOG_TAG, String.format(
+ "Short audio write. Wrote %dB, not %dB",
+ ret, buf.length));
+ // Buffer is full, so yield cpu for a while
+ Thread.sleep(100);
+ }
+ offset += ret;
+ }
+ } catch (InterruptedException e) {
+ Log.e(this.toString(), "Audio thread interrupted", e);
+ }
+ }
+ }
+ private AudioThread audio_thread;
+
+ final public int audioSampleRate() {
+ return AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
+ }
+
+ private void initAudio() throws AudioSetupException {
+ int sample_rate = audioSampleRate();
+ int buf_size =
+ AudioTrack.getMinBufferSize(sample_rate,
+ AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+ AudioFormat.ENCODING_PCM_16BIT);
+ if (buf_size < 0) {
+ int guess = AUDIO_FRAME_SIZE * sample_rate / 100; // 10ms of audio
+ Log.w(LOG_TAG, String.format(
+ "Unable to get min audio buffer size (error %d). Guessing %dB.",
+ buf_size, guess));
+ buf_size = guess;
+ }
+ Log.d(LOG_TAG, String.format("Using %dB buffer for %dHZ audio",
+ buf_size, sample_rate));
+ AudioTrack audio_track =
+ new AudioTrack(AudioManager.STREAM_MUSIC,
+ sample_rate,
+ AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+ AudioFormat.ENCODING_PCM_16BIT,
+ buf_size,
+ AudioTrack.MODE_STREAM);
+ if (audio_track.getState() != AudioTrack.STATE_INITIALIZED) {
+ Log.e(LOG_TAG, "Error initialising Android audio system.");
+ throw new AudioSetupException();
+ }
+
+ audio_thread = new AudioThread(this, audio_track, buf_size);
+ audio_thread.start();
+ }
+
+ public void pause() {
+ audio_thread.pauseAudio();
+ // TODO: need to pause engine too
+ }
+
+ public void resume() {
+ // TODO: need to resume engine too
+ audio_thread.resumeAudio();
+ }
+
+ static {
+ // For grabbing with gdb...
+ final boolean sleep_for_debugger = false;
+ if (sleep_for_debugger) {
+ try {
+ Thread.sleep(20*1000);
+ } catch (InterruptedException e) {
+ }
+ }
+
+ //System.loadLibrary("scummvm");
+ File cache_dir = ScummVMApplication.getLastCacheDir();
+ String libname = System.mapLibraryName("scummvm");
+ File libpath = new File(cache_dir, libname);
+ System.load(libpath.getPath());
+ }
+}
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
new file mode 100644
index 0000000000..b37b2b8a52
--- /dev/null
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
@@ -0,0 +1,466 @@
+package org.inodes.gus.scummvm;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.res.Configuration;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Message;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Toast;
+
+import java.io.IOException;
+
+public class ScummVMActivity extends Activity {
+ private boolean _do_right_click;
+ private boolean _last_click_was_right;
+
+ // game pixels to move per trackball/dpad event.
+ // FIXME: replace this with proper mouse acceleration
+ private final static int TRACKBALL_SCALE = 2;
+
+ private class MyScummVM extends ScummVM {
+ private boolean scummvmRunning = false;
+
+ private boolean usingSmallScreen() {
+ // Multiple screen sizes came in with Android 1.6. Have
+ // to use reflection in order to continue supporting 1.5
+ // devices :(
+ DisplayMetrics metrics = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ try {
+ // This 'density' term is very confusing.
+ int DENSITY_LOW = metrics.getClass().getField("DENSITY_LOW").getInt(null);
+ int densityDpi = metrics.getClass().getField("densityDpi").getInt(metrics);
+ return densityDpi <= DENSITY_LOW;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public MyScummVM() {
+ super(ScummVMActivity.this);
+
+ // Enable ScummVM zoning on 'small' screens.
+ enableZoning(usingSmallScreen());
+ }
+
+ @Override
+ protected void initBackend() throws ScummVM.AudioSetupException {
+ synchronized (this) {
+ scummvmRunning = true;
+ notifyAll();
+ }
+ super.initBackend();
+ }
+
+ public void waitUntilRunning() throws InterruptedException {
+ synchronized (this) {
+ while (!scummvmRunning)
+ wait();
+ }
+ }
+
+ @Override
+ protected void displayMessageOnOSD(String msg) {
+ Log.i(this.toString(), "OSD: " + msg);
+ Toast.makeText(ScummVMActivity.this, msg, Toast.LENGTH_LONG).show();
+ }
+
+ @Override
+ protected void setWindowCaption(final String caption) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ setTitle(caption);
+ }
+ });
+ }
+
+ @Override
+ protected String[] getPluginDirectories() {
+ String[] dirs = new String[1];
+ dirs[0] = ScummVMApplication.getLastCacheDir().getPath();
+ return dirs;
+ }
+
+ @Override
+ protected void showVirtualKeyboard(final boolean enable) {
+ if (getResources().getConfiguration().keyboard ==
+ Configuration.KEYBOARD_NOKEYS) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ showKeyboard(enable);
+ }
+ });
+ }
+ }
+ }
+ private MyScummVM scummvm;
+ private Thread scummvm_thread;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ _do_right_click = false;
+ setVolumeControlStream(AudioManager.STREAM_MUSIC);
+
+ setContentView(R.layout.main);
+ takeKeyEvents(true);
+
+ // This is a common enough error that we should warn about it
+ // explicitly.
+ if (!Environment.getExternalStorageDirectory().canRead()) {
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.no_sdcard_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(R.string.no_sdcard)
+ .setNegativeButton(R.string.quit,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int which) {
+ finish();
+ }
+ })
+ .show();
+ return;
+ }
+
+ SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
+ main_surface.setOnTouchListener(new View.OnTouchListener() {
+ public boolean onTouch(View v, MotionEvent event) {
+ return onTouchEvent(event);
+ }
+ });
+ main_surface.setOnKeyListener(new View.OnKeyListener() {
+ public boolean onKey(View v, int code, KeyEvent ev) {
+ return onKeyDown(code, ev);
+ }
+ });
+ main_surface.requestFocus();
+
+ // Start ScummVM
+ scummvm = new MyScummVM();
+ scummvm_thread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ runScummVM();
+ } catch (Exception e) {
+ Log.e("ScummVM", "Fatal error in ScummVM thread", e);
+ new AlertDialog.Builder(ScummVMActivity.this)
+ .setTitle("Error")
+ .setMessage(e.toString())
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .show();
+ finish();
+ }
+ }
+ }, "ScummVM");
+ scummvm_thread.start();
+
+ // Block UI thread until ScummVM has started. In particular,
+ // this means that surface and event callbacks should be safe
+ // after this point.
+ try {
+ scummvm.waitUntilRunning();
+ } catch (InterruptedException e) {
+ Log.e(this.toString(),
+ "Interrupted while waiting for ScummVM.initBackend", e);
+ finish();
+ }
+
+ scummvm.setSurface(main_surface.getHolder());
+ }
+
+ // Runs in another thread
+ private void runScummVM() throws IOException {
+ getFilesDir().mkdirs();
+ String[] args = {
+ "ScummVM-lib",
+ "--config=" + getFileStreamPath("scummvmrc").getPath(),
+ "--path=" + Environment.getExternalStorageDirectory().getPath(),
+ "--gui-theme=scummmodern",
+ "--savepath=" + getDir("saves", 0).getPath(),
+ };
+
+ int ret = scummvm.scummVMMain(args);
+
+ // On exit, tear everything down for a fresh
+ // restart next time.
+ System.exit(ret);
+ }
+
+ private boolean was_paused = false;
+
+ @Override
+ public void onPause() {
+ if (scummvm != null) {
+ was_paused = true;
+ scummvm.pause();
+ }
+ super.onPause();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (scummvm != null && was_paused)
+ scummvm.resume();
+ was_paused = false;
+ }
+
+ @Override
+ public void onStop() {
+ if (scummvm != null) {
+ scummvm.pushEvent(new Event(Event.EVENT_QUIT));
+ try {
+ scummvm_thread.join(1000); // 1s timeout
+ } catch (InterruptedException e) {
+ Log.i(this.toString(),
+ "Error while joining ScummVM thread", e);
+ }
+ }
+ super.onStop();
+ }
+
+ static final int MSG_MENU_LONG_PRESS = 1;
+ private final Handler keycodeMenuTimeoutHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_MENU_LONG_PRESS) {
+ InputMethodManager imm = (InputMethodManager)
+ getSystemService(INPUT_METHOD_SERVICE);
+ if (imm != null)
+ imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+ }
+ }
+ };
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent kevent) {
+ return onKeyDown(keyCode, kevent);
+ }
+
+ @Override
+ public boolean onKeyMultiple(int keyCode, int repeatCount,
+ KeyEvent kevent) {
+ return onKeyDown(keyCode, kevent);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent kevent) {
+ // Filter out "special" keys
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_MENU:
+ // Have to reimplement hold-down-menu-brings-up-softkeybd
+ // ourselves, since we are otherwise hijacking the menu
+ // key :(
+ // See com.android.internal.policy.impl.PhoneWindow.onKeyDownPanel()
+ // for the usual Android implementation of this feature.
+ if (kevent.getRepeatCount() > 0)
+ // Ignore keyrepeat for menu
+ return false;
+ boolean timeout_fired = false;
+ if (getResources().getConfiguration().keyboard ==
+ Configuration.KEYBOARD_NOKEYS) {
+ timeout_fired = !keycodeMenuTimeoutHandler.hasMessages(MSG_MENU_LONG_PRESS);
+ keycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
+ if (kevent.getAction() == KeyEvent.ACTION_DOWN) {
+ keycodeMenuTimeoutHandler.sendMessageDelayed(
+ keycodeMenuTimeoutHandler.obtainMessage(MSG_MENU_LONG_PRESS),
+ ViewConfiguration.getLongPressTimeout());
+ return true;
+ }
+ }
+ if (kevent.getAction() == KeyEvent.ACTION_UP) {
+ if (!timeout_fired)
+ scummvm.pushEvent(new Event(Event.EVENT_MAINMENU));
+ return true;
+ }
+ return false;
+ case KeyEvent.KEYCODE_CAMERA:
+ case KeyEvent.KEYCODE_SEARCH:
+ _do_right_click = (kevent.getAction() == KeyEvent.ACTION_DOWN);
+ return true;
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ case KeyEvent.KEYCODE_DPAD_RIGHT: {
+ // HTC Hero doesn't seem to generate
+ // MotionEvent.ACTION_DOWN events on trackball press :(
+ // We'll have to just fake one here.
+ // Some other handsets lack a trackball, so the DPAD is
+ // the only way of moving the cursor.
+ int motion_action;
+ // FIXME: this logic is a mess.
+ if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+ switch (kevent.getAction()) {
+ case KeyEvent.ACTION_DOWN:
+ motion_action = MotionEvent.ACTION_DOWN;
+ break;
+ case KeyEvent.ACTION_UP:
+ motion_action = MotionEvent.ACTION_UP;
+ break;
+ default: // ACTION_MULTIPLE
+ return false;
+ }
+ } else
+ motion_action = MotionEvent.ACTION_MOVE;
+
+ Event e = new Event(getEventType(motion_action));
+ e.mouse_x = 0;
+ e.mouse_y = 0;
+ e.mouse_relative = true;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_UP:
+ e.mouse_y = -TRACKBALL_SCALE;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ e.mouse_y = TRACKBALL_SCALE;
+ break;
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ e.mouse_x = -TRACKBALL_SCALE;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ e.mouse_x = TRACKBALL_SCALE;
+ break;
+ }
+ scummvm.pushEvent(e);
+ return true;
+ }
+ case KeyEvent.KEYCODE_BACK:
+ // skip isSystem() check and fall through to main code
+ break;
+ default:
+ if (kevent.isSystem())
+ return false;
+ }
+
+ // FIXME: what do I need to do for composed characters?
+
+ Event e = new Event();
+
+ switch (kevent.getAction()) {
+ case KeyEvent.ACTION_DOWN:
+ e.type = Event.EVENT_KEYDOWN;
+ e.synthetic = false;
+ break;
+ case KeyEvent.ACTION_UP:
+ e.type = Event.EVENT_KEYUP;
+ e.synthetic = false;
+ break;
+ case KeyEvent.ACTION_MULTIPLE:
+ // e.type is handled below
+ e.synthetic = true;
+ break;
+ default:
+ return false;
+ }
+
+ e.kbd_keycode = Event.androidKeyMap.containsKey(keyCode) ?
+ Event.androidKeyMap.get(keyCode) : Event.KEYCODE_INVALID;
+ e.kbd_ascii = kevent.getUnicodeChar();
+ if (e.kbd_ascii == 0)
+ e.kbd_ascii = e.kbd_keycode; // scummvm keycodes are mostly ascii
+
+
+ e.kbd_flags = 0;
+ if (kevent.isAltPressed())
+ e.kbd_flags |= Event.KBD_ALT;
+ if (kevent.isSymPressed()) // no ctrl key in android, so use sym (?)
+ e.kbd_flags |= Event.KBD_CTRL;
+ if (kevent.isShiftPressed()) {
+ if (keyCode >= KeyEvent.KEYCODE_0 &&
+ keyCode <= KeyEvent.KEYCODE_9) {
+ // Shift+number -> convert to F* key
+ int offset = keyCode == KeyEvent.KEYCODE_0 ?
+ 10 : keyCode - KeyEvent.KEYCODE_1; // turn 0 into 10
+ e.kbd_keycode = Event.KEYCODE_F1 + offset;
+ e.kbd_ascii = Event.ASCII_F1 + offset;
+ } else
+ e.kbd_flags |= Event.KBD_SHIFT;
+ }
+
+ if (kevent.getAction() == KeyEvent.ACTION_MULTIPLE) {
+ for (int i = 0; i <= kevent.getRepeatCount(); i++) {
+ e.type = Event.EVENT_KEYDOWN;
+ scummvm.pushEvent(e);
+ e.type = Event.EVENT_KEYUP;
+ scummvm.pushEvent(e);
+ }
+ } else
+ scummvm.pushEvent(e);
+
+ return true;
+ }
+
+ private int getEventType(int action) {
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ _last_click_was_right = _do_right_click;
+ return _last_click_was_right ?
+ Event.EVENT_RBUTTONDOWN : Event.EVENT_LBUTTONDOWN;
+ case MotionEvent.ACTION_UP:
+ return _last_click_was_right ?
+ Event.EVENT_RBUTTONUP : Event.EVENT_LBUTTONUP;
+ case MotionEvent.ACTION_MOVE:
+ return Event.EVENT_MOUSEMOVE;
+ default:
+ return Event.EVENT_INVALID;
+ }
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ int type = getEventType(event.getAction());
+ if (type == Event.EVENT_INVALID)
+ return false;
+
+ Event e = new Event(type);
+ e.mouse_x =
+ (int)(event.getX() * event.getXPrecision()) * TRACKBALL_SCALE;
+ e.mouse_y =
+ (int)(event.getY() * event.getYPrecision()) * TRACKBALL_SCALE;
+ e.mouse_relative = true;
+ scummvm.pushEvent(e);
+
+ return true;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ int type = getEventType(event.getAction());
+ if (type == Event.EVENT_INVALID)
+ return false;
+
+ Event e = new Event(type);
+ e.mouse_x = (int)event.getX();
+ e.mouse_y = (int)event.getY();
+ e.mouse_relative = false;
+ scummvm.pushEvent(e);
+
+ return true;
+ }
+
+ private void showKeyboard(boolean show) {
+ SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
+ InputMethodManager imm = (InputMethodManager)
+ getSystemService(INPUT_METHOD_SERVICE);
+ if (show)
+ imm.showSoftInput(main_surface, InputMethodManager.SHOW_IMPLICIT);
+ else
+ imm.hideSoftInputFromWindow(main_surface.getWindowToken(),
+ InputMethodManager.HIDE_IMPLICIT_ONLY);
+ }
+}
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java
new file mode 100644
index 0000000000..37a9d09e1a
--- /dev/null
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java
@@ -0,0 +1,29 @@
+package org.inodes.gus.scummvm;
+
+import android.app.Application;
+
+import java.io.File;
+
+public class ScummVMApplication extends Application {
+ public final static String ACTION_PLUGIN_QUERY = "org.inodes.gus.scummvm.action.PLUGIN_QUERY";
+ public final static String EXTRA_UNPACK_LIBS = "org.inodes.gus.scummvm.extra.UNPACK_LIBS";
+
+ private static File cache_dir;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ // This is still on /data :(
+ cache_dir = getCacheDir();
+ // This is mounted noexec :(
+ //cache_dir = new File(Environment.getExternalStorageDirectory(),
+ // "/.ScummVM.tmp");
+ // This is owned by download manager and requires special
+ // permissions to access :(
+ //cache_dir = Environment.getDownloadCacheDirectory();
+ }
+
+ public static File getLastCacheDir() {
+ return cache_dir;
+ }
+}
diff --git a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
new file mode 100644
index 0000000000..7280aac7d4
--- /dev/null
+++ b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
@@ -0,0 +1,370 @@
+package org.inodes.gus.scummvm;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.ProgressBar;
+
+import java.io.IOException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipEntry;
+
+public class Unpacker extends Activity {
+ private final static boolean PLUGINS_ENABLED = true;
+ private final static String META_NEXT_ACTIVITY =
+ "org.inodes.gus.unpacker.nextActivity";
+ private ProgressBar mProgress;
+ private File mUnpackDest; // location to unpack into
+ private AsyncTask<String, Integer, Void> mUnpacker;
+ private final static int REQUEST_MARKET = 1;
+
+ private static class UnpackJob {
+ public ZipFile zipfile;
+ public Set<String> paths;
+
+ public UnpackJob(ZipFile zipfile, Set<String> paths) {
+ this.zipfile = zipfile;
+ this.paths = paths;
+ }
+
+ public long UnpackSize() {
+ long size = 0;
+ for (String path: paths) {
+ ZipEntry entry = zipfile.getEntry(path);
+ if (entry != null) size += entry.getSize();
+ }
+ return size;
+ }
+ }
+
+ private class UnpackTask extends AsyncTask<String, Integer, Void> {
+ @Override
+ protected void onProgressUpdate(Integer... progress) {
+ mProgress.setIndeterminate(false);
+ mProgress.setMax(progress[1]);
+ mProgress.setProgress(progress[0]);
+ mProgress.postInvalidate();
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ Bundle md = getMetaData();
+ String nextActivity = md.getString(META_NEXT_ACTIVITY);
+ if (nextActivity != null) {
+ final ComponentName cn =
+ ComponentName.unflattenFromString(nextActivity);
+ if (cn != null) {
+ final Intent origIntent = getIntent();
+ Intent intent = new Intent();
+ intent.setComponent(cn);
+ if (origIntent.getExtras() != null)
+ intent.putExtras(origIntent.getExtras());
+ intent.putExtra(Intent.EXTRA_INTENT, origIntent);
+ intent.setDataAndType(origIntent.getData(),
+ origIntent.getType());
+ //intent.fillIn(getIntent(), 0);
+ intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
+ Log.i(this.toString(),
+ "Starting next activity with intent " + intent);
+ startActivity(intent);
+ } else {
+ Log.w(this.toString(),
+ "Unable to extract a component name from " + nextActivity);
+ }
+ }
+
+ finish();
+ }
+
+ @Override
+ protected Void doInBackground(String... all_libs) {
+ // This will contain all unpack jobs
+ Map<String, UnpackJob> unpack_jobs =
+ new HashMap<String, UnpackJob>(all_libs.length);
+
+ // This will contain all unpack filenames (so we can
+ // detect stale files in the unpack directory)
+ Set<String> all_files = new HashSet<String>(all_libs.length);
+
+ for (String lib: all_libs) {
+ final Uri uri = Uri.parse(lib);
+ final String pkg = uri.getAuthority();
+ final String path = uri.getPath().substring(1); // skip first /
+
+ all_files.add(new File(path).getName());
+
+ UnpackJob job = unpack_jobs.get(pkg);
+ if (job == null) {
+ try {
+ // getPackageResourcePath is hidden in Context,
+ // but exposed in ContextWrapper...
+ ContextWrapper context =
+ new ContextWrapper(createPackageContext(pkg, 0));
+ ZipFile zipfile =
+ new ZipFile(context.getPackageResourcePath());
+ job = new UnpackJob(zipfile, new HashSet<String>(1));
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(this.toString(), "Package " + pkg +
+ " not found", e);
+ continue;
+ } catch (IOException e) {
+ // FIXME: show some sort of GUI error dialog
+ Log.e(this.toString(),
+ "Error opening ZIP for package " + pkg, e);
+ continue;
+ }
+ unpack_jobs.put(pkg, job);
+ }
+ job.paths.add(path);
+ }
+
+ // Delete stale filenames from mUnpackDest
+ for (File file: mUnpackDest.listFiles()) {
+ if (!all_files.contains(file.getName())) {
+ Log.i(this.toString(),
+ "Deleting stale cached file " + file);
+ file.delete();
+ }
+ }
+
+ int total_size = 0;
+ for (UnpackJob job: unpack_jobs.values())
+ total_size += job.UnpackSize();
+
+ publishProgress(0, total_size);
+
+ mUnpackDest.mkdirs();
+
+ int progress = 0;
+
+ for (UnpackJob job: unpack_jobs.values()) {
+ try {
+ ZipFile zipfile = job.zipfile;
+ for (String path: job.paths) {
+ ZipEntry zipentry = zipfile.getEntry(path);
+ if (zipentry == null)
+ throw new FileNotFoundException(
+ "Couldn't find " + path + " in zip");
+ File dest = new File(mUnpackDest, new File(path).getName());
+ if (dest.exists() &&
+ dest.lastModified() == zipentry.getTime() &&
+ dest.length() == zipentry.getSize()) {
+ // Already unpacked
+ progress += zipentry.getSize();
+ } else {
+ if (dest.exists())
+ Log.d(this.toString(),
+ "Replacing " + dest.getPath() +
+ " old.mtime=" + dest.lastModified() +
+ " new.mtime=" + zipentry.getTime() +
+ " old.size=" + dest.length() +
+ " new.size=" + zipentry.getSize());
+ else
+ Log.i(this.toString(),
+ "Extracting " + zipentry.getName() +
+ " from " + zipfile.getName() +
+ " to " + dest.getPath());
+
+ long next_update = progress;
+
+ InputStream in = zipfile.getInputStream(zipentry);
+ OutputStream out = new FileOutputStream(dest);
+ int len;
+ byte[] buffer = new byte[4096];
+ while ((len = in.read(buffer)) != -1) {
+ out.write(buffer, 0, len);
+ progress += len;
+ if (progress >= next_update) {
+ publishProgress(progress, total_size);
+ // Arbitrary limit of 2% update steps
+ next_update += total_size / 50;
+ }
+ }
+
+ in.close();
+ out.close();
+ dest.setLastModified(zipentry.getTime());
+ }
+ publishProgress(progress, total_size);
+ }
+
+ zipfile.close();
+ } catch (IOException e) {
+ // FIXME: show some sort of GUI error dialog
+ Log.e(this.toString(), "Error unpacking plugin", e);
+ }
+ }
+
+ if (progress != total_size)
+ Log.d(this.toString(), "Ended with progress " + progress +
+ " != total size " + total_size);
+
+ setResult(RESULT_OK);
+
+ return null;
+ }
+ }
+
+ private class PluginBroadcastReciever extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!intent.getAction()
+ .equals(ScummVMApplication.ACTION_PLUGIN_QUERY)) {
+ Log.e(this.toString(),
+ "Received unexpected action " + intent.getAction());
+ return;
+ }
+
+ Bundle extras = getResultExtras(false);
+ if (extras == null) {
+ // Nothing for us to do.
+ Unpacker.this.setResult(RESULT_OK);
+ finish();
+ }
+
+ ArrayList<String> unpack_libs =
+ extras.getStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS);
+
+ if (unpack_libs != null && !unpack_libs.isEmpty()) {
+ final String[] libs =
+ unpack_libs.toArray(new String[unpack_libs.size()]);
+ mUnpacker = new UnpackTask().execute(libs);
+ }
+ }
+ }
+
+ private void initPlugins() {
+ Bundle extras = new Bundle(1);
+
+ ArrayList<String> unpack_libs = new ArrayList<String>(1);
+ // This is the common ScummVM code (not really a "plugin" as such)
+ unpack_libs.add(new Uri.Builder()
+ .scheme("plugin")
+ .authority(getPackageName())
+ .path("mylib/armeabi/libscummvm.so")
+ .toString());
+ extras.putStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS,
+ unpack_libs);
+
+ Intent intent = new Intent(ScummVMApplication.ACTION_PLUGIN_QUERY);
+ sendOrderedBroadcast(intent, Manifest.permission.SCUMMVM_PLUGIN,
+ new PluginBroadcastReciever(),
+ null, RESULT_OK, null, extras);
+ }
+
+ @Override
+ public void onCreate(Bundle b) {
+ super.onCreate(b);
+
+ mUnpackDest = ScummVMApplication.getLastCacheDir();
+
+ setContentView(R.layout.splash);
+ mProgress = (ProgressBar)findViewById(R.id.progress);
+
+ setResult(RESULT_CANCELED);
+
+ tryUnpack();
+ }
+
+ private void tryUnpack() {
+ Intent intent = new Intent(ScummVMApplication.ACTION_PLUGIN_QUERY);
+ List<ResolveInfo> plugins = getPackageManager()
+ .queryBroadcastReceivers(intent, 0);
+ if (PLUGINS_ENABLED && plugins.isEmpty()) {
+ // No plugins installed
+ AlertDialog.Builder alert = new AlertDialog.Builder(this)
+ .setTitle(R.string.no_plugins_title)
+ .setMessage(R.string.no_plugins_found)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }
+ })
+ .setNegativeButton(R.string.quit,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ });
+
+ final Uri uri = Uri.parse("market://search?q=ScummVM plugin");
+ final Intent market_intent = new Intent(Intent.ACTION_VIEW, uri);
+ if (getPackageManager().resolveActivity(market_intent, 0) != null) {
+ alert.setPositiveButton(R.string.to_market,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ try {
+ startActivityForResult(market_intent,
+ REQUEST_MARKET);
+ } catch (ActivityNotFoundException e) {
+ Log.e(this.toString(),
+ "Error starting market", e);
+ }
+ }
+ });
+ }
+
+ alert.show();
+
+ } else {
+ // Already have at least one plugin installed
+ initPlugins();
+ }
+ }
+
+ @Override
+ public void onStop() {
+ if (mUnpacker != null)
+ mUnpacker.cancel(true);
+ super.onStop();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode,
+ Intent data) {
+ switch (requestCode) {
+ case REQUEST_MARKET:
+ if (resultCode != RESULT_OK)
+ Log.w(this.toString(), "Market returned " + resultCode);
+ tryUnpack();
+ break;
+ }
+ }
+
+ private Bundle getMetaData() {
+ try {
+ ActivityInfo ai = getPackageManager()
+ .getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
+ return ai.metaData;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(this.toString(), "Unable to find my own meta-data", e);
+ return new Bundle();
+ }
+ }
+}
diff --git a/backends/platform/android/video.cpp b/backends/platform/android/video.cpp
new file mode 100644
index 0000000000..d4c002fbd0
--- /dev/null
+++ b/backends/platform/android/video.cpp
@@ -0,0 +1,334 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/trunk/backends/platform/null/null.cpp $
+ * $Id: null.cpp 34912 2008-11-06 15:02:50Z fingolfin $
+ *
+ */
+
+#include "base/main.h"
+#include "graphics/surface.h"
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <android/log.h>
+
+#include "common/rect.h"
+#include "common/array.h"
+#include "common/util.h"
+#include "common/tokenizer.h"
+
+#include "backends/platform/android/video.h"
+
+#undef LOG_TAG
+#define LOG_TAG "ScummVM-video"
+
+#if 0
+#define ENTER(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, args)
+#else
+#define ENTER(args...) /**/
+#endif
+
+#if 0
+#define CHECK_GL_ERROR() checkGlError(__FILE__, __LINE__)
+static const char* getGlErrStr(GLenum error) {
+ switch (error) {
+ case GL_NO_ERROR: return "GL_NO_ERROR";
+ case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
+ case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
+ case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
+ case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
+ case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
+ }
+
+ static char buf[40];
+ snprintf(buf, sizeof(buf), "(Unknown GL error code 0x%x)", error);
+ return buf;
+}
+static void checkGlError(const char* file, int line) {
+ GLenum error = glGetError();
+ if (error != GL_NO_ERROR)
+ warning("%s:%d: GL error: %s", file, line, getGlErrStr(error));
+}
+#else
+#define CHECK_GL_ERROR() do {} while (false)
+#endif
+
+// Supported GL extensions
+static bool npot_supported = false;
+#ifdef GL_OES_draw_texture
+static bool draw_tex_supported = false;
+#endif
+
+static inline GLfixed xdiv(int numerator, int denominator) {
+ assert(numerator < (1<<16));
+ return (numerator << 16) / denominator;
+}
+
+template <class T>
+static T nextHigher2(T k) {
+ if (k == 0)
+ return 1;
+ --k;
+ for (uint i = 1; i < sizeof(T)*CHAR_BIT; i <<= 1)
+ k = k | k >> i;
+ return k + 1;
+}
+
+void GLESTexture::initGLExtensions() {
+ const char* ext_string =
+ reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
+ __android_log_print(ANDROID_LOG_INFO, LOG_TAG,
+ "Extensions: %s", ext_string);
+ Common::StringTokenizer tokenizer(ext_string, " ");
+ while (!tokenizer.empty()) {
+ Common::String token = tokenizer.nextToken();
+ if (token == "GL_ARB_texture_non_power_of_two")
+ npot_supported = true;
+#ifdef GL_OES_draw_texture
+ if (token == "GL_OES_draw_texture")
+ draw_tex_supported = true;
+#endif
+ }
+}
+
+GLESTexture::GLESTexture() :
+ _texture_width(0),
+ _texture_height(0),
+ _all_dirty(true)
+{
+ glGenTextures(1, &_texture_name);
+ // This all gets reset later in allocBuffer:
+ _surface.w = 0;
+ _surface.h = 0;
+ _surface.pitch = _texture_width;
+ _surface.pixels = NULL;
+ _surface.bytesPerPixel = 0;
+}
+
+GLESTexture::~GLESTexture() {
+ debug("Destroying texture %u", _texture_name);
+ glDeleteTextures(1, &_texture_name);
+}
+
+void GLESTexture::reinitGL() {
+ glGenTextures(1, &_texture_name);
+ setDirty();
+}
+
+void GLESTexture::allocBuffer(GLuint w, GLuint h) {
+ CHECK_GL_ERROR();
+ int bpp = bytesPerPixel();
+ _surface.w = w;
+ _surface.h = h;
+ _surface.bytesPerPixel = bpp;
+
+ if (w <= _texture_width && h <= _texture_height)
+ // Already allocated a sufficiently large buffer
+ return;
+
+ if (npot_supported) {
+ _texture_width = _surface.w;
+ _texture_height = _surface.h;
+ } else {
+ _texture_width = nextHigher2(_surface.w);
+ _texture_height = nextHigher2(_surface.h);
+ }
+ _surface.pitch = _texture_width * bpp;
+
+ // Allocate room for the texture now, but pixel data gets uploaded
+ // later (perhaps with multiple TexSubImage2D operations).
+ CHECK_GL_ERROR();
+ glBindTexture(GL_TEXTURE_2D, _texture_name);
+ CHECK_GL_ERROR();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ CHECK_GL_ERROR();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ CHECK_GL_ERROR();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ CHECK_GL_ERROR();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ CHECK_GL_ERROR();
+ glTexImage2D(GL_TEXTURE_2D, 0, glFormat(),
+ _texture_width, _texture_height,
+ 0, glFormat(), glType(), NULL);
+ CHECK_GL_ERROR();
+}
+
+void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
+ const void* buf, int pitch) {
+ ENTER("updateBuffer(%u, %u, %u, %u, %p, %d)", x, y, w, h, buf, pitch);
+ glBindTexture(GL_TEXTURE_2D, _texture_name);
+
+ setDirtyRect(Common::Rect(x, y, x+w, y+h));
+
+ if (static_cast<int>(w) * bytesPerPixel() == pitch) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
+ glFormat(), glType(), buf);
+ } else {
+ // GLES removed the ability to specify pitch, so we
+ // have to do this row by row.
+ const byte* src = static_cast<const byte*>(buf);
+ do {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y,
+ w, 1, glFormat(), glType(), src);
+ ++y;
+ src += pitch;
+ } while (--h);
+ }
+}
+
+void GLESTexture::fillBuffer(byte x) {
+ byte tmpbuf[_surface.h * _surface.w * bytesPerPixel()];
+ memset(tmpbuf, 0, _surface.h * _surface.w * bytesPerPixel());
+ glBindTexture(GL_TEXTURE_2D, _texture_name);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _surface.w, _surface.h,
+ glFormat(), glType(), tmpbuf);
+ setDirty();
+}
+
+void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
+ glBindTexture(GL_TEXTURE_2D, _texture_name);
+
+#ifdef GL_OES_draw_texture
+ // Great extension, but only works under specific conditions.
+ // Still a work-in-progress - disabled for now.
+ if (false && draw_tex_supported && paletteSize() == 0) {
+ //glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ const GLint crop[4] = {0, _surface.h, _surface.w, -_surface.h};
+ glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+ glDrawTexiOES(x, y, 0, w, h);
+ } else
+#endif
+ {
+ const GLfixed tex_width = xdiv(_surface.w, _texture_width);
+ const GLfixed tex_height = xdiv(_surface.h, _texture_height);
+ const GLfixed texcoords[] = {
+ 0, 0,
+ tex_width, 0,
+ 0, tex_height,
+ tex_width, tex_height,
+ };
+ glTexCoordPointer(2, GL_FIXED, 0, texcoords);
+
+ const GLshort vertices[] = {
+ x, y,
+ x+w, y,
+ x, y+h,
+ x+w, y+h,
+ };
+ glVertexPointer(2, GL_SHORT, 0, vertices);
+
+ assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords));
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices)/2);
+ }
+
+ _all_dirty = false;
+ _dirty_rect = Common::Rect();
+}
+
+GLESPaletteTexture::GLESPaletteTexture() :
+ GLESTexture(),
+ _texture(NULL)
+{
+}
+
+GLESPaletteTexture::~GLESPaletteTexture() {
+ delete[] _texture;
+}
+
+void GLESPaletteTexture::allocBuffer(GLuint w, GLuint h) {
+ CHECK_GL_ERROR();
+ int bpp = bytesPerPixel();
+ _surface.w = w;
+ _surface.h = h;
+ _surface.bytesPerPixel = bpp;
+
+ if (w <= _texture_width && h <= _texture_height)
+ // Already allocated a sufficiently large buffer
+ return;
+
+ if (npot_supported) {
+ _texture_width = _surface.w;
+ _texture_height = _surface.h;
+ } else {
+ _texture_width = nextHigher2(_surface.w);
+ _texture_height = nextHigher2(_surface.h);
+ }
+ _surface.pitch = _texture_width * bpp;
+
+ // Texture gets uploaded later (from drawTexture())
+
+ byte* new_buffer = new byte[paletteSize() +
+ _texture_width * _texture_height * bytesPerPixel()];
+ if (_texture) {
+ memcpy(new_buffer, _texture, paletteSize()); // preserve palette
+ delete[] _texture;
+ }
+ _texture = new_buffer;
+ _surface.pixels = _texture + paletteSize();
+}
+
+void GLESPaletteTexture::fillBuffer(byte x) {
+ assert(_surface.pixels);
+ memset(_surface.pixels, x, _surface.pitch * _surface.h);
+ setDirty();
+}
+
+void GLESPaletteTexture::updateBuffer(GLuint x, GLuint y,
+ GLuint w, GLuint h,
+ const void* buf, int pitch) {
+ _all_dirty = true;
+
+ const byte* src = static_cast<const byte*>(buf);
+ byte* dst = static_cast<byte*>(_surface.getBasePtr(x, y));
+ do {
+ memcpy(dst, src, w * bytesPerPixel());
+ dst += _surface.pitch;
+ src += pitch;
+ } while (--h);
+}
+
+void GLESPaletteTexture::uploadTexture() const {
+ const size_t texture_size =
+ paletteSize() + _texture_width * _texture_height * bytesPerPixel();
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, glType(),
+ _texture_width, _texture_height,
+ 0, texture_size, _texture);
+ CHECK_GL_ERROR();
+}
+
+void GLESPaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
+ if (_all_dirty) {
+ glBindTexture(GL_TEXTURE_2D, _texture_name);
+ CHECK_GL_ERROR();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ CHECK_GL_ERROR();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ CHECK_GL_ERROR();
+ uploadTexture();
+ _all_dirty = false;
+ }
+
+ GLESTexture::drawTexture(x, y, w, h);
+}
diff --git a/backends/platform/android/video.h b/backends/platform/android/video.h
new file mode 100644
index 0000000000..ee707e4cb5
--- /dev/null
+++ b/backends/platform/android/video.h
@@ -0,0 +1,140 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/trunk/backends/platform/null/null.cpp $
+ * $Id: null.cpp 34912 2008-11-06 15:02:50Z fingolfin $
+ *
+ */
+
+#if defined(ANDROID)
+
+#include <GLES/gl.h>
+
+#include "graphics/surface.h"
+
+#include "common/rect.h"
+#include "common/array.h"
+
+class GLESTexture {
+public:
+ static void initGLExtensions();
+
+ GLESTexture();
+ virtual ~GLESTexture();
+ virtual void reinitGL();
+ virtual void allocBuffer(GLuint width, GLuint height);
+ const Graphics::Surface* surface_const() const { return &_surface; }
+ GLuint width() const { return _surface.w; }
+ GLuint height() const { return _surface.h; }
+ GLuint texture_name() const { return _texture_name; }
+ bool dirty() const { return _all_dirty || !_dirty_rect.isEmpty(); }
+ virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
+ const void* buf, int pitch);
+ virtual void fillBuffer(byte x);
+ virtual void drawTexture() {
+ drawTexture(0, 0, _surface.w, _surface.h);
+ }
+ virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
+
+protected:
+ virtual byte bytesPerPixel() const = 0;
+ virtual GLenum glFormat() const = 0;
+ virtual GLenum glType() const = 0;
+ virtual size_t paletteSize() const { return 0; };
+ void setDirty() {
+ _all_dirty = true;
+ _dirty_rect = Common::Rect();
+ }
+ void setDirtyRect(const Common::Rect& r) {
+ if (!_all_dirty) {
+ if (_dirty_rect.isEmpty())
+ _dirty_rect = r;
+ else
+ _dirty_rect.extend(r);
+ }
+ }
+ GLuint _texture_name;
+ Graphics::Surface _surface;
+ GLuint _texture_width;
+ GLuint _texture_height;
+ bool _all_dirty;
+ Common::Rect _dirty_rect; // Covers dirty area
+};
+
+// RGBA4444 texture
+class GLES4444Texture : public GLESTexture {
+protected:
+ virtual byte bytesPerPixel() const { return 2; }
+ virtual GLenum glFormat() const { return GL_RGBA; }
+ virtual GLenum glType() const { return GL_UNSIGNED_SHORT_4_4_4_4; }
+};
+
+// RGB565 texture
+class GLES565Texture : public GLESTexture {
+protected:
+ virtual byte bytesPerPixel() const { return 2; }
+ virtual GLenum glFormat() const { return GL_RGB; }
+ virtual GLenum glType() const { return GL_UNSIGNED_SHORT_5_6_5; }
+};
+
+// RGB888 256-entry paletted texture
+class GLESPaletteTexture : public GLESTexture {
+public:
+ GLESPaletteTexture();
+ virtual ~GLESPaletteTexture();
+ virtual void allocBuffer(GLuint width, GLuint height);
+ virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
+ const void* buf, int pitch);
+ Graphics::Surface* surface() {
+ setDirty();
+ return &_surface;
+ }
+ void* pixels() {
+ setDirty();
+ return _surface.pixels;
+ }
+ const byte* palette_const() const { return _texture; };
+ byte* palette() {
+ setDirty();
+ return _texture;
+ };
+ virtual void drawTexture() {
+ drawTexture(0, 0, _surface.w, _surface.h);
+ }
+ virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
+ virtual void fillBuffer(byte x);
+protected:
+ virtual byte bytesPerPixel() const { return 1; }
+ virtual GLenum glFormat() const { return GL_RGB; }
+ virtual GLenum glType() const { return GL_PALETTE8_RGB8_OES; }
+ virtual size_t paletteSize() const { return 256 * 3; };
+ virtual void uploadTexture() const;
+ byte* _texture;
+};
+
+// RGBA8888 256-entry paletted texture
+class GLESPaletteATexture : public GLESPaletteTexture {
+protected:
+ virtual GLenum glFormat() const { return GL_RGBA; }
+ virtual GLenum glType() const { return GL_PALETTE8_RGBA8_OES; }
+ virtual size_t paletteSize() const { return 256 * 4; };
+};
+
+#endif
diff --git a/backends/platform/dc/Makefile b/backends/platform/dc/Makefile
index 2dcf9b7a7c..4494e8da78 100644
--- a/backends/platform/dc/Makefile
+++ b/backends/platform/dc/Makefile
@@ -69,6 +69,8 @@ OBJS := dcmain.o time.o display.o audio.o input.o selector.o icon.o \
MODULE_DIRS += ./
+BACKEND := dc
+
include $(srcdir)/Makefile.common
scummvm.bin : scummvm.elf
diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h
index 8a122ebb27..057ab283cf 100644
--- a/backends/platform/dc/dc.h
+++ b/backends/platform/dc/dc.h
@@ -86,7 +86,7 @@ class OSystem_Dreamcast : private DCHardware, public BaseBackend, public Filesys
Graphics::PixelFormat getScreenFormat() const;
// Returns a list of all pixel formats supported by the backend.
- Common::List<Graphics::PixelFormat> getSupportedFormats();
+ Common::List<Graphics::PixelFormat> getSupportedFormats() const;
// Set the size of the video bitmap.
// Typically, 320x200
@@ -233,6 +233,9 @@ class OSystem_Dreamcast : private DCHardware, public BaseBackend, public Filesys
Common::SaveFileManager *createSavefileManager();
+
+ Common::SeekableReadStream *createConfigReadStream();
+ Common::WriteStream *createConfigWriteStream();
};
diff --git a/backends/platform/dc/dcmain.cpp b/backends/platform/dc/dcmain.cpp
index 5a9286093f..5fde919650 100644
--- a/backends/platform/dc/dcmain.cpp
+++ b/backends/platform/dc/dcmain.cpp
@@ -31,6 +31,7 @@
#include "icon.h"
#include "DCLauncherDialog.h"
#include <common/config-manager.h>
+#include <common/stream.h>
#include "backends/plugins/dc/dc-provider.h"
#include "sound/mixer_intern.h"
@@ -206,6 +207,16 @@ void OSystem_Dreamcast::getTimeAndDate(TimeDate &td) const {
td.tm_year = t.tm_year;
}
+Common::SeekableReadStream *OSystem_Dreamcast::createConfigReadStream() {
+ Common::FSNode file("/scummvm.ini");
+ Common::SeekableReadStream *s = file.createReadStream();
+ return s? s : new Common::MemoryReadStream((const byte *)"", 0);
+}
+
+Common::WriteStream *OSystem_Dreamcast::createConfigWriteStream() {
+ return 0;
+}
+
void DCHardware::dc_init_hardware()
{
#ifndef NOSERIAL
diff --git a/backends/platform/dc/display.cpp b/backends/platform/dc/display.cpp
index 35fc94b3cc..53dbff333d 100644
--- a/backends/platform/dc/display.cpp
+++ b/backends/platform/dc/display.cpp
@@ -198,7 +198,7 @@ Graphics::PixelFormat OSystem_Dreamcast::getScreenFormat() const
return screenFormats[_screenFormat];
}
-Common::List<Graphics::PixelFormat> OSystem_Dreamcast::getSupportedFormats()
+Common::List<Graphics::PixelFormat> OSystem_Dreamcast::getSupportedFormats() const
{
Common::List<Graphics::PixelFormat> list;
unsigned i;
diff --git a/backends/platform/dc/module.mk b/backends/platform/dc/module.mk
index eecb91909c..c52ca1a474 100644
--- a/backends/platform/dc/module.mk
+++ b/backends/platform/dc/module.mk
@@ -3,8 +3,7 @@ MODULE := backends/platform/dc
MODULE_OBJS := dcmain.o time.o display.o audio.o input.o selector.o icon.o \
label.o vmsave.o softkbd.o dcloader.o cache.o dc-fs.o
-MODULE_DIRS += \
- backends/platform/dc/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp
index 0d8e0a0188..0d9b931d2c 100644
--- a/backends/platform/dc/selector.cpp
+++ b/backends/platform/dc/selector.cpp
@@ -30,6 +30,7 @@
#include <base/plugins.h>
#include <common/fs.h>
#include <common/events.h>
+#include <common/config-manager.h>
#include "dc.h"
#include "icon.h"
#include "label.h"
@@ -200,12 +201,43 @@ static bool uniqueGame(const char *base, const char *dir,
return true;
}
-static int findGames(Game *games, int max)
+static int findGames(Game *games, int max, bool use_ini)
{
Dir *dirs = new Dir[MAX_DIR];
- int curr_game = 0, curr_dir = 0, num_dirs = 1;
- dirs[0].node = Common::FSNode("");
- while (curr_game < max && curr_dir < num_dirs) {
+ int curr_game = 0, curr_dir = 0, num_dirs = 0;
+
+ if (use_ini) {
+ ConfMan.loadDefaultConfigFile();
+ Common::ConfigManager::DomainMap &game_domains = ConfMan.getGameDomains();
+ for(Common::ConfigManager::DomainMap::const_iterator i =
+ game_domains.begin(); curr_game < max && i != game_domains.end(); i++) {
+ Common::String path = (*i)._value["path"];
+ if (path.size() && path.lastChar() != '/')
+ path += "/";
+ int j;
+ for (j=0; j<num_dirs; j++)
+ if (path.equals(dirs[j].node.getPath()))
+ break;
+ if (j >= num_dirs) {
+ if (num_dirs >= MAX_DIR)
+ continue;
+ dirs[j = num_dirs++].node = Common::FSNode(path);
+ }
+ if (curr_game < max) {
+ strcpy(games[curr_game].filename_base, (*i)._key.c_str());
+ strncpy(games[curr_game].dir, dirs[j].node.getPath().c_str(), 256);
+ games[curr_game].dir[255] = '\0';
+ games[curr_game].language = Common::UNK_LANG;
+ games[curr_game].platform = Common::kPlatformUnknown;
+ strcpy(games[curr_game].text, (*i)._value["description"].c_str());
+ curr_game++;
+ }
+ }
+ } else {
+ dirs[num_dirs++].node = Common::FSNode("");
+ }
+
+ while ((curr_game < max || use_ini) && 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';
@@ -214,44 +246,46 @@ static int findGames(Game *games, int max)
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(),
- "install")) {
+ if (!use_ini && num_dirs < MAX_DIR &&
+ strcasecmp(entry->getDisplayName().c_str(), "install")) {
dirs[num_dirs].node = *entry;
num_dirs++;
}
} else
if (isIcon(*entry))
strcpy(dirs[curr_dir-1].deficon, entry->getDisplayName().c_str());
- else
+ else if(!use_ini)
files.push_back(*entry);
}
- GameList candidates = EngineMan.detectGames(files);
-
- for (GameList::const_iterator ge = candidates.begin();
- ge != candidates.end(); ++ge)
- if (curr_game < max) {
- strcpy(games[curr_game].filename_base, ge->gameid().c_str());
- strcpy(games[curr_game].dir, dirs[curr_dir-1].name);
- games[curr_game].language = ge->language();
- games[curr_game].platform = ge->platform();
- if (uniqueGame(games[curr_game].filename_base,
- games[curr_game].dir,
- games[curr_game].language,
- games[curr_game].platform, games, curr_game)) {
-
- strcpy(games[curr_game].text, ge->description().c_str());
+ if (!use_ini) {
+ GameList candidates = EngineMan.detectGames(files);
+
+ for (GameList::const_iterator ge = candidates.begin();
+ ge != candidates.end(); ++ge)
+ if (curr_game < max) {
+ strcpy(games[curr_game].filename_base, ge->gameid().c_str());
+ strcpy(games[curr_game].dir, dirs[curr_dir-1].name);
+ games[curr_game].language = ge->language();
+ games[curr_game].platform = ge->platform();
+ if (uniqueGame(games[curr_game].filename_base,
+ games[curr_game].dir,
+ games[curr_game].language,
+ games[curr_game].platform, games, curr_game)) {
+
+ strcpy(games[curr_game].text, ge->description().c_str());
#if 0
- printf("Registered game <%s> (l:%d p:%d) in <%s> <%s> because of <%s> <*>\n",
- games[curr_game].text,
- (int)games[curr_game].language,
- (int)games[curr_game].platform,
- games[curr_game].dir, games[curr_game].filename_base,
- dirs[curr_dir-1].name);
+ printf("Registered game <%s> (l:%d p:%d) in <%s> <%s> because of <%s> <*>\n",
+ games[curr_game].text,
+ (int)games[curr_game].language,
+ (int)games[curr_game].platform,
+ games[curr_game].dir, games[curr_game].filename_base,
+ dirs[curr_dir-1].name);
#endif
- curr_game++;
+ curr_game++;
+ }
}
- }
+ }
}
for (int i=0; i<curr_game; i++)
@@ -426,7 +460,9 @@ bool selectGame(char *&ret, char *&dir_ret, Common::Language &lang_ret, Common::
void *mark = ta_txmark();
for (;;) {
- num_games = findGames(games, MAX_GAMES);
+ num_games = findGames(games, MAX_GAMES, true);
+ if (!num_games)
+ num_games = findGames(games, MAX_GAMES, false);
for (int i=0; i<num_games; i++) {
games[i].icon.create_texture();
diff --git a/backends/platform/ds/arm7/source/main.cpp b/backends/platform/ds/arm7/source/main.cpp
index c2e949cd90..75f7012ed0 100644
--- a/backends/platform/ds/arm7/source/main.cpp
+++ b/backends/platform/ds/arm7/source/main.cpp
@@ -8,17 +8,19 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
- * $Header: /cvsroot/scummvm/scummvm/backends/fs/fs.cpp,v 1.3.2.1 2004/12/18 02:33:52 fingolfin Exp $
*/
//////////////////////////////////////////////////////////////////////
@@ -58,10 +60,10 @@ s32 TOUCH_HEIGHT = TOUCH_CAL_Y2 - TOUCH_CAL_Y1;
s32 TOUCH_OFFSET_X = ( ((SCREEN_WIDTH -60) * TOUCH_CAL_X1) / TOUCH_WIDTH ) - 28;
s32 TOUCH_OFFSET_Y = ( ((SCREEN_HEIGHT-60) * TOUCH_CAL_Y1) / TOUCH_HEIGHT ) - 28;
-vu8* soundData;
+vu8 *soundData;
-vu8* soundBuffer;
-vu8* arm9Buffer;
+vu8 *soundBuffer;
+vu8 *arm9Buffer;
bool soundFilled[4];
int playingSection;
@@ -81,7 +83,7 @@ int adpcmBufferNum = 0;
//////////////////////////////////////////////////////////////////////
/*
-void startSound(int sampleRate, const void* data, uint32 bytes, u8 channel=0, u8 vol=0x7F, u8 pan=63, u8 format=0) {
+void startSound(int sampleRate, const void *data, uint32 bytes, u8 channel=0, u8 vol=0x7F, u8 pan=63, u8 format=0) {
SCHANNEL_TIMER(channel) = SOUND_FREQ(sampleRate);
SCHANNEL_SOURCE(channel) = (uint32)data;
SCHANNEL_LENGTH(channel) = bytes;
@@ -106,7 +108,7 @@ s8 getFreeSoundChannel() {
return -1;
}
-void startSound(int sampleRate, const void* data, uint32 bytes, u8 channel=0, u8 vol=0x7F, u8 pan=63, u8 format=0) {
+void startSound(int sampleRate, const void *data, uint32 bytes, u8 channel=0, u8 vol=0x7F, u8 pan=63, u8 format=0) {
// REG_IME = IME_DISABLE;
channel = getFreeSoundChannel();
@@ -177,7 +179,7 @@ void startSound(int sampleRate, const void* data, uint32 bytes, u8 channel=0, u8
- soundData = (vu8* ) data;
+ soundData = (vu8 *) data;
SCHANNEL_CR(channel) = flags;
SCHANNEL_CR(channel + 2) = flags;
@@ -386,7 +388,7 @@ void InterruptTimer1() {
//if ((!soundFilled[r]) && (!IPC->fillNeeded[playingSection])) {
memcpy((void *) (soundBuffer + (r * 1024)), (void *) (arm9Buffer + (r * 1024)), 1024);
- vu16* p = (vu16 *) (soundBuffer);
+ vu16 *p = (vu16 *) (soundBuffer);
//for (int t = 0; t < 2048; t++) {
// *(p + t) = (t & 1)? 0xF000: 0x0000;
//}
diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile
index c43c28c223..c9a665c442 100644
--- a/backends/platform/ds/arm9/makefile
+++ b/backends/platform/ds/arm9/makefile
@@ -111,7 +111,7 @@ USE_ARM_COSTUME_ASM = 1
#WRAP_MALLOC = 1
ifdef DS_BUILD_A
- DEFINES += -DDS_SCUMM_BUILD -DDS_BUILD_A -DUSE_ARM_GFX_ASM -DUSE_ARM_COSTUME_ASM
+ DEFINES = -DDS_BUILD_A -DUSE_ARM_GFX_ASM -DUSE_ARM_COSTUME_ASM
LOGO = logoa.bmp
ENABLE_SCUMM = $(ENABLED)
USE_ARM_GFX_ASM = 1
@@ -119,7 +119,7 @@ ifdef DS_BUILD_A
endif
ifdef DS_BUILD_B
- DEFINES += -DDS_NON_SCUMM_BUILD -DDS_BUILD_B
+ DEFINES = -DDS_BUILD_B
LOGO = logob.bmp
ENABLE_SKY = $(ENABLED)
ENABLE_QUEEN = $(ENABLED)
@@ -127,14 +127,14 @@ ifdef DS_BUILD_B
endif
ifdef DS_BUILD_C
- DEFINES += -DDS_NON_SCUMM_BUILD -DDS_BUILD_C
+ DEFINES = -DDS_BUILD_C
LOGO = logoc.bmp
ENABLE_AGOS = $(ENABLED)
BUILD=scummvm-C
endif
ifdef DS_BUILD_D
- DEFINES += -DDS_NON_SCUMM_BUILD -DDS_BUILD_D
+ DEFINES = -DDS_BUILD_D
LOGO = logod.bmp
ENABLE_GOB = $(ENABLED)
ENABLE_CINE = $(ENABLED)
@@ -143,42 +143,42 @@ ifdef DS_BUILD_D
endif
ifdef DS_BUILD_E
- DEFINES += -DDS_NON_SCUMM_BUILD -DDS_BUILD_E
+ DEFINES = -DDS_BUILD_E
LOGO = logoe.bmp
ENABLE_SAGA = $(ENABLED)
BUILD=scummvm-E
endif
ifdef DS_BUILD_F
- DEFINES += -DDS_NON_SCUMM_BUILD -DDS_BUILD_F
+ DEFINES = -DDS_BUILD_F
LOGO = logof.bmp
ENABLE_KYRA = $(ENABLED)
BUILD=scummvm-F
endif
ifdef DS_BUILD_G
- DEFINES += -DDS_NON_SCUMM_BUILD -DDS_BUILD_G
+ DEFINES = -DDS_BUILD_G
LOGO = logog.bmp
ENABLE_LURE = $(ENABLED)
BUILD=scummvm-G
endif
ifdef DS_BUILD_H
- DEFINES += -DDS_NON_SCUMM_BUILD -DDS_BUILD_H
+ DEFINES = -DDS_BUILD_H
LOGO = logoh.bmp
ENABLE_PARALLACTION = $(ENABLED)
BUILD=scummvm-H
endif
ifdef DS_BUILD_I
- DEFINES += -DDS_NON_SCUMM_BUILD -DDS_BUILD_I
+ DEFINES = -DDS_BUILD_I
LOGO = logoi.bmp
ENABLE_MADE = $(ENABLED)
BUILD=scummvm-I
endif
ifdef DS_BUILD_K
- DEFINES += -DDS_NON_SCUMM_BUILD -DDS_BUILD_K
+ DEFINES = -DDS_BUILD_K
LOGO = logok.bmp
ENABLE_CRUISE = $(ENABLED)
BUILD=scummvm-K
@@ -186,14 +186,14 @@ endif
#ifdef DS_BUILD_L
-# DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_L
+# DEFINES = -DDS_BUILD_L
# LOGO = logog.bmp
# ENABLE_DRASCULA = $(ENABLED)
# BUILD=scummvm-K
#endif
#ifdef DS_BUILD_M
-# DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_M
+# DEFINES = -DDS_BUILD_M
# LOGO = logog.bmp
# ENABLE_TUCKER = $(ENABLED)
# BUILD=scummvm-K
@@ -206,7 +206,6 @@ CXX = arm-eabi-g++
LD = arm-eabi-g++
CFLAGS = -Wno-multichar -Wall\
- -Wno-multichar -mcpu=arm9tdmi -mtune=arm9tdmi \
-mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\
-mthumb-interwork -DUSE_ARM_COSTUME_ASM=1 -DDISABLE_SID
@@ -252,9 +251,11 @@ ifdef WRAP_MALLOC
DEFINES += -DWRAP_MALLOC
endif
+BACKEND := ds
+
INCLUDES= -I$(portdir) -I$(srcdir) -I$(srcdir)/engines \
-I$(portdir)/data -I$(portdir)/../commoninclude \
- -I$(portdir)/source -I$(portdir)/source/mad -I$(portdir)/source/libcartreset \
+ -I$(portdir)/source -I$(portdir)/source/mad \
-I$(libndsdir)/include -include $(srcdir)/common/scummsys.h
LIBS = -lm -L$(libndsdir)/lib -L$(portdir)/lib -lnds9
@@ -271,12 +272,13 @@ PRE_OBJS_FLAGS = -Wl,--whole-archive
POST_OBJS_FLAGS = -Wl,--no-whole-archive
endif
-#-Lscumm -lscumm -Lbase -lbase -Lcommon -lcommon -Lgraphics -lgraphics -Lgui -lgui -Lsound -lsound
EXECUTABLE = scummvm.elf
+
PLUGIN_PREFIX =
PLUGIN_SUFFIX = .plg
PLUGIN_EXTRA_DEPS = $(srcdir)/backends/plugins/ds/plugin.ld $(srcdir)/backends/plugins/plugin.syms $(EXECUTABLE)
PLUGIN_LDFLAGS += -nostartfiles -Wl,-q,--target1-abs,--just-symbols,$(EXECUTABLE),-T$(srcdir)/backends/plugins/ds/plugin.ld,--retain-symbols-file,$(srcdir)/backends/plugins/plugin.syms -lstdc++ -lc -mthumb-interwork -mno-fpu#-Wl,--gc-sections -mno-crt0 $(DEVKITPRO)/devkitARM/arm-eabi/lib/ds_arm9_crt0.o
+
MKDIR = mkdir -p
RM = rm -f
RM_REC = rm -rf
@@ -286,72 +288,77 @@ OBJCOPY = arm-eabi-objcopy
AS = arm-eabi-as
HAVE_GCC3 = true
-PORT_OBJS := $(portdir)/source/blitters_arm.o $(portdir)/source/cdaudio.o $(portdir)/source/dsmain.o \
- $(portdir)/../../../fs/ds/ds-fs.o $(portdir)/source/gbampsave.o $(portdir)/source/scummhelp.o\
- $(portdir)/source/osystem_ds.o $(portdir)/source/ramsave.o\
- $(portdir)/source/touchkeyboard.o $(portdir)/source/zipreader.o\
- $(portdir)/source/dsoptions.o $(portdir)/source/keys.o $(portdir)/source/wordcompletion.o\
- $(portdir)/source/interrupt.o
+PORT_OBJS := \
+ $(portdir)/source/blitters_arm.o \
+ $(portdir)/source/cdaudio.o \
+ $(portdir)/source/dsmain.o \
+ $(portdir)/source/gbampsave.o \
+ $(portdir)/source/scummhelp.o \
+ $(portdir)/source/osystem_ds.o \
+ $(portdir)/source/touchkeyboard.o \
+ $(portdir)/source/zipreader.o \
+ $(portdir)/source/dsoptions.o \
+ $(portdir)/source/keys.o \
+ $(portdir)/source/wordcompletion.o \
+ $(portdir)/source/interrupt.o
ifdef USE_PROFILER
PORT_OBJS += $(portdir)/source/profiler/cyg-profile.o
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
+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
+
+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 \
+ $(portdir)/source/fat/io_mpcf.o \
+ $(portdir)/source/fat/io_sccf.o \
+ $(portdir)/source/fat/io_m3sd.o \
+ $(portdir)/source/fat/io_nmmc.o \
+ $(portdir)/source/fat/io_scsd.o \
+ $(portdir)/source/fat/io_scsd_asm.o \
+ $(portdir)/source/fat/io_njsd.o \
+ $(portdir)/source/fat/io_mmcf.o \
+ $(portdir)/source/fat/io_sd_common.o \
+ $(portdir)/source/fat/io_m3_common.o \
+ $(portdir)/source/fat/io_dldi.o \
+ $(portdir)/source/fat/m3sd.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\
- $(portdir)/source/fat/io_mpcf.o $(portdir)/source/fat/io_sccf.o\
- $(portdir)/source/fat/io_m3sd.o\
- $(portdir)/source/fat/io_nmmc.o $(portdir)/source/fat/io_scsd.o \
- $(portdir)/source/fat/io_scsd_asm.o \
- $(portdir)/source/fat/io_njsd.o \
- $(portdir)/source/fat/io_mmcf.o \
- $(portdir)/source/fat/io_sd_common.o \
- $(portdir)/source/fat/io_m3_common.o \
- $(portdir)/source/fat/io_dldi.o \
- $(portdir)/source/fat/m3sd.o
-
-
-# $(portdir)/source/fat/io_cf_common.o $(portdir)/source/fat/io_m3_common.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
# 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 mame.cpp rate.cpp isomap.cpp image.cpp gfx.cpp sprite.cpp actor_path.cpp actor_walk.cpp script.cpp
+OPTLIST := actor.cpp dsmain.cpp osystem_ds.cpp blitters.cpp mame.cpp rate.cpp isomap.cpp image.cpp gfx.cpp sprite.cpp actor_path.cpp actor_walk.cpp script.cpp
#OPTLIST :=
# Compiler options for files which should be optimised for speed
ifdef DS_BUILD_E
-# Another attempt to save some RAM in ITE
-OPT_SPEED := -O3 -mthumb
+ # Another attempt to save some RAM in ITE
+ OPT_SPEED := -O3 -mthumb
else
-#OPT_SPEED := -O3
-
-OPT_SPEED := -Os -mthumb
-
+ OPT_SPEED := -O3
endif
# Compiler options for files which should be optimised for space
OPT_SIZE := -Os -mthumb
-#-mthumb -fno-gcse -fno-schedule-insns2
-
+OBJS := $(DATA_OBJS) $(PORT_OBJS) $(FAT_OBJS)
-OBJS := $(DATA_OBJS) $(LIBCARTRESET_OBJS) $(PORT_OBJS) $(COMPRESSOR_OBJS) $(FAT_OBJS)
MODULE_DIRS += .
+#ndsall: plugins
+# make -f makefile scummvm.nds
+
ndsall: plugins
- make -f makefile scummvm.nds
+ make -f makefile scummvm.nds scummvm.ds.gba
include $(srcdir)/Makefile.common
@@ -360,26 +367,13 @@ semiclean:
clean:
$(RM) $(OBJS) $(EXECUTABLE)
- rm -rf gui engines sound common plugins base backends graphics scummvm.nds scummvm.elf scummvm-stripped.elf scummvm.ds.gba *.h
-
-plugin_dist :
- for p in $(PLUGINS); do \
- arm-elf-strip -g -o "`basename \"$$p\" | LC_CTYPE=C tr '[:lower:]' '[:upper:]'`" "$$p"; \
- done
+ rm -rf *.h engines plugins scummvm.nds scummvm.ds.gba
dist : SCUMMVM.BIN plugins plugin_dist
#---------------------------------------------------------------------------------
# canned command sequence for binary data
#---------------------------------------------------------------------------------
-#define bin2o
-# bin2s $< | $(AS) -mthumb -mthumb-interwork -o $(@)
-# echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_raw_end[];" > `(echo $(<F) | tr . _)`.h
-# echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_raw[];" >> `(echo $(<F) | tr . _)`.h
-# echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_raw_size";" >> `(echo $(<F) | tr . _)`.h
-#endef
-
-
define bin2o
bin2s $< | $(AS) -mthumb -mthumb-interwork -o $(@)
echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(<F) | tr . _)`.h
@@ -388,34 +382,10 @@ define bin2o
endef
-#define bin2o
-# @echo $(*)
-# cp $(<) $(*).tmp
-# $(OBJCOPY) -I binary -O elf32-littlearm -B arm \
-# --rename-section .data=.rodata \
-# --redefine-sym _binary_$(subst .,_,$(subst /,_,$(*)))_tmp_start=$(notdir $*)\
-# --redefine-sym _binary_$(subst .,_,$(subst /,_,$(*)))_tmp_end=$(notdir $*)_end\
-# $(*).tmp $(@)
-# echo "extern const u8" $(notdir $*)"[] __attribute__ ((aligned (4)));" > $(*).h
-# echo "extern const u32" $(notdir $(*))_size[]";" >> $(*).h
-#
-# echo $(*).h
-# rm $(*).tmp
-#endef
-
-
##############
# Replacement rule for the one in makefile.common
##############
%.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
@@ -423,12 +393,6 @@ endef
#---------------------------------------------------------------------------------
#---------------------------------------------------------------------------------
-%.o : %.pcx
-#---------------------------------------------------------------------------------
- @echo $(notdir $<)
- @$(bin2o)
-
-#---------------------------------------------------------------------------------
%.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@@ -447,31 +411,17 @@ endef
@$(bin2o)
#---------------------------------------------------------------------------------
-%.o : %.map
-#---------------------------------------------------------------------------------
- @echo $(notdir $<)
- @$(bin2o)
-
-#---------------------------------------------------------------------------------
-%.o : %.mdl
-#---------------------------------------------------------------------------------
- @echo $(notdir $<)
- @$(bin2o)
-
-#---------------------------------------------------------------------------------
%.nds: %.bin
- @echo ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../$(LOGO) "$(shell basename $@);ScummVM $(VERSION);DS Port"
- ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../$(LOGO) "$(shell basename $@);ScummVM $(VERSION);DS Port"
- dsbuild $@ -l ndsloader.bin
+ ndstool -c $@ -9 $< $(ARM7BIN) -b ../$(LOGO) "$(@F);ScummVM $(VERSION);DS Port"
- padbin 16 $(basename $@).ds.gba
+%.ds.gba: %.nds
+ dsbuild $< -o $@ -l $(portdir)/ndsloader.bin
+ padbin 16 $@
#---------------------------------------------------------------------------------
-# 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
+ $(OBJCOPY) -S -O binary $< $@
#%.o: %.s
# $(MKDIR) $(*D)/$(DEPDIR)
diff --git a/backends/platform/ds/arm9/source/blitters.cpp b/backends/platform/ds/arm9/source/blitters.cpp
index 07c6b3fee1..5d29672ef6 100644
--- a/backends/platform/ds/arm9/source/blitters.cpp
+++ b/backends/platform/ds/arm9/source/blitters.cpp
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -27,13 +30,13 @@
namespace DS {
-void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst,
+void asmDrawStripToScreen(int height, int width, byte const *text, byte const *src, byte *dst,
int vsPitch, int vmScreenWidth, int textSurfacePitch) {
-
- if (height <= 0) height = 1;
- if (width < 4) return;
-
+ if (height <= 0)
+ height = 1;
+ if (width < 4)
+ return;
width &= ~4;
// src = (const byte *) (((int) (src)) & (~4));
@@ -111,7 +114,7 @@ void asmDrawStripToScreen(int height, int width, byte const* text, byte const* s
-void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height) {
+void asmCopy8Col(byte *dst, int dstPitch, const byte *src, int height) {
asm("ands r0, %3, #1\n"
"addne %3, %3, #1\n"
"bne roll2\n"
@@ -141,22 +144,19 @@ void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height) {
static bool isDivBy5Ready = false;
static u32 DIV_BY_5[160];
-void ComputeDivBy5TableIFN()
-{
+void ComputeDivBy5TableIFN() {
if (isDivBy5Ready)
return;
isDivBy5Ready = true;
- for (int i=0; i<160; ++i)
- {
+ for (int i = 0; i < 160; ++i) {
DIV_BY_5[i] = (2*i+5)/10;
}
}
#ifdef PERFECT_5_TO_4_RESCALING
static inline void RescaleBlock_5x1555_To_4x1555( u16 s0, u16 s1, u16 s2, u16 s3, u16 s4,
- u16* dest)
-{
+ u16 *dest) {
u32 bs0 = s0 & 0x1F;
u32 bs1 = s1 & 0x1F;
u32 bs2 = s2 & 0x1F;
@@ -230,8 +230,7 @@ static inline void RescaleBlock_5x1555_To_4x1555( u16 s0, u16 s1, u16 s2, u16 s3
}
#else
static inline void RescaleBlock_5x1555_To_4x1555( u16 s0, u16 s1, u16 s2, u16 s3, u16 s4,
- u16* dest)
-{
+ u16 *dest) {
static const u32 MASK = 0x03E07C1F;
u32 argbargbs0 = u32(s0) | (u32(s0) << 16);
@@ -279,8 +278,7 @@ static inline void RescaleBlock_5x1555_To_4x1555( u16 s0, u16 s1, u16 s2, u16 s3
#endif
static inline void RescaleBlock_5x8888_To_4x1555( u32 s0, u32 s1, u32 s2, u32 s3, u32 s4,
- u16* dest)
-{
+ u16 *dest) {
u32 d0 = 4*s0 + s1;
u32 d1 = 2*s1 + s1 + 2*s2;
@@ -317,12 +315,10 @@ static inline void RescaleBlock_5x8888_To_4x1555( u32 s0, u32 s1, u32 s2, u32 s3
// Can't work in place
#ifdef PERFECT_5_TO_4_RESCALING
-static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16* dest, const u8* src, const u32* palette)
-{
+static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16 *dest, const u8 *src, const u32 *palette) {
ComputeDivBy5TableIFN();
- for (size_t i=0; i<64; ++i)
- {
+ for (size_t i = 0; i < 64; ++i) {
u32 s0 = palette[src[5*i+0]];
u32 s1 = palette[src[5*i+1]];
u32 s2 = palette[src[5*i+2]];
@@ -333,10 +329,8 @@ static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16* dest, const
}
}
#else
-static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16* dest, const u8* src, const u16* palette)
-{
- for (size_t i=0; i<64; ++i)
- {
+static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16 *dest, const u8 *src, const u16 *palette) {
+ for (size_t i = 0; i < 64; ++i) {
u16 s0 = palette[src[5*i+0]];
u16 s1 = palette[src[5*i+1]];
u16 s2 = palette[src[5*i+2]];
@@ -350,12 +344,10 @@ static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16* dest, const
// Can work in place, because it's a contraction
-static inline void Rescale_320x1555Scanline_To_256x1555Scanline(u16* dest, const u16* src)
-{
+static inline void Rescale_320x1555Scanline_To_256x1555Scanline(u16 *dest, const u16 *src) {
ComputeDivBy5TableIFN();
- for (size_t i=0; i<64; ++i)
- {
+ for (size_t i = 0; i < 64; ++i) {
u16 s0 = src[5*i+0];
u16 s1 = src[5*i+1];
u16 s2 = src[5*i+2];
@@ -367,13 +359,11 @@ static inline void Rescale_320x1555Scanline_To_256x1555Scanline(u16* dest, const
}
#ifdef PERFECT_5_TO_4_RESCALING
-void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, int destStride, int srcStride, const u16* palette)
-{
+void Rescale_320x256xPAL8_To_256x256x1555(u16 *dest, const u8 *src, int destStride, int srcStride, const u16 *palette) {
u32 fastRam[768];
// Palette lookup -> 0_888
- for (size_t i=0; i<256; ++i)
- {
+ for (size_t i = 0; i < 256; ++i) {
u32 col = palette[i];
u32 result = col & 0x0000001F;
result |= (col << 3) & 0x00001F00;
@@ -382,31 +372,26 @@ void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, int destStri
fastRam[i] = result;
}
- for (size_t i=0; i<200; ++i)
- {
+ for (size_t i = 0; i < 200; ++i) {
Rescale_320xPAL8Scanline_To_256x1555Scanline(dest + i*destStride, src + i *srcStride, fastRam);
}
}
#else
-void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, int destStride, int srcStride, const u16* palette)
-{
+void Rescale_320x256xPAL8_To_256x256x1555(u16 *dest, const u8 *src, int destStride, int srcStride, const u16 *palette) {
u16 fastRam[256];
- for (size_t i=0; i<128; ++i)
+ for (size_t i = 0; i < 128; ++i)
((u32*)fastRam)[i] = ((const u32*)palette)[i];
- for (size_t i=0; i<200; ++i)
- {
+ for (size_t i = 0; i < 200; ++i) {
Rescale_320xPAL8Scanline_To_256x1555Scanline(dest + i*destStride, src + i *srcStride, fastRam);
}
}
#endif
-void Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStride, int srcStride)
-{
- for (size_t i=0; i<200; ++i)
- {
+void Rescale_320x256x1555_To_256x256x1555(u16 *dest, const u16 *src, int destStride, int srcStride) {
+ for (size_t i = 0; i < 200; ++i) {
Rescale_320x1555Scanline_To_256x1555Scanline(dest + i*destStride, src + i *srcStride);
}
}
-}
+} // End of namespace DS
diff --git a/backends/platform/ds/arm9/source/blitters.h b/backends/platform/ds/arm9/source/blitters.h
index 5f541d1bd6..88506a4405 100644
--- a/backends/platform/ds/arm9/source/blitters.h
+++ b/backends/platform/ds/arm9/source/blitters.h
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -29,23 +32,23 @@
namespace DS {
-void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst,
+void asmDrawStripToScreen(int height, int width, byte const *text, byte const *src, byte *dst,
int vsPitch, int vmScreenWidth, int textSurfacePitch);
-void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height);
-void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, int destStride, int srcStride, const u16* palette);
-void Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStride, int srcStride);
+void asmCopy8Col(byte *dst, int dstPitch, const byte *src, int height);
+void Rescale_320x256xPAL8_To_256x256x1555(u16 *dest, const u8 *src, int destStride, int srcStride, const u16 *palette);
+void Rescale_320x256x1555_To_256x256x1555(u16 *dest, const u16 *src, int destStride, int srcStride);
-}
+} // End of namespace DS
#else
extern "C" {
-void ITCM_CODE asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst,
+void ITCM_CODE asmDrawStripToScreen(int height, int width, byte const *text, byte const *src, byte *dst,
int vsPitch, int vmScreenWidth, int textSurfacePitch);
-void ITCM_CODE asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height);
-void ITCM_CODE Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, int destStride, int srcStride, const u16* palette, u32 numLines);
-void ITCM_CODE Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStride, int srcStride);
+void ITCM_CODE asmCopy8Col(byte *dst, int dstPitch, const byte *src, int height);
+void ITCM_CODE Rescale_320x256xPAL8_To_256x256x1555(u16 *dest, const u8 *src, int destStride, int srcStride, const u16 *palette, u32 numLines);
+void ITCM_CODE Rescale_320x256x1555_To_256x256x1555(u16 *dest, const u16 *src, int destStride, int srcStride);
}
diff --git a/backends/platform/ds/arm9/source/cdaudio.cpp b/backends/platform/ds/arm9/source/cdaudio.cpp
index 7756286117..5860dea4f2 100644
--- a/backends/platform/ds/arm9/source/cdaudio.cpp
+++ b/backends/platform/ds/arm9/source/cdaudio.cpp
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -71,25 +74,25 @@ struct decoderFormat {
unsigned char sample[1024];
} __attribute__ ((packed));
-bool active = false;
-WaveHeader waveHeader;
-Header blockHeader;
-FILE* file;
-int fillPos;
-bool isPlayingFlag = false;
+static bool s_active = false;
+static WaveHeader waveHeader;
+static Header blockHeader;
+static FILE *s_file;
+static int fillPos;
+static bool isPlayingFlag = false;
-s16* audioBuffer;
-u32 sampleNum;
-s16* decompressionBuffer;
-int numLoops;
-int blockCount;
-int dataChunkStart;
-int blocksLeft;
-bool trackStartsAt2 = false;
+static s16 *audioBuffer;
+static u32 sampleNum;
+static s16 *decompressionBuffer;
+static int s_numLoops;
+static int blockCount;
+static int dataChunkStart;
+static int blocksLeft;
+static bool trackStartsAt2 = false;
// These are from Microsoft's document on DVI ADPCM
-const int stepTab[ 89 ] = {
+static const int stepTab[ 89 ] = {
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66,
@@ -103,7 +106,7 @@ const int stepTab[ 89 ] = {
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
32767 };
-const int indexTab[ 16 ] = { -1, -1, -1, -1, 2, 4, 6, 8,
+static const int indexTab[ 16 ] = { -1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8 };
void playNextBlock();
@@ -115,11 +118,11 @@ void allocBuffers() {
}
void setActive(bool active) {
- DS::CD::active = active;
+ s_active = active;
}
bool getActive() {
- return active;
+ return s_active;
}
void playTrack(int track, int numLoops, int startFrame, int duration) {
@@ -145,21 +148,21 @@ void playTrack(int track, int numLoops, int startFrame, int duration) {
sprintf(str, "track%d.wav", track);
fname = path + str;
- file = DS::std_fopen(fname.c_str(), "rb");
+ s_file = DS::std_fopen(fname.c_str(), "rb");
- if (!file) {
+ if (!s_file) {
sprintf(str, "track%02d.wav", track);
fname = path + str;
- file = DS::std_fopen(fname.c_str(), "rb");
+ s_file = DS::std_fopen(fname.c_str(), "rb");
}
- if (!file) {
+ if (!s_file) {
consolePrintf("Failed to open %s!\n", path.c_str());
return;
}
- DS::std_fread((const void *) &waveHeader, sizeof(waveHeader), 1, file);
+ DS::std_fread(&waveHeader, sizeof(waveHeader), 1, s_file);
consolePrintf("File: %s\n", fname.c_str());
@@ -171,7 +174,7 @@ void playTrack(int track, int numLoops, int startFrame, int duration) {
if ((waveHeader.fmtFormatTag != 17) && (waveHeader.fmtFormatTag != 20)) {
consolePrintf("Wave file is in the wrong format! You must use IMA-ADPCM 4-bit mono.\n");
- DS::std_fclose(file);
+ DS::std_fclose(s_file);
return;
}
@@ -183,14 +186,14 @@ void playTrack(int track, int numLoops, int startFrame, int duration) {
// Skip chunks until we reach the data chunk
chunkHeader chunk;
- DS::std_fread((const void *) &chunk, sizeof(chunkHeader), 1, file);
+ DS::std_fread(&chunk, sizeof(chunkHeader), 1, s_file);
while (!((chunk.name[0] == 'd') && (chunk.name[1] == 'a') && (chunk.name[2] == 't') && (chunk.name[3] == 'a'))) {
- DS::std_fseek(file, chunk.size, SEEK_CUR);
- DS::std_fread((const void *) &chunk, sizeof(chunkHeader), 1, file);
+ DS::std_fseek(s_file, chunk.size, SEEK_CUR);
+ DS::std_fread(&chunk, sizeof(chunkHeader), 1, s_file);
}
- dataChunkStart = DS::std_ftell(file);
+ dataChunkStart = DS::std_ftell(s_file);
static bool started = false;
@@ -234,14 +237,14 @@ void playTrack(int track, int numLoops, int startFrame, int duration) {
// No need to seek if we're starting from the beginning
if (block != 0) {
- DS::std_fseek(file, dataChunkStart + block * waveHeader.fmtBlockAlign, SEEK_SET);
+ DS::std_fseek(s_file, dataChunkStart + block * waveHeader.fmtBlockAlign, SEEK_SET);
// consolePrintf("Startframe: %d msec: %d (%d,%d)\n", startFrame, tenthssec, samples, block);
}
//decompressBlock();
playNextBlock();
- DS::CD::numLoops = numLoops;
+ s_numLoops = numLoops;
}
void update() {
@@ -263,20 +266,20 @@ void decompressBlock() {
do {
- DS::std_fread((const void *) &blockHeader, sizeof(blockHeader), 1, file);
+ DS::std_fread(&blockHeader, sizeof(blockHeader), 1, s_file);
- DS::std_fread(&block[0], waveHeader.fmtBlockAlign - sizeof(blockHeader), 1, file);
+ DS::std_fread(&block[0], waveHeader.fmtBlockAlign - sizeof(blockHeader), 1, s_file);
- if (DS::std_feof(file) ) {
+ if (DS::std_feof(s_file)) {
// Reached end of file, so loop
- if ((numLoops == -1) || (numLoops > 1)) {
+ if ((s_numLoops == -1) || (s_numLoops > 1)) {
// Seek file to first packet
- if (numLoops != -1) {
- numLoops--;
+ if (s_numLoops != -1) {
+ s_numLoops--;
}
- DS::std_fseek(file, dataChunkStart, SEEK_SET);
+ DS::std_fseek(s_file, dataChunkStart, SEEK_SET);
loop = true;
} else {
// Fill decompression buffer with zeros to prevent glitching
@@ -325,45 +328,30 @@ void decompressBlock() {
int offset = 0;
switch (7 - (r & 0x0007)) {
- case 0: {
- offset = (word & 0xF0000000) >> 28;
- break;
- }
-
- case 1: {
- offset = (word & 0x0F000000) >> 24;
- break;
- }
-
- case 2: {
- offset = (word & 0x00F00000) >> 20;
- break;
- }
-
- case 3: {
- offset = (word & 0x000F0000) >> 16;
- break;
- }
-
- case 4: {
- offset = (word & 0x0000F000) >> 12;
- break;
- }
-
- case 5: {
- offset = (word & 0x00000F00) >> 8;
- break;
- }
-
- case 6: {
- offset = (word & 0x000000F0) >> 4;
- break;
- }
-
- case 7: {
- offset = (word & 0x0000000F);
- break;
- }
+ case 0:
+ offset = (word & 0xF0000000) >> 28;
+ break;
+ case 1:
+ offset = (word & 0x0F000000) >> 24;
+ break;
+ case 2:
+ offset = (word & 0x00F00000) >> 20;
+ break;
+ case 3:
+ offset = (word & 0x000F0000) >> 16;
+ break;
+ case 4:
+ offset = (word & 0x0000F000) >> 12;
+ break;
+ case 5:
+ offset = (word & 0x00000F00) >> 8;
+ break;
+ case 6:
+ offset = (word & 0x000000F0) >> 4;
+ break;
+ case 7:
+ offset = (word & 0x0000000F);
+ break;
}
int diff = 0;
@@ -406,7 +394,8 @@ void decompressBlock() {
}
void playNextBlock() {
- if (!isPlayingFlag) return;
+ if (!isPlayingFlag)
+ return;
int lastBlockId = -1;
while (IPC->adpcm.semaphore); // Wait for buffer to become free if needed
@@ -442,9 +431,6 @@ void playNextBlock() {
// DC_FlushAll();
}
-
-
-
}
@@ -460,9 +446,10 @@ void playNextBlock() {
}
void stopTrack() {
- if (!isPlayingFlag) return;
+ if (!isPlayingFlag)
+ return;
- DS::std_fclose(file);
+ DS::std_fclose(s_file);
isPlayingFlag = false;
@@ -470,7 +457,7 @@ void stopTrack() {
audioBuffer[r] = 0;
}
- for (int r= 0; r < waveHeader.fmtExtra; r++) {
+ for (int r = 0; r < waveHeader.fmtExtra; r++) {
decompressionBuffer[r] = 0;
}
// DS::stopSound(1);
@@ -495,8 +482,8 @@ bool trackExists(int num) {
}
consolePrintf("Looking for %s...", path.c_str());
- FILE* file;
- if ((file = DS::std_fopen(path.c_str(), "r"))) {
+ FILE *file = DS::std_fopen(path.c_str(), "r");
+ if (file) {
consolePrintf("Success!\n");
setActive(true);
DS::std_fclose(file);
@@ -548,4 +535,4 @@ bool isPlaying() {
}
}
-}
+} // End of namespace DS
diff --git a/backends/platform/ds/arm9/source/cdaudio.h b/backends/platform/ds/arm9/source/cdaudio.h
index aac303dd5e..6e53ef7bd2 100644
--- a/backends/platform/ds/arm9/source/cdaudio.h
+++ b/backends/platform/ds/arm9/source/cdaudio.h
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -35,6 +38,6 @@ bool isPlaying();
void update();
}
-}
+} // End of namespace DS
#endif
diff --git a/backends/platform/ds/arm9/source/compressor/lz.cpp b/backends/platform/ds/arm9/source/compressor/lz.cpp
deleted file mode 100644
index 47a36646c6..0000000000
--- a/backends/platform/ds/arm9/source/compressor/lz.cpp
+++ /dev/null
@@ -1,539 +0,0 @@
-/*************************************************************************
-* Name: lz.c
-* Author: Marcus Geelnard
-* Description: LZ77 coder/decoder implementation.
-* Reentrant: Yes
-* $Id$
-*
-* The LZ77 compression scheme is a substitutional compression scheme
-* proposed by Abraham Lempel and Jakob Ziv in 1977. It is very simple in
-* its design, and uses no fancy bit level compression.
-*
-* This is my first attempt at an implementation of a LZ77 code/decoder.
-*
-* The principle of the LZ77 compression algorithm is to store repeated
-* occurrences of strings as references to previous occurrences of the same
-* string. The point is that the reference consumes less space than the
-* string itself, provided that the string is long enough (in this
-* implementation, the string has to be at least 4 bytes long, since the
-* minimum coded reference is 3 bytes long). Also note that the term
-* "string" refers to any kind of byte sequence (it does not have to be
-* an ASCII string, for instance).
-*
-* The coder uses a brute force approach to finding string matches in the
-* history buffer (or "sliding window", if you wish), which is very, very
-* slow. I recon the complexity is somewhere between O(n^2) and O(n^3),
-* depending on the input data.
-*
-* There is also a faster implementation that uses a large working buffer
-* in which a "jump table" is stored, which is used to quickly find
-* possible string matches (see the source code for LZ_CompressFast() for
-* more information). The faster method is an order of magnitude faster,
-* and also does a full string search in the entire input buffer (it does
-* not use a sliding window).
-*
-* The upside is that decompression is very fast, and the compression ratio
-* is often very good.
-*
-* The reference to a string is coded as a (length,offset) pair, where the
-* length indicates the length of the string, and the offset gives the
-* offset from the current data position. To distinguish between string
-* references and literal strings (uncompressed bytes), a string reference
-* is preceded by a marker byte, which is chosen as the least common byte
-* symbol in the input data stream (this marker byte is stored in the
-* output stream as the first byte).
-*
-* Occurrences of the marker byte in the stream are encoded as the marker
-* byte followed by a zero byte, which means that occurrences of the marker
-* byte have to be coded with two bytes.
-*
-* The lengths and offsets are coded in a variable length fashion, allowing
-* values of any magnitude (up to 4294967295 in this implementation).
-*
-* With this compression scheme, the worst case compression result is
-* (257/256)*insize + 1.
-*
-*-------------------------------------------------------------------------
-* Copyright (c) 2003-2004 Marcus Geelnard
-*
-* This software is provided 'as-is', without any express or implied
-* warranty. In no event will the authors be held liable for any damages
-* arising from the use of this software.
-*
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-*
-* 1. The origin of this software must not be misrepresented; you must not
-* claim that you wrote the original software. If you use this software
-* in a product, an acknowledgment in the product documentation would
-* be appreciated but is not required.
-*
-* 2. Altered source versions must be plainly marked as such, and must not
-* be misrepresented as being the original software.
-*
-* 3. This notice may not be removed or altered from any source
-* distribution.
-*
-* Marcus Geelnard
-* marcus.geelnard at home.se
-*************************************************************************/
-
-
-/*************************************************************************
-* Constants used for LZ77 coding
-*************************************************************************/
-
-/* Maximum offset (can be any size < 2^32). Lower values gives faster
- compression, while higher values gives better compression.
- NOTE: LZ_CompressFast does not use this constant. */
-#define LZ_MAX_OFFSET 512
-
-
-
-/*************************************************************************
-* INTERNAL FUNCTIONS *
-*************************************************************************/
-
-
-/*************************************************************************
-* _LZ_StringCompare() - Return maximum length string match.
-*************************************************************************/
-
-inline static unsigned int _LZ_StringCompare( unsigned char * str1,
- unsigned char * str2, unsigned int minlen, unsigned int maxlen )
-{
- unsigned int len;
-
- for ( len = minlen; (len < maxlen) && (str1[len] == str2[len]); ++ len );
-
- return len;
-}
-
-
-/*************************************************************************
-* _LZ_WriteVarSize() - Write unsigned integer with variable number of
-* bytes depending on value.
-*************************************************************************/
-
-inline static int _LZ_WriteVarSize( unsigned int x, unsigned char * buf )
-{
- unsigned int y;
- int num_bytes, i, b;
-
- /* Determine number of bytes needed to store the number x */
- y = x >> 3;
- for ( num_bytes = 5; num_bytes >= 2; -- num_bytes )
- {
- if ( y & 0xfe000000 ) break;
- y <<= 7;
- }
-
- /* Write all bytes, seven bits in each, with 8:th bit set for all */
- /* but the last byte. */
- for ( i = num_bytes-1; i >= 0; -- i )
- {
- b = (x >> (i*7)) & 0x0000007f;
- if ( i > 0 )
- {
- b |= 0x00000080;
- }
- *buf ++ = (unsigned char) b;
- }
-
- /* Return number of bytes written */
- return num_bytes;
-}
-
-
-/*************************************************************************
-* _LZ_ReadVarSize() - Read unsigned integer with variable number of
-* bytes depending on value.
-*************************************************************************/
-
-inline static int _LZ_ReadVarSize( unsigned int * x, unsigned char * buf )
-{
- unsigned int y, b, num_bytes;
-
- /* Read complete value (stop when byte contains zero in 8:th bit) */
- y = 0;
- num_bytes = 0;
- do
- {
- b = (unsigned int) (*buf ++);
- y = (y << 7) | (b & 0x0000007f);
- ++ num_bytes;
- }
- while ( b & 0x00000080 );
-
- /* Store value in x */
- *x = y;
-
- /* Return number of bytes read */
- return num_bytes;
-}
-
-
-
-/*************************************************************************
-* PUBLIC FUNCTIONS *
-*************************************************************************/
-
-
-/*************************************************************************
-* LZ_Compress() - Compress a block of data using an LZ77 coder.
-* in - Input (uncompressed) buffer.
-* out - Output (compressed) buffer. This buffer must be 0.4% larger
-* than the input buffer, plus one byte.
-* insize - Number of input bytes.
-* The function returns the size of the compressed data.
-*************************************************************************/
-
-int LZ_Compress( unsigned char *in, unsigned char *out,
- unsigned int insize )
-{
- unsigned char marker, symbol;
- unsigned int inpos, outpos, bytesleft, i;
- unsigned int maxoffset, offset, bestoffset;
- unsigned int maxlength, length, bestlength;
- unsigned int histogram[ 256 ];
- unsigned char *ptr1, *ptr2;
-
- /* Do we have anything to compress? */
- if ( insize < 1 )
- {
- return 0;
- }
-
- /* Create histogram */
- for ( i = 0; i < 256; ++ i )
- {
- histogram[ i ] = 0;
- }
- for ( i = 0; i < insize; ++ i )
- {
- ++ histogram[ in[ i ] ];
- }
-
- /* Find the least common byte, and use it as the code marker */
- marker = 0;
- for ( i = 1; i < 256; ++ i )
- {
- if ( histogram[ i ] < histogram[ marker ] )
- {
- marker = i;
- }
- }
-
- /* Remember the repetition marker for the decoder */
- out[ 0 ] = marker;
-
- /* Start of compression */
- inpos = 0;
- outpos = 1;
-
- /* Main compression loop */
- bytesleft = insize;
- do
- {
- /* Determine most distant position */
- if ( inpos > LZ_MAX_OFFSET ) maxoffset = LZ_MAX_OFFSET;
- else maxoffset = inpos;
-
- /* Get pointer to current position */
- ptr1 = &in[ inpos ];
-
- /* Search history window for maximum length string match */
- bestlength = 3;
- bestoffset = 0;
- for ( offset = 3; offset <= maxoffset; ++ offset )
- {
- /* Get pointer to candidate string */
- ptr2 = &ptr1[ -offset ];
-
- /* Quickly determine if this is a candidate (for speed) */
- if ( (ptr1[ 0 ] == ptr2[ 0 ]) &&
- (ptr1[ bestlength ] == ptr2[ bestlength ]) )
- {
- /* Determine maximum length for this offset */
- maxlength = (bytesleft < offset ? bytesleft : offset);
-
- /* Count maximum length match at this offset */
- length = _LZ_StringCompare( ptr1, ptr2, 0, maxlength );
-
- /* Better match than any previous match? */
- if ( length > bestlength )
- {
- bestlength = length;
- bestoffset = offset;
- }
- }
- }
-
- /* Was there a good enough match? */
- if ( (bestlength >= 8) ||
- ((bestlength == 4) && (bestoffset <= 0x0000007f)) ||
- ((bestlength == 5) && (bestoffset <= 0x00003fff)) ||
- ((bestlength == 6) && (bestoffset <= 0x001fffff)) ||
- ((bestlength == 7) && (bestoffset <= 0x0fffffff)) )
- {
- out[ outpos ++ ] = (unsigned char) marker;
- outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] );
- outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] );
- inpos += bestlength;
- bytesleft -= bestlength;
- }
- else
- {
- /* Output single byte (or two bytes if marker byte) */
- symbol = in[ inpos ++ ];
- out[ outpos ++ ] = symbol;
- if ( symbol == marker )
- {
- out[ outpos ++ ] = 0;
- }
- -- bytesleft;
- }
- }
- while ( bytesleft > 3 );
-
- /* Dump remaining bytes, if any */
- while ( inpos < insize )
- {
- if ( in[ inpos ] == marker )
- {
- out[ outpos ++ ] = marker;
- out[ outpos ++ ] = 0;
- }
- else
- {
- out[ outpos ++ ] = in[ inpos ];
- }
- ++ inpos;
- }
-
- return outpos;
-}
-
-
-/*************************************************************************
-* LZ_CompressFast() - Compress a block of data using an LZ77 coder.
-* in - Input (uncompressed) buffer.
-* out - Output (compressed) buffer. This buffer must be 0.4% larger
-* than the input buffer, plus one byte.
-* insize - Number of input bytes.
-* work - Pointer to a temporary buffer (internal working buffer), which
-* must be able to hold (insize+65536) unsigned integers.
-* The function returns the size of the compressed data.
-*************************************************************************/
-
-int LZ_CompressFast( unsigned char *in, unsigned char *out,
- unsigned int insize, unsigned int *work )
-{
- unsigned char marker, symbol;
- unsigned int inpos, outpos, bytesleft, i, index, symbols;
- unsigned int offset, bestoffset;
- unsigned int maxlength, length, bestlength;
- unsigned int histogram[ 256 ], *lastindex, *jumptable;
- unsigned char *ptr1, *ptr2;
-
- /* Do we have anything to compress? */
- if ( insize < 1 )
- {
- return 0;
- }
-
- /* Assign arrays to the working area */
- lastindex = work;
- jumptable = &work[ 65536 ];
-
- /* Build a "jump table". Here is how the jump table works:
- jumptable[i] points to the nearest previous occurrence of the same
- symbol pair as in[i]:in[i+1], so in[i] == in[jumptable[i]] and
- in[i+1] == in[jumptable[i]+1]. Following the jump table gives a
- dramatic boost for the string search'n'match loop compared to doing
- a brute force search. */
- for ( i = 0; i < 65536; ++ i )
- {
- lastindex[ i ] = 0xffffffff;
- }
- for ( i = 0; i < insize-1; ++ i )
- {
- symbols = (((unsigned int)in[i]) << 8) | ((unsigned int)in[i+1]);
- index = lastindex[ symbols ];
- lastindex[ symbols ] = i;
- jumptable[ i ] = index;
- }
- jumptable[ insize-1 ] = 0xffffffff;
-
- /* Create histogram */
- for ( i = 0; i < 256; ++ i )
- {
- histogram[ i ] = 0;
- }
- for ( i = 0; i < insize; ++ i )
- {
- ++ histogram[ in[ i ] ];
- }
-
- /* Find the least common byte, and use it as the code marker */
- marker = 0;
- for ( i = 1; i < 256; ++ i )
- {
- if ( histogram[ i ] < histogram[ marker ] )
- {
- marker = i;
- }
- }
-
- /* Remember the repetition marker for the decoder */
- out[ 0 ] = marker;
-
- /* Start of compression */
- inpos = 0;
- outpos = 1;
-
- /* Main compression loop */
- bytesleft = insize;
- do
- {
- /* Get pointer to current position */
- ptr1 = &in[ inpos ];
-
- /* Search history window for maximum length string match */
- bestlength = 3;
- bestoffset = 0;
- index = jumptable[ inpos ];
- while ( index != 0xffffffff )
- {
- /* Get pointer to candidate string */
- ptr2 = &in[ index ];
-
- /* Quickly determine if this is a candidate (for speed) */
- if ( ptr2[ bestlength ] == ptr1[ bestlength ] )
- {
- /* Determine maximum length for this offset */
- offset = inpos - index;
- maxlength = (bytesleft < offset ? bytesleft : offset);
-
- /* Count maximum length match at this offset */
- length = _LZ_StringCompare( ptr1, ptr2, 2, maxlength );
-
- /* Better match than any previous match? */
- if ( length > bestlength )
- {
- bestlength = length;
- bestoffset = offset;
- }
- }
-
- /* Get next possible index from jump table */
- index = jumptable[ index ];
- }
-
- /* Was there a good enough match? */
- if ( (bestlength >= 8) ||
- ((bestlength == 4) && (bestoffset <= 0x0000007f)) ||
- ((bestlength == 5) && (bestoffset <= 0x00003fff)) ||
- ((bestlength == 6) && (bestoffset <= 0x001fffff)) ||
- ((bestlength == 7) && (bestoffset <= 0x0fffffff)) )
- {
- out[ outpos ++ ] = (unsigned char) marker;
- outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] );
- outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] );
- inpos += bestlength;
- bytesleft -= bestlength;
- }
- else
- {
- /* Output single byte (or two bytes if marker byte) */
- symbol = in[ inpos ++ ];
- out[ outpos ++ ] = symbol;
- if ( symbol == marker )
- {
- out[ outpos ++ ] = 0;
- }
- -- bytesleft;
- }
- }
- while ( bytesleft > 3 );
-
- /* Dump remaining bytes, if any */
- while ( inpos < insize )
- {
- if ( in[ inpos ] == marker )
- {
- out[ outpos ++ ] = marker;
- out[ outpos ++ ] = 0;
- }
- else
- {
- out[ outpos ++ ] = in[ inpos ];
- }
- ++ inpos;
- }
-
- return outpos;
-}
-
-
-/*************************************************************************
-* LZ_Uncompress() - Uncompress a block of data using an LZ77 decoder.
-* in - Input (compressed) buffer.
-* out - Output (uncompressed) buffer. This buffer must be large
-* enough to hold the uncompressed data.
-* insize - Number of input bytes.
-*************************************************************************/
-
-void LZ_Uncompress( unsigned char *in, unsigned char *out,
- unsigned int insize )
-{
- unsigned char marker, symbol;
- unsigned int i, inpos, outpos, length, offset;
-
- /* Do we have anything to compress? */
- if ( insize < 1 )
- {
- return;
- }
-
- /* Get marker symbol from input stream */
- marker = in[ 0 ];
- inpos = 1;
-
- /* Main decompression loop */
- outpos = 0;
- do
- {
- symbol = in[ inpos ++ ];
- if ( symbol == marker )
- {
- /* We had a marker byte */
- if ( in[ inpos ] == 0 )
- {
- /* It was a single occurrence of the marker byte */
- out[ outpos ++ ] = marker;
- ++ inpos;
- }
- else
- {
- /* Extract true length and offset */
- inpos += _LZ_ReadVarSize( &length, &in[ inpos ] );
- inpos += _LZ_ReadVarSize( &offset, &in[ inpos ] );
-
- /* Copy corresponding data from history window */
- for ( i = 0; i < length; ++ i )
- {
- out[ outpos ] = out[ outpos - offset ];
- ++ outpos;
- }
- }
- }
- else
- {
- /* No marker, plain copy */
- out[ outpos ++ ] = symbol;
- }
- }
- while ( inpos < insize );
-}
diff --git a/backends/platform/ds/arm9/source/compressor/lz.h b/backends/platform/ds/arm9/source/compressor/lz.h
deleted file mode 100644
index e7ea1567ca..0000000000
--- a/backends/platform/ds/arm9/source/compressor/lz.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*************************************************************************
-* Name: lz.h
-* Author: Marcus Geelnard
-* Description: LZ77 coder/decoder interface.
-* Reentrant: Yes
-* $Id$
-*-------------------------------------------------------------------------
-* Copyright (c) 2003-2004 Marcus Geelnard
-*
-* This software is provided 'as-is', without any express or implied
-* warranty. In no event will the authors be held liable for any damages
-* arising from the use of this software.
-*
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-*
-* 1. The origin of this software must not be misrepresented; you must not
-* claim that you wrote the original software. If you use this software
-* in a product, an acknowledgment in the product documentation would
-* be appreciated but is not required.
-*
-* 2. Altered source versions must be plainly marked as such, and must not
-* be misrepresented as being the original software.
-*
-* 3. This notice may not be removed or altered from any source
-* distribution.
-*
-* Marcus Geelnard
-* marcus.geelnard at home.se
-*************************************************************************/
-
-#ifndef _lz_h_
-#define _lz_h_
-
-
-
-/*************************************************************************
-* Function prototypes
-*************************************************************************/
-
-int LZ_Compress( unsigned char *in, unsigned char *out,
- unsigned int insize );
-int LZ_CompressFast( unsigned char *in, unsigned char *out,
- unsigned int insize, unsigned int *work );
-void LZ_Uncompress( unsigned char *in, unsigned char *out,
- unsigned int insize );
-
-
-#endif /* _lz_h_ */
diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp
index ee9e4d7622..4c7d6b89ae 100644
--- a/backends/platform/ds/arm9/source/dsmain.cpp
+++ b/backends/platform/ds/arm9/source/dsmain.cpp
@@ -73,8 +73,6 @@
-//#define USE_LIBCARTRESET
-
#include <nds.h>
#include <nds/registers_alt.h>
#include <nds/arm9/exceptions.h>
@@ -100,20 +98,15 @@
#ifdef USE_DEBUGGER
#include "user_debugger.h"
#endif
-#include "ramsave.h"
#include "blitters.h"
-#include "libcartreset/cartreset_nolibfat.h"
#include "keys.h"
#ifdef USE_PROFILER
#include "profiler/cyg-profile.h"
#endif
-#include "base/version.h"
#include "engine.h"
-
-#include "backends/plugins/elf-provider.h"
#include "backends/plugins/ds/ds-provider.h"
-
+#include "backends/plugins/elf-provider.h"
#include "backends/fs/ds/ds-fs.h"
#include "base/version.h"
#include "common/util.h"
@@ -388,6 +381,9 @@ void uploadSpriteGfx();
static TransferSound soundControl;
+static bool isScrollingWithDPad() {
+ return (getKeysHeld() & (KEY_L | KEY_R)) != 0;
+}
bool isCpuScalerEnabled() {
return cpuScalerEnable || !displayModeIs8Bit;
@@ -1344,7 +1340,7 @@ void doScreenTapMode(OSystem_DS *system) {
right = true;
}
- if (!(getKeysHeld() & (KEY_L | KEY_R))) {
+ if (!isScrollingWithDPad()) {
if (getKeysDown() & KEY_LEFT) {
event.type = Common::EVENT_LBUTTONDOWN;
@@ -1381,7 +1377,7 @@ void doButtonSelectMode(OSystem_DS *system) {
Common::Event event;
- if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
+ if (!isScrollingWithDPad()) {
event.type = Common::EVENT_MOUSEMOVE;
event.mouse = Common::Point(getPenX(), getPenY());
system->addEvent(event);
@@ -1404,7 +1400,7 @@ void doButtonSelectMode(OSystem_DS *system) {
if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) {
- if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
+ if (getPenDown() && !isScrollingWithDPad()) {
if (mouseMode == MOUSE_LEFT) {
event.type = Common::EVENT_LBUTTONDOWN;
leftButtonDown = true;
@@ -1446,7 +1442,7 @@ void doButtonSelectMode(OSystem_DS *system) {
}
}
- if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState()) && (!getKeyboardEnable())) {
+ if (!isScrollingWithDPad() && !getIndyFightState() && !getKeyboardEnable()) {
if (!getPenHeld() || (mouseMode != MOUSE_HOVER)) {
if (getKeysDown() & KEY_LEFT) {
@@ -1542,7 +1538,7 @@ void addEventsToQueue() {
if (!indyFightState) {
- if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) && (getKeysDown() & KEY_B)) {
+ if (!isScrollingWithDPad() && (getKeysDown() & KEY_B)) {
if (s_currentGame->control == CONT_AGI) {
event.kbd.keycode = Common::KEYCODE_RETURN;
event.kbd.ascii = 13;
@@ -1614,7 +1610,7 @@ void addEventsToQueue() {
}
- if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState()) && (!getKeyboardEnable())) {
+ if (!isScrollingWithDPad() && !getIndyFightState() && !getKeyboardEnable()) {
if ((getKeysDown() & KEY_A) && (!indyFightState)) {
gameScreenSwap = !gameScreenSwap;
@@ -1653,7 +1649,7 @@ void addEventsToQueue() {
}
}
- if (!getIndyFightState() && !((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (getKeysDown() & KEY_X)) {
+ if (!getIndyFightState() && !isScrollingWithDPad() && (getKeysDown() & KEY_X)) {
setKeyboardEnable(!keyboardEnable);
}
@@ -1675,7 +1671,7 @@ void addEventsToQueue() {
if (!keyboardEnable) {
- if (((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) || (indyFightState)) && (displayModeIs8Bit)) {
+ if ((isScrollingWithDPad() || (indyFightState)) && (displayModeIs8Bit)) {
// Controls specific to the control method
if (s_currentGame->control == CONT_SKY) {
@@ -2017,7 +2013,7 @@ void VBlankHandler(void) {
soundUpdate();
- if ((!gameScreenSwap) && (!(getKeysHeld() & KEY_L) && !(getKeysHeld() & KEY_R))) {
+ if ((!gameScreenSwap) && !isScrollingWithDPad()) {
if (s_currentGame) {
if (s_currentGame->control != CONT_SCUMM_SAMNMAX) {
if (getPenHeld() && (getPenY() < SCUMM_GAME_HEIGHT)) {
@@ -2059,7 +2055,7 @@ void VBlankHandler(void) {
callbackTimer -= FRAME_TIME;
}
- if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) {
+ if (isScrollingWithDPad()) {
if ((!dragging) && (getPenHeld()) && (penDownFrames > 5)) {
dragging = true;
@@ -2113,7 +2109,7 @@ void VBlankHandler(void) {
bool zooming = false;
- if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) {
+ if (isScrollingWithDPad()) {
if ((getKeysHeld() & KEY_A) && (subScreenScale < ratio)) {
subScreenScale += 1;
zooming = true;
@@ -2190,7 +2186,7 @@ void VBlankHandler(void) {
if (displayModeIs8Bit) {
- if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) {
+ if (isScrollingWithDPad()) {
int offsX = 0, offsY = 0;
@@ -2777,31 +2773,6 @@ GLvector getPenPos() {
return v;
}
-#ifdef GBA_SRAM_SAVE
-
-void formatSramOption() {
- consolePrintf("The following files are present in save RAM:\n");
- DSSaveFileManager::instance()->listFiles();
-
- consolePrintf("\nAre you sure you want to\n");
- consolePrintf("DELETE all files?\n");
- consolePrintf("A = Yes, X = No\n");
-
- while (true) {
- if (keysHeld() & KEY_A) {
- DSSaveFileManager::instance()->formatSram();
- consolePrintf("SRAM cleared!\n");
- return;
- }
-
- if (keysHeld() & KEY_X) {
- consolePrintf("Whew, that was close!\n");
- return;
- }
- }
-}
-#endif
-
void setIndyFightState(bool st) {
indyFightState = st;
indyFightRight = true;
@@ -2886,61 +2857,6 @@ void debug_print_stub(char *string) {
}
#endif
-#ifdef USE_LIBCARTRESET
-
-struct cardTranslate {
- int cartResetId;
- int svmId;
- char dldiId[5];
-};
-
-cardTranslate cardReaderTable[] = {
- {DEVICE_TYPE_M3SD, DEVICE_M3SD, "M3SD"},
- {DEVICE_TYPE_M3CF, DEVICE_M3CF, "M3CF"},
- {DEVICE_TYPE_MPCF, DEVICE_MPCF, "MPCF"},
- {DEVICE_TYPE_SCCF, DEVICE_SCCF, "SCCF"},
- {DEVICE_TYPE_SCSD, DEVICE_SCSD, "SCSD"},
- {DEVICE_TYPE_SCSD, DEVICE_SCSD, "SCLT"},
- {DEVICE_TYPE_NMMC, DEVICE_NMMC, "NMMC"},
-};
-
-void reboot() {
- int deviceType = -1;
-
-
- if (disc_getDeviceId() == DEVICE_DLDI) {
-
- char id[6];
- disc_getDldiId(id);
-
- consolePrintf("DLDI Device ID: %s\n", id);
-
- for (int r = 0; r < ARRAYSIZE(cardReaderTable); r++) {
- if (!stricmp(id, cardReaderTable[r].dldiId)) {
- deviceType = cardReaderTable[r].cartResetId;
- }
- }
- } else {
- for (int r = 0; r < ARRAYSIZE(cardReaderTable); r++) {
- if (disc_getDeviceId() == cardReaderTable[r].svmId) {
- deviceType = cardReaderTable[r].cartResetId;
- }
- }
- }
-
-
- consolePrintf("Device number: %x\n", deviceType);
-
- if (deviceType == -1) {
- IPC->reset = true; // Send message to ARM7 to turn power off
- } else {
- cartSetMenuMode(deviceType);
- passmeloopEnter();
- }
-
- while (true); // Stop the program continuing beyond this point
-}
-#endif
void powerOff() {
while (keysHeld() != 0) { // Wait for all keys to be released.
@@ -2955,12 +2871,10 @@ void powerOff() {
while (true);
} else {
-#ifdef USE_LIBCARTRESET
- reboot();
-#else
IPC->reset = true; // Send message to ARM7 to turn power off
- while (true); // Stop the program continuing beyond this point
-#endif
+ while (true) {
+ // Stop the program from continuing beyond this point
+ }
}
}
@@ -2981,7 +2895,7 @@ void dsExceptionHandler() {
int offset = 8;
- if ( currentMode == 0x17 ) {
+ if (currentMode == 0x17) {
consolePrintf("\x1b[10Cdata abort!\n\n");
codeAddress = exceptionRegisters[15] - offset;
if ( (codeAddress > 0x02000000 && codeAddress < 0x02400000) ||
@@ -3004,16 +2918,19 @@ void dsExceptionHandler() {
int i;
- for ( i=0; i < 8; i++ ) {
+ for (i = 0; i < 8; i++) {
consolePrintf(" %s: %08X %s: %08X\n",
registerNames[i], exceptionRegisters[i],
registerNames[i+8],exceptionRegisters[i+8]);
}
- while(1);
+
+ while(1)
+ ; // endles loop
+
u32 *stack = (u32 *)exceptionRegisters[13];
- for ( i=0; i<10; i++ ) {
+ for (i = 0; i < 10; i++) {
consolePrintf("%08X %08X %08X\n", stack[i*3], stack[i*3+1], stack[(i*3)+2] );
}
@@ -3264,12 +3181,6 @@ 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;
// printf("'%s'", Common::ConfigManager::kTransientDomain.c_str());
diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h
index beda592ba2..bd627fa620 100644
--- a/backends/platform/ds/arm9/source/dsmain.h
+++ b/backends/platform/ds/arm9/source/dsmain.h
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -25,7 +28,6 @@
#include <nds.h>
#include "osystem_ds.h"
-#include "NDS/scummvm_ipc.h"
namespace DS {
@@ -38,7 +40,7 @@ enum controlType {
CONT_FUTURE_WARS,
CONT_AGI,
CONT_GOBLINS,
- CONT_NIPPON,
+ CONT_NIPPON
};
struct gameListType {
@@ -68,9 +70,6 @@ int leftHandedSwap(int keys);
void setGameScreenSwap(bool enable);
void setSensitivity(int sensitivity);
-// Controls options
-void setControls(char* gameName);
-
// Video
void displayMode8Bit(); // Switch to 8-bit mode5
void displayMode16Bit(); // Switch to 16-bit mode5
@@ -79,8 +78,8 @@ void displayMode16Bit(); // Switch to 16-bit mode5
void displayMode16BitFlipBuffer();
// Get address of current back buffer
-u16* get16BitBackBuffer();
-u16* get8BitBackBuffer();
+u16 * get16BitBackBuffer();
+u16 * get8BitBackBuffer();
s32 get8BitBackBufferStride();
u16* getScalerBuffer();
@@ -99,7 +98,7 @@ void doTimerCallback(); // Call callback function if required
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 playSound(const void *data, u32 length, bool loop, bool adpcm = false, int rate = 22050); // Start a sound
void stopSound(int channel);
int getSoundFrequency();
@@ -109,7 +108,7 @@ void VBlankHandler();
// Sam and Max Stuff
void setGameID(int id);
-void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY);
+void setCursorIcon(const u8 *icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY);
void setShowCursor(bool enable);
void setMouseCursorVisible(bool visible);
@@ -155,10 +154,10 @@ void fastRamReset();
void* fastRamAlloc(int size);
void exitGame();
-gameListType* getCurrentGame();
-}
+} // End of namespace DS
+
int cygprofile_getHBlanks();
diff --git a/backends/platform/ds/arm9/source/dsoptions.cpp b/backends/platform/ds/arm9/source/dsoptions.cpp
index 9937e81e61..6721a4910a 100644
--- a/backends/platform/ds/arm9/source/dsoptions.cpp
+++ b/backends/platform/ds/arm9/source/dsoptions.cpp
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -31,6 +34,8 @@
#include "touchkeyboard.h"
#include "gui/PopUpWidget.h"
+#include "common/translation.h"
+
#define ALLOW_CPU_SCALER
namespace DS {
@@ -51,27 +56,27 @@ static int confGetInt(Common::String key, int defaultVal) {
DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
- new GUI::ButtonWidget(this, 10, 170, 72, 16, "Close", GUI::kCloseCmd, 'C');
- new GUI::ButtonWidget(this, 320 - 10 - 130, 170, 120, 16, "ScummVM Main Menu", 0x40000000, 'M');
+ new GUI::ButtonWidget(this, 10, 170, 72, 16, _("~C~lose"), 0, GUI::kCloseCmd);
+ new GUI::ButtonWidget(this, 320 - 10 - 130, 170, 120, 16, _("ScummVM Main Menu"), 0, 0x40000000, 'M');
_tab = new GUI::TabWidget(this, 10, 5, 300, 230 - 20 - 40 - 20);
_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');
+ _leftHandedCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 130, 20, _("~L~eft handed mode"));
+ _indyFightCheckbox = new GUI::CheckboxWidget(_tab, 5, 20, 140, 20, _("~I~ndy fight controls"));
+ _showCursorCheckbox = new GUI::CheckboxWidget(_tab, 150, 5, 130, 20, _("Show mouse cursor"), 0, 0, 'T');
+ _snapToBorderCheckbox = new GUI::CheckboxWidget(_tab, 150, 20, 130, 20, _("Snap to edges"), 0, 0, 'T');
- new GUI::StaticTextWidget(_tab, 20, 35, 100, 15, "Touch X Offset", Graphics::kTextAlignLeft);
- _touchX = new GUI::SliderWidget(_tab, 130, 35, 130, 12, 1);
+ new GUI::StaticTextWidget(_tab, 20, 35, 100, 15, _("Touch X Offset"), Graphics::kTextAlignLeft);
+ _touchX = new GUI::SliderWidget(_tab, 130, 35, 130, 12, "TODO: Add tooltip", 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", Graphics::kTextAlignLeft);
- _touchY = new GUI::SliderWidget(_tab, 130, 50, 130, 12, 2);
+ new GUI::StaticTextWidget(_tab, 20, 50, 100, 15, _("Touch Y Offset"), Graphics::kTextAlignLeft);
+ _touchY = new GUI::SliderWidget(_tab, 130, 50, 130, 12, "TODO: Add tooltip", 2);
_touchY->setMinValue(-8);
_touchY->setMaxValue(+8);
_touchY->setValue(0);
@@ -82,11 +87,11 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
new GUI::StaticTextWidget(_tab, 130 - 20, 65, 20, 15, "-8", Graphics::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');
+ _touchPadStyle = new GUI::CheckboxWidget(_tab, 5, 80, 270, 20, _("Use laptop trackpad-style cursor control"), 0, 0x20000001, 'T');
+ _screenTaps = new GUI::CheckboxWidget(_tab, 5, 95, 285, 20, _("Tap for left click, double tap right click"), 0, 0x20000002, 'T');
- _sensitivityLabel = new GUI::StaticTextWidget(_tab, 20, 110, 110, 15, "Sensitivity", Graphics::kTextAlignLeft);
- _sensitivity = new GUI::SliderWidget(_tab, 130, 110, 130, 12, 1);
+ _sensitivityLabel = new GUI::StaticTextWidget(_tab, 20, 110, 110, 15, _("Sensitivity"), Graphics::kTextAlignLeft);
+ _sensitivity = new GUI::SliderWidget(_tab, 130, 110, 130, 12, "TODO: Add tooltip", 1);
_sensitivity->setMinValue(4);
_sensitivity->setMaxValue(16);
_sensitivity->setValue(8);
@@ -94,20 +99,20 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
_tab->addTab("Graphics");
- new GUI::StaticTextWidget(_tab, 5, 67, 180, 15, "Initial top screen scale:", Graphics::kTextAlignLeft);
+ new GUI::StaticTextWidget(_tab, 5, 67, 180, 15, _("Initial top screen scale:"), Graphics::kTextAlignLeft);
- _100PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 82, 80, 20, "100%", 0x30000001, 'T');
- _150PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 97, 80, 20, "150%", 0x30000002, 'T');
- _200PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 112, 80, 20, "200%", 0x30000003, 'T');
+ _100PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 82, 80, 20, "100%", "TODO: Add tooltip", 0x30000001, 'T');
+ _150PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 97, 80, 20, "150%", "TODO: Add tooltip", 0x30000002, 'T');
+ _200PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 112, 80, 20, "200%", "TODO: Add tooltip", 0x30000003, 'T');
- new GUI::StaticTextWidget(_tab, 5, 5, 180, 15, "Main screen scaling:", Graphics::kTextAlignLeft);
+ new GUI::StaticTextWidget(_tab, 5, 5, 180, 15, _("Main screen scaling:"), Graphics::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');
+ _hardScaler = new GUI::CheckboxWidget(_tab, 5, 20, 270, 20, _("Hardware scale (fast, but low quality)"), 0, 0x10000001, 'T');
+ _cpuScaler = new GUI::CheckboxWidget(_tab, 5, 35, 270, 20, _("Software scale (good quality, but slower)"), 0, 0x10000002, 'S');
+ _unscaledCheckbox = new GUI::CheckboxWidget(_tab, 5, 50, 270, 20, _("Unscaled (you must scroll left and right)"), 0, 0x10000003, 'S');
- new GUI::StaticTextWidget(_tab, 5, 125, 110, 15, "Brightness:", Graphics::kTextAlignLeft);
- _gammaCorrection = new GUI::SliderWidget(_tab, 130, 120, 130, 12, 1);
+ new GUI::StaticTextWidget(_tab, 5, 125, 110, 15, _("Brightness:"), Graphics::kTextAlignLeft);
+ _gammaCorrection = new GUI::SliderWidget(_tab, 130, 120, 130, 12, "TODO: Add tooltip", 1);
_gammaCorrection->setMinValue(0);
_gammaCorrection->setMaxValue(8);
_gammaCorrection->setValue(0);
@@ -116,24 +121,18 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
_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');
+ _highQualityAudioCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 250, 20, _("High quality audio (slower) (reboot)"), 0, 0, 'T');
+ _disablePowerOff = new GUI::CheckboxWidget(_tab, 5, 20, 200, 20, _("Disable power off"), 0, 0, 'T');
_tab->setActiveTab(0);
_radioButtonMode = false;
-#ifdef DS_SCUMM_BUILD
- if (!DS::isGBAMPAvailable()) {
-// addButton(this, 100, 140, "Delete Save", 'dels', 'D');
- }
-#endif
-
// new GUI::StaticTextWidget(this, 90, 10, 130, 15, "ScummVM DS Options", Graphics::kTextAlignCenter);
//#ifdef ALLOW_CPU_SCALER
-// _cpuScaler = new GUI::CheckboxWidget(this, 160, 115, 90, 20, "CPU scaler", 0, 'T');
+// _cpuScaler = new GUI::CheckboxWidget(this, 160, 115, 90, 20, "CPU scaler", 0, 0, 'T');
//#endif
@@ -364,7 +363,7 @@ void showOptionsDialog() {
DS::displayMode16Bit();
- DSOptionsDialog* d = new DSOptionsDialog();
+ DSOptionsDialog *d = new DSOptionsDialog();
d->runModal();
delete d;
@@ -418,7 +417,7 @@ void setOptions() {
DS::setTrackPadStyleEnable(enable);
- if ((enable) and (firstLoad)) {
+ if (enable && 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);
@@ -436,4 +435,5 @@ void setOptions() {
firstLoad = false;
}
-}
+} // End of namespace DS
+
diff --git a/backends/platform/ds/arm9/source/dsoptions.h b/backends/platform/ds/arm9/source/dsoptions.h
index 4b3ac36d45..1bdc7c1f27 100644
--- a/backends/platform/ds/arm9/source/dsoptions.h
+++ b/backends/platform/ds/arm9/source/dsoptions.h
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -46,30 +49,30 @@ protected:
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
void updateConfigManager();
- GUI::TabWidget* _tab;
+ GUI::TabWidget *_tab;
- GUI::StaticTextWidget* _sensitivityLabel;
+ GUI::StaticTextWidget *_sensitivityLabel;
- GUI::SliderWidget* _touchX;
- GUI::SliderWidget* _touchY;
- GUI::SliderWidget* _sensitivity;
- GUI::SliderWidget* _gammaCorrection;
- GUI::CheckboxWidget* _leftHandedCheckbox;
- GUI::CheckboxWidget* _unscaledCheckbox;
- GUI::CheckboxWidget* _100PercentCheckbox;
- GUI::CheckboxWidget* _150PercentCheckbox;
- GUI::CheckboxWidget* _200PercentCheckbox;
- GUI::CheckboxWidget* _indyFightCheckbox;
- GUI::CheckboxWidget* _highQualityAudioCheckbox;
- GUI::CheckboxWidget* _disablePowerOff;
- GUI::CheckboxWidget* _showCursorCheckbox;
- GUI::CheckboxWidget* _snapToBorderCheckbox;
+ GUI::SliderWidget *_touchX;
+ GUI::SliderWidget *_touchY;
+ GUI::SliderWidget *_sensitivity;
+ GUI::SliderWidget *_gammaCorrection;
+ GUI::CheckboxWidget *_leftHandedCheckbox;
+ GUI::CheckboxWidget *_unscaledCheckbox;
+ GUI::CheckboxWidget *_100PercentCheckbox;
+ GUI::CheckboxWidget *_150PercentCheckbox;
+ GUI::CheckboxWidget *_200PercentCheckbox;
+ GUI::CheckboxWidget *_indyFightCheckbox;
+ GUI::CheckboxWidget *_highQualityAudioCheckbox;
+ GUI::CheckboxWidget *_disablePowerOff;
+ GUI::CheckboxWidget *_showCursorCheckbox;
+ GUI::CheckboxWidget *_snapToBorderCheckbox;
- GUI::CheckboxWidget* _hardScaler;
- GUI::CheckboxWidget* _cpuScaler;
+ GUI::CheckboxWidget *_hardScaler;
+ GUI::CheckboxWidget *_cpuScaler;
- GUI::CheckboxWidget* _touchPadStyle;
- GUI::CheckboxWidget* _screenTaps;
+ GUI::CheckboxWidget *_touchPadStyle;
+ GUI::CheckboxWidget *_screenTaps;
bool _radioButtonMode;
@@ -78,6 +81,6 @@ protected:
extern void showOptionsDialog();
extern void setOptions();
-}
+} // End of namespace DS
#endif
diff --git a/backends/platform/ds/arm9/source/elf32.h b/backends/platform/ds/arm9/source/elf32.h
deleted file mode 100644
index d72b71664d..0000000000
--- a/backends/platform/ds/arm9/source/elf32.h
+++ /dev/null
@@ -1,196 +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$
- *
- */
-
-#ifndef BACKENDS_ELF_H
-#define BACKENDS_ELF_H
-
-/* ELF stuff */
-
-typedef unsigned short Elf32_Half, Elf32_Section;
-typedef unsigned int Elf32_Word, Elf32_Addr, Elf32_Off;
-typedef signed int Elf32_Sword;
-typedef Elf32_Half Elf32_Versym;
-
-#define EI_NIDENT (16)
-#define SELFMAG 6
-
-/* ELF File format structures. Look up ELF structure for more details */
-
-// ELF header (contains info about the file)
-typedef struct {
- unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
- Elf32_Half e_type; /* Object file type */
- Elf32_Half e_machine; /* Architecture */
- Elf32_Word e_version; /* Object file version */
- Elf32_Addr e_entry; /* Entry point virtual address */
- Elf32_Off e_phoff; /* Program header table file offset */
- Elf32_Off e_shoff; /* Section header table file offset */
- Elf32_Word e_flags; /* Processor-specific flags */
- Elf32_Half e_ehsize; /* ELF header size in bytes */
- Elf32_Half e_phentsize; /* Program header table entry size */
- Elf32_Half e_phnum; /* Program header table entry count */
- Elf32_Half e_shentsize; /* Section header table entry size */
- Elf32_Half e_shnum; /* Section header table entry count */
- Elf32_Half e_shstrndx; /* Section header string table index */
-} Elf32_Ehdr;
-
-// Should be in e_ident
-#define ELFMAG "\177ELF\1\1" /* ELF Magic number */
-
-// e_type values
-#define ET_NONE 0 /* no file type */
-#define ET_REL 1 /* relocatable */
-#define ET_EXEC 2 /* executable */
-#define ET_DYN 3 /* shared object */
-#define ET_CORE 4 /* core file */
-
-// e_machine values
-#define EM_ARM 40
-
-// Program header (contains info about segment)
-typedef struct {
- Elf32_Word p_type; /* Segment type */
- Elf32_Off p_offset; /* Segment file offset */
- Elf32_Addr p_vaddr; /* Segment virtual address */
- Elf32_Addr p_paddr; /* Segment physical address */
- Elf32_Word p_filesz; /* Segment size in file */
- Elf32_Word p_memsz; /* Segment size in memory */
- Elf32_Word p_flags; /* Segment flags */
- Elf32_Word p_align; /* Segment alignment */
-} Elf32_Phdr;
-
-// p_type values
-#define PT_NULL 0 /* ignored */
-#define PT_LOAD 1 /* loadable segment */
-#define PT_DYNAMIC 2 /* dynamic linking info */
-#define PT_INTERP 3 /* info about interpreter */
-#define PT_NOTE 4 /* note segment */
-#define PT_SHLIB 5 /* reserved */
-#define PT_PHDR 6 /* Program header table */
-#define PT_ARM_ARCHEXT 0x70000000 /* Platform architecture compatibility information */
-#define PT_ARM_EXIDX 0x70000001 /* Exception unwind tables */
-
-// p_flags value
-#define PF_X 1 /* execute */
-#define PF_W 2 /* write */
-#define PF_R 4 /* read */
-
-// Section header (contains info about section)
-typedef struct {
- Elf32_Word sh_name; /* Section name (string tbl index) */
- Elf32_Word sh_type; /* Section type */
- Elf32_Word sh_flags; /* Section flags */
- Elf32_Addr sh_addr; /* Section virtual addr at execution */
- Elf32_Off sh_offset; /* Section file offset */
- Elf32_Word sh_size; /* Section size in bytes */
- Elf32_Word sh_link; /* Link to another section */
- Elf32_Word sh_info; /* Additional section information */
- Elf32_Word sh_addralign; /* Section alignment */
- Elf32_Word sh_entsize; /* Entry size if section holds table */
-} Elf32_Shdr;
-
-// sh_type values
-#define SHT_NULL 0 /* Inactive section */
-#define SHT_PROGBITS 1 /* Proprietary */
-#define SHT_SYMTAB 2 /* Symbol table */
-#define SHT_STRTAB 3 /* String table */
-#define SHT_RELA 4 /* Relocation entries with addend */
-#define SHT_HASH 5 /* Symbol hash table */
-#define SHT_DYNAMIC 6 /* Info for dynamic linking */
-#define SHT_NOTE 7 /* Note section */
-#define SHT_NOBITS 8 /* Occupies no space */
-#define SHT_REL 9 /* Relocation entries without addend */
-#define SHT_SHLIB 10 /* Reserved */
-#define SHT_DYNSYM 11 /* Minimal set of dynamic linking symbols */
-#define SHT_ARM_EXIDX 0x70000001 /* Exception Index table */
-#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking pre-emption map */
-#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility attributes */
-
-// sh_flags values
-#define SHF_WRITE 0 /* writable section */
-#define SHF_ALLOC 2 /* section occupies memory */
-#define SHF_EXECINSTR 4 /* machine instructions */
-
-// Symbol entry (contain info about a symbol)
-typedef struct {
- Elf32_Word st_name; /* Symbol name (string tbl index) */
- Elf32_Addr st_value; /* Symbol value */
- Elf32_Word st_size; /* Symbol size */
- unsigned char st_info; /* Symbol type and binding */
- unsigned char st_other; /* Symbol visibility */
- Elf32_Section st_shndx; /* Section index */
-} Elf32_Sym;
-
-// Extract from the st_info
-#define SYM_TYPE(x) ((x)&0xF)
-#define SYM_BIND(x) ((x)>>4)
-
-// Symbol binding values from st_info
-#define STB_LOCAL 0 /* Symbol not visible outside object */
-#define STB_GLOBAL 1 /* Symbol visible to all object files */
-#define STB_WEAK 2 /* Similar to STB_GLOBAL */
-
-// Symbol type values from st_info
-#define STT_NOTYPE 0 /* Not specified */
-#define STT_OBJECT 1 /* Data object e.g. variable */
-#define STT_FUNC 2 /* Function */
-#define STT_SECTION 3 /* Section */
-#define STT_FILE 4 /* Source file associated with object file */
-
-// Special section header index values from st_shndex
-#define SHN_UNDEF 0
-#define SHN_LOPROC 0xFF00 /* Extended values */
-#define SHN_ABS 0xFFF1 /* Absolute value: don't relocate */
-#define SHN_COMMON 0xFFF2 /* Common block. Not allocated yet */
-#define SHN_HIPROC 0xFF1F
-#define SHN_HIRESERVE 0xFFFF
-
-// Relocation entry (info about how to relocate)
-typedef struct {
- Elf32_Addr r_offset; /* Address */
- Elf32_Word r_info; /* Relocation type and symbol index */
-} Elf32_Rel;
-
-typedef struct
-{
- Elf32_Addr r_offset; /* Address */
- Elf32_Word r_info; /* Relocation type and symbol index */
- Elf32_Sword r_addend; /* Addend */
-} Elf32_Rela;
-
-// Access macros for the relocation info
-#define REL_TYPE(x) ((unsigned char) (x)) /* Extract relocation type */
-#define REL_INDEX(x) ((x)>>8) /* Extract relocation index into symbol table */
-
-// ARM relocation types
-#define R_ARM_NONE 0
-#define R_ARM_ABS32 2
-#define R_ARM_THM_CALL 10
-#define R_ARM_CALL 28
-#define R_ARM_JUMP24 29
-#define R_ARM_TARGET1 38
-#define R_ARM_V4BX 40
-
-#endif /* BACKENDS_ELF_H */
diff --git a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c
index b70d9e7b99..07affd8839 100644
--- a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c
+++ b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c
@@ -294,9 +294,9 @@ u16 getRTCtoFileTime (void)
{
#ifdef NDS
return (
- ( ( (IPC->rtc_hours > 11 ? IPC->rtc_hours - 40 : IPC->rtc_hours) & 0x1F) << 11) |
- ( (IPC->rtc_minutes & 0x3F) << 5) |
- ( (IPC->rtc_seconds >> 1) & 0x1F) );
+ ( ( (IPC->rtc.hours > 11 ? IPC->rtc.hours - 40 : IPC->rtc.hours) & 0x1F) << 11) |
+ ( (IPC->rtc.minutes & 0x3F) << 5) |
+ ( (IPC->rtc.seconds >> 1) & 0x1F) );
#else
return 0;
#endif
@@ -306,9 +306,9 @@ u16 getRTCtoFileDate (void)
{
#ifdef NDS
return (
- ( ((IPC->rtc_year + 20) & 0x7F) <<9) |
- ( (IPC->rtc_month & 0xF) << 5) |
- (IPC->rtc_day & 0x1F) );
+ ( ((IPC->rtc.year + 20) & 0x7F) <<9) |
+ ( (IPC->rtc.month & 0xF) << 5) |
+ (IPC->rtc.day & 0x1F) );
#else
return 0;
#endif
diff --git a/backends/platform/ds/arm9/source/gbampsave.cpp b/backends/platform/ds/arm9/source/gbampsave.cpp
index 820e569555..d0fb8fff3b 100644
--- a/backends/platform/ds/arm9/source/gbampsave.cpp
+++ b/backends/platform/ds/arm9/source/gbampsave.cpp
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -29,7 +32,7 @@
// GBAMP Save File
/////////////////////////
-GBAMPSaveFile::GBAMPSaveFile(char* name, bool saveOrLoad) {
+GBAMPSaveFile::GBAMPSaveFile(char *name, bool saveOrLoad) {
handle = DS::std_fopen(name, saveOrLoad? "w": "r");
// consolePrintf("%s handle is %d\n", name, handle);
// consolePrintf("Created %s\n", name);
@@ -44,10 +47,10 @@ GBAMPSaveFile::~GBAMPSaveFile() {
// consolePrintf("Closed file\n");
}
-uint32 GBAMPSaveFile::read(void *buf, uint32 size) {
- saveSize += size;
-// consolePrintf("Read %d %d ", size, saveSize);
- return DS::std_fread(buf, 1, size, handle);
+uint32 GBAMPSaveFile::read(void *buf, uint32 length) {
+ saveSize += length;
+// consolePrintf("Read %d %d ", length, saveSize);
+ return DS::std_fread(buf, 1, length, handle);
}
bool GBAMPSaveFile::eos() const {
@@ -74,27 +77,27 @@ int32 GBAMPSaveFile::pos() const {
int32 GBAMPSaveFile::size() const {
int position = pos();
DS::std_fseek(handle, 0, SEEK_END);
- int size = DS::std_ftell(handle);
+ int length = DS::std_ftell(handle);
DS::std_fseek(handle, position, SEEK_SET);
- return size;
+ return length;
}
-bool GBAMPSaveFile::seek(int32 pos, int whence) {
- return DS::std_fseek(handle, pos, whence) == 0;
+bool GBAMPSaveFile::seek(int32 newPos, int whence) {
+ return DS::std_fseek(handle, newPos, whence) == 0;
}
-uint32 GBAMPSaveFile::write(const void *buf, uint32 size) {
- if (bufferPos + size > SAVE_BUFFER_SIZE) {
+uint32 GBAMPSaveFile::write(const void *buf, uint32 length) {
+ if (bufferPos + length > SAVE_BUFFER_SIZE) {
flushSaveBuffer();
- saveSize += size;
-// consolePrintf("Writing %d bytes from %x", size, buf);
-// DS::std_fwrite(buf, 1, size, handle);
+ saveSize += length;
+// consolePrintf("Writing %d bytes from %x", length, buf);
+// DS::std_fwrite(buf, 1, length, handle);
- memcpy(buffer + bufferPos, buf, size);
- bufferPos += size;
+ memcpy(buffer + bufferPos, buf, length);
+ bufferPos += length;
- saveSize += size;
+ saveSize += length;
/* int pos = 0;
@@ -104,31 +107,31 @@ uint32 GBAMPSaveFile::write(const void *buf, uint32 size) {
bufferPos = 512;
pos += rest;
flushSaveBuffer();
- size -= rest;
+ length -= rest;
// consolePrintf("First section: %d\n", rest);
- while (size >= 512) {
+ while (length >= 512) {
DS::std_fwrite(((char *) (buf)) + pos, 1, 512, handle);
- size -= 512;
+ length -= 512;
pos += 512;
-// consolePrintf("Full chunk, %d left ", size);
+// consolePrintf("Full chunk, %d left ", length);
}
bufferPos = 0;
- memcpy(buffer + bufferPos, ((char *) (buf)) + pos, size);
- bufferPos += size;
+ memcpy(buffer + bufferPos, ((char *) (buf)) + pos, length);
+ bufferPos += length;
// consolePrintf("%d left in buffer ", bufferPos);*/
} else {
- memcpy(buffer + bufferPos, buf, size);
- bufferPos += size;
+ memcpy(buffer + bufferPos, buf, length);
+ bufferPos += length;
- saveSize += size;
+ saveSize += length;
}
-// if ((size > 100) || (size <= 0)) consolePrintf("Write %d bytes\n", size);
- return size;
+// if ((length > 100) || (length <= 0)) consolePrintf("Write %d bytes\n", length);
+ return length;
}
@@ -196,7 +199,7 @@ Common::StringArray GBAMPSaveFileManager::listSavefiles(const Common::String &pa
// consolePrintf("Real cwd:%d\n", realName);
- char* p = realName;
+ char *p = realName;
while (*p) {
if (*p == '\\') *p = '/';
p++;
diff --git a/backends/platform/ds/arm9/source/gbampsave.h b/backends/platform/ds/arm9/source/gbampsave.h
index bc4fdaa1a4..ad929236cd 100644
--- a/backends/platform/ds/arm9/source/gbampsave.h
+++ b/backends/platform/ds/arm9/source/gbampsave.h
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -24,19 +27,20 @@
#define _GBAMPSAVE_H_
#include "common/system.h"
+#include "common/savefile.h"
#include "backends/fs/ds/ds-fs.h"
#define SAVE_BUFFER_SIZE 100000
class GBAMPSaveFile : public Common::InSaveFile, public Common::OutSaveFile {
- DS::fileHandle* handle;
+ DS::fileHandle *handle;
char buffer[SAVE_BUFFER_SIZE];
int bufferPos;
int saveSize;
int flushed;
public:
- GBAMPSaveFile(char* name, bool saveOrLoad);
+ GBAMPSaveFile(char *name, bool saveOrLoad);
virtual ~GBAMPSaveFile();
virtual uint32 read(void *buf, uint32 size);
@@ -62,12 +66,12 @@ public:
GBAMPSaveFileManager();
~GBAMPSaveFileManager();
-// static GBAMPSaveFileManager* instance() { return instancePtr; }
+// static GBAMPSaveFileManager *instance() { return instancePtr; }
GBAMPSaveFile *openSavefile(const char *filename, bool saveOrLoad);
- virtual Common::OutSaveFile* openForSaving(const Common::String &filename) { return openSavefile(filename.c_str(), true); }
- virtual Common::InSaveFile* openForLoading(const Common::String &filename) { return openSavefile(filename.c_str(), false); }
+ virtual Common::OutSaveFile *openForSaving(const Common::String &filename) { return openSavefile(filename.c_str(), true); }
+ virtual Common::InSaveFile *openForLoading(const Common::String &filename) { return openSavefile(filename.c_str(), false); }
virtual bool removeSavefile(const Common::String &filename) { return false; } // TODO: Implement this
virtual Common::StringArray listSavefiles(const Common::String &pattern);
diff --git a/backends/platform/ds/arm9/source/keys.cpp b/backends/platform/ds/arm9/source/keys.cpp
index 63fae866e5..2f8497ab19 100644
--- a/backends/platform/ds/arm9/source/keys.cpp
+++ b/backends/platform/ds/arm9/source/keys.cpp
@@ -74,7 +74,6 @@
#include <nds/system.h>
#include <nds/arm9/input.h>
-//------------------------------------------------------------------------------
#define KEYS_CUR (( ((~REG_KEYINPUT)&0x3ff) | (((~IPC->buttons)&3)<<10) | (((~IPC->buttons)<<6) & (KEY_TOUCH|KEY_LID) ))^KEY_LID)
@@ -89,63 +88,50 @@ static u8 delay = 60, repeat = 30, count = 60;
static uint16 oldx = 0;
static uint16 oldy = 0;
-//------------------------------------------------------------------------------
void scanKeys(void) {
-//------------------------------------------------------------------------------
keysold = keys;
keys = KEYS_CUR;
oldx = IPC->touchXpx;
oldy = IPC->touchYpx;
- if ( delay != 0 ) {
- if ( keys != keysold ) {
- count = delay ;
- keysrepeat = keysDown() ;
+ if (delay != 0) {
+ if (keys != keysold) {
+ count = delay;
+ keysrepeat = keysDown();
}
count--;
- if ( count == 0 ) {
+ if (count == 0) {
count = repeat;
keysrepeat = keys;
}
}
}
-//------------------------------------------------------------------------------
uint32 keysHeld(void) {
-//------------------------------------------------------------------------------
return keys;
}
-//------------------------------------------------------------------------------
uint32 keysDown(void) {
-//------------------------------------------------------------------------------
return (keys ^ keysold) & keys;
}
-//------------------------------------------------------------------------------
uint32 keysDownRepeat(void) {
-//------------------------------------------------------------------------------
uint32 tmp = keysrepeat;
-
keysrepeat = 0;
-
return tmp;
}
-//------------------------------------------------------------------------------
void keysSetRepeat( u8 setDelay, u8 setRepeat ) {
-//------------------------------------------------------------------------------
- delay = setDelay ;
- repeat = setRepeat ;
- count = delay ;
- keysrepeat = 0 ;
+ delay = setDelay;
+ repeat = setRepeat;
+ count = delay;
+ keysrepeat = 0;
}
-//------------------------------------------------------------------------------
uint32 keysUp(void) {
-//------------------------------------------------------------------------------
return (keys ^ keysold) & (~keys);
}
-} // namespace ds
+} // End of namespace DS
+
diff --git a/backends/platform/ds/arm9/source/keys.h b/backends/platform/ds/arm9/source/keys.h
index e0f28a12cf..8d08014232 100644
--- a/backends/platform/ds/arm9/source/keys.h
+++ b/backends/platform/ds/arm9/source/keys.h
@@ -1,4 +1,27 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
namespace DS {
@@ -7,7 +30,7 @@ void scanKeys(void);
uint32 keysHeld(void);
uint32 keysDown(void);
uint32 keysDownRepeat(void);
-void keysSetRepeat( u8 setDelay, u8 setRepeat );
+void keysSetRepeat(u8 setDelay, u8 setRepeat);
uint32 keysUp(void);
-}
+} // End of namespace DS
diff --git a/backends/platform/ds/arm9/source/libcartreset/cartreset.c b/backends/platform/ds/arm9/source/libcartreset/cartreset.c
deleted file mode 100644
index 6fb906b86d..0000000000
--- a/backends/platform/ds/arm9/source/libcartreset/cartreset.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/**********************************
- Copyright (C) Rick Wong (Lick)
- http://licklick.wordpress.com/
-***********************************/
-#include <cartreset_nolibfat.h>
-
-
-#ifdef ARM9
-
-bool cartSetMenuMode(u32 _deviceType)
-{
- *(vu16*)(0x04000204) &= ~0x0880; //sysSetBusOwners(true, true);
- u32 deviceType = _deviceType;
-
- *((vu32*)0x027FFFF8) = 0x080000C0; // ARM7 reset address
-
- if(deviceType == DEVICE_TYPE_EFA2)
- {
- *(u16 *)0x9FE0000 = 0xD200;
- *(u16 *)0x8000000 = 0x1500;
- *(u16 *)0x8020000 = 0xD200;
- *(u16 *)0x8040000 = 0x1500;
- *(u16 *)0x9880000 = 1 << 15;
- *(u16 *)0x9FC0000 = 0x1500;
- return true;
- }
- else if(deviceType == DEVICE_TYPE_MPCF)
- {
- return true;
- }
- else if(deviceType == DEVICE_TYPE_EZSD)
- {
- return true;
- }
- else if(deviceType == DEVICE_TYPE_M3CF || deviceType == DEVICE_TYPE_M3SD)
- {
- u32 mode = 0x00400004;
- vu16 tmp;
- tmp = *(vu16*)(0x08E00002);
- tmp = *(vu16*)(0x0800000E);
- tmp = *(vu16*)(0x08801FFC);
- tmp = *(vu16*)(0x0800104A);
- tmp = *(vu16*)(0x08800612);
- tmp = *(vu16*)(0x08000000);
- tmp = *(vu16*)(0x08801B66);
- tmp = *(vu16*)(0x08000000 + (mode << 1));
- tmp = *(vu16*)(0x0800080E);
- tmp = *(vu16*)(0x08000000);
-
- tmp = *(vu16*)(0x080001E4);
- tmp = *(vu16*)(0x080001E4);
- tmp = *(vu16*)(0x08000188);
- tmp = *(vu16*)(0x08000188);
- return true;
- }
- else if(deviceType == DEVICE_TYPE_SCCF || deviceType == DEVICE_TYPE_SCSD)
- {
- *(vu16*)0x09FFFFFE = 0xA55A;
- *(vu16*)0x09FFFFFE = 0xA55A;
- *(vu16*)0x09FFFFFE = 0;
- *(vu16*)0x09FFFFFE = 0;
- *((vu32*)0x027FFFF8) = 0x08000000; // Special ARM7 reset address
- return true;
- }
-
- return false;
-}
-
-
-
-void passmeloopEnter()
-{
- *(vu16*)(0x04000208) = 0; //REG_IME = IME_DISABLE;
- *(vu16*)(0x04000204) |= 0x0880; //sysSetBusOwners(false, false);
- *((vu32*)0x027FFFFC) = 0;
- *((vu32*)0x027FFE04) = (u32)0xE59FF018;
- *((vu32*)0x027FFE24) = (u32)0x027FFE04;
- asm("swi 0x00"); //swiSoftReset();
- asm("bx lr");
-}
-
-#endif
-
-
-#ifdef ARM7
-
-bool passmeloopQuery()
-{
- if(*((vu32*)0x027FFE24) == (u32)0x027FFE04)
- return true;
- return false;
-}
-
-
-
-void cartExecute()
-{
- *(vu16*)(0x04000208) = 0; //REG_IME = IME_DISABLE;
- *((vu32*)0x027FFE34) = *((vu32*)0x027FFFF8);
- asm("swi 0x00"); //swiSoftReset();
- asm("bx lr");
-}
-
-#endif
-
-
-
diff --git a/backends/platform/ds/arm9/source/libcartreset/cartreset_nolibfat.h b/backends/platform/ds/arm9/source/libcartreset/cartreset_nolibfat.h
deleted file mode 100644
index ddc4b1d4c2..0000000000
--- a/backends/platform/ds/arm9/source/libcartreset/cartreset_nolibfat.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/**********************************
- Copyright (C) Rick Wong (Lick)
- http://licklick.wordpress.com/
-***********************************/
-#ifndef CARTRESET_H
-#define CARTRESET_H
-
-//#include <fat.h>
-#include <nds.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef ARM9
-// Auto detect:
-#define DEVICE_TYPE_AUTO 0x00000000 // doesn't work in libcartreset "nolibfat" version
-
-// Not supported:
-#define DEVICE_TYPE_FCSR 0x52534346
-#define DEVICE_TYPE_MMCF 0x46434D4D
-#define DEVICE_TYPE_NJSD 0x44534A4E
-#define DEVICE_TYPE_NMMC 0x434D4D4E
-
-// Supported:
-#define DEVICE_TYPE_EFA2 0x32414645
-#define DEVICE_TYPE_MPCF 0x4643504D
-#define DEVICE_TYPE_M3CF 0x4643334D
-#define DEVICE_TYPE_M3SD 0x4453334D
-#define DEVICE_TYPE_SCCF 0x46434353
-#define DEVICE_TYPE_SCSD 0x44534353
-
-// Supported, but libfat doesn't detect the device:
-#define DEVICE_TYPE_EZSD 0x44535A45
-
-
-bool cartSetMenuMode(u32 _deviceType);
-void passmeloopEnter();
-
-#endif
-
-
-#ifdef ARM7
-
-bool passmeloopQuery();
-void cartExecute();
-
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp
index 691fb2ec7a..c4ff241de0 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -66,9 +66,14 @@
#define DEFAULT_CONFIG_FILE "scummvmj.ini"
#elif defined(DS_BUILD_K)
#define DEFAULT_CONFIG_FILE "scummvmk.ini"
+#else
+ // Use the "scummvm.ini" as config file if no build was specified. This
+ // currently only happens with builds made using the regular ScummVM build
+ // system (as opposed to the nds specific build system).
+#define DEFAULT_CONFIG_FILE "scummvm.ini"
#endif
-OSystem_DS* OSystem_DS::_instance = NULL;
+OSystem_DS *OSystem_DS::_instance = NULL;
OSystem_DS::OSystem_DS()
: eventNum(0), lastPenFrame(0), queuePos(0), _mixer(NULL), _timer(NULL), _frameBufferExists(false),
@@ -128,7 +133,7 @@ bool OSystem_DS::getFeatureState(Feature f) {
return false;
}
-const OSystem::GraphicsMode* OSystem_DS::getSupportedGraphicsModes() const {
+const OSystem::GraphicsMode *OSystem_DS::getSupportedGraphicsModes() const {
return s_supportedGraphicsModes;
}
@@ -203,8 +208,7 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
}
}
-void OSystem_DS::restoreHardwarePalette()
-{
+void OSystem_DS::restoreHardwarePalette() {
// Set the hardware palette up based on the stored palette
for (int r = 0; r < 255; r++) {
@@ -238,13 +242,13 @@ void OSystem_DS::setCursorPalette(const byte *colors, uint start, uint num) {
refreshCursor();
}
-bool OSystem_DS::grabRawScreen(Graphics::Surface* surf) {
+bool OSystem_DS::grabRawScreen(Graphics::Surface *surf) {
surf->create(DS::getGameWidth(), DS::getGameHeight(), 1);
// Ensure we copy using 16 bit quantities due to limitation of VRAM addressing
- const u16* image = (const u16 *) DS::get8BitBackBuffer();
+ const u16 *image = (const u16 *) DS::get8BitBackBuffer();
for (int y = 0; y < DS::getGameHeight(); y++) {
DC_FlushRange(image + (y << 8), DS::getGameWidth());
for (int x = 0; x < DS::getGameWidth() >> 1; x++) {
@@ -277,9 +281,9 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
// consolePrintf("CopyRectToScreen %d\n", w * h);
- u16* bg;
+ u16 *bg;
s32 stride;
- u16* bgSub = (u16 *)BG_GFX_SUB;
+ 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.
@@ -304,14 +308,14 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
// the keyboard image uses the same VRAM addresses.
for (int dy = y; dy < y + h; dy++) {
- u8* dest = ((u8 *) (bg)) + (dy * stride) + x;
- u8* src = (u8 *) buf + (pitch * by);
+ u8 *dest = ((u8 *) (bg)) + (dy * stride) + x;
+ const u8 *src = (const u8 *) buf + (pitch * by);
u32 dx;
u32 pixelsLeft = w;
- if (MISALIGNED16(dest)) {
+ if (MISALIGNED16(dest)) {
// Read modify write
dest--;
@@ -326,9 +330,9 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
}
// We can now assume dest is aligned
- u16* dest16 = (u16 *) dest;
+ u16 *dest16 = (u16 *) dest;
- for (dx = 0; dx < pixelsLeft; dx+=2) {
+ for (dx = 0; dx < pixelsLeft; dx+=2) {
u16 mix;
mix = *src + (*(src + 1) << 8);
@@ -355,15 +359,15 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
// When they keyboard is not on screen, update both vram copies
for (int dy = y; dy < y + h; dy++) {
- u8* dest = ((u8 *) (bg)) + (dy * stride) + x;
- u8* destSub = ((u8 *) (bgSub)) + (dy * 512) + x;
- u8* src = (u8 *) buf + (pitch * by);
+ u8 *dest = ((u8 *) (bg)) + (dy * stride) + x;
+ u8 *destSub = ((u8 *) (bgSub)) + (dy * 512) + x;
+ const u8 *src = (const u8 *) buf + (pitch * by);
u32 dx;
u32 pixelsLeft = w;
- if (MISALIGNED16(dest)) {
+ if (MISALIGNED16(dest)) {
// Read modify write
dest--;
@@ -380,10 +384,10 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
}
// We can now assume dest is aligned
- u16* dest16 = (u16 *) dest;
- u16* destSub16 = (u16 *) destSub;
+ u16 *dest16 = (u16 *) dest;
+ u16 *destSub16 = (u16 *) destSub;
- for (dx = 0; dx < pixelsLeft; dx+=2) {
+ for (dx = 0; dx < pixelsLeft; dx+=2) {
u16 mix;
mix = *src + (*(src + 1) << 8);
@@ -417,12 +421,12 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
// Stuff is aligned to 16-bit boundaries, so it's safe to do DMA.
- u16* src = (u16 *) buf;
+ u16 *src = (u16 *) buf;
if (DS::getKeyboardEnable()) {
for (int dy = y; dy < y + h; dy++) {
- u16* dest = bg + (dy * (stride >> 1)) + (x >> 1);
+ u16 *dest = bg + (dy * (stride >> 1)) + (x >> 1);
DC_FlushRange(src, w << 1);
DC_FlushRange(dest, w << 1);
@@ -435,8 +439,8 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
} else {
for (int dy = y; dy < y + h; dy++) {
- u16* dest1 = bg + (dy * (stride >> 1)) + (x >> 1);
- u16* dest2 = bgSub + (dy << 8) + (x >> 1);
+ 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);
@@ -458,7 +462,7 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
}
void OSystem_DS::updateScreen() {
- static int cnt = 0;
+// static int cnt = 0;
// consolePrintf("updatescr %d\n", cnt++);
if ((_frameBufferExists) && (DS::getIsDisplayMode8Bit())) {
@@ -498,13 +502,13 @@ void OSystem_DS::clearOverlay() {
// consolePrintf("clearovl\n");
}
-void OSystem_DS::grabOverlay(OverlayColor* buf, int pitch) {
+void OSystem_DS::grabOverlay(OverlayColor *buf, int pitch) {
// consolePrintf("grabovl\n")
- u16* start = DS::get16BitBackBuffer();
+ u16 *start = DS::get16BitBackBuffer();
for (int y = 0; y < 200; y++) {
- u16* src = start + (y * 320);
- u16* dest = ((u16 *) (buf)) + (y * pitch);
+ u16 *src = start + (y * 320);
+ u16 *dest = ((u16 *) (buf)) + (y * pitch);
for (int x = 0; x < 320; x++) {
*dest++ = *src++;
@@ -514,8 +518,8 @@ void OSystem_DS::grabOverlay(OverlayColor* buf, int pitch) {
}
void OSystem_DS::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
- u16* bg = (u16 *) DS::get16BitBackBuffer();
- const u16* src = (const u16 *) buf;
+ u16 *bg = (u16 *) DS::get16BitBackBuffer();
+ const u16 *src = (const u16 *) buf;
// if (x + w > 256) w = 256 - x;
//if (x + h > 256) h = 256 - y;
@@ -586,7 +590,7 @@ void OSystem_DS::refreshCursor() {
DS::setCursorIcon(_cursorImage, _cursorW, _cursorH, _cursorKey, _cursorHotX, _cursorHotY);
}
-void OSystem_DS::addEvent(Common::Event& e) {
+void OSystem_DS::addEvent(const Common::Event& e) {
eventQueue[queuePos++] = e;
}
@@ -724,31 +728,15 @@ void OSystem_DS::quit() {
swiSoftReset();*/
}
-Common::SaveFileManager* OSystem_DS::getSavefileManager() {
- bool forceSram;
-
- if (ConfMan.hasKey("forcesramsave", "ds")) {
- forceSram = ConfMan.getBool("forcesramsave", "ds");
- } else {
- forceSram = false;
- }
- if (forceSram) {
- consolePrintf("Using SRAM save method!\n");
- }
-
- if (DS::isGBAMPAvailable() && (!forceSram)) {
+Common::SaveFileManager *OSystem_DS::getSavefileManager() {
+ if (DS::isGBAMPAvailable()) {
return &mpSaveManager;
- } else {
-#ifdef GBA_SRAM_SAVE
- return &saveManager;
-#else
- return NULL;
-#endif
}
+ return NULL;
}
-Graphics::Surface* OSystem_DS::createTempFrameBuffer() {
+Graphics::Surface *OSystem_DS::createTempFrameBuffer() {
// Ensure we copy using 16 bit quantities due to limitation of VRAM addressing
@@ -773,13 +761,13 @@ Graphics::Surface* OSystem_DS::createTempFrameBuffer() {
s32 width = DS::getGameWidth();
s32 stride = DS::get8BitBackBufferStride();
- u16* src = DS::get8BitBackBuffer();
- u16* dest = DS::getScalerBuffer();
+ u16 *src = DS::get8BitBackBuffer();
+ u16 *dest = DS::getScalerBuffer();
for (int y = 0; y < height; y++) {
- u16* destLine = dest + (y * (width / 2));
- u16* srcLine = src + (y * (stride / 2));
+ u16 *destLine = dest + (y * (width / 2));
+ u16 *srcLine = src + (y * (stride / 2));
DC_FlushRange(srcLine, width);
@@ -800,7 +788,7 @@ Graphics::Surface* OSystem_DS::createTempFrameBuffer() {
size_t imageStrideInBytes = DS::get8BitBackBufferStride();
size_t imageStrideInWords = imageStrideInBytes / 2;
- u16* image = (u16 *) DS::get8BitBackBuffer();
+ u16 *image = (u16 *) DS::get8BitBackBuffer();
for (int y = 0; y < DS::getGameHeight(); y++) {
DC_FlushRange(image + (y * imageStrideInWords), DS::getGameWidth());
for (int x = 0; x < DS::getGameWidth() >> 1; x++) {
@@ -846,13 +834,13 @@ void OSystem_DS::setCharactersEntered(int count) {
DS::setCharactersEntered(count);
}
-Common::SeekableReadStream* OSystem_DS::createConfigReadStream() {
+Common::SeekableReadStream *OSystem_DS::createConfigReadStream() {
Common::FSNode file(DEFAULT_CONFIG_FILE);
// consolePrintf("R %s", DEFAULT_CONFIG_FILE);
return file.createReadStream();
}
-Common::WriteStream* OSystem_DS::createConfigWriteStream() {
+Common::WriteStream *OSystem_DS::createConfigWriteStream() {
Common::FSNode file(DEFAULT_CONFIG_FILE);
// consolePrintf("W %s", DEFAULT_CONFIG_FILE);
return file.createWriteStream();
diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h
index 10b4c87f66..65ac3f4f7e 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.h
+++ b/backends/platform/ds/arm9/source/osystem_ds.h
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -27,7 +30,6 @@
#include "backends/base-backend.h"
#include "common/events.h"
#include "nds.h"
-#include "ramsave.h"
#include "gbampsave.h"
#include "backends/saves/default/default-saves.h"
#include "backends/timer/default/default-timer.h"
@@ -44,17 +46,14 @@ protected:
Common::Event eventQueue[96];
int queuePos;
-#ifdef GBA_SRAM_SAVE
- DSSaveFileManager saveManager;
-#endif
GBAMPSaveFileManager mpSaveManager;
- Audio::MixerImpl* _mixer;
- DefaultTimerManager* _timer;
+ Audio::MixerImpl *_mixer;
+ DefaultTimerManager *_timer;
Graphics::Surface _framebuffer;
bool _frameBufferExists;
bool _graphicsEnable;
- static OSystem_DS* _instance;
+ static OSystem_DS *_instance;
u16 _palette[256];
u16 _cursorPalette[256];
@@ -68,7 +67,7 @@ protected:
int _cursorScale;
- Graphics::Surface* createTempFrameBuffer();
+ Graphics::Surface *createTempFrameBuffer();
bool _disableCursorPalette;
int _gammaValue;
@@ -94,7 +93,7 @@ public:
virtual int16 getHeight();
virtual int16 getWidth();
virtual void setPalette(const byte *colors, uint start, uint num);
- virtual void grabPalette(unsigned char* colors, uint start, uint num);
+ virtual void grabPalette(unsigned char *colors, uint start, uint num);
void restoreHardwarePalette();
virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
@@ -136,10 +135,10 @@ public:
virtual Common::SaveFileManager *getSavefileManager();
- void addEvent(Common::Event& e);
- bool isEventQueueEmpty() { return queuePos == 0; }
+ void addEvent(const Common::Event& e);
+ bool isEventQueueEmpty() const { return queuePos == 0; }
- virtual bool grabRawScreen(Graphics::Surface* surf);
+ virtual bool grabRawScreen(Graphics::Surface *surf);
virtual void setFocusRectangle(const Common::Rect& rect);
@@ -150,10 +149,10 @@ public:
virtual Graphics::Surface *lockScreen();
virtual void unlockScreen();
- virtual Audio::Mixer* getMixer() { return _mixer; }
- Audio::MixerImpl* getMixerImpl() { return _mixer; }
+ virtual Audio::Mixer *getMixer() { return _mixer; }
+ Audio::MixerImpl *getMixerImpl() { return _mixer; }
- virtual Common::TimerManager* getTimerManager() { return _timer; }
+ virtual Common::TimerManager *getTimerManager() { return _timer; }
static int timerHandler(int t);
@@ -161,8 +160,8 @@ 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]; }
+ u16 getDSPaletteEntry(u32 entry) const { return _palette[entry]; }
+ u16 getDSCursorPaletteEntry(u32 entry) const { return !_disableCursorPalette? _cursorPalette[entry]: _palette[entry]; }
virtual void setCursorPalette(const byte *colors, uint start, uint num);
@@ -172,8 +171,8 @@ public:
void refreshCursor();
- Common::WriteStream* createConfigWriteStream();
- Common::SeekableReadStream* createConfigReadStream();
+ Common::WriteStream *createConfigWriteStream();
+ Common::SeekableReadStream *createConfigReadStream();
u16 applyGamma(u16 colour);
void setGammaValue(int gamma) { _gammaValue = gamma; }
diff --git a/backends/platform/ds/arm9/source/portdefs.cpp b/backends/platform/ds/arm9/source/portdefs.cpp
deleted file mode 100644
index 0dcdc1d5a3..0000000000
--- a/backends/platform/ds/arm9/source/portdefs.cpp
+++ /dev/null
@@ -1,35 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#include <string.h>
-#include "nds/dma.h"
-#include "osystem_ds.h"
-
-/*
-extern "C" time_t __wrap_time(time_t* t) {
- if (t) {
- *t = OSystem_DS::instance()->getMillis() / 1000;
- }
-
- return OSystem_DS::instance()->getMillis() / 1000;
-}
-*/
diff --git a/backends/platform/ds/arm9/source/portdefs.h b/backends/platform/ds/arm9/source/portdefs.h
index 5472b711b8..cc38d66a73 100644
--- a/backends/platform/ds/arm9/source/portdefs.h
+++ b/backends/platform/ds/arm9/source/portdefs.h
@@ -8,39 +8,29 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
#ifndef _PORTDEFS_H_
#define _PORTDEFS_H_
-
-
-/*
-typedef unsigned char u8;
-typedef signed char s8;
-
-typedef unsigned short u16;
-typedef signed short s16;
-
-typedef unsigned int u32;
-typedef signed int s32;
-*/
-
+// Include ndstypes.h for uint16 etc. typedefs
#include "nds/ndstypes.h"
-
-// Somebody removed these from scummsys.h, but they're still required, so I'm adding them here
-// in the hope that they'll stay.
+// Somebody removed these from scummsys.h, but they're still required, so I'm
+// adding them here in the hope that they'll stay.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -50,18 +40,21 @@ typedef signed int s32;
#define double float
-#define CT_NO_TRANSPARENCY
-
+#ifndef DISABLE_TEXT_CONSOLE
#define DISABLE_TEXT_CONSOLE
+#endif
+
+#ifndef DISABLE_COMMAND_LINE
#define DISABLE_COMMAND_LINE
+#endif
+#ifndef STREAM_AUDIO_FROM_DISK
#define STREAM_AUDIO_FROM_DISK
+#endif
-//#undef assert
-//#define assert(expr) consolePrintf("Asserted!")
+// FIXME: What is "NO_DEBUG_MSGS" good for?
#define NO_DEBUG_MSGS
-
// This is defined in dsmain.cpp
#ifdef __cplusplus
extern "C" {
@@ -76,14 +69,22 @@ void consolePrintf(const char *format, ...);
#undef assert
#endif
-#define assert(s) if (!(s)) consolePrintf("Assertion failed: '##s##' at file %s, line %d\n", __FILE__, __LINE__)
+#ifdef NDEBUG
-//#include "ds-fs.h"
+#define assert(e) ((void)0)
-//#define debug(fmt, ...) consolePrintf(fmt, ##__VA_ARGS__)
-//#define debug(fmt, ...) debug(0, fmt, ##__VA_ARGS__)
+#else
-#define ITCM_DATA __attribute__((section(".itcm")))
+// FIXME: Shouldn't assert() also bail out / exit / halt the program? Right now we just
+// print an error message...
+#define assert(s) \
+ do { \
+ if (!(s)) { \
+ consolePrintf("Assertion failed: '##s##' at file %s, line %d\n", __FILE__, __LINE__); \
+ } \
+ } while (0)
+
+#endif
// FIXME: 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
diff --git a/backends/platform/ds/arm9/source/ramsave.cpp b/backends/platform/ds/arm9/source/ramsave.cpp
deleted file mode 100644
index a0f4633988..0000000000
--- a/backends/platform/ds/arm9/source/ramsave.cpp
+++ /dev/null
@@ -1,538 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-#ifdef GBA_SRAM_SAVE
-
-
-#include "ramsave.h"
-#include "nds.h"
-#include "compressor/lz.h"
-
-#define CART_RAM ((vu8 *) (0x0A000000))
-#define SRAM_SAVE_MAX (65533)
-
-DSSaveFile::DSSaveFile() {
- ptr = 0;
- saveCompressed = false;
- save.isValid = false;
- ownsData = false;
- isOpenFlag = true;
- isTempFile = false;
-}
-
-DSSaveFile::DSSaveFile(SCUMMSave* s, bool compressed, u8* data) {
- save = *s;
- saveData = data;
- ptr = 0;
- saveCompressed = compressed;
- isOpenFlag = true;
-
- if (saveCompressed) {
- u8* uncompressed = new unsigned char[save.size];
- if (!uncompressed) consolePrintf("Out of memory allocating %d!\n", save.size);
- LZ_Uncompress(saveData, uncompressed, save.compressedSize);
- saveData = uncompressed;
- ownsData = true;
- saveCompressed = false;
-// consolePrintf("Decompressed. name=%s size=%d (%d)", save.name, save.size, save.compressedSize);
-
- } else {
- ownsData = false;
- origHeader = s;
- }
-
- if (save.magic == (int) 0xBEEFCAFE) {
- save.isValid = true;
- } else {
- save.isValid = false;
- }
-
- isTempFile = false;
- eosReached = false;
-}
-
-DSSaveFile::~DSSaveFile() {
- if (!ownsData) {
- *origHeader = save;
- DSSaveFileManager::instance()->flushToSaveRAM();
- }
- if (ownsData) {
- delete[] saveData;
- }
-}
-
-bool DSSaveFile::loadFromSaveRAM(vu8* address) {
-
- SCUMMSave newSave;
-
- for (int t = 0; t < (int) sizeof(newSave); t++) {
- ((char *) (&newSave))[t] = *(address + t);
- }
-
- if (newSave.magic == 0xBEEFCAFE) {
- newSave.isValid = true;
-
- *((u16 *) (0x4000204)) |= 0x3;
-
- saveData = new unsigned char[newSave.compressedSize];
-
- for (int t = 0; t < (int) newSave.compressedSize; t++) {
- ((char *) (saveData))[t] = *(address + t + sizeof(newSave));
- }
-
- if (ownsData) delete[] this->saveData;
- save = newSave;
- saveCompressed = true;
- this->saveData = saveData;
- ownsData = true;
- ptr = 0;
-
- return true;
- }
-
- return false;
-}
-
-void DSSaveFile::compress() {
- if (!saveCompressed) {
- unsigned char* compBuffer = new unsigned char[(save.size * 110) / 100];
- int compSize = LZ_Compress((u8 *) saveData, compBuffer, save.size);
- save.compressedSize = compSize;
-
-
-
- delete[] saveData;
-
- // Make the save smaller
- saveData = (u8 *) realloc(compBuffer, save.compressedSize);
- saveCompressed = true;
- }
-}
-
-int DSSaveFile::saveToSaveRAM(vu8* address) {
-
- unsigned char* compBuffer;
- bool failed;
-
-
- int compSize;
-
- compress();
-
- compSize = save.compressedSize;
- compBuffer = saveData;
-
- if (DSSaveFileManager::instance()->getBytesFree() >= getRamUsage()) {
-
- DSSaveFileManager::instance()->addBytesFree(-getRamUsage());
-
- // Write header
- for (int t = 0; t < sizeof(save); t++) {
- while (*(address + t) != ((char *) (&save))[t]) {
- *(address + t) = ((char *) (&save))[t];
- }
- }
-
- // Write compressed buffer
- for (int t = sizeof(save); t < (int) sizeof(save) + compSize; t++) {
- while (*(address + t) != compBuffer[t - sizeof(save)]) {
- *(address + t) = compBuffer[t - sizeof(save)];
- }
- }
-
- failed = false;
- } else {
- failed = true;
- }
-
-
- return failed? 0: compSize + sizeof(save);
-
-}
-
-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);
-// consolePrintf("byte: %d ", ((u8 *) (buf))[0]);
-
- ptr += size;
- return size;
-}
-
-int32 DSSaveFile::pos() const {
- return ptr;
-}
-
-int32 DSSaveFile::size() const {
- return save.size;
-}
-
-bool DSSaveFile::seek(int32 pos, int whence) {
- switch (whence) {
- case SEEK_SET: {
- ptr = pos;
- break;
- }
- case SEEK_CUR: {
- ptr += pos;
- break;
- }
- case SEEK_END: {
- ptr = save.size + pos;
- break;
- }
- }
- eosReached = false;
- return true;
-}
-
-bool DSSaveFile::eos() const {
- return eosReached;
-}
-
-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) {
-
- if (ptr + size > DS_MAX_SAVE_SIZE) {
- size = DS_MAX_SAVE_SIZE - ptr;
- }
-
- memcpy(saveData + ptr, buf, size);
- ptr += size;
- save.size += size;
- return size;
-}
-
-bool DSSaveFile::matches(const char *prefix, int num) {
- char str[16];
- if (isValid()) {
- sprintf(str, "%s%02d", prefix, num);
- if (!strcmp(str, save.name)) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
-}
-
-bool DSSaveFile::matches(const char *filename) {
- if (isValid()) {
- return !strcmp(save.name, filename);
- } else {
- return false;
- }
-}
-
-void DSSaveFile::setName(char *name) {
- save.isValid = true;
- save.magic = 0xBEEFCAFE;
- ownsData = true;
- save.size = 0;
- save.compressedSize = 0;
- saveData = new unsigned char[DS_MAX_SAVE_SIZE];
- strcpy(save.name, name);
-
- if ((strstr(name, ".s99")) || (strstr(name, ".c"))) {
- isTempFile = true;
- } else {
- isTempFile = false;
- }
-}
-
-void DSSaveFile::clearData() {
- save.size = 0;
-
- if (saveCompressed) {
- if (ownsData) {
- delete[] saveData;
- DSSaveFileManager::instance()->addBytesFree(getRamUsage());
- }
- saveData = new unsigned char[DS_MAX_SAVE_SIZE];
- saveCompressed = false;
- ownsData = true;
- }
-
-}
-
-void DSSaveFile::deleteFile() {
- if (isValid()) {
- if (ownsData) {
- DSSaveFileManager::instance()->addBytesFree(getRamUsage());
- delete[] saveData;
- saveData = NULL;
- }
- ptr = 0;
- saveCompressed = false;
- save.isValid = false;
- ownsData = false;
- isOpenFlag = true;
- }
-}
-
-DSSaveFileManager::DSSaveFileManager() {
- instancePtr = this;
-
- *((u16 *) (0x4000204)) |= 0x3;
- swiWaitForVBlank();
-
- loadAllFromSRAM();
-}
-
-DSSaveFileManager::~DSSaveFileManager() {
- instancePtr = NULL;
-}
-
-void DSSaveFileManager::loadAllFromSRAM() {
- int addr = 1;
-
- for (int r = 0; r < 8; r++) {
- gbaSave[r].deleteFile();
- }
-
- sramBytesFree = SRAM_SAVE_MAX;
-
- // Try to find saves in save RAM
- for (int r = 0; r < 8; r++) {
- if (gbaSave[r].loadFromSaveRAM(CART_RAM + addr)) {
- addr += gbaSave[r].getRamUsage();
- sramBytesFree -= gbaSave[r].getRamUsage();
- }
- }
-
-}
-
-void DSSaveFileManager::formatSram() {
- for (int r = 0; r < SRAM_SAVE_MAX; r++) {
- *(CART_RAM + r) = 0;
- }
-
- loadAllFromSRAM();
-}
-
-void DSSaveFileManager::listFiles() {
- for (int r = 0; r < 8; r++) {
- if (gbaSave[r].isValid()) {
- consolePrintf("'%s': %d bytes\n", gbaSave[r].getName(), gbaSave[r].getRamUsage());
- }
- }
- consolePrintf("SRAM free: %d bytes\n", getBytesFree());
-}
-
-DSSaveFileManager* DSSaveFileManager::instancePtr = NULL;
-
-DSSaveFile *DSSaveFileManager::openSavefile(const char *filename, bool saveOrLoad) {
- for (int r = 0; r < 8; r++) {
- if (gbaSave[r].isValid() && (gbaSave[r].matches(filename))) {
-// consolePrintf("Matched save %d (%d)\n", r, gbaSave[r].getSize());
- gbaSave[r].reset();
- //consolePrintf("reset ");
- if (saveOrLoad) gbaSave[r].clearData();
-// consolePrintf("cleared ");
- return gbaSave[r].clone();
- }
- }
-
- if (saveOrLoad) {
- return makeSaveFile(filename, saveOrLoad);
- } else {
- return NULL;
- }
-}
-
-
-
-DSSaveFile* DSSaveFile::clone() {
-// consolePrintf("Clone %s %d\n", save.name, save.size);
- return new DSSaveFile(&save, saveCompressed, saveData);
-}
-
-void DSSaveFileManager::deleteFile(const char* name) {
-// consolePrintf("Deleting %s", name);
- for (int r = 0; r < 8; r++) {
- if (gbaSave[r].isValid() && (gbaSave[r].matches(name))) {
- gbaSave[r].deleteFile();
- }
- }
- flushToSaveRAM();
-}
-
-bool DSSaveFileManager::removeSavefile(const Common::String &filename) {
- consolePrintf("DSSaveFileManager::removeSavefile : Not implemented yet.\n");
- assert(false);
- //TODO: Implement this. Most likely, you just have to use the code of deleteFile?
- return false;
-}
-
-
-Common::StringArray DSSaveFileManager::listSavefiles(const Common::String &pattern) {
- consolePrintf("DSSaveFileManager::listSavefiles : Not implemented yet.\n");
- assert(false);
- return Common::StringArray();
- /*
- TODO: Implement this. If you don't understand what it should do, just ask
- (e.g. on scummvm-devel or Fingolfin). It should be pretty simple if you
- use Common::matchString from common/util.h and read the Doxygen docs,
- then combine this with the old code below...
- */
-}
-
-
-/*
-void DSSaveFileManager::listSavefiles(const char *prefix, bool *marks, int num) {
- memset(marks, true, num * sizeof(bool));
- return;
-
- memset(marks, false, num*sizeof(bool));
-
- for (int saveNum = 0; saveNum < num; saveNum++) {
- for (int r = 0; r < 8; r++) {
- if (gbaSave[r].isValid() && (gbaSave[r].matches(prefix, saveNum))) {
- marks[saveNum] = true;
- }
- }
- }
-
-}
-*/
-
-
-DSSaveFile *DSSaveFileManager::makeSaveFile(const char *filename, bool saveOrLoad) {
-
- // Find a free save slot
- int r = 0;
-
- while ((r < 8) && (gbaSave[r].isValid())) {
- r++;
- }
-
- if ((r == 8) && (gbaSave[r].isValid())) {
- // No more saves
- return NULL;
- } else {
- // Allocate this save
-// consolePrintf("Allocated save %d\n", r);
- gbaSave[r].setName((char *) filename);
- gbaSave[r].reset();
- return gbaSave[r].clone();
- }
-}
-
-void DSSaveFileManager::flushToSaveRAM() {
- int cartAddr = 1;
- int s;
- int extraData = DSSaveFileManager::getExtraData();
-
- *((u16 *) (0x4000204)) |= 0x3;
-
- swiWaitForVBlank();
-
- int size = 0;
- for (int r = 0; (r < 8); r++) {
- if (gbaSave[r].isValid()) {
- gbaSave[r].compress();
- if (!gbaSave[r].isTemp()) size += gbaSave[r].getRamUsage();
- }
- }
-
- if (size <= SRAM_SAVE_MAX) {
-
- for (int r = 0; r < SRAM_SAVE_MAX; r++) {
- *(CART_RAM + r) = 0;
- }
-
- sramBytesFree = SRAM_SAVE_MAX;
-
- for (int r = 0; (r < 8); r++) {
- if (gbaSave[r].isValid() && (!gbaSave[r].isTemp())) {
-
- cartAddr += s = gbaSave[r].saveToSaveRAM(CART_RAM + cartAddr);
-
- /* if (s == 0) {
- consolePrintf("WARNING: Save didn't fit in cart RAM and has been lost!! Delete files and save again.", gbaSave[r].getName());
- failed = true;
- }*/
- }
- }
- } else {
-
- consolePrintf("WARNING: Save didn't fit in cart RAM and has been lost!! Delete files and save again.");
- loadAllFromSRAM();
-
- }
-
- DSSaveFileManager::setExtraData(extraData);
-// consolePrintf("SRAM free: %d bytes\n", getBytesFree());
-}
-
-void DSSaveFileManager::setExtraData(int data) {
- // Offset of extra data is 31. This overlaps the padding and reserved bytes of the first save entry.
- // which have not been used up until now. So it should be safe.
-
- vu8* sram = CART_RAM + 31;
-
- *(sram + 0) = 0xF0; // This is an identifier to check
- *(sram + 1) = 0x0D; // that extra data is present.
-
- *(sram + 2) = (data & 0xFF000000) >> 24; // Now write the actual data
- *(sram + 3) = (data & 0x00FF0000) >> 16; // taking care to use single
- *(sram + 4) = (data & 0x0000FF00) >> 8; // byte writes (it's an 8-bit bus)
- *(sram + 5) = (data & 0x000000FF);
-}
-
-bool DSSaveFileManager::isExtraDataPresent() {
- vu8* sram = CART_RAM + 31;
-
- // Check for the identifier
- return ((*(sram + 0) == 0xF0) && (*(sram + 1) == 0x0D));
-}
-
-int DSSaveFileManager::getExtraData() {
- vu8* sram = CART_RAM + 31;
-
- if (isExtraDataPresent()) {
- int value = (*(sram + 2) << 24) | (*(sram + 3) << 16) | (*(sram + 4) << 8) | (*(sram + 5));
- return value;
- } else {
- return 0;
- }
-}
-
-#endif
diff --git a/backends/platform/ds/arm9/source/ramsave.h b/backends/platform/ds/arm9/source/ramsave.h
deleted file mode 100644
index e74df94952..0000000000
--- a/backends/platform/ds/arm9/source/ramsave.h
+++ /dev/null
@@ -1,150 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _RAMSAVE_H_
-#define _RAMSAVE_H_
-
-#include "common/system.h"
-#include "common/savefile.h"
-
-// SaveFileManager class
-
-#define DS_MAX_SAVE_SIZE 150000
-
-class DSSaveFile : public Common::InSaveFile, public Common::OutSaveFile {
- int address;
- int ptr;
- bool ownsData;
- bool saveCompressed;
-
- struct SCUMMSave {
- u32 magic; // 4
- bool isValid; // 5
- bool pad; // 6
- char name[16]; // 22
- u32 size; // 26
- u32 compressedSize; // 30
- u16 extraMagic; // 32
- u32 reserved; // 36
- } __attribute__ ((packed));
-
- SCUMMSave save;
- u8* saveData;
- SCUMMSave* origHeader;
- bool isOpenFlag;
- bool isTempFile;
- bool eosReached;
-
-public:
- DSSaveFile();
- DSSaveFile(SCUMMSave* s, bool saveCompressed, u8* data);
- ~DSSaveFile();
-
- void reset();
-
- bool isOpen() const { return isOpenFlag; }
- virtual bool eos() const;
- virtual void clearErr();
- virtual bool skip(uint32 size);
-
- 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);
-
- void setName(char *name);
- char* getName() { return save.name; }
-
- bool isValid() { return save.isValid; }
- bool isTemp() { return isTempFile; }
- bool matches(const char *prefix, int num);
- bool matches(const char *filename);
-
- void clearData();
- void compress();
-
- int getRamUsage() { return sizeof(save) + save.compressedSize; }
- char* getRamImage() { return (char *) &save; }
-
- int getSize() { return save.size; }
-
- DSSaveFile* clone();
-
- bool loadFromSaveRAM(vu8* address);
- int saveToSaveRAM(vu8* address);
-
-
-
- void deleteFile();
-
- void operator delete(void *p) {
-// consolePrintf("Finished! size=%d\n", ((DSSaveFile *) (p))->save->size);
- }
-
-
-
-};
-
-
-
-class DSSaveFileManager : public Common::SaveFileManager {
-
- DSSaveFile gbaSave[8];
- static DSSaveFileManager* instancePtr;
- int sramBytesFree;
-
-public:
- DSSaveFileManager();
- ~DSSaveFileManager();
-
- static DSSaveFileManager* instance() { return instancePtr; }
-
- DSSaveFile *openSavefile(const char *filename, bool saveOrLoad);
-
- virtual Common::OutSaveFile* openForSaving(const Common::String &filename) { return openSavefile(filename.c_str(), true); }
- virtual Common::InSaveFile* openForLoading(const Common::String &filename) { return openSavefile(filename.c_str(), false); }
-
- virtual bool removeSavefile(const Common::String &filename);
- virtual Common::StringArray listSavefiles(const Common::String &pattern);
-
- void flushToSaveRAM();
-
- void addBytesFree(int size) { sramBytesFree += size; }
- int getBytesFree() { return sramBytesFree; }
-
- void deleteFile(char* name);
- void listFiles();
- void formatSram();
-
- void loadAllFromSRAM();
-
- static bool isExtraDataPresent();
- static int getExtraData();
- static void setExtraData(int data);
-
-protected:
- DSSaveFile *makeSaveFile(const Common::String &filename, bool saveOrLoad);
-};
-
-#endif
diff --git a/backends/platform/ds/arm9/source/scummhelp.cpp b/backends/platform/ds/arm9/source/scummhelp.cpp
index e1ddaecc2c..f1e8ba4fb2 100644
--- a/backends/platform/ds/arm9/source/scummhelp.cpp
+++ b/backends/platform/ds/arm9/source/scummhelp.cpp
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -91,7 +94,8 @@ void updateStrings(byte gameId, byte version, Common::Platform platform,
}
-}
+} // End of namespace DS
+
#undef ADD_BIND
diff --git a/backends/platform/ds/arm9/source/scummhelp.h b/backends/platform/ds/arm9/source/scummhelp.h
index 602cb5f788..4be28dca6a 100644
--- a/backends/platform/ds/arm9/source/scummhelp.h
+++ b/backends/platform/ds/arm9/source/scummhelp.h
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -31,6 +34,7 @@ namespace DS {
void updateStrings(byte gameId, byte version, Common::Platform platform,
int page, Common::String &title, Common::String *&key, Common::String *&dsc);
-}
+} // End of namespace DS
+
#endif
diff --git a/backends/platform/ds/arm9/source/touchkeyboard.cpp b/backends/platform/ds/arm9/source/touchkeyboard.cpp
index 2d4b6a94f4..71f4f93c27 100644
--- a/backends/platform/ds/arm9/source/touchkeyboard.cpp
+++ b/backends/platform/ds/arm9/source/touchkeyboard.cpp
@@ -20,6 +20,7 @@
*
*/
#include <nds.h>
+#include "NDS/scummvm_ipc.h"
#include "touchkeyboard.h"
#include "keyboard_raw.h"
#include "keyboard_pal_raw.h"
@@ -43,124 +44,124 @@ struct key_data {
#define DS_CAPSLOCK 1
-key_data keys[DS_NUM_KEYS] = {
+static key_data keys[DS_NUM_KEYS] = {
// Key number x y character
// Numbers
- {28, 3, 0, '1'},
- {29, 5, 0, '2'},
- {30, 7, 0, '3'},
- {31, 9, 0, '4'},
- {32, 11, 0, '5'},
- {33, 13, 0, '6'},
- {34, 15, 0, '7'},
- {35, 17, 0, '8'},
- {36, 19, 0, '9'},
- {27, 21, 0, '0'},
- {45, 23, 0, Common::KEYCODE_MINUS},
- {50, 25, 0, Common::KEYCODE_EQUALS},
- {52, 27, 0, Common::KEYCODE_BACKSPACE},
+ {28, 3, 0, '1', false},
+ {29, 5, 0, '2', false},
+ {30, 7, 0, '3', false},
+ {31, 9, 0, '4', false},
+ {32, 11, 0, '5', false},
+ {33, 13, 0, '6', false},
+ {34, 15, 0, '7', false},
+ {35, 17, 0, '8', false},
+ {36, 19, 0, '9', false},
+ {27, 21, 0, '0', false},
+ {45, 23, 0, Common::KEYCODE_MINUS, false},
+ {50, 25, 0, Common::KEYCODE_EQUALS, false},
+ {52, 27, 0, Common::KEYCODE_BACKSPACE, false},
// Top row
- {'Q'-'A' + 1, 4, 2, 'Q'},
- {'W'-'A' + 1, 6, 2, 'W'},
- {'E'-'A' + 1, 8, 2, 'E'},
- {'R'-'A' + 1, 10, 2, 'R'},
- {'T'-'A' + 1, 12, 2, 'T'},
- {'Y'-'A' + 1, 14, 2, 'Y'},
- {'U'-'A' + 1, 16, 2, 'U'},
- {'I'-'A' + 1, 18, 2, 'I'},
- {'O'-'A' + 1, 20, 2, 'O'},
- {'P'-'A' + 1, 22, 2, 'P'},
- {43, 24, 2, Common::KEYCODE_LEFTBRACKET},
- {44, 26, 2, Common::KEYCODE_RIGHTBRACKET},
+ {'Q'-'A' + 1, 4, 2, 'Q', false},
+ {'W'-'A' + 1, 6, 2, 'W', false},
+ {'E'-'A' + 1, 8, 2, 'E', false},
+ {'R'-'A' + 1, 10, 2, 'R', false},
+ {'T'-'A' + 1, 12, 2, 'T', false},
+ {'Y'-'A' + 1, 14, 2, 'Y', false},
+ {'U'-'A' + 1, 16, 2, 'U', false},
+ {'I'-'A' + 1, 18, 2, 'I', false},
+ {'O'-'A' + 1, 20, 2, 'O', false},
+ {'P'-'A' + 1, 22, 2, 'P', false},
+ {43, 24, 2, Common::KEYCODE_LEFTBRACKET, false},
+ {44, 26, 2, Common::KEYCODE_RIGHTBRACKET, false},
// Middle row
- {55, 3, 4, DS_CAPSLOCK},
- {'A'-'A' + 1, 5, 4, 'A'},
- {'S'-'A' + 1, 7, 4, 'S'},
- {'D'-'A' + 1, 9, 4, 'D'},
- {'F'-'A' + 1, 11, 4, 'F'},
- {'G'-'A' + 1, 13, 4, 'G'},
- {'H'-'A' + 1, 15, 4, 'H'},
- {'J'-'A' + 1, 17, 4, 'J'},
- {'K'-'A' + 1, 19, 4, 'K'},
- {'L'-'A' + 1, 21, 4, 'L'},
- {42, 23, 4, Common::KEYCODE_SEMICOLON},
- {41, 25, 4, Common::KEYCODE_QUOTE},
- {46, 27, 4, Common::KEYCODE_RETURN},
+ {55, 3, 4, DS_CAPSLOCK, false},
+ {'A'-'A' + 1, 5, 4, 'A', false},
+ {'S'-'A' + 1, 7, 4, 'S', false},
+ {'D'-'A' + 1, 9, 4, 'D', false},
+ {'F'-'A' + 1, 11, 4, 'F', false},
+ {'G'-'A' + 1, 13, 4, 'G', false},
+ {'H'-'A' + 1, 15, 4, 'H', false},
+ {'J'-'A' + 1, 17, 4, 'J', false},
+ {'K'-'A' + 1, 19, 4, 'K', false},
+ {'L'-'A' + 1, 21, 4, 'L', false},
+ {42, 23, 4, Common::KEYCODE_SEMICOLON, false},
+ {41, 25, 4, Common::KEYCODE_QUOTE, false},
+ {46, 27, 4, Common::KEYCODE_RETURN, false},
// Bottom row
- {51, 4, 6, DS_SHIFT},
- {'Z'-'A' + 1, 6, 6, 'Z'},
- {'X'-'A' + 1, 8, 6, 'X'},
- {'C'-'A' + 1, 10, 6, 'C'},
- {'V'-'A' + 1, 12, 6, 'V'},
- {'B'-'A' + 1, 14, 6, 'B'},
- {'N'-'A' + 1, 16, 6, 'N'},
- {'M'-'A' + 1, 18, 6, 'M'},
- {38, 20, 6, Common::KEYCODE_COMMA},
- {39, 22, 6, Common::KEYCODE_PERIOD},
- {40, 24, 6, Common::KEYCODE_SLASH},
+ {51, 4, 6, DS_SHIFT, false},
+ {'Z'-'A' + 1, 6, 6, 'Z', false},
+ {'X'-'A' + 1, 8, 6, 'X', false},
+ {'C'-'A' + 1, 10, 6, 'C', false},
+ {'V'-'A' + 1, 12, 6, 'V', false},
+ {'B'-'A' + 1, 14, 6, 'B', false},
+ {'N'-'A' + 1, 16, 6, 'N', false},
+ {'M'-'A' + 1, 18, 6, 'M', false},
+ {38, 20, 6, Common::KEYCODE_COMMA, false},
+ {39, 22, 6, Common::KEYCODE_PERIOD, false},
+ {40, 24, 6, Common::KEYCODE_SLASH, false},
// Space bar
- {47, 9, 8, Common::KEYCODE_SPACE},
- {48, 11, 8, Common::KEYCODE_SPACE},
- {48, 13, 8, Common::KEYCODE_SPACE},
- {48, 15, 8, Common::KEYCODE_SPACE},
- {48, 17, 8, Common::KEYCODE_SPACE},
- {49, 19, 8, Common::KEYCODE_SPACE},
+ {47, 9, 8, Common::KEYCODE_SPACE, false},
+ {48, 11, 8, Common::KEYCODE_SPACE, false},
+ {48, 13, 8, Common::KEYCODE_SPACE, false},
+ {48, 15, 8, Common::KEYCODE_SPACE, false},
+ {48, 17, 8, Common::KEYCODE_SPACE, false},
+ {49, 19, 8, Common::KEYCODE_SPACE, false},
// Cursor arrows
- {52, 27, 8, Common::KEYCODE_LEFT},
- {54, 29, 8, Common::KEYCODE_DOWN},
- {53, 31, 8, Common::KEYCODE_RIGHT},
- {51, 29, 6, Common::KEYCODE_UP},
+ {52, 27, 8, Common::KEYCODE_LEFT, false},
+ {54, 29, 8, Common::KEYCODE_DOWN, false},
+ {53, 31, 8, Common::KEYCODE_RIGHT, false},
+ {51, 29, 6, Common::KEYCODE_UP, false},
// Close button
- {56, 30, 0, Common::KEYCODE_INVALID},
+ {56, 30, 0, Common::KEYCODE_INVALID, false},
// Function keys (needed for AGI)
- {57, 4, -2, Common::KEYCODE_F1},
- {58, 6, -2, Common::KEYCODE_F2},
- {59, 8, -2, Common::KEYCODE_F3},
- {60, 10, -2, Common::KEYCODE_F4},
- {61, 14, -2, Common::KEYCODE_F5},
- {62, 16, -2, Common::KEYCODE_F6},
- {63, 18, -2, Common::KEYCODE_F7},
- {64, 20, -2, Common::KEYCODE_F8},
- {65, 24, -2, Common::KEYCODE_F9},
- {66, 26, -2, Common::KEYCODE_F10},
- {67, 28, -2, Common::KEYCODE_F11},
- {68, 30, -2, Common::KEYCODE_F12},
+ {57, 4, -2, Common::KEYCODE_F1, false},
+ {58, 6, -2, Common::KEYCODE_F2, false},
+ {59, 8, -2, Common::KEYCODE_F3, false},
+ {60, 10, -2, Common::KEYCODE_F4, false},
+ {61, 14, -2, Common::KEYCODE_F5, false},
+ {62, 16, -2, Common::KEYCODE_F6, false},
+ {63, 18, -2, Common::KEYCODE_F7, false},
+ {64, 20, -2, Common::KEYCODE_F8, false},
+ {65, 24, -2, Common::KEYCODE_F9, false},
+ {66, 26, -2, Common::KEYCODE_F10, false},
+ {67, 28, -2, Common::KEYCODE_F11, false},
+ {68, 30, -2, Common::KEYCODE_F12, false},
};
-int keyboardX;
-int keyboardY;
+static int keyboardX;
+static int keyboardY;
-int mapBase;
-int tileBase;
+static int s_mapBase;
+static int s_tileBase;
-u16* baseAddress;
+static u16 *baseAddress;
-bool shiftState;
-bool capsLockState;
+static bool shiftState;
+static bool capsLockState;
-bool closed;
+static bool closed;
-char autoCompleteWord[NUM_WORDS][32];
-int autoCompleteCount;
+static char autoCompleteWord[NUM_WORDS][32];
+static int autoCompleteCount;
-char autoCompleteBuffer[128];
+static char autoCompleteBuffer[128];
-int selectedCompletion = -1;
-int charactersEntered = 0;
-int typingTimeout = 0;
+static int selectedCompletion = -1;
+static int charactersEntered = 0;
+static int typingTimeout = 0;
// Render text onto the tiled screen
-void drawText(int tx, int ty, char* string, bool highlight) {
+void drawText(int tx, int ty, const char *string, bool highlight) {
u16 baseValue = 0;
@@ -181,7 +182,7 @@ void drawText(int tx, int ty, char* string, bool highlight) {
-void restoreVRAM(int tileBase, int mapBase, u16* saveSpace) {
+void restoreVRAM(int tileBase, int mapBase, u16 *saveSpace) {
/* for (int r = 0; r < 32 * 32; r++) {
((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase))[r] = *saveSpace++;
}
@@ -191,7 +192,7 @@ void restoreVRAM(int tileBase, int mapBase, u16* saveSpace) {
}*/
}
-void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) {
+void drawKeyboard(int tileBase, int mapBase, u16 *saveSpace) {
/* int keyboardDataSize = 4736 * 2; */
for (int r = 0; r < 32 * 32; r++) {
@@ -211,8 +212,8 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) {
// this is the font
for (int tile = 0; tile < 94; tile++) {
- u16* tileAddr = (u16 *) (CHAR_BASE_BLOCK_SUB(tileBase) + ((KEYBOARD_DATA_SIZE) + (tile * 32)));
- u8* src = ((u8 *) (::_8x8font_tga_raw)) + 18 + tile * 8;
+ u16 *tileAddr = (u16 *) (CHAR_BASE_BLOCK_SUB(tileBase) + ((KEYBOARD_DATA_SIZE) + (tile * 32)));
+ const u8 *src = ((const u8 *) (::_8x8font_tga_raw)) + 18 + tile * 8;
for (int y = 0 ; y < 8; y++) {
for (int x = 0; x < 2; x++) {
@@ -247,8 +248,8 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) {
keyboardX = -2;
keyboardY = 2;
- DS::mapBase = mapBase;
- DS::tileBase = tileBase;
+ DS::s_mapBase = mapBase;
+ DS::s_tileBase = tileBase;
shiftState = false;
capsLockState = false;
@@ -256,7 +257,7 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) {
int x = keyboardX;
int y = keyboardY;
- u16* base = ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase));
+ u16 *base = ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase));
baseAddress = base;
for (int r = 0; r < DS_NUM_KEYS; r++) {
@@ -314,7 +315,7 @@ bool getKeyboardClosed() {
}
void setKeyHighlight(int key, bool highlight) {
- u16* base = ((u16 *) SCREEN_BASE_BLOCK_SUB(DS::mapBase));
+ u16 *base = ((u16 *) SCREEN_BASE_BLOCK_SUB(DS::s_mapBase));
if (highlight) {
base[(keyboardY + keys[key].y) * 32 + keyboardX + keys[key].x] |= 0x1000;
@@ -329,7 +330,7 @@ void setKeyHighlight(int key, bool highlight) {
}
}
-void addAutoComplete(const char* word) {
+void addAutoComplete(const char *word) {
if (autoCompleteCount == NUM_WORDS) return;
strcpy(&autoCompleteWord[autoCompleteCount++][0], word);
drawAutoComplete();
@@ -353,7 +354,7 @@ void clearAutoComplete() {
void typeCompletion(int current) {
Common::Event event;
- /* OSystem_DS* system = OSystem_DS::instance(); */
+ /* OSystem_DS *system = OSystem_DS::instance(); */
strcat(autoCompleteBuffer, &autoCompleteWord[current][charactersEntered]);
strcat(autoCompleteBuffer, " ");
@@ -384,7 +385,7 @@ void typeCompletion(int current) {
void updateTypeEvents() {
if (autoCompleteBuffer[0] != '\0') {
Common::Event event;
- OSystem_DS* system = OSystem_DS::instance();
+ OSystem_DS *system = OSystem_DS::instance();
event.kbd.keycode = (Common::KeyCode) autoCompleteBuffer[0];
event.kbd.ascii = autoCompleteBuffer[0];
@@ -395,8 +396,7 @@ void updateTypeEvents() {
event.type = Common::EVENT_KEYUP;
system->addEvent(event);
- for (int r = 0; r < (int)strlen(autoCompleteBuffer); r++)
- {
+ for (int r = 0; r < (int)strlen(autoCompleteBuffer); r++) {
autoCompleteBuffer[r] = autoCompleteBuffer[r + 1];
}
@@ -404,8 +404,7 @@ void updateTypeEvents() {
}
}
-void createKeyEvent(int keyNum, Common::Event& event)
-{
+void createKeyEvent(int keyNum, Common::Event& event) {
event.kbd.flags = 0;
if ((keys[keyNum].character >= '0') && (keys[keyNum].character <= '9')) {
@@ -443,7 +442,7 @@ void releaseAllKeys() {
if (keys[r].pressed) {
DS::setKeyHighlight(r, false);
- OSystem_DS* system = OSystem_DS::instance();
+ OSystem_DS *system = OSystem_DS::instance();
Common::Event event;
createKeyEvent(r, event);
@@ -502,7 +501,7 @@ void addKeyboardEvents() {
for (int r = 0; r < DS_NUM_KEYS; r++) {
if (( (tx >= keys[r].x) && (tx <= keys[r].x + 1)) &&
(ty >= keys[r].y) && (ty <= keys[r].y + 1)) {
- OSystem_DS* system = OSystem_DS::instance();
+ OSystem_DS *system = OSystem_DS::instance();
Common::Event event;
// consolePrintf("Key: %d\n", r);
@@ -551,7 +550,7 @@ void addKeyboardEvents() {
if (keys[r].pressed) {
DS::setKeyHighlight(r, false);
- OSystem_DS* system = OSystem_DS::instance();
+ OSystem_DS *system = OSystem_DS::instance();
Common::Event event;
if ((keys[r].character == Common::KEYCODE_INVALID)) {
@@ -586,5 +585,4 @@ void addKeyboardEvents() {
}
-}
-
+} // End of namespace DS
diff --git a/backends/platform/ds/arm9/source/touchkeyboard.h b/backends/platform/ds/arm9/source/touchkeyboard.h
index 6ceb83bfc7..7644e48bff 100644
--- a/backends/platform/ds/arm9/source/touchkeyboard.h
+++ b/backends/platform/ds/arm9/source/touchkeyboard.h
@@ -8,15 +8,18 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
@@ -27,23 +30,25 @@
namespace DS {
-static const int NUM_WORDS = 12;
-static const int KEYBOARD_DATA_SIZE = 4736 * 2;
-static const int KEYBOARD_BOTTOM_Y = 105;
+enum {
+ NUM_WORDS = 12,
+ KEYBOARD_DATA_SIZE = 4736 * 2,
+ KEYBOARD_BOTTOM_Y = 105
+};
void createKeyEvent(int keyNum, Common::Event& event);
-void drawKeyboard(int tileBase, int mapBase, u16* saveSpace);
-void restoreVRAM(int tileBase, int mapBase, u16* saveSpace);
+void drawKeyboard(int tileBase, int mapBase, u16 *saveSpace);
+void restoreVRAM(int tileBase, int mapBase, u16 *saveSpace);
void addKeyboardEvents();
bool getKeyboardClosed();
bool isInsideKeyboard(int x, int y);
-void addAutoComplete(const char* word);
+void addAutoComplete(const char *word);
void clearAutoComplete();
void setCharactersEntered(int count);
void releaseAllKeys();
-}
+} // End of namespace DS
#endif
diff --git a/backends/platform/ds/arm9/source/wordcompletion.cpp b/backends/platform/ds/arm9/source/wordcompletion.cpp
index 035f6a631d..43a16486c5 100644
--- a/backends/platform/ds/arm9/source/wordcompletion.cpp
+++ b/backends/platform/ds/arm9/source/wordcompletion.cpp
@@ -1,3 +1,28 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "wordcompletion.h"
#include "osystem_ds.h"
#include "engines/agi/agi.h" // Caution for #define for NUM_CHANNELS, causes problems in mixer_intern.h
@@ -14,7 +39,7 @@ namespace DS {
char wordBuffer[WORD_BUFFER_SIZE];
int wordBufferPos = 0;
-char* wordBufferPtr[MAX_WORD_COUNT];
+char *wordBufferPtr[MAX_WORD_COUNT];
int wordBufferPtrPos = 0;
void addAutoCompleteLine(const char *line) {
@@ -53,7 +78,7 @@ void addAutoCompleteLine(const char *line) {
}
}
-int stringCompare(const void* a, const void* b) {
+int stringCompare(const void *a, const void *b) {
const char** as = (const char **) a;
const char** bs = (const char **) b;
@@ -71,7 +96,7 @@ void sortAutoCompleteWordList() {
}
// Sends the current available words to the virtual keyboard code for display
-bool findWordCompletions(const char* input) {
+bool findWordCompletions(const char *input) {
int min = 0;
int max = wordBufferPtrPos - 1;
char *word;
@@ -82,7 +107,7 @@ bool findWordCompletions(const char* input) {
if (wordBufferPtrPos == 0)
return false;
- OSystem_DS* system = (OSystem_DS *) g_system;
+ OSystem_DS *system = (OSystem_DS *) g_system;
system->clearAutoComplete();
int start = 0;
@@ -176,5 +201,6 @@ bool findWordCompletions(const char* input) {
}
-}
+} // End of namespace DS
+
#endif
diff --git a/backends/platform/ds/arm9/source/wordcompletion.h b/backends/platform/ds/arm9/source/wordcompletion.h
index e50bade37b..55a0bc8b5a 100644
--- a/backends/platform/ds/arm9/source/wordcompletion.h
+++ b/backends/platform/ds/arm9/source/wordcompletion.h
@@ -1,3 +1,28 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
namespace DS {
extern void clearAutoCompleteWordList();
@@ -5,4 +30,4 @@ extern bool findWordCompletions(const char *input);
extern void addAutoCompleteLine(const char *line);
extern void sortAutoCompleteWordList();
-}
+} // End of namespace DS
diff --git a/backends/platform/ds/arm9/source/zipreader.cpp b/backends/platform/ds/arm9/source/zipreader.cpp
index fd6da4e9b9..d4f055ee82 100644
--- a/backends/platform/ds/arm9/source/zipreader.cpp
+++ b/backends/platform/ds/arm9/source/zipreader.cpp
@@ -8,19 +8,23 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
+#include "common/scummsys.h"
#include "zipreader.h"
ZipFile::ZipFile() {
@@ -28,7 +32,7 @@ ZipFile::ZipFile() {
// consolePrintf("ZIP file check...");
- char* p = (char *) ZF_SEARCH_START;
+ char *p = (char *) ZF_SEARCH_START;
bool found = false;
_zipFile = NULL;
@@ -75,7 +79,6 @@ bool ZipFile::restartFile() {
bool more = true;
while (!currentFileInFolder() && more) {
- char name[128];
getFileName(name);
more = skipFile();
}
@@ -112,7 +115,7 @@ bool ZipFile::currentFileInFolder() {
return false;
}
-void ZipFile::getFileName(char* name) {
+void ZipFile::getFileName(char *name) {
strncpy(name, (char *) (_currentFile + 1), _currentFile->nameLength);
for (int r = 0; name[r] != 0; r++) {
@@ -207,7 +210,7 @@ void ZipFile::changeToRoot() {
_directory[0] = 0;
}
-void ZipFile::changeDirectory(const char* dir) {
+void ZipFile::changeDirectory(const char *dir) {
// consolePrintf("Current dir now '%s'\n", dir);
assert(dir && *dir);
diff --git a/backends/platform/ds/arm9/source/zipreader.h b/backends/platform/ds/arm9/source/zipreader.h
index d1f70942ce..5429954088 100644
--- a/backends/platform/ds/arm9/source/zipreader.h
+++ b/backends/platform/ds/arm9/source/zipreader.h
@@ -8,21 +8,26 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
*
*/
#ifndef _ZIPREADER_H_
#define _ZIPREADER_H_
-#include "portdefs.h"
+
+#include <nds/ndstypes.h>
+
#define ZF_SEARCH_START 0x08000000
#define ZF_SEARCH_END 0x09000000
#define ZF_SEARCH_STRIDE 16
@@ -43,12 +48,12 @@ class ZipFile {
u16 extraLength; // Length of any extra data
} __attribute__ ((packed));
- char* _zipFile;
+ char *_zipFile;
char _directory[128];
bool _allFilesVisible;
- FileHeader* _currentFile;
+ FileHeader *_currentFile;
public:
ZipFile();
@@ -61,13 +66,13 @@ public:
bool findFile(const char *search);
// These return the file's data and information
- char* getFile();
+ char *getFile();
int getFileSize();
- void getFileName(char* name);
+ void getFileName(char *name);
bool isDirectory();
// These set the current directory
- void changeDirectory(const char* name);
+ void changeDirectory(const char *name);
void changeToRoot();
void setAllFilesVisible(bool state) { _allFilesVisible = state; }
diff --git a/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h b/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h
index f41548f400..cf6436634a 100644
--- a/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h
+++ b/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h
@@ -33,34 +33,32 @@
//////////////////////////////////////////////////////////////////////
-typedef struct sTransferSoundData {
-//---------------------------------------------------------------------------------
- const void *data;
- u32 len;
- u32 rate;
- u8 vol;
- u8 pan;
- u8 format;
- u8 PADDING;
-} TransferSoundData, * pTransferSoundData;
+typedef struct {
+ const void *data;
+ u32 len;
+ u32 rate;
+ u8 vol;
+ u8 pan;
+ u8 format;
+ u8 PADDING;
+} TransferSoundData;
//---------------------------------------------------------------------------------
-typedef struct sTransferSound {
-//---------------------------------------------------------------------------------
- TransferSoundData data[16];
- u8 count;
- u8 PADDING[3];
-} TransferSound, * pTransferSound;
+typedef struct {
+ TransferSoundData data[16];
+ u8 count;
+ u8 PADDING[3];
+} TransferSound;
-typedef struct _adpcmBuffer {
- u8* buffer[8];
+typedef struct {
+ u8 *buffer[8];
bool filled[8];
- u8* arm7Buffer[8];
+ u8 *arm7Buffer[8];
bool arm7Dirty[8];
bool semaphore;
} adpcmBuffer;
@@ -82,22 +80,22 @@ typedef struct scummvmTransferRegion {
uint8 curtime[8]; // current time response from RTC
struct {
- u8 rtc_command;
- u8 rtc_year; //add 2000 to get 4 digit year
- u8 rtc_month; //1 to 12
- u8 rtc_day; //1 to (days in month)
-
- u8 rtc_incr;
- u8 rtc_hours; //0 to 11 for AM, 52 to 63 for PM
- u8 rtc_minutes; //0 to 59
- u8 rtc_seconds; //0 to 59
- };
+ u8 command;
+ u8 year; //add 2000 to get 4 digit year
+ u8 month; //1 to 12
+ u8 day; //1 to (days in month)
+
+ u8 incr;
+ u8 hours; //0 to 11 for AM, 52 to 63 for PM
+ u8 minutes; //0 to 59
+ u8 seconds; //0 to 59
+ } rtc;
};
uint16 battery; // battery life ?? hopefully. :)
uint16 aux; // i have no idea...
- pTransferSound soundData;
+ TransferSound *soundData;
adpcmBuffer adpcm;
@@ -127,7 +125,7 @@ typedef struct scummvmTransferRegion {
// Streaming sound
bool streamFillNeeded[4];
int streamPlayingSection;
-} scummTransferRegion, * pscummTransferRegion;
+} scummTransferRegion;
//////////////////////////////////////////////////////////////////////
diff --git a/backends/platform/ds/ds.mk b/backends/platform/ds/ds.mk
index aeba1820c6..a9ed3e0096 100644
--- a/backends/platform/ds/ds.mk
+++ b/backends/platform/ds/ds.mk
@@ -1,44 +1,165 @@
-# Repeat "all" target here, to make sure it is the first target
-# Currently disabled, so only arm7.bin gets build
-#all:
+# To approximate the DS builds A, B, C, ... run our configure like this
+# configure --host=ds --disable-translation --disable-all-engines OPTIONS
+# where OPTIONS is...
+# build A: --enable-scumm
+# build B: --enable-sky --enable-queen
+# build C: --enable-agos
+# build D: --enable-gob --enable-cine --enable-agi
+# build E: --enable-saga --disable-mad
+# build F: --enable-kyra --disable-mad
+# build G: --enable-lure
+# build H: --enable-parallaction
+# build I: --enable-made --disable-mad
+# build K: --enable-cruise --disable-mad
+#
+# However, this could be automated using a simple script, which generates
+# subdirs for each build, and runs configure in those subdirs with the right
+# parameters (all builds would still share the same set of source code files,
+# thanks to our "out of tree" building support).
+#
+# This does not currently take care of some things:
+# * It does not #define DS_BUILD_A etc. -- most uses of that should be
+# eliminated, though. Only usage should be for selecting the default config
+# file (and for that we should really rather allow overriding the value of
+# DEFAULT_CONFIG_FILE).
+# There are a few game specific hacks which are currently controlled by this,
+# too; we need to investigate those.
+# * It does not currently adjust the logo. Ideally, if we ever get real plugin
+# support, that should be necessary anymore anyway.
+# * No support for USE_DEBUGGER and USE_PROFILER yet. I envision that we would
+# integrate them with the --enable-debug and --enable-profiling configure options,
+# I simply haven't gotten around to do that yet.
+# * ...
+
+# Set location of ndsdir so that we can easily refer to files in it
+ndsdir = backends/platform/ds
+
+
+# Until we fix logo support, always use the A logo
+LOGO = logoa.bmp
+
+# Uncomment the following line to enable support for the
+# ace DS Debugger (remembering to make the same change in the arm7 makefile):
+#USE_DEBUGGER = 1
+# TODO: Need to reimplement this (for arm9 and arm7).
+#ifdef USE_DEBUGGER
+# DEFINES += -DUSE_DEBUGGER
+# CFLAGS += -g
+#endif
+
+# Uncomment the following line to enable the profiler
+#USE_PROFILER = 1
+# TODO: Need to reimplement this; and maybe replace it by the --enable-profiling
+# configure directive. Below is USE_PROFILER related code from the old NDS
+# build system:
+#ifdef USE_PROFILER
+# CFLAGS += -mpoke-function-name -finstrument-functions -g
+# DEFINES += -DUSE_PROFILER
+#endif
+# And this for module.mk:
+#ifdef USE_PROFILER
+# PORT_OBJS += arm9/source/profiler/cyg-profile.o
+#endif
+
+
+
+# NOTE: The header and libs for the debugger is assumed to be in the libnds
+# folder.
+
+ifdef WRAP_MALLOC
+ LDFLAGS += -Wl,--wrap,malloc
+ DEFINES += -DWRAP_MALLOC
+endif
-# 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 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 := -O3
+OPT_SPEED := -O3 -mno-thumb
# Compiler options for files which should be optimised for space
OPT_SIZE := -Os -mthumb
+# By default optimize for size
+CXXFLAGS += $(OPT_SIZE)
+
+# Files listed below will be optimisied for speed, otherwise they will be optimised for space.
+# TODO: Several of these files probably should not be optimized for speed, but for now
+# we replicate the *precise* list from the old DS makefile, to ensure full compatibility.
+# Eventually, we should tune this list.
+$(ndsdir)/arm9/source/blitters.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+$(ndsdir)/arm9/source/dsmain.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+$(ndsdir)/arm9/source/osystem_ds.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+base/main.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+sound/rate.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+sound/softsynth/opl/mame.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/agi/sprite.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/agos/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/agos/script.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/cine/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/cruise/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/cruise/script.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/draci/script.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/draci/sprite.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/gob/script.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/groovie/script.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/kyra/script.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/m4/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/m4/script.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/m4/sprite.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/made/script.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/actor_path.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/actor_walk.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/image.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/isomap.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/script.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/sprite.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/sci/engine/script.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/scumm/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/scumm/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/scumm/script.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/sword2/sprite.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/teenagent/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+# TODO: Fingolfin says: optimizing kyra/staticres.o for size would
+# save about 30k, so maybe consider that?
+#engines/kyra/staticres.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
-#-mthumb -fno-gcse -fno-schedule-insns2
-OBJS := $(DATA_OBJS) $(LIBCARTRESET_OBJS) $(PORT_OBJS) $(COMPRESSOR_OBJS) $(FAT_OBJS)
+#############################################################################
+#
+# ARM9 rules.
+#
+#############################################################################
+
+all: scummvm.nds scummvm.ds.gba
+clean: dsclean
-# TODO: Handle files in OPTLIST.
-# For this, the list should be made explicit. So, replace actor.cpp by path/to/actor.cpp --
-# in fact, there are several actor.cpp files, and right now all are "optimized", but
-# I think Neil only had the SAGA one in mind. Same for gfx.cpp
+dsclean:
+ $(RM) $(addprefix $(ndsdir)/, $(ARM7_MODULE_OBJS)) scummvm.nds scummvm.ds.gba
+.PHONY: dsclean
+# TODO: Add a 'dsdist' target ?
+%.bin: %.elf
+ $(OBJCOPY) -S -O binary $< $@
+%.nds: %.bin $(ndsdir)/arm7/arm7.bin
+ ndstool -c $@ -9 $< -7 $(ndsdir)/arm7/arm7.bin -b $(srcdir)/$(ndsdir)/$(LOGO) "$(@F);ScummVM $(VERSION);DS Port"
+%.ds.gba: %.nds
+ dsbuild $< -o $@ -l $(srcdir)/$(ndsdir)/arm9/ndsloader.bin
+ padbin 16 $@
#############################################################################
#############################################################################
#############################################################################
-#ndsdir = $(srcdir)/backends/platform/ds
-ndsdir = backends/platform/ds
-
#############################################################################
#
# ARM7 rules.
@@ -47,12 +168,6 @@ ndsdir = backends/platform/ds
#
#############################################################################
-$(ndsdir)/arm7/arm7.bin: $(ndsdir)/arm7/arm7.elf
-
-$(ndsdir)/arm7/arm7.elf: \
- $(ndsdir)/arm7/source/libcartreset/cartreset.o \
- $(ndsdir)/arm7/source/main.o
-
# HACK/FIXME: C compiler, for cartreset.c -- we should switch this to use CXX
# as soon as possible.
CC := $(DEVKITARM)/bin/arm-eabi-gcc
@@ -65,7 +180,7 @@ OBJCOPY := $(DEVKITARM)/bin/arm-eabi-objcopy
#
ARM7_ARCH := -mthumb-interwork
-# note: arm9tdmi isn't the correct CPU arch, but anything newer and LD
+# note: arm7tdmi isn't the correct CPU arch, but anything newer and LD
# *insists* it has a FPU or VFP, and it won't take no for an answer!
ARM7_CFLAGS := -g -Wall -O2\
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\
@@ -89,7 +204,6 @@ ARM7_LDFLAGS := -g $(ARM7_ARCH) -mno-fpu
$(MKDIR) $(*D)/$(DEPDIR)
$(CC) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
-
# Set custom build flags for cartreset.o
$(ndsdir)/arm7/source/libcartreset/cartreset.o: CXXFLAGS=$(ARM7_CFLAGS)
$(ndsdir)/arm7/source/libcartreset/cartreset.o: CPPFLAGS=
@@ -98,14 +212,28 @@ $(ndsdir)/arm7/source/libcartreset/cartreset.o: CPPFLAGS=
$(ndsdir)/arm7/source/main.o: CXXFLAGS=$(ARM7_CXXFLAGS)
$(ndsdir)/arm7/source/main.o: CPPFLAGS=
+# Rule for creating ARM7 .elf files by linking .o files together with a special linker script
+$(ndsdir)/arm7/arm7.elf: \
+ $(ndsdir)/arm7/source/libcartreset/cartreset.o \
+ $(ndsdir)/arm7/source/main.o
+ $(CXX) $(ARM7_LDFLAGS) -specs=ds_arm7.specs $+ -L$(DEVKITPRO)/libnds/lib -lnds7 -o $@
+
# Rule for creating ARM7 .bin files from .elf files
-%.bin: %.elf
- @echo ------
- @echo Building $@...
+$(ndsdir)/arm7/arm7.bin: $(ndsdir)/arm7/arm7.elf
$(OBJCOPY) -O binary $< $@
-# Rule for creating ARM7 .elf files by linking .o files together with a special linker script
-%.elf:
- @echo ------
- @echo Building $@...
- $(CXX) $(ARM7_LDFLAGS) -specs=ds_arm7.specs $+ -L/opt/devkitPro/libnds/lib -lnds7 -o $@
+
+
+
+
+
+
+# Command to build libmad is:
+# ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork'
+#
+# 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
+#
+# Fingolfin used
+# CXX=arm-eabi-g++ CC=arm-eabi-gcc ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork' --disable-shared --disable-debugging LDFLAGS=$DEVKITPRO/libnds/lib/libnds9.a
+
diff --git a/backends/platform/ds/makefile b/backends/platform/ds/makefile
index f6f9033161..58d6fd4c02 100644
--- a/backends/platform/ds/makefile
+++ b/backends/platform/ds/makefile
@@ -1,6 +1,8 @@
#SUBDIRS:= `ls | egrep -v '^(CVS|tools)$$'`
+
+
export PATH := $(DEVKITARM)/bin:$(PATH)
export portdir = $(CURDIR)/arm9
@@ -22,25 +24,43 @@ export:
allbuilds:
$(MAKE) semiclean
$(MAKE) all SCUMM_BUILD=a
+ $(MAKE) semiclean
$(MAKE) all SCUMM_BUILD=b
+ $(MAKE) semiclean
$(MAKE) all SCUMM_BUILD=c
+ $(MAKE) semiclean
$(MAKE) all SCUMM_BUILD=d
+ $(MAKE) semiclean
$(MAKE) all SCUMM_BUILD=e
+ $(MAKE) semiclean
$(MAKE) all SCUMM_BUILD=f
+ $(MAKE) semiclean
$(MAKE) all SCUMM_BUILD=g
+ $(MAKE) semiclean
$(MAKE) all SCUMM_BUILD=h
+ $(MAKE) semiclean
$(MAKE) all SCUMM_BUILD=i
+ $(MAKE) semiclean
$(MAKE) all SCUMM_BUILD=k
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
+ $(MAKE) clean SCUMM_BUILD=i
$(MAKE) all SCUMM_BUILD=i
+ $(MAKE) clean SCUMM_BUILD=k
$(MAKE) all SCUMM_BUILD=k
diff --git a/backends/platform/ds/module.mk b/backends/platform/ds/module.mk
index f2640c49e3..7298267db4 100644
--- a/backends/platform/ds/module.mk
+++ b/backends/platform/ds/module.mk
@@ -8,18 +8,15 @@ PORT_OBJS := \
arm9/source/blitters_arm.o \
arm9/source/cdaudio.o \
arm9/source/dsmain.o \
- ../../fs/ds/ds-fs.o \
arm9/source/gbampsave.o \
arm9/source/scummhelp.o \
arm9/source/osystem_ds.o \
- arm9/source/ramsave.o \
arm9/source/touchkeyboard.o \
arm9/source/zipreader.o \
arm9/source/dsoptions.o \
arm9/source/keys.o \
arm9/source/wordcompletion.o \
- arm9/source/interrupt.o \
- arm9/source/dsloader.o
+ arm9/source/interrupt.o
DATA_OBJS := \
arm9/data/icons.o \
@@ -28,9 +25,9 @@ DATA_OBJS := \
arm9/data/default_font.o \
arm9/data/8x8font_tga.o
-COMPRESSOR_OBJS := #arm9/source/compressor/lz.o
-
-FAT_OBJS := arm9/source/fat/disc_io.o arm9/source/fat/gba_nds_fat.o\
+FAT_OBJS := \
+ arm9/source/fat/disc_io.o \
+ arm9/source/fat/gba_nds_fat.o \
arm9/source/fat/io_fcsr.o \
arm9/source/fat/io_m3cf.o \
arm9/source/fat/io_mpcf.o \
@@ -47,16 +44,7 @@ FAT_OBJS := arm9/source/fat/disc_io.o arm9/source/fat/gba_nds_fat.o\
arm9/source/fat/m3sd.o
-# arm9/source/fat/io_cf_common.o arm9/source/fat/io_m3_common.o\
-# arm9/source/fat/io_sd_common.o arm9/source/fat/io_scsd_s.o \
-# arm9/source/fat/io_sc_common.o arm9/source/fat/io_sd_common.o
-
-LIBCARTRESET_OBJS := \
-# arm9/source/libcartreset/cartreset.o
-
-
-#MODULE_OBJS := $(PORT_OBJS) $(DATA_OBJS) $(FAT_OBJS)
-MODULE_OBJS := $(DATA_OBJS) $(LIBCARTRESET_OBJS) $(PORT_OBJS) $(COMPRESSOR_OBJS) $(FAT_OBJS)
+MODULE_OBJS := $(DATA_OBJS) $(PORT_OBJS) $(FAT_OBJS)
#---------------------------------------------------------------------------------
@@ -110,12 +98,10 @@ $(MODULE)/arm9/source/touchkeyboard.o: \
MODULE_DIRS += \
- backends/platform/ds/ \
backends/platform/ds/arm7/source/ \
backends/platform/ds/arm7/source/libcartreset/ \
- backends/platform/ds/arm9/source/ \
- backends/platform/ds/arm9/source/fat/ \
- backends/platform/ds/arm9/source/libcartreset/
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/ds/setup-builddirs.sh b/backends/platform/ds/setup-builddirs.sh
new file mode 100755
index 0000000000..11aacc1233
--- /dev/null
+++ b/backends/platform/ds/setup-builddirs.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+# TODO: Allow specifying (a list of) build ids (a, b, ...) on the command line.
+# TODO: Allow overriding the LOGO variable
+
+# TODO: Computer srcdir in a better way
+srcdir=../../../`dirname $0`/..
+
+BASE_PARAM="--host=ds --disable-translation --disable-debug --disable-all-engines"
+
+for build in a b c d e f g h i k; do
+ echo "--- Setting up build $build ---"
+ mkdir -p build-$build && cd build-$build
+ case $build in
+ a)
+ EXTRA_PARAM="--enable-scumm"
+ ;;
+ b)
+ EXTRA_PARAM="--enable-sky --enable-queen"
+ ;;
+ c)
+ EXTRA_PARAM="--enable-agos"
+ ;;
+ d)
+ EXTRA_PARAM="--enable-gob --enable-cine --enable-agi"
+ ;;
+ e)
+ EXTRA_PARAM="--enable-saga --disable-mad"
+ ;;
+ f)
+ EXTRA_PARAM="--enable-kyra --disable-mad"
+ ;;
+ g)
+ EXTRA_PARAM="--enable-lure"
+ ;;
+ h)
+ EXTRA_PARAM="--enable-parallaction"
+ ;;
+ i)
+ EXTRA_PARAM="--enable-made --disable-mad"
+ ;;
+ k)
+ EXTRA_PARAM="--enable-cruise --disable-mad"
+ ;;
+ *)
+ echo "Invalid build $build selected"
+ exit 1
+ ;;
+ esac
+
+ defname="DS_BUILD_`echo $build | tr '[a-z]' '[A-Z]'`"
+ CPPFLAGS="$CPPFLAGS -D$defname"
+ $srcdir/configure $BASE_PARAM $EXTRA_PARAM
+ cd ..
+ echo DONE
+ echo
+done
diff --git a/backends/platform/gp2x/build/bundle.sh b/backends/platform/gp2x/build/bundle.sh
index c68c62191b..d17f8bd831 100755
--- a/backends/platform/gp2x/build/bundle.sh
+++ b/backends/platform/gp2x/build/bundle.sh
@@ -1,52 +1,10 @@
-#!/bin/bash
+#!/bin/sh
echo Quick script to make building a distribution of the GP2X port more consistent.
-PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin:$PATH
-PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin:$PATH
-export CXX=arm-open2x-linux-g++
-export CXXFLAGS=-march=armv4t
-export CPPFLAGS=-I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include
-export LDFLAGS=-L/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib
+cd ../../../..
-echo Collecting files.
-mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`"
-mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`/saves"
-mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`/plugins"
-mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`/engine-data"
+echo Building ScummVM for GP2X Wiz.
-echo "Please put your save games in this dir" >> "scummvm-gp2x-`date '+%Y-%m-%d'`/saves/PUT_SAVES_IN_THIS_DIR"
+make gp2x-bundle
-cp ./scummvm.gpe ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ./scummvm.png ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ./README-GP2X ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ./mmuhack.o ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ../../../../scummvm.gp2x ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ../../../../AUTHORS ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ../../../../README ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ../../../../COPYING ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ../../../../COPYRIGHT ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ../../../../NEWS ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ../../../../gui/themes/scummmodern.zip ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ../../../../backends/vkeybd/packs/vkeybd_default.zip ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ../../../../dists/pred.dic ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-cp ../../../../dists/engine-data/* ./scummvm-gp2x-`date '+%Y-%m-%d'`/engine-data
-cp ../../../../plugins/* ./scummvm-gp2x-`date '+%Y-%m-%d'`/plugins
-
-echo Making Stripped GPE.
-arm-open2x-linux-strip ./scummvm-gp2x-`date '+%Y-%m-%d'`/scummvm.gp2x
-
-echo Building ZIP bundle.
-if [ -f /usr/bin/zip ]
- then
- rm ./"scummvm-gp2x-`date '+%Y-%m-%d'`.zip"
- cd "scummvm-gp2x-`date '+%Y-%m-%d'`"
- zip -r -9 "../scummvm-gp2x-`date '+%Y-%m-%d'`.zip" *
- echo You should have a "scummvm-gp2x-`date '+%Y-%m-%d'`.zip" for the GP2X port ready to go.
- cd ..
- rm -R ./"scummvm-gp2x-`date '+%Y-%m-%d'`"
- else
- echo - /usr/bin/zip not found, ZIP bundle not created.
- echo All included files can also be found in ./"scummvm-gp2x-`date '+%Y-%m-%d'`"
- echo - Please use you preferred archive tool to bundle these files.
-fi
diff --git a/backends/platform/gp2x/events.cpp b/backends/platform/gp2x/events.cpp
index 496e045ab0..a40967743c 100644
--- a/backends/platform/gp2x/events.cpp
+++ b/backends/platform/gp2x/events.cpp
@@ -229,6 +229,7 @@ int GP2X_BUTTON_STATE_L = false;
bool OSystem_GP2X::pollEvent(Common::Event &event) {
SDL_Event ev;
+ ev.type = SDL_NOEVENT;
int axis;
byte b = 0;
diff --git a/backends/platform/gp2x/gp2x-bundle.mk b/backends/platform/gp2x/gp2x-bundle.mk
new file mode 100755
index 0000000000..c6fb72c1c3
--- /dev/null
+++ b/backends/platform/gp2x/gp2x-bundle.mk
@@ -0,0 +1,60 @@
+# Special target to create bundles for the GP2X.
+
+bundle_name = release/scummvm-gp2x
+
+gp2x-bundle: $(EXECUTABLE)
+ $(MKDIR) "$(bundle_name)"
+ $(MKDIR) "$(bundle_name)/saves"
+ $(MKDIR) "$(bundle_name)/engine-data"
+
+ echo "Please put your save games in this dir" >> "$(bundle_name)/saves/PUT_SAVES_IN_THIS_DIR"
+
+ $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.gpe $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.png $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gp2x/build/README-GP2X $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gp2x/build/mmuhack.o $(bundle_name)/
+
+ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/
+ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/
+ $(INSTALL) -c -m 644 $(DIST_FILES_ENGINEDATA) $(bundle_name)/engine-data
+ $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip $(bundle_name)/
+
+ $(STRIP) $(EXECUTABLE) -o $(bundle_name)/$(EXECUTABLE)
+
+ifdef DYNAMIC_MODULES
+ $(INSTALL) -d "$(bundle_name)/plugins"
+ $(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/plugins"
+ $(STRIP) $(bundle_name)/plugins/*
+endif
+
+ tar -C $(bundle_name) -cvjf $(bundle_name).tar.bz2 .
+ rm -R ./$(bundle_name)
+
+gp2x-bundle-debug: $(EXECUTABLE)
+ $(MKDIR) "$(bundle_name)"
+ $(MKDIR) "$(bundle_name)/saves"
+ $(MKDIR) "$(bundle_name)/engine-data"
+
+ echo "Please put your save games in this dir" >> "$(bundle_name)/saves/PUT_SAVES_IN_THIS_DIR"
+
+ $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.gpe $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.png $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gp2x/build/README-GP2X $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gp2x/build/mmuhack.o $(bundle_name)/
+
+ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/
+ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/
+ $(INSTALL) -c -m 644 $(DIST_FILES_ENGINEDATA) $(bundle_name)/engine-data
+ $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip $(bundle_name)/
+
+ $(INSTALL) -c -m 777 $(srcdir)/$(EXECUTABLE) $(bundle_name)/$(EXECUTABLE)
+
+ifdef DYNAMIC_MODULES
+ $(INSTALL) -d "$(bundle_name)/scummvm/plugins"
+ $(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/scummvm/plugins"
+endif
+
+ tar -C $(bundle_name) -cvjf $(bundle_name)-debug.tar.bz2 .
+ rm -R ./$(bundle_name)
+
+.PHONY: gp2x-bundle gp2x-bundle-debug
diff --git a/backends/platform/gp2x/module.mk b/backends/platform/gp2x/module.mk
index 50a771219a..d4f145c64f 100644
--- a/backends/platform/gp2x/module.mk
+++ b/backends/platform/gp2x/module.mk
@@ -7,8 +7,7 @@ MODULE_OBJS := \
graphics.o \
gp2x.o \
-MODULE_DIRS += \
- backends/platform/gp2x/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/gp2xwiz/build/bundle-debug.sh b/backends/platform/gp2xwiz/build/bundle-debug.sh
index d275f681ea..cd5145b31d 100755
--- a/backends/platform/gp2xwiz/build/bundle-debug.sh
+++ b/backends/platform/gp2xwiz/build/bundle-debug.sh
@@ -2,53 +2,8 @@
echo Quick script to make building a distribution of the GP2X Wiz backend more consistent.
-echo Collecting files.
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`"
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm"
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/saves"
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/plugins"
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/engine-data"
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib"
+cd ../../../..
+echo Building ScummVM for GP2X Wiz.
-echo "Please put your save games in this dir" >> "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
-
-cp ./scummvm-gdb.gpe ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/scummvm.gpe
-cp ./scummvm.png ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ./README-GP2XWIZ ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ./scummvm.ini ./scummvm-wiz-`date '+%Y-%m-%d'`/
-cp ../../../../scummvm.wiz ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../AUTHORS ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../README ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../COPYING ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../COPYRIGHT ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../NEWS ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../gui/themes/scummmodern.zip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../backends/vkeybd/packs/vkeybd_default.zip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../dists/pred.dic ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../dists/engine-data/* ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/engine-data
-cp ../../../../plugins/* ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/plugins
-
-# Copy over dynamic libs needed by the app (as the ones in the default filesystem are broken).
-f=`which arm-open2x-linux-g++`
-loc=`dirname "$f"`
-cp $loc/../lib/libz.so.1.2.3 ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib/libz.so.1
-cp $loc/../lib/libvorbisidec.so.1.0.2 ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib/libvorbisidec.so.1
-
-echo Building ZIP bundle.
-if [ -f /usr/bin/zip ]
- then
- rm ./"scummvm-wiz-`date '+%Y-%m-%d'`.zip"
- cd "scummvm-wiz-`date '+%Y-%m-%d'`"
- zip -r -9 "../scummvm-wiz-`date '+%Y-%m-%d'`.zip" *
- echo You should have a "scummvm-wiz-`date '+%Y-%m-%d'`.zip" for the GP2X Wiz backend ready to go.
- cd ..
- rm -R ./"scummvm-wiz-`date '+%Y-%m-%d'`"
- else
- echo - /usr/bin/zip not found, ZIP bundle not created.
- echo All included files can also be found in ./"scummvm-wiz-`date '+%Y-%m-%d'`"
- echo - Please use you preferred archive tool to bundle these files.
-fi
-
-echo Please ensure GDB is installed somewhere in the path on your Wiz.
-
+make gp2xwiz-bundle-debug
diff --git a/backends/platform/gp2xwiz/build/bundle.sh b/backends/platform/gp2xwiz/build/bundle.sh
index 065bd7a685..579e2dc77b 100755
--- a/backends/platform/gp2xwiz/build/bundle.sh
+++ b/backends/platform/gp2xwiz/build/bundle.sh
@@ -2,56 +2,8 @@
echo Quick script to make building a distribution of the GP2X Wiz backend more consistent.
-echo Collecting files.
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`"
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm"
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/saves"
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/plugins"
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/engine-data"
-mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib"
+cd ../../../..
+echo Building ScummVM for GP2X Wiz.
-echo "Please put your save games in this dir" >> "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
-
-cp ./scummvm.gpe ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ./scummvm.png ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ./README-GP2XWIZ ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ./scummvm.ini ./scummvm-wiz-`date '+%Y-%m-%d'`/
-cp ../../../../scummvm.wiz ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../AUTHORS ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../README ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../COPYING ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../COPYRIGHT ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../NEWS ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../gui/themes/scummmodern.zip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../backends/vkeybd/packs/vkeybd_default.zip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../dists/pred.dic ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/
-cp ../../../../dists/engine-data/* ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/engine-data
-cp ../../../../plugins/* ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/plugins
-
-# Copy over dynamic libs needed by the app (as the ones in the default filesystem are broken).
-f=`which arm-open2x-linux-g++`
-loc=`dirname "$f"`
-cp $loc/../lib/libz.so.1.2.3 ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib/libz.so.1
-cp $loc/../lib/libvorbisidec.so.1.0.2 ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib/libvorbisidec.so.1
-
-echo Making Stripped Binary.
-arm-open2x-linux-strip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/scummvm.wiz
-
-echo Making Stripped Plugins.
-arm-open2x-linux-strip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/plugins/*
-
-echo Building ZIP bundle.
-if [ -f /usr/bin/zip ]
- then
- rm ./"scummvm-wiz-`date '+%Y-%m-%d'`.zip"
- cd "scummvm-wiz-`date '+%Y-%m-%d'`"
- zip -r -9 "../scummvm-wiz-`date '+%Y-%m-%d'`.zip" *
- echo You should have a "scummvm-wiz-`date '+%Y-%m-%d'`.zip" for the GP2X Wiz backend ready to go.
- cd ..
- rm -R ./"scummvm-wiz-`date '+%Y-%m-%d'`"
- else
- echo - /usr/bin/zip not found, ZIP bundle not created.
- echo All included files can also be found in ./"scummvm-wiz-`date '+%Y-%m-%d'`"
- echo - Please use you preferred archive tool to bundle these files.
-fi
+make gp2xwiz-bundle
diff --git a/backends/platform/gp2xwiz/gp2xwiz-bundle.mk b/backends/platform/gp2xwiz/gp2xwiz-bundle.mk
new file mode 100755
index 0000000000..fa5a247865
--- /dev/null
+++ b/backends/platform/gp2xwiz/gp2xwiz-bundle.mk
@@ -0,0 +1,73 @@
+# Special target to create bundles for the GP2X Wiz.
+
+#bundle_name = release/scummvm-wiz-`date '+%Y-%m-%d'`
+bundle_name = release/scummvm-gp2xwiz
+f=$(shell which $(STRIP))
+libloc = $(shell dirname $(f))
+
+gp2xwiz-bundle: $(EXECUTABLE)
+ $(MKDIR) "$(bundle_name)"
+ $(MKDIR) "$(bundle_name)/scummvm"
+ $(MKDIR) "$(bundle_name)/scummvm/saves"
+ $(MKDIR) "$(bundle_name)/scummvm/engine-data"
+ $(MKDIR) "$(bundle_name)/scummvm/lib"
+
+ echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
+
+ $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.gpe $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gp2xwiz/build/README-GP2XWIZ $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.ini $(bundle_name)/
+
+ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/
+ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/
+ $(INSTALL) -c -m 644 $(DIST_FILES_ENGINEDATA) $(bundle_name)/scummvm/engine-data
+ $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip $(bundle_name)/scummvm/
+
+ $(STRIP) $(EXECUTABLE) -o $(bundle_name)/scummvm/$(EXECUTABLE)
+
+ifdef DYNAMIC_MODULES
+ $(INSTALL) -d "$(bundle_name)/scummvm/plugins"
+ $(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/scummvm/plugins"
+ $(STRIP) $(bundle_name)/scummvm/plugins/*
+endif
+
+ $(CP) $(libloc)/../lib/libz.so.1.2.3 $(bundle_name)/scummvm/lib/libz.so.1
+ $(CP) $(libloc)/../lib/libvorbisidec.so.1.0.2 $(bundle_name)/scummvm/lib/libvorbisidec.so.1
+
+ tar -C $(bundle_name) -cvjf $(bundle_name).tar.bz2 .
+ rm -R ./$(bundle_name)
+
+gp2xwiz-bundle-debug: $(EXECUTABLE)
+ $(MKDIR) "$(bundle_name)"
+ $(MKDIR) "$(bundle_name)/scummvm"
+ $(MKDIR) "$(bundle_name)/scummvm/saves"
+ $(MKDIR) "$(bundle_name)/scummvm/engine-data"
+ $(MKDIR) "$(bundle_name)/scummvm/lib"
+
+ echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
+
+ $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe
+ $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gp2xwiz/build/README-GP2XWIZ $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.ini $(bundle_name)/
+
+ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/
+ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/
+ $(INSTALL) -c -m 644 $(DIST_FILES_ENGINEDATA) $(bundle_name)/scummvm/engine-data
+ $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip $(bundle_name)/scummvm/
+
+ $(INSTALL) -c -m 777 $(srcdir)/$(EXECUTABLE) $(bundle_name)/scummvm/$(EXECUTABLE)
+
+ifdef DYNAMIC_MODULES
+ $(INSTALL) -d "$(bundle_name)/scummvm/plugins"
+ $(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/scummvm/plugins"
+endif
+
+ $(CP) $(libloc)/../lib/libz.so.1.2.3 $(bundle_name)/scummvm/lib/libz.so.1
+ $(CP) $(libloc)/../lib/libvorbisidec.so.1.0.2 $(bundle_name)/scummvm/lib/libvorbisidec.so.1
+
+ tar -C $(bundle_name) -cvjf $(bundle_name)-debug.tar.bz2 .
+ rm -R ./$(bundle_name)
+
+.PHONY: gp2xwiz-bundle gp2xwiz-bundle-debug
diff --git a/backends/platform/gp2xwiz/gp2xwiz-events.cpp b/backends/platform/gp2xwiz/gp2xwiz-events.cpp
index a69aa42967..19ef24ef58 100644
--- a/backends/platform/gp2xwiz/gp2xwiz-events.cpp
+++ b/backends/platform/gp2xwiz/gp2xwiz-events.cpp
@@ -165,6 +165,7 @@ int GP2X_BUTTON_STATE_L = false;
/* Override the SDL pollEvent with the Wiz's own event code. */
bool OSystem_GP2XWIZ::pollEvent(Common::Event &event) {
SDL_Event ev;
+ ev.type = SDL_NOEVENT;
int axis;
byte b = 0;
diff --git a/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp b/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp
index ff3bd725be..921558131a 100644
--- a/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp
+++ b/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp
@@ -138,7 +138,7 @@ bool OSystem_GP2XWIZ::loadGFXMode() {
if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400)
_videoMode.aspectRatioCorrection = false;
- OSystem_SDL::loadGFXMode();
+ return OSystem_SDL::loadGFXMode();
}
void OSystem_GP2XWIZ::drawMouse() {
diff --git a/backends/platform/gp2xwiz/module.mk b/backends/platform/gp2xwiz/module.mk
index e162555493..c76238f679 100644
--- a/backends/platform/gp2xwiz/module.mk
+++ b/backends/platform/gp2xwiz/module.mk
@@ -7,11 +7,10 @@ MODULE_OBJS := \
gp2xwiz-main.o \
gp2xwiz-loader.o
-MODULE_DIRS += \
- backends/platform/gp2xwiz/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
# Hack to ensure the SDL backend is built so we can use OSystem_SDL.
-include $(srcdir)/backends/platform/sdl/module.mk \ No newline at end of file
diff --git a/backends/platform/iphone/iphone_video.m b/backends/platform/iphone/iphone_video.m
index faa0719b6c..cd8b38acb3 100644
--- a/backends/platform/iphone/iphone_video.m
+++ b/backends/platform/iphone/iphone_video.m
@@ -276,7 +276,7 @@ uint getSizeNextPOT(uint size) {
glGenTextures(1, &_screenTexture);
glBindTexture(GL_TEXTURE_2D, _screenTexture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if (_textureBuffer) {
free(_textureBuffer);
diff --git a/backends/platform/iphone/module.mk b/backends/platform/iphone/module.mk
index 28bc8d3ac7..9768e6ded4 100644
--- a/backends/platform/iphone/module.mk
+++ b/backends/platform/iphone/module.mk
@@ -10,8 +10,7 @@ MODULE_OBJS := \
iphone_keyboard.o \
blit_arm.o
-MODULE_DIRS += \
- backends/platform/iphone/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/iphone/osys_events.cpp b/backends/platform/iphone/osys_events.cpp
index 72408be89a..c1c7ffdc0c 100644
--- a/backends/platform/iphone/osys_events.cpp
+++ b/backends/platform/iphone/osys_events.cpp
@@ -24,6 +24,7 @@
*/
#include "gui/message.h"
+#include "common/translation.h"
#include "osys_main.h"
@@ -335,9 +336,9 @@ bool OSystem_IPHONE::handleEvent_mouseSecondDragged(Common::Event &event, int x,
_touchpadModeEnabled = !_touchpadModeEnabled;
const char *dialogMsg;
if (_touchpadModeEnabled)
- dialogMsg = "Touchpad mode enabled.";
+ dialogMsg = _("Touchpad mode enabled.");
else
- dialogMsg = "Touchpad mode disabled.";
+ dialogMsg = _("Touchpad mode disabled.");
GUI::TimedMessageDialog dialog(dialogMsg, 1500);
dialog.runModal();
return false;
diff --git a/backends/platform/linuxmoto/module.mk b/backends/platform/linuxmoto/module.mk
index 8123d6e2ac..316ecbf78e 100644
--- a/backends/platform/linuxmoto/module.mk
+++ b/backends/platform/linuxmoto/module.mk
@@ -7,11 +7,10 @@ MODULE_OBJS := \
linuxmoto-sdl.o \
hardwarekeys.o
-MODULE_DIRS += \
- backends/platform/linuxmoto/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
# HACK: The linuxmoto backend is based on the SDL one, so we load that, too.
include $(srcdir)/backends/platform/sdl/module.mk
diff --git a/backends/platform/n64/Makefile b/backends/platform/n64/Makefile
index 914e6e9c9e..b8b2e61f77 100644
--- a/backends/platform/n64/Makefile
+++ b/backends/platform/n64/Makefile
@@ -64,6 +64,8 @@ ENABLE_SCUMM = $(ENABLED)
OBJS := nintendo64.o osys_n64_base.o osys_n64_events.o osys_n64_utilities.o pakfs_save_manager.o framfs_save_manager.o
+BACKEND := n64
+
include $(srcdir)/Makefile.common
MODULE_DIRS += ./
diff --git a/backends/platform/n64/README.N64 b/backends/platform/n64/README.N64
index 1cdd82e1e9..276436b676 100644
--- a/backends/platform/n64/README.N64
+++ b/backends/platform/n64/README.N64
@@ -13,6 +13,8 @@ Requirements
Build cart images from sources
==============================
+You can download hkz-libn64 sources from here: http://hkzlab.ipv7.net/consoles.html
+hkz-libn64 is a library to control Nintendo64 hardware (es, video, audio, input, etc.).
* TODO *
Build cart images from binaries
diff --git a/backends/platform/n64/module.mk b/backends/platform/n64/module.mk
index 34a7badb44..429b63802e 100644
--- a/backends/platform/n64/module.mk
+++ b/backends/platform/n64/module.mk
@@ -1,10 +1,14 @@
MODULE := backends/platform/n64
MODULE_OBJS := \
- nintendo64.o
+ nintendo64.o \
+ osys_n64_base.o \
+ osys_n64_events.o \
+ osys_n64_utilities.o \
+ pakfs_save_manager.o \
+ framfs_save_manager.o
-MODULE_DIRS += \
- backends/platform/n64/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/null/module.mk b/backends/platform/null/module.mk
index 12a2cbc510..30345d7ac2 100644
--- a/backends/platform/null/module.mk
+++ b/backends/platform/null/module.mk
@@ -3,8 +3,7 @@ MODULE := backends/platform/null
MODULE_OBJS := \
null.o
-MODULE_DIRS += \
- backends/platform/null/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/ps2/Makefile.gdb b/backends/platform/ps2/Makefile.gdb
index 41ac58d629..53646a9546 100644
--- a/backends/platform/ps2/Makefile.gdb
+++ b/backends/platform/ps2/Makefile.gdb
@@ -75,6 +75,8 @@ OBJS := backends/platform/ps2/DmaPipe.o \
MODULE_DIRS += .
+BACKEND := ps2
+
include $(srcdir)/Makefile.common
LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T $(PS2SDK)/ee/startup/linkfile
diff --git a/backends/platform/ps2/Makefile.ps2 b/backends/platform/ps2/Makefile.ps2
index 717bc94379..f836bd3eaa 100644
--- a/backends/platform/ps2/Makefile.ps2
+++ b/backends/platform/ps2/Makefile.ps2
@@ -92,6 +92,11 @@ PLUGIN_EXTRA_DEPS = $(srcdir)/backends/plugins/plugin.syms elf/scummvm.elf
PLUGIN_LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o
PLUGIN_LDFLAGS += -nostartfiles -Wl,-q,--just-symbols,elf/scummvm.elf,-T$(srcdir)/backends/plugins/ps2/plugin.ld,--retain-symbols-file,$(srcdir)/backends/plugins/plugin.syms -lstdc++ -lc
+
+BACKEND := ps2
+
+include $(srcdir)/Makefile.common
+
LDFLAGS = -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T $(srcdir)/backends/plugins/ps2/main_prog.ld
LDFLAGS += -L $(PS2SDK)/ee/lib -L .
LDFLAGS += $(addprefix -L$(PS2_EXTRA),$(PS2_EXTRA_LIBS))
diff --git a/backends/platform/ps2/module.mk b/backends/platform/ps2/module.mk
index 69a28b93c4..a12d10771f 100644
--- a/backends/platform/ps2/module.mk
+++ b/backends/platform/ps2/module.mk
@@ -19,8 +19,7 @@ MODULE_OBJS := \
ps2debug.o \
ps2loader.o
-MODULE_DIRS += \
- backends/platform/ps2/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/psp/Makefile b/backends/platform/psp/Makefile
index 754bc775f0..9c011220b8 100644
--- a/backends/platform/psp/Makefile
+++ b/backends/platform/psp/Makefile
@@ -64,7 +64,6 @@ ifeq ($(PSPSDK),)
$(error $$(PSPSDK) cannot be obtained.)
endif
-
# Variables for common Scummvm makefile
CXX = psp-g++
CXXFLAGS = -O3 -Wall -Wno-multichar -fno-exceptions -fno-rtti
@@ -124,16 +123,12 @@ CXXFLAGS += -pg -g
LDFLAGS += -pg
endif
-# SDL Libs and Flags
-SDLFLAGS := $(shell $(PSPBIN)/sdl-config --cflags)
-SDLLIBS := $(shell $(PSPBIN)/sdl-config --libs)
# PSP LIBS
PSPLIBS = -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk \
-lpsputility -lpspuser -lpsppower -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lpspkernel
# Add in PSPSDK includes and libraries.
-CXXFLAGS += $(SDLFLAGS)
-LIBS += -lpng -lSDL -lz $(findstring -lGL,$(SDLLIBS)) -lstdc++ -lc -lm $(filter -L%,$(SDLLIBS)) $(PSPLIBS)
+LIBS += -lpng -lz -lstdc++ -lc -lm $(PSPLIBS)
OBJS := powerman.o \
psp_main.o \
@@ -147,8 +142,15 @@ OBJS := powerman.o \
cursor.o \
trace.o \
psploader.o \
- pspkeyboard.o
+ pspkeyboard.o \
+ audio.o \
+ thread.o \
+ rtc.o \
+ mp3.o \
+ tests.o
+
+BACKEND := psp
# Include common Scummvm makefile
include $(srcdir)/Makefile.common
diff --git a/backends/platform/psp/README.PSP b/backends/platform/psp/README.PSP
index 45f31483f7..f4d5bae6d6 100644
--- a/backends/platform/psp/README.PSP
+++ b/backends/platform/psp/README.PSP
@@ -99,8 +99,6 @@ To build ScummVM for PSP you need:
Note: This usually gets installed by the PSP toolchain,
so you don't have to do it manually.
-- SDL (svn co svn://svn.pspdev.org/psp/trunk/SDL)
-
- zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib)
- libPNG (svn co svn://svn.pspdev.org/psp/trunk/libpng)
diff --git a/backends/platform/psp/README.PSP.in b/backends/platform/psp/README.PSP.in
index d9f75974f1..2d53fd3b47 100644
--- a/backends/platform/psp/README.PSP.in
+++ b/backends/platform/psp/README.PSP.in
@@ -99,8 +99,6 @@ To build ScummVM for PSP you need:
Note: This usually gets installed by the PSP toolchain,
so you don't have to do it manually.
-- SDL (svn co svn://svn.pspdev.org/psp/trunk/SDL)
-
- zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib)
- libPNG (svn co svn://svn.pspdev.org/psp/trunk/libpng)
diff --git a/backends/platform/psp/audio.cpp b/backends/platform/psp/audio.cpp
new file mode 100644
index 0000000000..14691befee
--- /dev/null
+++ b/backends/platform/psp/audio.cpp
@@ -0,0 +1,150 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 <pspthreadman.h>
+#include <pspaudio.h>
+
+#include "common/scummsys.h"
+#include "backends/platform/psp/audio.h"
+
+//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
+//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
+
+#include "backends/platform/psp/trace.h"
+
+bool PspAudio::open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, callbackFunc callback, void *userData) {
+ DEBUG_ENTER_FUNC();
+ if (_init) {
+ PSP_ERROR("audio device already initialized\n");
+ return true;
+ }
+
+ PSP_DEBUG_PRINT("freq[%d], numOfChannels[%d], numOfSamples[%d], callback[%p], userData[%x]\n",
+ freq, numOfChannels, numOfSamples, callback, (uint32)userData);
+
+ numOfSamples = PSP_AUDIO_SAMPLE_ALIGN(numOfSamples);
+ uint32 bufLen = numOfSamples * numOfChannels * NUM_BUFFERS * sizeof(uint16);
+
+ PSP_DEBUG_PRINT("total buffer size[%d]\n", bufLen);
+
+ _buffers[0] = (byte *)memalign(64, bufLen);
+ if (!_buffers[0]) {
+ PSP_ERROR("failed to allocate memory for audio buffers\n");
+ return false;
+ }
+ memset(_buffers[0], 0, bufLen); // clean the buffer
+
+ // Fill in the rest of the buffer pointers
+ byte *pBuffer = _buffers[0];
+ for (int i = 1; i < NUM_BUFFERS; i++) {
+ pBuffer += numOfSamples * numOfChannels * sizeof(uint16);
+ _buffers[i] = pBuffer;
+ }
+
+ // Reserve a HW channel for our audio
+ _pspChannel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, numOfSamples, numOfChannels == 2 ? PSP_AUDIO_FORMAT_STEREO : PSP_AUDIO_FORMAT_MONO);
+ if (_pspChannel < 0) {
+ PSP_ERROR("failed to reserve audio channel\n");
+ return false;
+ }
+
+ PSP_DEBUG_PRINT("reserved channel[%d] for audio\n", _pspChannel);
+
+ // Save our data
+ _numOfChannels = numOfChannels;
+ _numOfSamples = numOfSamples;
+ _bufferSize = numOfSamples * numOfChannels * sizeof(uint16); // should be the right size to send the app
+ _callback = callback;
+ _userData = userData;
+ _bufferToFill = 0;
+ _bufferToPlay = 0;
+
+ _init = true;
+ _paused = true; // start in paused mode
+
+ threadCreateAndStart("audioThread", PRIORITY_AUDIO_THREAD, STACK_AUDIO_THREAD); // start the consumer thread
+
+ return true;
+}
+
+// The real thread function
+void PspAudio::threadFunction() {
+ assert(_callback);
+ PSP_DEBUG_PRINT_FUNC("audio thread started\n");
+
+ while (_init) { // Keep looping so long as we haven't been told to stop
+ if (_paused)
+ PSP_DEBUG_PRINT("audio thread paused\n");
+ while (_paused) { // delay until we stop pausing
+ PspThread::delayMicros(100000); // 100ms
+ if (!_paused)
+ PSP_DEBUG_PRINT("audio thread unpaused\n");
+ }
+
+ PSP_DEBUG_PRINT("remaining samples[%d]\n", _remainingSamples);
+
+ PSP_DEBUG_PRINT("filling buffer[%d]\n", _bufferToFill);
+ _callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in data
+ nextBuffer(_bufferToFill);
+
+ PSP_DEBUG_PRINT("playing buffer[%d].\n", _bufferToPlay);
+ playBuffer();
+ nextBuffer(_bufferToPlay);
+ } // while _init
+
+ // destroy everything
+ free(_buffers[0]);
+ sceAudioChRelease(_pspChannel);
+ PSP_DEBUG_PRINT("audio thread exiting. ****************************\n");
+}
+
+// Much faster than using %, especially with conditional moves (MIPS)
+inline void PspAudio::nextBuffer(int &bufferIdx) {
+ DEBUG_ENTER_FUNC();
+ bufferIdx++;
+ if (bufferIdx >= NUM_BUFFERS)
+ bufferIdx = 0;
+}
+
+// Don't do it with blocking
+inline bool PspAudio::playBuffer() {
+ DEBUG_ENTER_FUNC();
+ int ret;
+ if (_numOfChannels == 1)
+ ret = sceAudioOutputBlocking(_pspChannel, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]);
+ else
+ ret = sceAudioOutputPannedBlocking(_pspChannel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]);
+
+ if (ret < 0) {
+ PSP_ERROR("failed to output audio. Error[%d]\n", ret);
+ return false;
+ }
+ return true;
+}
+
+void PspAudio::close() {
+ PSP_DEBUG_PRINT("close has been called ***************\n");
+ _init = false;
+}
diff --git a/backends/platform/psp/audio.h b/backends/platform/psp/audio.h
new file mode 100644
index 0000000000..07f70cec7d
--- /dev/null
+++ b/backends/platform/psp/audio.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 PSP_AUDIO_H
+#define PSP_AUDIO_H
+
+#include "backends/platform/psp/thread.h"
+
+class PspAudio : public PspThreadable {
+public:
+ enum {
+ NUM_BUFFERS = 2,
+ FREQUENCY = 44100 /* only frequency we allow */
+ };
+ typedef void (* callbackFunc)(void *userData, byte *samples, int len); // audio callback to call
+ PspAudio() : _pspChannel(0),
+ _numOfChannels(0), _numOfSamples(0), _callback(0),
+ _bufferToPlay(0), _bufferToFill(0),
+ _init(false), _paused(true) {
+ for (int i=0; i<NUM_BUFFERS; i++)
+ _buffers[i] = 0;
+ }
+ ~PspAudio() { close(); }
+ bool playBuffer();
+ void nextBuffer(int &bufferIdx);
+ bool open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, callbackFunc callback, void *userData);
+ void close();
+ uint32 getFrequency() { return FREQUENCY; }
+ void pause() { _paused = true; }
+ void unpause() { _paused = false; }
+ virtual void threadFunction(); // actual audio thread
+
+private:
+ int _pspChannel; // chosen hardware output channel
+ uint32 _numOfChannels; // 1 for mono; 2 for stereo
+ uint32 _numOfSamples;
+ callbackFunc _callback; // the callback to call between outputting audio
+ void *_userData; // userData to send with callback
+ byte *_buffers[NUM_BUFFERS];
+ int _bufferToPlay; // the next buffer to output
+ int _bufferToFill;
+ int _bufferSize;
+ bool _init; // flag for initialization
+ bool _paused;
+};
+
+#endif /* PSP_AUDIO_H */
diff --git a/backends/platform/psp/cursor.cpp b/backends/platform/psp/cursor.cpp
index ae3b8f0050..cf879e095a 100644
--- a/backends/platform/psp/cursor.cpp
+++ b/backends/platform/psp/cursor.cpp
@@ -18,8 +18,8 @@
* 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/trunk/backends/platform/psp/osys_psp.h $
- * $Id: osys_psp.h 46120 2009-11-24 10:33:30Z Bluddy $
+ * $URL$
+ * $Id$
*
*/
diff --git a/backends/platform/psp/default_display_client.h b/backends/platform/psp/default_display_client.h
index 716e6fcc35..2e33632eb1 100644
--- a/backends/platform/psp/default_display_client.h
+++ b/backends/platform/psp/default_display_client.h
@@ -18,8 +18,8 @@
* 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/trunk/backends/platform/psp/trace.h $
- * $Id: trace.h 44276 2009-09-23 16:11:23Z joostp $
+ * $URL$
+ * $Id$
*
*/
diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp
index 90c41e796d..6360772c96 100644
--- a/backends/platform/psp/display_client.cpp
+++ b/backends/platform/psp/display_client.cpp
@@ -18,8 +18,8 @@
* 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/trunk/backends/platform/psp/osys_psp.cpp $
- * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $
+ * $URL$
+ * $Id$
*
*/
@@ -340,11 +340,17 @@ void Buffer::copyFromRect(const byte *buf, uint32 pitch, int destX, int destY, u
if (pitch == realWidthInBytes && pitch == recWidthInBytes) {
//memcpy(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth));
- Copier::copy(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth), &_pixelFormat);
+ if (_pixelFormat.swapRB)
+ PspMemory::fastSwap(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth), _pixelFormat);
+ else
+ PspMemory::fastCopy(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth));
} else {
do {
//memcpy(dst, buf, recWidthInBytes);
- Copier::copy(dst, buf, recWidthInBytes, &_pixelFormat);
+ if (_pixelFormat.swapRB)
+ PspMemory::fastSwap(dst, buf, recWidthInBytes, _pixelFormat);
+ else
+ PspMemory::fastCopy(dst, buf, recWidthInBytes);
buf += pitch;
dst += realWidthInBytes;
} while (--recHeight);
@@ -363,7 +369,10 @@ void Buffer::copyToArray(byte *dst, int pitch) {
do {
//memcpy(dst, src, sourceWidthInBytes);
- Copier::copy(dst, src, sourceWidthInBytes, &_pixelFormat);
+ if (_pixelFormat.swapRB)
+ PspMemory::fastSwap(dst, src, sourceWidthInBytes, _pixelFormat);
+ else
+ PspMemory::fastCopy(dst, src, sourceWidthInBytes);
src += realWidthInBytes;
dst += pitch;
} while (--h);
@@ -686,17 +695,18 @@ void GuRenderer::fillVertices(Vertex *vertices) {
uint32 gapX = _useGlobalScaler ? (PSP_SCREEN_WIDTH - outputWidth) >> 1 : 0;
uint32 gapY = _useGlobalScaler ? (PSP_SCREEN_HEIGHT - outputHeight) >> 1 : 0;
+ // Save scaled offset on screen
+ float scaledOffsetOnScreenX = scaleSourceToOutputX(_offsetOnScreen.x);
+ float scaledOffsetOnScreenY = scaleSourceToOutputY(_offsetOnScreen.y);
+
float imageStartX, imageStartY, imageEndX, imageEndY;
- imageStartX = gapX + (scaleSourceToOutputX(_maxTextureOffset.x));
- imageStartY = gapY;
-
- imageStartX += scaleSourceToOutputX(_offsetOnScreen.x);
- imageStartY += scaleSourceToOutputY(_offsetOnScreen.y);
+ imageStartX = gapX + scaledOffsetOnScreenX + (scaleSourceToOutputX(_maxTextureOffset.x));
+ imageStartY = gapY + scaledOffsetOnScreenY;
if (_fullScreen) { // shortcut
- imageEndX = PSP_SCREEN_WIDTH - gapX;
- imageEndY = PSP_SCREEN_HEIGHT - gapY;
+ imageEndX = PSP_SCREEN_WIDTH - gapX + scaledOffsetOnScreenX;
+ imageEndY = PSP_SCREEN_HEIGHT - gapY + scaledOffsetOnScreenY; // needed for screen shake
} else { /* !fullScreen */
imageEndX = imageStartX + scaleSourceToOutputX(_drawSize.width);
imageEndY = imageStartY + scaleSourceToOutputY(_drawSize.height);
diff --git a/backends/platform/psp/display_manager.cpp b/backends/platform/psp/display_manager.cpp
index 0982512a86..544e5a1b25 100644
--- a/backends/platform/psp/display_manager.cpp
+++ b/backends/platform/psp/display_manager.cpp
@@ -18,8 +18,8 @@
* 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/trunk/backends/platform/psp/osys_psp.cpp $
- * $Id: osys_psp.cpp 47541 2010-01-25 01:39:44Z lordhoto $
+ * $URL$
+ * $Id$
*
*/
@@ -64,37 +64,24 @@ const OSystem::GraphicsMode DisplayManager::_supportedModes[] = {
void MasterGuRenderer::setupCallbackThread() {
DEBUG_ENTER_FUNC();
- int thid = sceKernelCreateThread("displayCbThread", guCallbackThread, 0x11, 4*1024, THREAD_ATTR_USER, 0);
- PSP_DEBUG_PRINT("Display CB thread id is %x\n", thid);
-
- // We want to pass the pointer to this, but we'll have to take address of this so use a little trick
- MasterGuRenderer *_this = this;
-
- if (thid >= 0) {
- sceKernelStartThread(thid, sizeof(uint32 *), &_this);
- } else
- PSP_ERROR("failed to create display callback thread\n");
+ // start the thread that updates the display
+ threadCreateAndStart("DisplayCbThread", PRIORITY_DISPLAY_THREAD, STACK_DISPLAY_THREAD);
}
-// thread that reacts to the callback
-int MasterGuRenderer::guCallbackThread(SceSize, void *__this) {
+// this function gets called by PspThread when starting the new thread
+void MasterGuRenderer::threadFunction() {
DEBUG_ENTER_FUNC();
- // Dereferenced the copied value which was this
- MasterGuRenderer *_this = *(MasterGuRenderer **)__this;
-
// Create the callback. It should always get the pointer to MasterGuRenderer
- _this->_callbackId = sceKernelCreateCallback("Display Callback", guCallback, _this);
- if (_this->_callbackId < 0) {
- PSP_ERROR("failed to create display callback\n");
- return -1;
+ _callbackId = sceKernelCreateCallback("Display Callback", guCallback, this);
+ if (_callbackId < 0) {
+ PSP_ERROR("failed to create display callback\n");
}
PSP_DEBUG_PRINT("created callback. Going to sleep\n");
- sceKernelSleepThreadCB(); // sleep until we get a callback
- return 0;
+ sceKernelSleepThreadCB(); // sleep until we get a callback
}
// This callback is called when the render is finished. It swaps the buffers
@@ -310,27 +297,29 @@ void DisplayManager::calculateScaleParams() {
}
}
-void DisplayManager::renderAll() {
+// return true if we really rendered or no dirty. False otherwise
+bool DisplayManager::renderAll() {
DEBUG_ENTER_FUNC();
#ifdef USE_DISPLAY_CALLBACK
if (!_masterGuRenderer.isRenderFinished()) {
PSP_DEBUG_PRINT("Callback render not finished.\n");
- return;
+ return false; // didn't render
}
#endif /* USE_DISPLAY_CALLBACK */
- if (!isTimeToUpdate())
- return;
-
+ // This is cheaper than checking time, so we do it first
if (!_screen->isDirty() &&
(!_overlay->isDirty()) &&
(!_cursor->isDirty()) &&
(!_keyboard->isDirty())) {
PSP_DEBUG_PRINT("Nothing dirty\n");
- return;
+ return true; // nothing to render
}
+ if (!isTimeToUpdate())
+ return false; // didn't render
+
PSP_DEBUG_PRINT("screen[%s], overlay[%s], cursor[%s], keyboard[%s]\n",
_screen->isDirty() ? "true" : "false",
_overlay->isDirty() ? "true" : "false",
@@ -360,6 +349,8 @@ void DisplayManager::renderAll() {
_keyboard->setClean();
_masterGuRenderer.guPostRender();
+
+ return true; // rendered successfully
}
inline bool DisplayManager::isTimeToUpdate() {
@@ -374,7 +365,7 @@ inline bool DisplayManager::isTimeToUpdate() {
return true;
}
-Common::List<Graphics::PixelFormat> DisplayManager::getSupportedPixelFormats() {
+Common::List<Graphics::PixelFormat> DisplayManager::getSupportedPixelFormats() const {
Common::List<Graphics::PixelFormat> list;
// In order of preference
diff --git a/backends/platform/psp/display_manager.h b/backends/platform/psp/display_manager.h
index 5864f39b36..72f252faae 100644
--- a/backends/platform/psp/display_manager.h
+++ b/backends/platform/psp/display_manager.h
@@ -18,18 +18,20 @@
* 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/trunk/backends/platform/psp/osys_psp.cpp $
- * $Id: osys_psp.cpp 47541 2010-01-25 01:39:44Z lordhoto $
+ * $URL$
+ * $Id$
*
*/
#ifndef PSP_DISPLAY_MAN_H
#define PSP_DISPLAY_MAN_H
+#include "backends/platform/psp/thread.h"
+
/**
* Class used only by DisplayManager to start/stop GU rendering
*/
-class MasterGuRenderer {
+class MasterGuRenderer : public PspThreadable {
public:
MasterGuRenderer() : _lastRenderTime(0), _renderFinished(true), _callbackId(-1) {}
void guInit();
@@ -37,15 +39,15 @@ public:
void guPostRender();
void guShutDown();
bool isRenderFinished() { return _renderFinished; }
- void setupCallbackThread();
+ void setupCallbackThread();
private:
+ virtual void threadFunction(); // for the display callback thread
static uint32 _displayList[];
- uint32 _lastRenderTime; // For measuring rendering
+ uint32 _lastRenderTime; // For measuring rendering time
void guProgramDisplayBufferSizes();
- static int guCallbackThread(SceSize, void *); // for the graphics callbacks
- static int guCallback(int, int, void *__this);
- bool _renderFinished;
- int _callbackId;
+ static int guCallback(int, int, void *__this); // for the display callback
+ bool _renderFinished; // for sync with render callback
+ int _callbackId; // to keep track of render callback
};
class Screen;
@@ -68,7 +70,7 @@ public:
~DisplayManager();
void init();
- void renderAll();
+ bool renderAll(); // return true if rendered or nothing dirty. False otherwise
bool setGraphicsMode(int mode);
bool setGraphicsMode(const char *name);
int getGraphicsMode() const { return _graphicsMode; }
@@ -83,12 +85,12 @@ public:
void setSizeAndPixelFormat(uint width, uint height, const Graphics::PixelFormat *format);
// Getters
- float getScaleX() { return _displayParams.scaleX; }
- float getScaleY() { return _displayParams.scaleY; }
- uint32 getOutputWidth() { return _displayParams.screenOutput.width; }
- uint32 getOutputHeight() { return _displayParams.screenOutput.height; }
- uint32 getOutputBitsPerPixel() { return _displayParams.outputBitsPerPixel; }
- Common::List<Graphics::PixelFormat> getSupportedPixelFormats();
+ float getScaleX() const { return _displayParams.scaleX; }
+ float getScaleY() const { return _displayParams.scaleY; }
+ uint32 getOutputWidth() const { return _displayParams.screenOutput.width; }
+ uint32 getOutputHeight() const { return _displayParams.screenOutput.height; }
+ uint32 getOutputBitsPerPixel() const { return _displayParams.outputBitsPerPixel; }
+ Common::List<Graphics::PixelFormat> getSupportedPixelFormats() const;
private:
struct GlobalDisplayParams {
diff --git a/backends/platform/psp/input.cpp b/backends/platform/psp/input.cpp
index 4fe7cb3f92..2a91ce455a 100644
--- a/backends/platform/psp/input.cpp
+++ b/backends/platform/psp/input.cpp
@@ -18,8 +18,8 @@
* 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/trunk/backends/platform/psp/osys_psp.cpp $
- * $Id: osys_psp.cpp 43618 2009-08-21 22:44:49Z joostp $
+ * $URL$
+ * $Id$
*
*/
diff --git a/backends/platform/psp/memory.cpp b/backends/platform/psp/memory.cpp
index e134a7d0f4..29d0482d9a 100644
--- a/backends/platform/psp/memory.cpp
+++ b/backends/platform/psp/memory.cpp
@@ -35,129 +35,408 @@
#include "backends/platform/psp/trace.h"
-void Copier::copy(byte *dst, const byte *src, uint32 bytes, PSPPixelFormat *format /* = NULL */) {
+//#define TEST_MEMORY_COPY
+
+extern "C" {
+
+#ifdef TEST_MEMORY_COPY /* we won't be able to run in this case b/c of printouts */
+extern void *__real_memcpy(void *dst, void *src, size_t bytes);
+#endif
+
+void *__wrap_memcpy(void *dst, void *src, size_t bytes) {
+#ifdef TEST_MEMORY_COPY /* we won't be able to run in this case */
+ return __real_memcpy(dst, src, bytes);
+#else
+ PspMemory::fastCopy((byte *)dst, (byte *)src, bytes);
+ return dst;
+#endif
+}
+
+}
+
+void PspMemory::copy(byte *dst, const byte *src, uint32 bytes) {
DEBUG_ENTER_FUNC();
- uint32 prefixDst = (((uint32)dst) & 0x3);
- prefixDst = prefixDst ? 4 - prefixDst : 0; // prefix only if we have address % 4 != 0
- uint32 prefixSrc = (((uint32)src) & 0x3);
- prefixSrc = prefixSrc ? 4 - prefixSrc : 0; // prefix only if we have address % 4 != 0
- uint32 *dst32, *src32;
- bool swapRB = format ? format->swapRB : false; // take swap value from pixelformat if it's given
-#ifdef __PSP_DEBUG_PRINT__
+#ifdef TEST_MEMORY_COPY
uint32 debugBytes = bytes;
const byte *debugDst = dst, *debugSrc = src;
#endif
- uint32 words, remainingBytes;
- //PSP_DEBUG_PRINT("dst[%p], src[%p], bytes[%d], swap[%s], prefixDst[%u], prefixSrc[%u]\n", dst, src, bytes, swapRB ? "true" : "false", prefixDst, prefixSrc);
+ PSP_DEBUG_PRINT("copy(): dst[%p], src[%p], bytes[%d]\n", dst, src, bytes);
- if (prefixDst || prefixSrc) { // we're not aligned to word boundaries
- if (prefixDst != prefixSrc) { // worst case: we can never be aligned. this mode is highly inefficient. try to get engines not to use this mode too much
- PSP_DEBUG_PRINT("misaligned copy of %u bytes from %p to %p\n", bytes, src, dst);
- if ((prefixDst & 1) || (prefixSrc & 1))
- copy8(dst, src, bytes); // no swap is possible on 8 bit
- else
- copy16((uint16 *)dst, (uint16 *)src, bytes, format);
-
- goto test;
- }
-
- // Do the prefix: the part to get us aligned
- if (prefixDst & 1) { // byte
- copy8(dst, src, prefixDst); // no swap available
- } else { // short
- copy16((uint16 *)dst, (uint16 *)src, prefixDst, format);
- }
- if (bytes > prefixDst) // check that we can afford to subtract from bytes
- bytes -= prefixDst;
- else {
+ // align the destination pointer first
+ uint32 prefixDst = (((uint32)dst) & 0x3);
+
+ if (prefixDst) {
+ prefixDst = 4 - prefixDst; // prefix only if we have address % 4 != 0
+ PSP_DEBUG_PRINT("prefixDst[%d]\n", prefixDst);
+
+ bytes -= prefixDst; // remember we assume bytes >= 4
+
+ if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY) { // check if it's worthwhile to continue
+ copy8(dst, src, bytes + prefixDst);
+#ifdef TEST_MEMORY_COPY
+ testCopy(debugDst, debugSrc, debugBytes);
+#endif
return;
}
- dst32 = (uint32 *)(dst + prefixDst);
- src32 = (uint32 *)(src + prefixSrc);
- } else { // We're aligned to word boundaries
- dst32 = (uint32 *)dst;
- src32 = (uint32 *)src;
+
+ while (prefixDst--) {
+ *dst++ = *src++;
+ }
}
-
- words = bytes >> 2;
- remainingBytes = bytes & 0x3;
-
- if (swapRB) { // need to swap
- for (; words > 0; words--) {
- *dst32 = format->swapRedBlue32(*src32);
- dst32++;
- src32++;
- }
- } else { // no swapping
- for (; words > 0; words--) {
- *dst32 = *src32;
- dst32++;
- src32++;
- }
+
+ // check the source pointer alignment now
+ uint32 alignSrc = (((uint32)src) & 0x3);
+
+ if (alignSrc) { // we'll need to realign our reads
+ copy32Misaligned((uint32 *)dst, src, bytes, alignSrc);
+ } else {
+ copy32Aligned((uint32 *)dst, (uint32 *)src, bytes);
}
- // Do any remaining bytes
- if (remainingBytes) {
- if (remainingBytes & 1) // we have bytes left
- copy8((byte *)dst32, (byte *)src32, remainingBytes);
- else // 16bits left
- copy16((uint16*)dst32, (uint16 *)src32, remainingBytes, format);
- }
+#ifdef TEST_MEMORY_COPY
+ testCopy(debugDst, debugSrc, debugBytes);
+#endif
+}
-test:
- // debug
-#ifdef __PSP_DEBUG_PRINT__
+void PspMemory::testCopy(const byte *debugDst, const byte *debugSrc, uint32 debugBytes) {
+
bool mismatch = false;
+ PSP_INFO_PRINT("testing fastCopy...");
for (uint32 i = 0; i < debugBytes; i++) {
if (debugDst[i] != debugSrc[i]) {
- if (mismatch == false) {
- PSP_DEBUG_PRINT_SAMELN("mismatch in copy:\n");
- PSP_DEBUG_PRINT("dst[%p], src[%p], bytes[%u], swap[%s], prefixDst[%u], prefixSrc[%u]\n", debugDst, debugSrc, debugBytes, swapRB ? "true" : "false", prefixDst, prefixSrc);
+ if (!mismatch) {
+ PSP_INFO_PRINT("**** mismatch in copy! ****\n");
+ PSP_INFO_PRINT("dst[%p], src[%p], bytes[%u]\n", debugDst, debugSrc, debugBytes);
mismatch = true;
}
- PSP_DEBUG_PRINT_SAMELN("%x!=%x ", debugSrc[i], debugDst[i]);
+ PSP_INFO_PRINT("[%d]%x!=%x ", i, debugSrc[i], debugDst[i]);
}
}
- if (mismatch)
- PSP_DEBUG_PRINT("\n");
+ if (mismatch) {
+ PSP_INFO_PRINT("\n");
+ } else {
+ PSP_INFO_PRINT("ok\n");
+ }
+}
+
+//
+// used to swap red and blue
+void PspMemory::swap(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) {
+ DEBUG_ENTER_FUNC();
+
+#ifdef TEST_MEMORY_COPY
+ uint32 debugBytes = bytes;
+ const uint16 *debugDst = dst16, *debugSrc = src16;
#endif
+
+ // align the destination pointer first
+ uint32 prefixDst = (((uint32)dst16) & 0x3); // for swap, we can only have 2 or 0 as our prefix
+
+ if (prefixDst) {
+ bytes -= prefixDst; // remember we assume bytes > 4
+ *dst16++ = format.swapRedBlue16(*src16++);
+
+ if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY) { // check if it's worthwhile to continue
+ swap16(dst16, src16, bytes, format);
+
+#ifdef TEST_MEMORY_COPY
+ testSwap(debugDst, debugSrc, debugBytes, format);
+#endif
+ return;
+ }
+ }
+
+ // check the source pointer alignment now
+ uint32 alignSrc = (((uint32)src16) & 0x3);
+
+ if (alignSrc) { // we'll need to realign our reads
+ PSP_DEBUG_PRINT("misaligned copy of %u bytes from %p to %p\n", bytes, src16, dst16);
+ swap32Misaligned((uint32 *)dst16, src16, bytes, format);
+ } else {
+ swap32Aligned((uint32 *)dst16, (const uint32 *)src16, bytes, format);
+ }
+
+#ifdef TEST_MEMORY_COPY
+ testSwap(debugDst, debugSrc, debugBytes, format);
+#endif
+
+}
+
+void PspMemory::testSwap(const uint16 *debugDst, const uint16 *debugSrc, uint32 debugBytes, PSPPixelFormat &format) {
+
+ bool mismatch = false;
+ PSP_INFO_PRINT("testing fastSwap...");
+
+ uint32 shorts = debugBytes >> 1;
+
+ for (uint32 i = 0; i < shorts; i++) {
+ if (debugDst[i] != format.swapRedBlue16(debugSrc[i])) {
+ if (!mismatch) {
+ PSP_INFO_PRINT("**** mismatch in swap! ****\n");
+ PSP_INFO_PRINT("dst[%p], src[%p], bytes[%u]\n", debugDst, debugSrc, debugBytes);
+ mismatch = true;
+ }
+ PSP_INFO_PRINT("[%d]%x!=%x ", i<<1, format.swapRedBlue16(debugSrc[i]), debugDst[i]);
+ }
+ }
+ if (mismatch) {
+ PSP_INFO_PRINT("\n");
+ } else {
+ PSP_INFO_PRINT("ok\n");
+ }
+}
+
+
+void PspMemory::copy32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes) {
+ PSP_DEBUG_PRINT("copy32Aligned(): dst32[%p], src32[%p], bytes[%d]\n", dst32, src32, bytes);
+
+ int words8 = bytes >> 5;
+
+ // try blocks of 8 words at a time
+ if (words8) {
+ while (words8--) {
+ uint32 a, b, c, d;
+ a = src32[0];
+ b = src32[1];
+ c = src32[2];
+ d = src32[3];
+ dst32[0] = a;
+ dst32[1] = b;
+ dst32[2] = c;
+ dst32[3] = d;
+ a = src32[4];
+ b = src32[5];
+ c = src32[6];
+ d = src32[7];
+ dst32[4] = a;
+ dst32[5] = b;
+ dst32[6] = c;
+ dst32[7] = d;
+ dst32 += 8;
+ src32 += 8;
+ }
+ }
+
+ int words4 = (bytes & 0x1F) >> 4;
+
+ // try blocks of 4 words at a time
+ if (words4) {
+ uint32 a, b, c, d;
+ a = src32[0];
+ b = src32[1];
+ c = src32[2];
+ d = src32[3];
+ dst32[0] = a;
+ dst32[1] = b;
+ dst32[2] = c;
+ dst32[3] = d;
+ dst32 += 4;
+ src32 += 4;
+ }
+
+ int bytesLeft = (bytes & 0xF); // only look at bytes left after we did the above
+ int wordsLeft = bytesLeft >> 2;
+
+ // now just do single words
+ while (wordsLeft) {
+ *dst32++ = *src32++;
+ wordsLeft--;
+ }
- return; // So we have something to jump to with the label
+ bytesLeft = bytes & 0x3; // get remaining bytes
+
+ PSP_DEBUG_PRINT("bytesLeft[%d]\n", bytesLeft);
+
+ byte *dst = (byte *)dst32;
+ byte *src = (byte *)src32;
+
+ while (bytesLeft--) {
+ *dst++ = *src++;
+ }
}
-inline void Copier::copy8(byte *dst, const byte *src, uint32 bytes) {
- for (; bytes > 0; bytes--) {
- *dst = *src;
- dst++;
- src++;
+void PspMemory::swap32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes, PSPPixelFormat &format) {
+ DEBUG_ENTER_FUNC();
+ int words4 = bytes >> 4;
+
+ // try blocks of 4 words at a time
+ while (words4--) {
+ uint32 a, b, c, d;
+ a = format.swapRedBlue32(src32[0]);
+ b = format.swapRedBlue32(src32[1]);
+ c = format.swapRedBlue32(src32[2]);
+ d = format.swapRedBlue32(src32[3]);
+ dst32[0] = a;
+ dst32[1] = b;
+ dst32[2] = c;
+ dst32[3] = d;
+ dst32 += 4;
+ src32 += 4;
+ }
+
+ uint32 bytesLeft = bytes & 0xF;
+ uint32 words = bytesLeft >> 2;
+
+ // now just do words
+ while (words--) {
+ *dst32++ = format.swapRedBlue32(*src32++);
+ }
+
+ bytesLeft = bytes & 0x3;
+
+ if (bytesLeft) { // for swap, can only be 1 short left
+ *((uint16 *)dst32) = format.swapRedBlue16(*((uint16 *)src32));
}
}
-inline void Copier::copy16(uint16 *dst, const uint16 *src, uint32 bytes, PSPPixelFormat *format /* = NULL */) {
- uint32 shorts = bytes >> 1;
- uint32 remainingBytes = bytes & 1;
- bool swapRB = format ? format->swapRB : false;
- if (swapRB) {
- for (; shorts > 0 ; shorts--) {
- *dst = format->swapRedBlue16(*src);
- dst++;
- src++;
+// More challenging -- need to shift
+// Assume dst is aligned
+void PspMemory::copy32Misaligned(uint32 *dst32, const byte *src, uint32 bytes, uint32 alignSrc) {
+ PSP_DEBUG_PRINT("copy32Misaligned: dst32[%p], src[%p], bytes[%d], alignSrc[%d]\n", dst32, src, bytes, alignSrc);
+
+ uint32 *src32 = (uint32 *)(((uint32)src) & 0xFFFFFFFC); // remove misalignment
+ uint32 shiftValue, lastShiftValue;
+
+ switch (alignSrc) {
+ case 1:
+ shiftValue = 8;
+ lastShiftValue = 24;
+ break;
+ case 2:
+ shiftValue = 16;
+ lastShiftValue = 16;
+ break;
+ default: /* 3 */
+ shiftValue = 24;
+ lastShiftValue = 8;
+ break;
+ }
+
+ uint32 dstWord, srcWord;
+
+ // Try to do groups of 4 words
+ uint32 words4 = bytes >> 4;
+
+ srcWord = *src32; // preload 1st word so we read ahead
+
+ for (; words4; words4--) {
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[1];
+ dstWord |= srcWord << lastShiftValue;
+ dst32[0] = dstWord;
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[2];
+ dstWord |= srcWord << lastShiftValue;
+ dst32[1] = dstWord;
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[3];
+ dstWord |= srcWord << lastShiftValue;
+ dst32[2] = dstWord;
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[4];
+ dstWord |= srcWord << lastShiftValue;
+ dst32[3] = dstWord;
+ src32 += 4;
+ dst32 += 4;
+ }
+
+ uint32 words = (bytes & 0xF) >> 2; // now get remaining words
+
+ // we read one word ahead of what we write
+ // setup the first read
+
+ for (; words ;words--) {
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[1]; // we still go one ahead
+ src32++;
+ dstWord |= srcWord << lastShiftValue;
+ *dst32++ = dstWord;
+ }
+
+ uint32 bytesLeft = bytes & 3; // and remaining bytes
+
+ if (bytesLeft) {
+ byte *dst8 = (byte *)dst32;
+ byte *src8 = ((byte *)src32) + ((uint32)src & 0x3); // get exact location we should be at
+
+ for(; bytesLeft; bytesLeft--) {
+ *dst8++ = *src8++;
}
- } else {
- for (; shorts > 0 ; shorts--) {
- *dst = *src;
- dst++;
- src++;
+ }
+}
+
+// More challenging -- need to shift
+// We assume dst is aligned
+void PspMemory::swap32Misaligned(uint32 *dst32, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) {
+ DEBUG_ENTER_FUNC();
+
+ const uint32 shiftValue = 16;
+ uint32 *src32 = (uint32 *)(((uint32)src16) & 0xFFFFFFFC); // remove misalignment
+
+ // Try to do groups of 4 words
+ uint32 words4 = bytes >> 4;
+ uint32 srcWord = src32[0]; // preload
+
+ while (words4--) {
+ uint32 dstWord = srcWord >> shiftValue;
+ srcWord = src32[1];
+ dstWord |= srcWord << shiftValue;
+ dst32[0] = format.swapRedBlue32(dstWord);
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[2];
+ dstWord |= srcWord << shiftValue;
+ dst32[1] = format.swapRedBlue32(dstWord);
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[3];
+ dstWord |= srcWord << shiftValue;
+ dst32[2] = format.swapRedBlue32(dstWord);
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[4];
+ dstWord |= srcWord << shiftValue;
+ dst32[3] = format.swapRedBlue32(dstWord);
+ src32 += 4;
+ dst32 += 4;
+ }
+
+ uint32 words = (bytes & 0xF) >> 2;
+
+ // we read one word ahead of what we write
+ // setup the first read
+ if (words) {
+ //srcWord = *src32++; // don't need this. already loaded
+ src32++; // we already have the value loaded in
+
+ while (words--) {
+ uint32 dstWord = srcWord >> shiftValue;
+ srcWord = *src32++;
+ dstWord |= srcWord << shiftValue;
+ *dst32++ = format.swapRedBlue32(dstWord);
}
}
- if (remainingBytes)
- *(byte *)dst = *(byte *)src;
+
+ uint32 bytesLeft = bytes & 3;
+
+ if (bytesLeft) { // for swap, can only be 1 short left
+ *((uint16 *)dst32) = format.swapRedBlue16((uint16)(srcWord >> shiftValue));
+ }
}
+inline void PspMemory::copy16(uint16 *dst16, const uint16 *src16, uint32 bytes) {
+ PSP_DEBUG_PRINT("copy16(): dst16[%p], src16[%p], bytes[%d]\n", dst16, src16, bytes);
+
+ uint32 shorts = bytes >> 1;
+ uint32 remainingBytes = bytes & 1;
+
+ for (; shorts > 0 ; shorts--) {
+ *dst16++ = *src16++;
+ }
+ if (remainingBytes)
+ *(byte *)dst16 = *(byte *)src16;
+}
// Class VramAllocator -----------------------------------
diff --git a/backends/platform/psp/memory.h b/backends/platform/psp/memory.h
index a198095090..793bc94888 100644
--- a/backends/platform/psp/memory.h
+++ b/backends/platform/psp/memory.h
@@ -27,17 +27,68 @@
#ifndef PSP_MEMORY_H
#define PSP_MEMORY_H
+#include "backends/platform/psp/psppixelformat.h"
+#include "common/list.h"
+
#define UNCACHED(x) ((byte *)(((uint32)(x)) | 0x40000000)) /* make an uncached access */
#define CACHED(x) ((byte *)(((uint32)(x)) & 0xBFFFFFFF)) /* make an uncached access into a cached one */
+#define MIN_AMOUNT_FOR_COMPLEX_COPY 8
+#define MIN_AMOUNT_FOR_MISALIGNED_COPY 8
+
+//#define __PSP_DEBUG_PRINT__
+
+#include "backends/platform/psp/trace.h"
+
/**
* Class that does memory copying and swapping if needed
*/
-class Copier {
-public:
- static void copy(byte *dst, const byte *src, uint32 bytes, PSPPixelFormat *format = NULL);
- static void copy8(byte *dst, const byte *src, uint32 bytes);
- static void copy16(uint16 *dst, const uint16 *src, uint32 bytes, PSPPixelFormat *format = NULL);
+class PspMemory {
+private:
+ static void testCopy(const byte *debugDst, const byte *debugSrc, uint32 debugBytes);
+ static void testSwap(const uint16 *debugDst, const uint16 *debugSrc, uint32 debugBytes, PSPPixelFormat &format);
+ static void copy(byte *dst, const byte *src, uint32 bytes);
+ static void swap(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format);
+ static void copy32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes);
+ static void swap32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes, PSPPixelFormat &format);
+ static void copy32Misaligned(uint32 *dst32, const byte *src, uint32 bytes, uint32 alignSrc);
+ static void swap32Misaligned(uint32 *dst32, const uint16 *src16, uint32 bytes, PSPPixelFormat &format);
+ static void copy16(uint16 *dst, const uint16 *src, uint32 bytes);
+
+ // For swapping, we know that we have multiples of 16 bits
+ static void swap16(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) {
+ PSP_DEBUG_PRINT("swap16 called with dst16[%p], src16[%p], bytes[%d]\n", dst16, src16, bytes);
+ uint32 shorts = bytes >> 1;
+
+ while (shorts--) {
+ *dst16++ = format.swapRedBlue16(*src16++);
+ }
+ }
+
+ static void copy8(byte *dst, const byte *src, uint32 bytes) {
+ PSP_DEBUG_PRINT("copy8 called with dst[%p], src[%p], bytes[%d]\n", dst, src, bytes);
+ while (bytes--) {
+ *dst++ = *src++;
+ }
+ }
+
+public:
+ // This is the interface to the outside world
+ static void fastCopy(byte *dst, const byte *src, uint32 bytes) {
+ if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY) {
+ copy8(dst, src, bytes);
+ } else { // go to more powerful copy
+ copy(dst, src, bytes);
+ }
+ }
+
+ static void fastSwap(byte *dst, const byte *src, uint32 bytes, PSPPixelFormat &format) {
+ if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY * 2) {
+ swap16((uint16 *)dst, (uint16 *)src, bytes, format);
+ } else { // go to more powerful copy
+ swap((uint16 *)dst, (uint16 *)src, bytes, format);
+ }
+ }
};
/**
diff --git a/backends/platform/psp/module.mk b/backends/platform/psp/module.mk
index f7191fe14f..4652189ab4 100644
--- a/backends/platform/psp/module.mk
+++ b/backends/platform/psp/module.mk
@@ -12,10 +12,14 @@ MODULE_OBJS := powerman.o \
cursor.o \
trace.o \
psploader.o \
- pspkeyboard.o
+ pspkeyboard.o \
+ audio.o \
+ thread.o \
+ rtc.o \
+ mp3.o \
+ tests.o
-MODULE_DIRS += \
- backends/platform/psp/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/psp/mp3.cpp b/backends/platform/psp/mp3.cpp
new file mode 100644
index 0000000000..e25891396b
--- /dev/null
+++ b/backends/platform/psp/mp3.cpp
@@ -0,0 +1,487 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+
+#include "common/debug.h"
+#include "common/stream.h"
+#include "common/util.h"
+#include "common/singleton.h"
+#include "common/mutex.h"
+
+#include "sound/audiostream.h"
+
+#include <pspaudiocodec.h>
+#include <psputility_modules.h>
+#include <pspthreadman.h>
+#include <pspsysmem.h>
+#include <pspmodulemgr.h>
+#include <psputility_avmodules.h>
+#include <mad.h>
+#include "backends/platform/psp/mp3.h"
+
+//#define DISABLE_PSP_MP3 // to make us use the regular MAD decoder instead
+
+//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */
+//#define __PSP_DEBUG_PRINT__
+#include "backends/platform/psp/trace.h"
+
+//#define PRINT_BUFFERS /* to debug MP3 buffers */
+
+namespace Audio {
+
+class Mp3PspStream;
+
+bool Mp3PspStream::_decoderInit = false; // has the decoder been initialized
+#ifdef DISABLE_PSP_MP3
+bool Mp3PspStream::_decoderFail = true; // pretend the decoder failed
+#else
+bool Mp3PspStream::_decoderFail = false; // has the decoder failed to load
+#endif
+
+bool Mp3PspStream::initDecoder() {
+ DEBUG_ENTER_FUNC();
+
+ if (_decoderInit) {
+ PSP_ERROR("Already initialized!");
+ return true;
+ }
+
+ // Based on PSP firmware version, we need to do different things to do Media Engine processing
+ uint32 firmware = sceKernelDevkitVersion();
+ PSP_DEBUG_PRINT("Firmware version 0x%x\n", firmware);
+ if (firmware == 0x01050001){
+ if (!loadStartAudioModule((char *)(void *)"flash0:/kd/me_for_vsh.prx",
+ PSP_MEMORY_PARTITION_KERNEL)) {
+ PSP_ERROR("failed to load me_for_vsh.prx. ME cannot start.\n");
+ _decoderFail = true;
+ return false;
+ }
+ if (!loadStartAudioModule((char *)(void *)"flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL)) {
+ PSP_ERROR("failed to load audiocodec.prx. ME cannot start.\n");
+ _decoderFail = true;
+ return false;
+ }
+ } else {
+ if (sceUtilityLoadAvModule(PSP_AV_MODULE_AVCODEC) < 0) {
+ PSP_ERROR("failed to load AVCODEC module. ME cannot start.\n");
+ _decoderFail = true;
+ return false;
+ }
+ }
+
+ PSP_DEBUG_PRINT("Using PSP's ME for MP3\n"); // important to know this is happening
+
+ _decoderInit = true;
+ return true;
+}
+
+bool Mp3PspStream::stopDecoder() {
+ DEBUG_ENTER_FUNC();
+
+ if (!_decoderInit)
+ return true;
+
+ // Based on PSP firmware version, we need to do different things to do Media Engine processing
+ if (sceKernelDevkitVersion() == 0x01050001){
+/* if (!unloadAudioModule("flash0:/kd/me_for_vsh.prx", PSP_MEMORY_PARTITION_KERNEL) ||
+ !unloadAudioModule("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL) {
+ PSP_ERROR("failed to unload audio module\n");
+ return false;
+ }
+*/
+ }else{
+ if (sceUtilityUnloadModule(PSP_MODULE_AV_AVCODEC) < 0) {
+ PSP_ERROR("failed to unload avcodec module\n");
+ return false;
+ }
+ }
+
+ _decoderInit = false;
+ return true;
+}
+
+//Load a PSP audio module
+bool Mp3PspStream::loadStartAudioModule(const char *modname, int partition){
+ DEBUG_ENTER_FUNC();
+
+ SceKernelLMOption option;
+ SceUID modid;
+
+ memset(&option, 0, sizeof(option));
+ option.size = sizeof(option);
+ option.mpidtext = partition;
+ option.mpiddata = partition;
+ option.position = 0;
+ option.access = 1;
+
+ modid = sceKernelLoadModule(modname, 0, &option);
+ if (modid < 0) {
+ PSP_ERROR("Failed to load module %s. Got error 0x%x\n", modname, modid);
+ return false;
+ }
+
+ int ret = sceKernelStartModule(modid, 0, NULL, NULL, NULL);
+ if (ret < 0) {
+ PSP_ERROR("Failed to start module %s. Got error 0x%x\n", modname, ret);
+ return false;
+ }
+ return true;
+}
+
+// TODO: make parallel function for unloading the 1.50 modules
+
+Mp3PspStream::Mp3PspStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) :
+ _inStream(inStream),
+ _disposeAfterUse(dispose),
+ _pcmLength(0),
+ _posInFrame(0),
+ _state(MP3_STATE_INIT),
+ _length(0, 1000),
+ _sampleRate(0),
+ _totalTime(mad_timer_zero) {
+
+ DEBUG_ENTER_FUNC();
+
+ assert(_decoderInit); // must be initialized by now
+
+ // let's leave the buffer guard -- who knows, it may be good?
+ memset(_buf, 0, sizeof(_buf));
+ memset(_codecInBuffer, 0, sizeof(_codecInBuffer));
+
+ initStream(); // init needed stuff for the stream
+
+ while (_state != MP3_STATE_EOS)
+ findValidHeader(); // get a first header so we can read basic stuff
+
+ _sampleRate = _header.samplerate; // copy it before it gets destroyed
+
+ _length = Timestamp(mad_timer_count(_totalTime, MAD_UNITS_MILLISECONDS), getRate());
+
+ //initStreamME(); // init the stuff needed for the ME to work
+
+ deinitStream();
+ //releaseStreamME();
+
+ _state = MP3_STATE_INIT;
+}
+
+int Mp3PspStream::initStream() {
+ DEBUG_ENTER_FUNC();
+
+ if (_state != MP3_STATE_INIT)
+ deinitStream();
+
+ // Init MAD
+ mad_stream_init(&_stream);
+ mad_header_init(&_header);
+
+ // Reset the stream data
+ _inStream->seek(0, SEEK_SET);
+ _totalTime = mad_timer_zero;
+ _posInFrame = 0;
+
+ // Update state
+ _state = MP3_STATE_READY;
+
+ // Read the first few sample bytes into the buffer
+ readMP3DataIntoBuffer();
+
+ return true;
+}
+
+bool Mp3PspStream::initStreamME() {
+ // The following will eventually go into the thread
+ sceAudiocodecReleaseEDRAM(_codecParams); // do we need this?
+
+ memset(_codecParams, 0, sizeof(_codecParams));
+
+ // Init the MP3 hardware
+ int ret = 0;
+ ret = sceAudiocodecCheckNeedMem(_codecParams, 0x1002);
+ if (ret < 0) {
+ PSP_ERROR("failed to init MP3 ME module. sceAudiocodecCheckNeedMem returned 0x%x.\n", ret);
+ return false;
+ }
+ PSP_DEBUG_PRINT("sceAudiocodecCheckNeedMem returned %d\n", ret);
+ ret = sceAudiocodecGetEDRAM(_codecParams, 0x1002);
+ if (ret < 0) {
+ PSP_ERROR("failed to init MP3 ME module. sceAudiocodecGetEDRAM returned 0x%x.\n", ret);
+ return false;
+ }
+ PSP_DEBUG_PRINT("sceAudioCodecGetEDRAM returned %d\n", ret);
+
+ PSP_DEBUG_PRINT("samplerate[%d]\n", _sampleRate);
+ _codecParams[10] = _sampleRate;
+
+ ret = sceAudiocodecInit(_codecParams, 0x1002);
+ if (ret < 0) {
+ PSP_ERROR("failed to init MP3 ME module. sceAudiocodecInit returned 0x%x.\n", ret);
+ return false;
+ }
+
+ return true;
+}
+
+Mp3PspStream::~Mp3PspStream() {
+ DEBUG_ENTER_FUNC();
+
+ deinitStream();
+ releaseStreamME(); // free the memory used for this stream
+
+ if (_disposeAfterUse == DisposeAfterUse::YES)
+ delete _inStream;
+}
+
+void Mp3PspStream::deinitStream() {
+ DEBUG_ENTER_FUNC();
+
+ if (_state == MP3_STATE_INIT)
+ return;
+
+ // Deinit MAD
+ mad_header_finish(&_header);
+ mad_stream_finish(&_stream);
+
+ _state = MP3_STATE_EOS;
+}
+
+void Mp3PspStream::releaseStreamME() {
+ sceAudiocodecReleaseEDRAM(_codecParams);
+}
+
+void Mp3PspStream::decodeMP3Data() {
+ DEBUG_ENTER_FUNC();
+
+ do {
+ if (_state == MP3_STATE_INIT) {
+ initStream();
+ initStreamME();
+ }
+
+ if (_state == MP3_STATE_EOS)
+ return;
+
+ findValidHeader(); // seach for next valid header
+
+ while (_state == MP3_STATE_READY) {
+ _stream.error = MAD_ERROR_NONE;
+
+ uint32 frame_size = _stream.next_frame - _stream.this_frame;
+ uint32 samplesPerFrame = _header.layer == MAD_LAYER_III ? 576 : 1152; // Varies by layer
+ // calculate frame size -- try
+ //uint32 calc_frame_size = ((144 * _header.bitrate) / 22050) + (_header.flags & MAD_FLAG_PADDING ? 1 : 0);
+
+ // Get stereo/mono
+ uint32 multFactor = 1;
+ if (_header.mode != MAD_MODE_SINGLE_CHANNEL) // mono - x2 for 16bit
+ multFactor *= 2; // stereo - x4 for 16bit
+
+ PSP_DEBUG_PRINT("MP3 frame size[%d]. Samples[%d]. Multfactor[%d] pad[%d]\n", frame_size, samplesPerFrame, multFactor, _header.flags & MAD_FLAG_PADDING);
+ memcpy(_codecInBuffer, _stream.this_frame, frame_size); // we need it aligned
+
+ // set up parameters for ME
+ _codecParams[6] = (unsigned long)_codecInBuffer;
+ _codecParams[8] = (unsigned long)_pcmSamples;
+ _codecParams[7] = frame_size;
+ _codecParams[9] = samplesPerFrame * multFactor; // x2 for stereo
+
+ // debug
+#ifdef PRINT_BUFFERS
+ PSP_DEBUG_PRINT("mp3 frame:\n");
+ for (int i=0; i < (int)frame_size; i++) {
+ PSP_DEBUG_PRINT_SAMELN("%x ", _codecInBuffer[i]);
+ }
+ PSP_DEBUG_PRINT("\n");
+#endif
+ // Decode the next frame
+ // This function blocks. We'll want to put it in a thread
+ int ret = sceAudiocodecDecode(_codecParams, 0x1002);
+ if (ret < 0) {
+ PSP_INFO_PRINT("failed to decode MP3 data in ME. sceAudiocodecDecode returned 0x%x\n", ret);
+ // handle error here
+ }
+
+#ifdef PRINT_BUFFERS
+ PSP_DEBUG_PRINT("PCM frame:\n");
+ for (int i=0; i < (int)_codecParams[9]; i+=2) { // changed from i+=2
+ PSP_DEBUG_PRINT_SAMELN("%d ", (int16)_pcmSamples[i]);
+ }
+ PSP_DEBUG_PRINT("\n");
+#endif
+ _pcmLength = samplesPerFrame;
+ _posInFrame = 0;
+ break;
+ }
+ } while (_state != MP3_STATE_EOS && _stream.error == MAD_ERROR_BUFLEN);
+
+ if (_stream.error != MAD_ERROR_NONE) // catch EOS
+ _state = MP3_STATE_EOS;
+}
+
+void Mp3PspStream::readMP3DataIntoBuffer() {
+ DEBUG_ENTER_FUNC();
+
+ uint32 remaining = 0;
+
+ // Give up immediately if we already used up all data in the stream
+ if (_inStream->eos()) {
+ _state = MP3_STATE_EOS;
+ return;
+ }
+
+ if (_stream.next_frame) {
+ // If there is still data in the MAD stream, we need to preserve it.
+ // Note that we use memmove, as we are reusing the same buffer,
+ // and hence the data regions we copy from and to may overlap.
+ remaining = _stream.bufend - _stream.next_frame;
+ assert(remaining < BUFFER_SIZE); // Paranoia check
+ memmove(_buf, _stream.next_frame, remaining); // TODO: may want another buffer
+ }
+
+ // Try to read the next block
+ uint32 size = _inStream->read(_buf + remaining, BUFFER_SIZE - remaining);
+ if (size <= 0) {
+ _state = MP3_STATE_EOS;
+ return;
+ }
+
+ // Feed the data we just read into the stream decoder
+ _stream.error = MAD_ERROR_NONE;
+ mad_stream_buffer(&_stream, _buf, size + remaining); // just setup the pointers
+}
+
+bool Mp3PspStream::seek(const Timestamp &where) {
+ DEBUG_ENTER_FUNC();
+
+ if (where == _length) {
+ _state = MP3_STATE_EOS;
+ return true;
+ } else if (where > _length) {
+ return false;
+ }
+
+ const uint32 time = where.msecs();
+
+ mad_timer_t destination;
+ mad_timer_set(&destination, time / 1000, time % 1000, 1000);
+
+ // Check if we need to rewind
+ if (_state != MP3_STATE_READY || mad_timer_compare(destination, _totalTime) < 0) {
+ initStream();
+ initStreamME();
+ }
+
+ // The ME will need clear data no matter what once we seek?
+ //if (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS)
+ // initStreamME();
+
+ // Skip ahead
+ while (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS)
+ findValidHeader();
+
+ return (_state != MP3_STATE_EOS);
+}
+
+// Seek in the stream, finding the next valid header
+void Mp3PspStream::findValidHeader() {
+ DEBUG_ENTER_FUNC();
+
+ if (_state != MP3_STATE_READY)
+ return;
+
+ // If necessary, load more data into the stream decoder
+ if (_stream.error == MAD_ERROR_BUFLEN)
+ readMP3DataIntoBuffer();
+
+ while (_state != MP3_STATE_EOS) {
+ _stream.error = MAD_ERROR_NONE;
+
+ // Decode the next header.
+ if (mad_header_decode(&_header, &_stream) == -1) {
+ if (_stream.error == MAD_ERROR_BUFLEN) {
+ readMP3DataIntoBuffer(); // Read more data
+ continue;
+ } else if (MAD_RECOVERABLE(_stream.error)) {
+ debug(6, "MP3PSPStream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
+ continue;
+ } else {
+ warning("MP3PSPStream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
+ break;
+ }
+ }
+
+ // Sum up the total playback time so far
+ mad_timer_add(&_totalTime, _header.duration);
+ break;
+ }
+
+ if (_stream.error != MAD_ERROR_NONE)
+ _state = MP3_STATE_EOS;
+}
+
+int Mp3PspStream::readBuffer(int16 *buffer, const int numSamples) {
+ DEBUG_ENTER_FUNC();
+
+ int samples = 0;
+#ifdef PRINT_BUFFERS
+ int16 *debugBuffer = buffer;
+#endif
+
+ // Keep going as long as we have input available
+ while (samples < numSamples && _state != MP3_STATE_EOS) {
+ const int len = MIN(numSamples, samples + (int)(_pcmLength - _posInFrame) * MAD_NCHANNELS(&_header));
+
+ while (samples < len) {
+ *buffer++ = _pcmSamples[_posInFrame << 1];
+ samples++;
+ if (MAD_NCHANNELS(&_header) == 2) {
+ *buffer++ = _pcmSamples[(_posInFrame << 1) + 1];
+ samples++;
+ }
+ _posInFrame++; // always skip an extra sample since ME always outputs stereo
+ }
+
+ //memcpy(buffer, &_pcmSamples[_posInFrame], len << 1); // 16 bits
+ //_posInFrame += len; // next time we start from the middle
+
+ if (_posInFrame >= _pcmLength) {
+ // We used up all PCM data in the current frame -- read & decode more
+ decodeMP3Data();
+ }
+ }
+
+#ifdef PRINT_BUFFERS
+ PSP_INFO_PRINT("buffer:\n");
+ for (int i = 0; i<numSamples; i++)
+ PSP_INFO_PRINT("%d ", debugBuffer[i]);
+ PSP_INFO_PRINT("\n\n");
+#endif
+
+ return samples;
+}
+
+} // End of namespace Audio
+
+
diff --git a/backends/platform/psp/mp3.h b/backends/platform/psp/mp3.h
new file mode 100644
index 0000000000..029b3e498c
--- /dev/null
+++ b/backends/platform/psp/mp3.h
@@ -0,0 +1,121 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef SOUND_MP3_PSP_H
+#define SOUND_MP3_PSP_H
+
+#include "common/types.h"
+#include "common/scummsys.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Audio {
+
+class AudioStream;
+class SeekableAudioStream;
+
+class Mp3PspStream : public SeekableAudioStream {
+protected:
+ enum State {
+ MP3_STATE_INIT, // Need to init the decoder
+ MP3_STATE_READY, // ready for processing data
+ MP3_STATE_EOS // end of data reached (may need to loop)
+ };
+
+ #define MAX_SAMPLES_PER_FRAME 2048 * 2
+ int16 _pcmSamples[MAX_SAMPLES_PER_FRAME] __attribute__((aligned(64))); // samples to output PCM data into
+ byte _codecInBuffer[3072] __attribute__((aligned(64))); // the codec always needs alignment
+ unsigned long _codecParams[65]__attribute__((aligned(64))); // TODO: change to struct
+
+ Common::SeekableReadStream *_inStream;
+ DisposeAfterUse::Flag _disposeAfterUse;
+
+ uint32 _pcmLength; // how many pcm samples we have (/2 for mono)
+
+ uint _posInFrame; // position in frame
+ State _state; // what state the stream is in
+
+ Timestamp _length;
+ uint32 _sampleRate;
+
+ mad_timer_t _totalTime;
+ mad_stream _stream; //
+ mad_header _header; // This is all we need from libmad
+
+ static bool _decoderInit; // has the decoder been initialized
+ static bool _decoderFail; // has the decoder failed to load
+
+ enum {
+ BUFFER_SIZE = 5 * 8192
+ };
+
+ // This buffer contains a slab of input data
+ byte _buf[BUFFER_SIZE + MAD_BUFFER_GUARD];
+
+ void decodeMP3Data();
+ void readMP3DataIntoBuffer();
+
+ static bool loadStartAudioModule(const char *modname, int partition);
+ int initStream();
+ void findValidHeader();
+ void deinitStream();
+
+ // to init and uninit ME decoder
+ static bool initDecoder();
+ static bool stopDecoder();
+
+ // ME functions for stream
+ bool initStreamME();
+ void releaseStreamME();
+
+public:
+ Mp3PspStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose);
+ ~Mp3PspStream();
+
+ // This function avoids having to create streams when it's not possible
+ static inline bool isOkToCreateStream() {
+ if (_decoderFail) // fatal failure
+ return false;
+ if (!_decoderInit) // if we're not initialized
+ if (!initDecoder()) // check if we failed init
+ return false;
+ return true;
+ }
+
+ int readBuffer(int16 *buffer, const int numSamples);
+
+ bool endOfData() const { return _state == MP3_STATE_EOS; }
+ bool isStereo() const { return MAD_NCHANNELS(&_header) == 2; }
+ int getRate() const { return _sampleRate; }
+
+ bool seek(const Timestamp &where);
+ Timestamp getLength() const { return _length; }
+};
+
+} // End of namespace Audio
+
+#endif // #ifndef SOUND_MP3_PSP_H
diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp
index 58d98bc219..b09d9c0c00 100644
--- a/backends/platform/psp/osys_psp.cpp
+++ b/backends/platform/psp/osys_psp.cpp
@@ -37,6 +37,7 @@
#include "backends/platform/psp/psppixelformat.h"
#include "backends/platform/psp/osys_psp.h"
#include "backends/platform/psp/powerman.h"
+#include "backends/platform/psp/rtc.h"
#include "backends/saves/psp/psp-saves.h"
#include "backends/timer/default/default-timer.h"
@@ -48,7 +49,6 @@
#include "backends/platform/psp/trace.h"
-
#define SAMPLES_PER_SEC 44100
static int timer_handler(int t) {
@@ -57,10 +57,6 @@ static int timer_handler(int t) {
return t;
}
-void OSystem_PSP::initSDL() {
- SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER);
-}
-
OSystem_PSP::~OSystem_PSP() {}
#define PSP_SCREEN_WIDTH 480
@@ -69,6 +65,9 @@ OSystem_PSP::~OSystem_PSP() {}
void OSystem_PSP::initBackend() {
DEBUG_ENTER_FUNC();
+ // Instantiate real time clock
+ PspRtc::instance();
+
_cursor.enableCursorPalette(false);
_cursor.setXY(PSP_SCREEN_WIDTH >> 1, PSP_SCREEN_HEIGHT >> 1); // Mouse in the middle of the screen
@@ -84,8 +83,6 @@ void OSystem_PSP::initBackend() {
_inputHandler.setKeyboard(&_keyboard);
_inputHandler.init();
- initSDL();
-
_savefile = new PSPSaveFileManager;
_timer = new DefaultTimerManager();
@@ -122,11 +119,13 @@ int OSystem_PSP::getDefaultGraphicsMode() const {
bool OSystem_PSP::setGraphicsMode(int mode) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
return _displayManager.setGraphicsMode(mode);
}
bool OSystem_PSP::setGraphicsMode(const char *name) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
return _displayManager.setGraphicsMode(name);
}
@@ -141,7 +140,7 @@ Graphics::PixelFormat OSystem_PSP::getScreenFormat() const {
return _screen.getScummvmPixelFormat();
}
-Common::List<Graphics::PixelFormat> OSystem_PSP::getSupportedFormats() {
+Common::List<Graphics::PixelFormat> OSystem_PSP::getSupportedFormats() const {
return _displayManager.getSupportedPixelFormats();
}
@@ -149,6 +148,7 @@ Common::List<Graphics::PixelFormat> OSystem_PSP::getSupportedFormats() {
void OSystem_PSP::initSize(uint width, uint height, const Graphics::PixelFormat *format) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_displayManager.setSizeAndPixelFormat(width, height, format);
_cursor.setVisible(false);
@@ -167,6 +167,7 @@ int16 OSystem_PSP::getHeight() {
void OSystem_PSP::setPalette(const byte *colors, uint start, uint num) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_screen.setPartialPalette(colors, start, num);
_cursor.setScreenPalette(colors, start, num);
_cursor.clearKeyColor();
@@ -174,6 +175,7 @@ void OSystem_PSP::setPalette(const byte *colors, uint start, uint num) {
void OSystem_PSP::setCursorPalette(const byte *colors, uint start, uint num) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_cursor.setCursorPalette(colors, start, num);
_cursor.enableCursorPalette(true);
_cursor.clearKeyColor(); // Do we need this?
@@ -181,37 +183,43 @@ void OSystem_PSP::setCursorPalette(const byte *colors, uint start, uint num) {
void OSystem_PSP::disableCursorPalette(bool disable) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_cursor.enableCursorPalette(!disable);
}
void OSystem_PSP::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_screen.copyFromRect(buf, pitch, x, y, w, h);
}
Graphics::Surface *OSystem_PSP::lockScreen() {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
return _screen.lockAndGetForEditing();
}
void OSystem_PSP::unlockScreen() {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
// The screen is always completely updated anyway, so we don't have to force a full update here.
_screen.unlock();
}
void OSystem_PSP::updateScreen() {
DEBUG_ENTER_FUNC();
- _displayManager.renderAll();
+ _pendingUpdate = !_displayManager.renderAll(); // if we didn't update, we have a pending update
}
void OSystem_PSP::setShakePos(int shakeOffset) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_screen.setShakePos(shakeOffset);
}
void OSystem_PSP::showOverlay() {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_overlay.setVisible(true);
_cursor.setLimits(_overlay.getWidth(), _overlay.getHeight());
_cursor.useGlobalScaler(false); // mouse with overlay is 1:1
@@ -219,6 +227,7 @@ void OSystem_PSP::showOverlay() {
void OSystem_PSP::hideOverlay() {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_overlay.setVisible(false);
_cursor.setLimits(_screen.getWidth(), _screen.getHeight());
_cursor.useGlobalScaler(true); // mouse needs to be scaled with screen
@@ -226,6 +235,7 @@ void OSystem_PSP::hideOverlay() {
void OSystem_PSP::clearOverlay() {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_overlay.clearBuffer();
}
@@ -236,6 +246,7 @@ void OSystem_PSP::grabOverlay(OverlayColor *buf, int pitch) {
void OSystem_PSP::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_overlay.copyFromRect(buf, pitch, x, y, w, h);
}
@@ -254,6 +265,8 @@ void OSystem_PSP::grabPalette(byte *colors, uint start, uint num) {
bool OSystem_PSP::showMouse(bool v) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
+
PSP_DEBUG_PRINT("%s\n", v ? "true" : "false");
bool last = _cursor.isVisible();
_cursor.setVisible(v);
@@ -263,11 +276,14 @@ bool OSystem_PSP::showMouse(bool v) {
void OSystem_PSP::warpMouse(int x, int y) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_cursor.setXY(x, y);
}
void OSystem_PSP::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
+
PSP_DEBUG_PRINT("pbuf[%p], w[%u], h[%u], hotspot:X[%d], Y[%d], keycolor[%d], scale[%d], pformat[%p]\n", buf, w, h, hotspotX, hotspotY, keycolor, cursorTargetScale, format);
if (format) {
PSP_DEBUG_PRINT("format: bpp[%d], rLoss[%d], gLoss[%d], bLoss[%d], aLoss[%d], rShift[%d], gShift[%d], bShift[%d], aShift[%d]\n", format->bytesPerPixel, format->rLoss, format->gLoss, format->bLoss, format->aLoss, format->rShift, format->gShift, format->bShift, format->aShift);
@@ -287,39 +303,54 @@ bool OSystem_PSP::pollEvent(Common::Event &event) {
// Pausing the engine is a necessary fix for games that use the timer for music synchronization
// recovering many hours later causes the game to crash. We're polling without mutexes since it's not critical to
// get it right now.
-
PowerMan.pollPauseEngine();
+ // A hack:
+ // Check if we have a pending update that we missed for some reason (FPS throttling for example)
+ // Time between event polls is usually 5-10ms, so waiting for 4 calls before checking to update the screen should be fine
+ if (_pendingUpdate) {
+ _pendingUpdateCounter++;
+
+ if (_pendingUpdateCounter >= 4) {
+ PSP_DEBUG_PRINT("servicing pending update\n");
+ updateScreen();
+ if (!_pendingUpdate) // we handled the update
+ _pendingUpdateCounter = 0;
+ }
+ } else
+ _pendingUpdateCounter = 0; // reset the counter, no pending
+
return _inputHandler.getAllInputs(event);
}
-
uint32 OSystem_PSP::getMillis() {
- return SDL_GetTicks();
+ return PspRtc::instance().getMillis();
}
void OSystem_PSP::delayMillis(uint msecs) {
- SDL_Delay(msecs);
+ PspThread::delayMillis(msecs);
}
void OSystem_PSP::setTimerCallback(TimerProc callback, int interval) {
- SDL_SetTimer(interval, (SDL_TimerCallback)callback);
+ _pspTimer.setCallback((PspTimer::CallbackFunc)callback);
+ _pspTimer.setIntervalMs(interval);
+ _pspTimer.start();
}
OSystem::MutexRef OSystem_PSP::createMutex(void) {
- return (MutexRef)SDL_CreateMutex();
+ return (MutexRef) new PspMutex(true); // start with a full mutex
}
void OSystem_PSP::lockMutex(MutexRef mutex) {
- SDL_mutexP((SDL_mutex *)mutex);
+ ((PspMutex *)mutex)->lock();
}
void OSystem_PSP::unlockMutex(MutexRef mutex) {
- SDL_mutexV((SDL_mutex *)mutex);
+ ((PspMutex *)mutex)->unlock();
}
void OSystem_PSP::deleteMutex(MutexRef mutex) {
- SDL_DestroyMutex((SDL_mutex *)mutex);
+ delete (PspMutex *)mutex;
}
void OSystem_PSP::mixCallback(void *sys, byte *samples, int len) {
@@ -331,8 +362,6 @@ void OSystem_PSP::mixCallback(void *sys, byte *samples, int len) {
}
void OSystem_PSP::setupMixer(void) {
- SDL_AudioSpec desired;
- SDL_AudioSpec obtained;
// Determine the desired output sampling frequency.
uint32 samplesPerSec = 0;
@@ -349,38 +378,21 @@ void OSystem_PSP::setupMixer(void) {
while (samples * 16 > samplesPerSec * 2)
samples >>= 1;
- memset(&desired, 0, sizeof(desired));
- desired.freq = samplesPerSec;
- desired.format = AUDIO_S16SYS;
- desired.channels = 2;
- desired.samples = samples;
- desired.callback = mixCallback;
- desired.userdata = this;
-
assert(!_mixer);
- if (SDL_OpenAudio(&desired, &obtained) != 0) {
- warning("Could not open audio: %s", SDL_GetError());
- _mixer = new Audio::MixerImpl(this, samplesPerSec);
- assert(_mixer);
- _mixer->setReady(false);
- } else {
- // Note: This should be the obtained output rate, but it seems that at
- // least on some platforms SDL will lie and claim it did get the rate
- // even if it didn't. Probably only happens for "weird" rates, though.
- samplesPerSec = obtained.freq;
-
- // Create the mixer instance and start the sound processing
- _mixer = new Audio::MixerImpl(this, samplesPerSec);
- assert(_mixer);
- _mixer->setReady(true);
-
- SDL_PauseAudio(0);
+
+ if (!_audio.open(samplesPerSec, 2, samples, mixCallback, this)) {
+ PSP_ERROR("failed to open audio\n");
+ return;
}
+ samplesPerSec = _audio.getFrequency(); // may have been changed by audio system
+ _mixer = new Audio::MixerImpl(this, samplesPerSec);
+ assert(_mixer);
+ _mixer->setReady(true);
+ _audio.unpause();
}
void OSystem_PSP::quit() {
- SDL_CloseAudio();
- SDL_Quit();
+ _audio.close();
sceKernelExitGame();
}
diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h
index 8c5b40dcdf..5721296c94 100644
--- a/backends/platform/psp/osys_psp.h
+++ b/backends/platform/psp/osys_psp.h
@@ -38,8 +38,9 @@
#include "backends/platform/psp/pspkeyboard.h"
#include "backends/platform/psp/display_manager.h"
#include "backends/platform/psp/input.h"
-
-#include <SDL.h>
+#include "backends/platform/psp/audio.h"
+#include "backends/timer/psp/timer.h"
+#include "backends/platform/psp/thread.h"
class OSystem_PSP : public BaseBackend {
private:
@@ -47,6 +48,8 @@ private:
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
Common::TimerManager *_timer;
+ bool _pendingUpdate; // save an update we couldn't perform
+ uint32 _pendingUpdateCounter; // prevent checking for pending update too often, in a cheap way
// All needed sub-members
Screen _screen;
@@ -55,11 +58,11 @@ private:
DisplayManager _displayManager;
PSPKeyboard _keyboard;
InputHandler _inputHandler;
-
- void initSDL();
+ PspAudio _audio;
+ PspTimer _pspTimer;
public:
- OSystem_PSP() : _savefile(0), _mixer(0), _timer(0) {}
+ OSystem_PSP() : _savefile(0), _mixer(0), _timer(0), _pendingUpdate(false), _pendingUpdateCounter(0) {}
~OSystem_PSP();
static OSystem *instance();
@@ -79,7 +82,7 @@ public:
int getGraphicsMode() const;
#ifdef USE_RGB_COLOR
virtual Graphics::PixelFormat getScreenFormat() const;
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats();
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
#endif
// Screen size
diff --git a/backends/platform/psp/powerman.cpp b/backends/platform/psp/powerman.cpp
index df8da12f6d..eaadad16c5 100644
--- a/backends/platform/psp/powerman.cpp
+++ b/backends/platform/psp/powerman.cpp
@@ -23,16 +23,16 @@
*
*/
-//#define __PSP_DEBUG_FUNCS__ /* can put this locally too */
-//#define __PSP_DEBUG_PRINT__
-#include "backends/platform/psp/trace.h"
-
#include <psppower.h>
#include <pspthreadman.h>
#include "backends/platform/psp/powerman.h"
#include "engine.h"
+//#define __PSP_DEBUG_FUNCS__ /* can put this locally too */
+//#define __PSP_DEBUG_PRINT__
+#include "backends/platform/psp/trace.h"
+
DECLARE_SINGLETON(PowerManager)
// Function to debug the Power Manager (we have no output to screen)
@@ -47,68 +47,30 @@ inline void PowerManager::debugPM() {
* Constructor
*
********************************************/
-PowerManager::PowerManager() {
- DEBUG_ENTER_FUNC();
-
- _flagMutex = NULL; /* Init mutex handle */
- _listMutex = NULL; /* Init mutex handle */
- _condSuspendable = NULL; /* Init condition variable */
- _condPM = NULL;
-
- _condSuspendable = SDL_CreateCond();
- if (_condSuspendable <= 0) {
- PSP_ERROR("Couldn't create Suspendable condition variable\n");
- }
-
- _condPM = SDL_CreateCond();
- if (_condPM <= 0) {
- PSP_ERROR("Couldn't create PM condition variable\n");
- }
-
- _flagMutex = SDL_CreateMutex();
- if (_flagMutex <= 0) {
- PSP_ERROR("Couldn't create flag Mutex\n");
- }
-
- _listMutex = SDL_CreateMutex();
- if (_listMutex <= 0) {
- PSP_ERROR("Couldn't create list Mutex\n");
- }
-
- _suspendFlag = false;
- _criticalCounter = 0; // How many are in the critical section
- _pauseFlag = 0;
- _pauseFlagOld = 0;
- _pauseClientState = 0;
- _listCounter = 0;
- PMStatusSet(kInitDone);
- _error = 0;
-}
+PowerManager::PowerManager() : _pauseFlag(false), _pauseFlagOld(false), _pauseClientState(UNPAUSED),
+ _suspendFlag(false), _flagMutex(true), _listMutex(true),
+ _criticalCounter(0), _listCounter(0), _error(0), _PMStatus(kInitDone) {}
/*******************************************
*
* Function to register to be notified when suspend/resume time comes
*
********************************************/
-int PowerManager::registerSuspend(Suspendable *item) {
+bool PowerManager::registerForSuspend(Suspendable *item) {
DEBUG_ENTER_FUNC();
// Register in list
debugPM();
- if (SDL_mutexP(_listMutex) != 0) {
- PSP_ERROR("Couldn't lock _listMutex[%p]\n", _listMutex);
- }
+ _listMutex.lock();
_suspendList.push_front(item);
_listCounter++;
- if (SDL_mutexV(_listMutex) != 0) {
- PSP_ERROR("Couldn't unlock _listMutex[%p]\n", _listMutex);
- }
+ _listMutex.unlock();
debugPM();
- return 0;
+ return true;
}
/*******************************************
@@ -116,26 +78,20 @@ int PowerManager::registerSuspend(Suspendable *item) {
* Function to unregister to be notified when suspend/resume time comes
*
********************************************/
-int PowerManager::unregisterSuspend(Suspendable *item) {
+bool PowerManager::unregisterForSuspend(Suspendable *item) {
DEBUG_ENTER_FUNC();
debugPM();
// Unregister from stream list
- if (SDL_mutexP(_listMutex) != 0) {
- PSP_ERROR("Couldn't unlock _listMutex[%p]\n", _listMutex);
- }
-
+ _listMutex.lock();
+
_suspendList.remove(item);
_listCounter--;
- if (SDL_mutexV(_listMutex) != 0) {
- PSP_ERROR("Couldn't unlock _listMutex[%p]\n", _listMutex);
- }
+ _listMutex.unlock();
- PSP_DEBUG_PRINT("Out of unregisterSuspend\n");
debugPM();
-
- return 0;
+ return true;
}
/*******************************************
@@ -144,21 +100,7 @@ int PowerManager::unregisterSuspend(Suspendable *item) {
*
********************************************/
PowerManager::~PowerManager() {
- DEBUG_ENTER_FUNC();
-
- PMStatusSet(kDestroyPM);
-
- SDL_DestroyCond(_condSuspendable);
- _condSuspendable = 0;
-
- SDL_DestroyCond(_condPM);
- _condPM = 0;
-
- SDL_DestroyMutex(_flagMutex);
- _flagMutex = 0;
-
- SDL_DestroyMutex(_listMutex);
- _listMutex = 0;
+ _PMStatus = kDestroyPM;
}
/*******************************************
@@ -171,114 +113,92 @@ PowerManager::~PowerManager() {
*
********************************************/
void PowerManager::pollPauseEngine() {
-
+ DEBUG_ENTER_FUNC();
+
+
bool pause = _pauseFlag; // We copy so as not to have multiple values
- if ((pause != _pauseFlagOld) && g_engine) { // Check to see if we have an engine
- if (pause && _pauseClientState == PowerManager::Unpaused) {
- _pauseClientState = PowerManager::Pausing; // Tell PM we're in the middle of pausing
- g_engine->pauseEngine(true);
- PSP_DEBUG_PRINT_FUNC("Pausing engine\n");
- _pauseClientState = PowerManager::Paused; // Tell PM we're done pausing
- } else if (!pause && _pauseClientState == PowerManager::Paused) {
- g_engine->pauseEngine(false);
- PSP_DEBUG_PRINT_FUNC("Unpausing for resume\n");
- _pauseClientState = PowerManager::Unpaused; // Tell PM we're in the middle of pausing
+ if (pause != _pauseFlagOld) {
+ if (g_engine) { // Check to see if we have an engine
+ if (pause && _pauseClientState == UNPAUSED) {
+ _pauseClientState = PAUSING; // Tell PM we're in the middle of pausing
+ g_engine->pauseEngine(true);
+ PSP_DEBUG_PRINT_FUNC("Pausing engine\n");
+ _pauseClientState = PAUSED; // Tell PM we're done pausing
+ } else if (!pause && _pauseClientState == PAUSED) {
+ g_engine->pauseEngine(false);
+ PSP_DEBUG_PRINT_FUNC("Unpausing for resume\n");
+ _pauseClientState = UNPAUSED; // Tell PM we're unpaused
+ }
}
-
_pauseFlagOld = pause;
}
}
/*******************************************
*
-* Function to be called by threads wanting to block on the PSP entering suspend
-* Use this for small critical sections where you can easily restore the previous state.
-*
-********************************************/
-int PowerManager::blockOnSuspend() {
- return beginCriticalSection(true);
-}
-
-/*******************************************
-*
* Function to block on a suspend, then start a non-suspendable critical section
* Use this for large or REALLY critical critical-sections.
* Make sure to call endCriticalSection or the PSP won't suspend.
+* returns true if blocked, false if not blocked
********************************************/
-int PowerManager::beginCriticalSection(bool justBlock) {
+bool PowerManager::beginCriticalSection() {
DEBUG_ENTER_FUNC();
- int ret = NotBlocked;
-
- if (SDL_mutexP(_flagMutex) != 0) {
- PSP_ERROR("PowerManager::blockOnSuspend(): Couldn't lock flagMutex[%p]\n", _flagMutex);
- ret = Error;
- }
+ bool ret = false;
+
+ _flagMutex.lock();
// Check the access flag
- if (_suspendFlag == true) {
- PSP_DEBUG_PRINT("We're being blocked!\n");
- debugPM();
- ret = Blocked;
+ if (_suspendFlag) {
+ ret = true;
- // If it's true, we wait for a signal to continue
- if (SDL_CondWait(_condSuspendable, _flagMutex) != 0) {
- PSP_DEBUG_PRINT("PowerManager::blockOnSuspend(): Couldn't wait on cond[%p]\n", _condSuspendable);
- }
+ PSP_DEBUG_PRINT("I got blocked. ThreadId[%x]\n", sceKernelGetThreadId());
+ debugPM();
+
+ _threadSleep.wait(_flagMutex);
- PSP_DEBUG_PRINT("We got blocked!!\n");
+ PSP_DEBUG_PRINT_FUNC("I got released. ThreadId[%x]\n", sceKernelGetThreadId());
debugPM();
}
// Now prevent the PM from suspending until we're done
- if (justBlock == false)
- _criticalCounter++;
+ _criticalCounter++;
- if (SDL_mutexV(_flagMutex) != 0) {
- PSP_ERROR("PowerManager::blockOnSuspend(): Couldn't unlock flagMutex[%p]\n", _flagMutex);
- ret = Error;
- }
+ _flagMutex.unlock();
return ret;
}
-int PowerManager::endCriticalSection() {
+// returns success = true
+void PowerManager::endCriticalSection() {
DEBUG_ENTER_FUNC();
- int ret = 0;
- if (SDL_mutexP(_flagMutex) != 0) {
- PSP_ERROR("PowerManager::endCriticalSection(): Couldn't lock flagMutex[%p]\n", _flagMutex);
- ret = Error;
- }
+ _flagMutex.lock();
// We're done with our critical section
_criticalCounter--;
if (_criticalCounter <= 0) {
- if (_suspendFlag == true) { // If the PM is sleeping, this flag must be set
- PSP_DEBUG_PRINT("Unblocked thread waking up the PM.\n");
- debugPM();
-
- SDL_CondBroadcast(_condPM);
-
- PSP_DEBUG_PRINT("Woke up the PM\n");
- debugPM();
+ if (_suspendFlag) { // If the PM is sleeping, this flag must be set
+ PSP_DEBUG_PRINT_FUNC("PM is asleep. Waking it up.\n");
+ debugPM();
+
+ _pmSleep.releaseAll();
+
+ PSP_DEBUG_PRINT_FUNC("Woke up the PM\n");
+
+ debugPM();
}
if (_criticalCounter < 0) { // Check for bad usage of critical sections
- PSP_ERROR("Critical counter[%d]\n", _criticalCounter);
+ PSP_ERROR("Critical counter[%d]!!!\n", _criticalCounter);
debugPM();
}
}
- if (SDL_mutexV(_flagMutex) != 0) {
- PSP_ERROR("Couldn't unlock flagMutex[%p]\n", _flagMutex);
- ret = Error;
- }
-
- return ret;
+ _flagMutex.unlock();
}
/*******************************************
@@ -286,90 +206,77 @@ int PowerManager::endCriticalSection() {
* Callback function to be called to put every Suspendable to suspend
*
********************************************/
-int PowerManager::suspend() {
+void PowerManager::suspend() {
DEBUG_ENTER_FUNC();
- int ret = 0;
- if (_pauseFlag) return ret; // Very important - make sure we only suspend once
+ if (_pauseFlag)
+ return; // Very important - make sure we only suspend once
- scePowerLock(0); // Critical to make sure PSP doesn't suspend before we're done
+ scePowerLock(0); // Also critical to make sure PSP doesn't suspend before we're done
// The first stage of suspend is pausing the engine if possible. We don't want to cause files
// to block, or we might not get the engine to pause. On the other hand, we might wait for polling
// and it'll never happen. We also want to do this w/o mutexes (for speed) which is ok in this case.
_pauseFlag = true;
- PMStatusSet(kWaitForClientPause);
+ _PMStatus = kWaitForClientPause;
// Now we wait, giving the engine thread some time to find our flag.
- for (int i = 0; i < 10 && _pauseClientState == Unpaused; i++)
- sceKernelDelayThread(50000); // We wait 50 msec x 10 times = 0.5 seconds
+ for (int i = 0; i < 10 && _pauseClientState == UNPAUSED; i++)
+ PspThread::delayMicros(50000); // We wait 50 msec x 10 times = 0.5 seconds
- if (_pauseClientState == Pausing) { // Our event has been acknowledged. Let's wait until the client is done.
- PMStatusSet(kWaitForClientToFinishPausing);
+ if (_pauseClientState == PAUSING) { // Our event has been acknowledged. Let's wait until the client is done.
+ _PMStatus = kWaitForClientToFinishPausing;
- while (_pauseClientState != Paused)
- sceKernelDelayThread(50000); // We wait 50 msec at a time
+ while (_pauseClientState != PAUSED)
+ PspThread::delayMicros(50000); // We wait 50 msec at a time
}
- // It's possible that the polling thread missed our pause event, but there's nothing we can do about that.
- // We can't know if there's polling going on or not. It's usually not a critical thing anyway.
+ // It's possible that the polling thread missed our pause event, but there's
+ // nothing we can do about that.
+ // We can't know if there's polling going on or not.
+ // It's usually not a critical thing anyway.
- PMStatusSet(kGettingFlagMutexSuspend);
+ _PMStatus = kGettingFlagMutexSuspend;
// Now we set the suspend flag to true to cause reading threads to block
+ _flagMutex.lock();
- if (SDL_mutexP(_flagMutex) != 0) {
- PSP_ERROR("Couldn't lock flagMutex[%p]\n", _flagMutex);
- _error = Error;
- ret = Error;
- }
-
- PMStatusSet(kGotFlagMutexSuspend);
+ _PMStatus = kGotFlagMutexSuspend;
_suspendFlag = true;
// Check if anyone is in a critical section. If so, we'll wait for them
if (_criticalCounter > 0) {
- PMStatusSet(kWaitCritSectionSuspend);
- SDL_CondWait(_condPM, _flagMutex);
- PMStatusSet(kDoneWaitingCritSectionSuspend);
- }
+ _PMStatus = kWaitCritSectionSuspend;
+
+ _pmSleep.wait(_flagMutex);
+
+ _PMStatus = kDoneWaitingCritSectionSuspend;
+ }
+
+ _flagMutex.unlock();
- if (SDL_mutexV(_flagMutex) != 0) {
- PSP_ERROR("Couldn't unlock flagMutex[%p]\n", _flagMutex);
- _error = Error;
- ret = Error;
- }
-
- PMStatusSet(kGettingListMutexSuspend);
+ _PMStatus = kGettingListMutexSuspend;
// Loop over list, calling suspend()
- if (SDL_mutexP(_listMutex) != 0) {
- PSP_ERROR("Couldn't lock listMutex[%p]\n", _listMutex);
- _error = Error;
- ret = Error;
- }
- PMStatusSet(kIteratingListSuspend);
+ _listMutex.lock();
+
+ _PMStatus = kIteratingListSuspend;
// Iterate
Common::List<Suspendable *>::iterator i;
for (i = _suspendList.begin(); i != _suspendList.end(); ++i) {
(*i)->suspend();
}
+ _PMStatus = kDoneIteratingListSuspend;
- PMStatusSet(kDoneIteratingListSuspend);
-
- if (SDL_mutexV(_listMutex) != 0) {
- PSP_ERROR("Couldn't unlock listMutex[%p]\n", _listMutex);
- _error = Error;
- ret = Error;
- }
- PMStatusSet(kDoneSuspend);
+ _listMutex.unlock();
+ _PMStatus = kDoneSuspend;
scePowerUnlock(0); // Allow the PSP to go to sleep now
-
- return ret;
+
+ _PMStatus = kDonePowerUnlock;
}
/*******************************************
@@ -377,24 +284,26 @@ int PowerManager::suspend() {
* Callback function to resume every Suspendable
*
********************************************/
-int PowerManager::resume() {
+void PowerManager::resume() {
DEBUG_ENTER_FUNC();
- int ret = 0;
+
+ _PMStatus = kBeginResume;
// Make sure we can't get another suspend
scePowerLock(0);
- if (!_pauseFlag) return ret; // Make sure we can only resume once
+ _PMStatus = kCheckingPauseFlag;
+
+ if (!_pauseFlag)
+ return; // Make sure we can only resume once
- PMStatusSet(kGettingListMutexResume);
+ _PMStatus = kGettingListMutexResume;
// First we notify our Suspendables. Loop over list, calling resume()
- if (SDL_mutexP(_listMutex) != 0) {
- PSP_ERROR("Couldn't lock listMutex[%p]\n", _listMutex);
- _error = Error;
- ret = Error;
- }
- PMStatusSet(kIteratingListResume);
+ _listMutex.lock();
+
+ _PMStatus = kIteratingListResume;
+
// Iterate
Common::List<Suspendable *>::iterator i = _suspendList.begin();
@@ -402,46 +311,31 @@ int PowerManager::resume() {
(*i)->resume();
}
- PMStatusSet(kDoneIteratingListResume);
+ _PMStatus = kDoneIteratingListResume;
- if (SDL_mutexV(_listMutex) != 0) {
- PSP_ERROR("Couldn't unlock listMutex[%p]\n", _listMutex);
- _error = Error;
- ret = Error;
- }
-
- PMStatusSet(kGettingFlagMutexResume);
+ _listMutex.unlock();
+
+ _PMStatus = kGettingFlagMutexResume;
// Now we set the suspend flag to false
- if (SDL_mutexP(_flagMutex) != 0) {
- PSP_ERROR("Couldn't lock flagMutex %p\n", _flagMutex);
- _error = Error;
- ret = Error;
- }
- PMStatusSet(kGotFlagMutexResume);
+ _flagMutex.lock();
+
+ _PMStatus = kGotFlagMutexResume;
_suspendFlag = false;
- PMStatusSet(kSignalSuspendedThreadsResume);
+ _PMStatus = kSignalSuspendedThreadsResume;
- // Signal the other threads to wake up
- if (SDL_CondBroadcast(_condSuspendable) != 0) {
- PSP_ERROR("Couldn't broadcast condition[%p]\n", _condSuspendable);
- _error = Error;
- ret = Error;
- }
- PMStatusSet(kDoneSignallingSuspendedThreadsResume);
+ // Signal the threads to wake up
+ _threadSleep.releaseAll();
+
+ _PMStatus = kDoneSignallingSuspendedThreadsResume;
- if (SDL_mutexV(_flagMutex) != 0) {
- PSP_ERROR("Couldn't unlock flagMutex[%p]\n", _flagMutex);
- _error = Error;
- ret = Error;
- }
- PMStatusSet(kDoneResume);
+ _flagMutex.unlock();
+
+ _PMStatus = kDoneResume;
- _pauseFlag = false; // Signal engine to unpause
+ _pauseFlag = false; // Signal engine to unpause -- no mutex needed
scePowerUnlock(0); // Allow new suspends
-
- return ret;
}
diff --git a/backends/platform/psp/powerman.h b/backends/platform/psp/powerman.h
index af3134adee..5f09bc7794 100644
--- a/backends/platform/psp/powerman.h
+++ b/backends/platform/psp/powerman.h
@@ -26,8 +26,7 @@
#ifndef POWERMAN_H
#define POWERMAN_H
-#include <SDL/SDL_thread.h>
-#include <SDL/SDL_mutex.h>
+#include "backends/platform/psp/thread.h"
#include "common/singleton.h"
#include "common/list.h"
@@ -53,12 +52,12 @@ class PowerManager: public Common::Singleton<PowerManager> {
public:
int blockOnSuspend(); /* block if suspending */
- int beginCriticalSection(bool justBlock = false); /* Use a critical section to block (if suspend was already pressed) */
- int endCriticalSection(); /* and to prevent the PSP from suspending in a particular section */
- int registerSuspend(Suspendable *item); /* register to be called to suspend/resume */
- int unregisterSuspend(Suspendable *item); /* remove from suspend/resume list */
- int suspend(); /* callback to have all items in list suspend */
- int resume(); /* callback to have all items in list resume */
+ bool beginCriticalSection(); /* Use a critical section to block (if suspend was already pressed) */
+ void endCriticalSection(); /* and to prevent the PSP from suspending in a particular section */
+ bool registerForSuspend(Suspendable *item); /* register to be called to suspend/resume */
+ bool unregisterForSuspend(Suspendable *item); /* remove from suspend/resume list */
+ void suspend(); /* callback to have all items in list suspend */
+ void resume(); /* callback to have all items in list resume */
// Functions for pausing the engine
void pollPauseEngine(); /* Poll whether the engine should be paused */
@@ -69,11 +68,9 @@ public:
};
enum PauseState {
- Unpaused = 0,
- PauseEvent,
- UnpauseEvent,
- Pausing,
- Paused
+ UNPAUSED = 0,
+ PAUSING,
+ PAUSED
};
private:
@@ -81,34 +78,38 @@ private:
PowerManager();
~PowerManager();
- Common::List<Suspendable *> _suspendList; /* list to register in */
+ Common::List<Suspendable *> _suspendList; // list to register in
- volatile bool _pauseFlag; /* For pausing, which is before suspending */
- volatile bool _pauseFlagOld; /* Save the last state of the flag while polling */
- volatile int _pauseClientState; /* Pause state of the target */
+ volatile bool _pauseFlag; // For pausing, which is before suspending
+ volatile bool _pauseFlagOld; // Save the last state of the flag while polling
+ volatile PauseState _pauseClientState; // Pause state of the target
- volatile bool _suspendFlag; /* protected variable */
- SDL_mutex *_flagMutex; /* mutex to access access flag */
- SDL_mutex *_listMutex; /* mutex to access Suspendable list */
- SDL_cond *_condSuspendable; /* signal to synchronize accessing threads */
- SDL_cond *_condPM; /* signal to wake up the PM from a critical section */
- volatile int _criticalCounter; /* Counter of how many threads are in a critical section */
- int _error; /* error code - PM can't talk to us. For debugging */
+ volatile bool _suspendFlag; // protected variable
+ PspMutex _flagMutex; // mutex to access access flag
+ PspMutex _listMutex; // mutex to access Suspendable list
+ PspCondition _threadSleep; // signal to synchronize accessing threads
+ PspCondition _pmSleep; // signal to wake up the PM from a critical section
+ volatile int _criticalCounter; // Counter of how many threads are in a critical section
+ int _error; // error code - PM can't talk to us. For debugging
+ volatile int _PMStatus; // What the PM is doing. for debugging
// States for PM to be in (used for debugging)
enum PMState {
- kInitDone = 1 ,
- kDestroyPM,
- kWaitForClientPause,
- kWaitForClientToFinishPausing,
- kGettingFlagMutexSuspend,
- kGotFlagMutexSuspend,
- kWaitCritSectionSuspend,
- kDoneWaitingCritSectionSuspend,
- kGettingListMutexSuspend,
- kIteratingListSuspend,
- kDoneIteratingListSuspend,
- kDoneSuspend,
+ kInitDone = 1,
+ kDestroyPM = 2,
+ kWaitForClientPause = 3,
+ kWaitForClientToFinishPausing = 4,
+ kGettingFlagMutexSuspend = 5,
+ kGotFlagMutexSuspend = 6,
+ kWaitCritSectionSuspend = 7,
+ kDoneWaitingCritSectionSuspend = 8,
+ kGettingListMutexSuspend = 9,
+ kIteratingListSuspend = 10,
+ kDoneIteratingListSuspend = 11,
+ kDoneSuspend = 12,
+ kDonePowerUnlock,
+ kBeginResume,
+ kCheckingPauseFlag,
kGettingListMutexResume,
kIteratingListResume,
kDoneIteratingListResume,
@@ -122,8 +123,6 @@ private:
volatile int _listCounter; /* How many people are in the list - just for debugging */
void debugPM(); /* print info about the PM */
- void PMStatusSet(PMState s) { _PMStatus = s; }
- volatile int _PMStatus; /* What the PM is doing */
public:
int getPMStatus() const { return _PMStatus; }
diff --git a/backends/platform/psp/psp.spec b/backends/platform/psp/psp.spec
index debdab3208..ac325b7fd6 100644
--- a/backends/platform/psp/psp.spec
+++ b/backends/platform/psp/psp.spec
@@ -1,3 +1,3 @@
%rename lib old_lib
*lib:
-%(old_lib) -lz -lstdc++ -lc -lm -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk -lpsputility -lpspuser -lpsppower -lpsphprm -lpsprtc -lpspaudio -lpspkernel
+%(old_lib) -lz -lstdc++ -lc -lm -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk -lpsputility -lpspuser -lpsppower -lpsphprm -lpsprtc -lpspaudio -lpspaudiocodec -lpspkernel
diff --git a/backends/platform/psp/psp_main.cpp b/backends/platform/psp/psp_main.cpp
index e568184990..dba9a8fc2b 100644
--- a/backends/platform/psp/psp_main.cpp
+++ b/backends/platform/psp/psp_main.cpp
@@ -39,10 +39,12 @@
#include <base/main.h>
#include <base/plugins.h>
#include "backends/platform/psp/powerman.h"
+#include "backends/platform/psp/thread.h"
#include "backends/plugins/psp/psp-provider.h"
#include "backends/platform/psp/psppixelformat.h"
#include "backends/platform/psp/osys_psp.h"
+#include "backends/platform/psp/tests.h" /* for unit/speed tests */
#include "backends/platform/psp/trace.h"
#ifdef ENABLE_PROFILING
@@ -109,12 +111,13 @@ int exit_callback(void) {
}
/* Function for handling suspend/resume */
-void power_callback(int , int powerinfo) {
+int power_callback(int , int powerinfo, void *) {
if (powerinfo & PSP_POWER_CB_POWER_SWITCH || powerinfo & PSP_POWER_CB_SUSPENDING) {
PowerMan.suspend();
} else if (powerinfo & PSP_POWER_CB_RESUME_COMPLETE) {
PowerMan.resume();
}
+ return 0;
}
/* Callback thread */
@@ -140,7 +143,7 @@ int CallbackThread(SceSize /*size*/, void *arg) {
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
- int thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, THREAD_ATTR_USER, 0);
+ int thid = sceKernelCreateThread("power_thread", CallbackThread, PRIORITY_POWER_THREAD, STACK_POWER_THREAD, THREAD_ATTR_USER, 0);
if (thid >= 0) {
sceKernelStartThread(thid, 0, 0);
}
@@ -167,6 +170,13 @@ int main(void) {
PluginManager::instance().addPluginProvider(new PSPPluginProvider());
#endif
+/* unit/speed tests */
+#if defined (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS)
+ PSP_INFO_PRINT("running tests\n");
+ psp_tests();
+ sceKernelSleepThread(); // that's it. That's all we're doing
+#endif
+
int res = scummvm_main(argc, argv);
g_system->quit(); // TODO: Consider removing / replacing this!
diff --git a/backends/platform/psp/rtc.cpp b/backends/platform/psp/rtc.cpp
new file mode 100644
index 0000000000..57edea7e49
--- /dev/null
+++ b/backends/platform/psp/rtc.cpp
@@ -0,0 +1,87 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/trunk/backends/platform/psp/osys_psp.cpp $
+ * $Id: osys_psp.cpp 49903 2010-06-16 09:04:27Z Bluddy $
+ *
+ */
+
+#include <time.h>
+#include <psptypes.h>
+#include <psprtc.h>
+
+#include "common/scummsys.h"
+#include "backends/platform/psp/rtc.h"
+
+//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
+//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
+
+#include "backends/platform/psp/trace.h"
+
+
+// Class PspRtc ---------------------------------------------------------------
+DECLARE_SINGLETON(PspRtc)
+
+void PspRtc::init() { // init our starting ticks
+ uint32 ticks[2];
+ sceRtcGetCurrentTick((u64 *)ticks);
+
+ _startMillis = ticks[0]/1000;
+ _startMicros = ticks[0];
+ //_lastMillis = ticks[0]/1000; //debug - only when we don't subtract startMillis
+}
+
+#define MS_LOOP_AROUND 4294967 /* We loop every 2^32 / 1000 = 71 minutes */
+#define MS_LOOP_CHECK 60000 /* Threading can cause weird mixups without this */
+
+// Note that after we fill up 32 bits ie 50 days we'll loop back to 0, which may cause
+// unpredictable results
+uint32 PspRtc::getMillis() {
+ uint32 ticks[2];
+
+ sceRtcGetCurrentTick((u64 *)ticks); // can introduce weird thread delays
+
+ uint32 millis = ticks[0]/1000;
+ millis -= _startMillis; // get ms since start of program
+
+ if ((int)_lastMillis - (int)millis > MS_LOOP_CHECK) { // we must have looped around
+ if (_looped == false) { // check to make sure threads do this once
+ _looped = true;
+ _milliOffset += MS_LOOP_AROUND; // add the needed offset
+ PSP_DEBUG_PRINT("looping around. last ms[%d], curr ms[%d]\n", _lastMillis, millis);
+ }
+ } else {
+ _looped = false;
+ }
+
+ _lastMillis = millis;
+
+ return millis + _milliOffset;
+}
+
+uint32 PspRtc::getMicros() {
+ uint32 ticks[2];
+
+ sceRtcGetCurrentTick((u64 *)ticks);
+ ticks[0] -= _startMicros;
+
+ return ticks[0];
+}
+
diff --git a/backends/fs/palmos/palmos-fs-factory.h b/backends/platform/psp/rtc.h
index 72729c570d..7c1a28474d 100644
--- a/backends/fs/palmos/palmos-fs-factory.h
+++ b/backends/platform/psp/rtc.h
@@ -8,42 +8,43 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public 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 PALMOS_FILESYSTEM_FACTORY_H
-#define PALMOS_FILESYSTEM_FACTORY_H
-
-#include "common/singleton.h"
-#include "backends/fs/fs-factory.h"
-
-/**
- * Creates PalmOSFilesystemNode objects.
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $
+ * $Id: osys_psp.cpp 49903 2010-06-16 09:04:27Z Bluddy $
*
- * Parts of this class are documented in the base interface class, FilesystemFactory.
*/
-class PalmOSFilesystemFactory : public FilesystemFactory, public Common::Singleton<PalmOSFilesystemFactory> {
-public:
- virtual AbstractFSNode *makeRootFileNode() const;
- virtual AbstractFSNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFSNode *makeFileNodePath(const Common::String &path) const;
-protected:
- PalmOSFilesystemFactory() {};
+#ifndef _PSP_RTC_H_
+#define _PSP_RTC_H_
+#include "common/singleton.h"
+
+class PspRtc : public Common::Singleton<PspRtc> {
private:
- friend class Common::Singleton<SingletonBaseType>;
+ uint32 _startMillis;
+ uint32 _startMicros;
+ uint32 _lastMillis;
+ uint32 _milliOffset; // to prevent looping around of millis
+ bool _looped; // make sure we only loop once - for threading
+public:
+ PspRtc()
+ : _startMillis(0), _startMicros(0),
+ _lastMillis(0), _milliOffset(0),
+ _looped(false) {
+ init();
+ }
+ void init();
+ uint32 getMillis();
+ uint32 getMicros();
};
-#endif /*PALMOS_FILESYSTEM_FACTORY_H*/
+#endif \ No newline at end of file
diff --git a/backends/platform/psp/tests.cpp b/backends/platform/psp/tests.cpp
new file mode 100644
index 0000000000..d1bdb9e640
--- /dev/null
+++ b/backends/platform/psp/tests.cpp
@@ -0,0 +1,565 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/trunk/backends/platform/psp/osys_psp.cpp $
+ * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $
+ *
+ */
+
+// PSP speed and unit tests. Activate in tests.h
+// You may also want to build without any engines.
+
+#include "backends/platform/psp/tests.h"
+
+#if defined (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS)
+
+#include "common/scummsys.h"
+#include <pspiofilemgr_fcntl.h>
+#include <pspiofilemgr_stat.h>
+#include <pspiofilemgr.h>
+#include <pspthreadman.h>
+#include <pspsdk.h>
+#include <psprtc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <psputils.h>
+#include "backends/platform/psp/rtc.h"
+#include "backends/platform/psp/thread.h"
+#include "backends/platform/psp/memory.h"
+
+
+#define UNCACHED(x) ((byte *)(((uint32)(x)) | 0x40000000)) /* make an uncached access */
+#define CACHED(x) ((byte *)(((uint32)(x)) & 0xBFFFFFFF)) /* make an uncached access into a cached one */
+
+//#define __PSP_DEBUG_FUNCS__
+//#define __PSP_DEBUG_PRINT__
+
+// Results: (333Mhz/222Mhz)
+// Getting a tick: 1-2 us
+// Getting a time structure: 9/14us
+// ie. using a tick and just dividing by 1000 saves us time.
+
+#include "backends/platform/psp/trace.h"
+
+class PspSpeedTests {
+public:
+ void tickSpeed();
+ void getMicrosSpeed();
+ void seekSpeed();
+ void msReadSpeed();
+ void threadFunctionsSpeed();
+ void semaphoreSpeed();
+ static int threadFunc(SceSize args, void *argp);
+ void semaphoreManyThreadSpeed();
+ void fastCopySpeed();
+
+private:
+ enum {
+ MEMCPY_BUFFER_SIZE = 8192
+ };
+ static PspSemaphore _sem; // semaphore
+
+ void readAndTime(uint32 bytes, char *buffer, FILE *file);
+ void seekAndTime(int bytes, int origin, FILE *file);
+ void fastCopySpecificSize(byte *dst, byte *src, uint32 bytes);
+ void fastCopyDifferentSizes(byte *dst, byte *src);
+ int getThreadIdSpeed();
+ void getPrioritySpeed();
+ void changePrioritySpeed(int id, int priority);
+};
+
+PspSemaphore PspSpeedTests::_sem(0);
+
+void PspSpeedTests::tickSpeed() {
+ uint32 ticksPerSecond = sceRtcGetTickResolution();
+ PSP_INFO_PRINT("ticksPerSecond[%d]\n", ticksPerSecond);
+
+ uint32 currentTicks1[2];
+ uint32 currentTicks2[2];
+
+ sceRtcGetCurrentTick((u64 *)currentTicks1);
+ sceRtcGetCurrentTick((u64 *)currentTicks2);
+ PSP_INFO_PRINT("current tick[%x %x][%u %u]\n", currentTicks1[0], currentTicks1[1], currentTicks1[0], currentTicks1[1]);
+ PSP_INFO_PRINT("current tick[%x %x][%u %u]\n", currentTicks2[0], currentTicks2[1], currentTicks2[0], currentTicks2[1]);
+
+ pspTime time;
+ sceRtcSetTick(&time, (u64 *)currentTicks2);
+ PSP_INFO_PRINT("current tick in time, year[%d] month[%d] day[%d] hour[%d] minutes[%d] seconds[%d] us[%d]\n", time.year, time.month, time.day, time.hour, time.minutes, time.seconds, time.microseconds);
+
+ pspTime time1;
+ pspTime time2;
+ sceRtcGetCurrentClockLocalTime(&time1);
+ sceRtcGetCurrentClockLocalTime(&time2);
+ PSP_INFO_PRINT("time1, year[%d] month[%d] day[%d] hour[%d] minutes[%d] seconds[%d] us[%d]\n", time1.year, time1.month, time1.day, time1.hour, time1.minutes, time1.seconds, time1.microseconds);
+ PSP_INFO_PRINT("time2, year[%d] month[%d] day[%d] hour[%d] minutes[%d] seconds[%d] us[%d]\n", time2.year, time2.month, time2.day, time2.hour, time2.minutes, time2.seconds, time2.microseconds);
+}
+
+void PspSpeedTests::getMicrosSpeed() {
+ uint32 time1, time2, time3, time4;
+ time1 = PspRtc::instance().getMicros();
+ time2 = PspRtc::instance().getMicros();
+ time3 = PspRtc::instance().getMicros();
+ time4 = PspRtc::instance().getMicros();
+
+ PSP_INFO_PRINT("getMicros() times: %d, %d, %d\n", time4-time3, time3-time2, time2-time1);
+}
+
+void PspSpeedTests::readAndTime(uint32 bytes, char *buffer, FILE *file) {
+ uint32 time1 = PspRtc::instance().getMicros();
+ // test minimal read
+ fread(buffer, bytes, 1, file);
+ uint32 time2 = PspRtc::instance().getMicros();
+
+ PSP_INFO_PRINT("Reading %d byte takes %dus\n", bytes, time2-time1);
+}
+
+/*
+ 333MHz/222MHz
+ Reading 1 byte takes 2590us / 3167
+ Reading 10 byte takes 8us / 9
+ Reading 50 byte takes 8us / 11
+ Reading 100 byte takes 8us / 11
+ Reading 1000 byte takes 915us / 1131
+ Reading 2000 byte takes 1806us / 2,284
+ Reading 3000 byte takes 2697us / 3,374
+ Reading 5000 byte takes 4551us / 5,544
+ Reading 6000 byte takes 5356us / 6,676
+ Reading 7000 byte takes 6800us / 8,358
+ Reading 8000 byte takes 6794us / 8,454
+ Reading 9000 byte takes 6782us / 8,563
+ Reading 10000 byte takes 8497us / 10,631
+ Reading 30000 byte takes 25995us / 32,473
+ Reading 80000 byte takes 68457us / 85,291
+ Reading 100000 byte takes 85103us / 106,163
+*/
+// Function to test the impact of MS reads
+// These tests can't be done from shell - the cache screws them up
+void PspSpeedTests::msReadSpeed() {
+ FILE *file;
+ file = fopen("ms0:/psp/music/track1.mp3", "r");
+
+ char *buffer = (char *)malloc(2 * 1024 * 1024);
+
+ readAndTime(1, buffer, file);
+ readAndTime(10, buffer, file);
+ readAndTime(50, buffer, file);
+ readAndTime(100, buffer, file);
+ readAndTime(1000, buffer, file);
+ readAndTime(2000, buffer, file);
+ readAndTime(3000, buffer, file);
+ readAndTime(5000, buffer, file);
+ readAndTime(6000, buffer, file);
+ readAndTime(7000, buffer, file);
+ readAndTime(8000, buffer, file);
+ readAndTime(9000, buffer, file);
+ readAndTime(10000, buffer, file);
+ readAndTime(30000, buffer, file);
+ readAndTime(50000, buffer, file);
+ readAndTime(80000, buffer, file);
+ readAndTime(100000, buffer, file);
+
+ fclose(file);
+ free(buffer);
+}
+
+void PspSpeedTests::seekAndTime(int bytes, int origin, FILE *file) {
+ char buffer[1000];
+
+ uint32 time1 = PspRtc::instance().getMicros();
+ // test minimal read
+ fseek(file, bytes, origin);
+ uint32 time2 = PspRtc::instance().getMicros();
+
+ PSP_INFO_PRINT("Seeking %d byte from %d took %dus\n", bytes, origin, time2-time1);
+
+ time1 = PspRtc::instance().getMicros();
+ // test minimal read
+ fread(buffer, 1000, 1, file);
+ time2 = PspRtc::instance().getMicros();
+
+ PSP_INFO_PRINT("Reading 1000 bytes took %dus\n", time2-time1);
+}
+
+/*
+333MHz
+Seeking 0 byte from 0 took 946us
+Reading 1000 bytes took 1781us
+Seeking 5 byte from 0 took 6us
+Reading 1000 bytes took 19us
+Seeking 1000 byte from 0 took 5us
+Reading 1000 bytes took 913us
+Seeking 100 byte from 0 took 955us
+Reading 1000 bytes took 906us
+Seeking 10000 byte from 0 took 963us
+Reading 1000 bytes took 905us
+Seeking -5 byte from 1 took 1022us
+Reading 1000 bytes took 949us
+Seeking -100 byte from 1 took 1040us
+Reading 1000 bytes took 907us
+Seeking 100 byte from 1 took 1044us
+Reading 1000 bytes took 930us
+Seeking 0 byte from 2 took 7211us
+Reading 1000 bytes took 80us
+Seeking 10000 byte from 2 took 3636us
+Reading 1000 bytes took 110us
+*/
+
+void PspSpeedTests::seekSpeed() {
+ FILE *file;
+ file = fopen("ms0:/psp/music/track1.mp3", "r");
+
+ seekAndTime(0, SEEK_SET, file);
+ seekAndTime(5, SEEK_SET, file);
+ seekAndTime(1000, SEEK_SET, file);
+ seekAndTime(100, SEEK_SET, file);
+ seekAndTime(10000, SEEK_SET, file);
+ seekAndTime(-5, SEEK_CUR, file);
+ seekAndTime(-100, SEEK_CUR, file);
+ seekAndTime(100, SEEK_CUR, file);
+ seekAndTime(0, SEEK_END, file);
+ seekAndTime(-10000, SEEK_END, file);
+
+ fclose(file);
+}
+
+// 222: 5-7us
+int PspSpeedTests::getThreadIdSpeed() {
+ uint32 time1 = PspRtc::instance().getMicros();
+ int threadId = sceKernelGetThreadId();
+ uint32 time2 = PspRtc::instance().getMicros();
+
+ PSP_INFO_PRINT("Getting thread ID %d took %dus\n", threadId, time2-time1);
+
+ return threadId;
+}
+
+// 222: 4-5us
+void PspSpeedTests::getPrioritySpeed() {
+ uint32 time1 = PspRtc::instance().getMicros();
+ int priority = sceKernelGetThreadCurrentPriority();
+ uint32 time2 = PspRtc::instance().getMicros();
+
+ PSP_INFO_PRINT("Getting thread priority %d took %dus\n", priority, time2-time1);
+}
+
+// 222: 9-10us
+void PspSpeedTests::changePrioritySpeed(int id, int priority) {
+ uint32 time1 = PspRtc::instance().getMicros();
+ sceKernelChangeThreadPriority(id, priority);
+ uint32 time2 = PspRtc::instance().getMicros();
+
+ PSP_INFO_PRINT("Changing thread priority to %d for id %d took %dus\n", priority, id, time2-time1);
+}
+
+void PspSpeedTests::threadFunctionsSpeed() {
+ // very unscientific -- just ballpark
+ int id;
+ id = getThreadIdSpeed();
+ getThreadIdSpeed();
+ getPrioritySpeed();
+ getPrioritySpeed();
+ changePrioritySpeed(id, 30);
+ changePrioritySpeed(id, 35);
+ changePrioritySpeed(id, 25);
+
+ // test context switch time
+ for (int i=0; i<10; i++) {
+ uint time1 = PspRtc::instance().getMicros();
+ PspThread::delayMicros(0);
+ uint time2 = PspRtc::instance().getMicros();
+ PSP_INFO_PRINT("poll %d. context switch Time = %dus\n", i, time2-time1); // 10-15us
+ }
+}
+
+void PspSpeedTests::semaphoreSpeed() {
+ PspSemaphore sem(1);
+
+ uint32 time1 = PspRtc::instance().getMicros();
+
+ sem.take();
+
+ uint32 time2 = PspRtc::instance().getMicros();
+
+ PSP_INFO_PRINT("taking semaphore took %d us\n", time2-time1); // 10us
+
+ uint32 time3 = PspRtc::instance().getMicros();
+
+ sem.give();
+
+ uint32 time4 = PspRtc::instance().getMicros();
+ PSP_INFO_PRINT("releasing semaphore took %d us\n", time4-time3); //10us-55us
+}
+
+int PspSpeedTests::threadFunc(SceSize args, void *argp) {
+ PSP_INFO_PRINT("thread %x created.\n", sceKernelGetThreadId());
+
+ _sem.take();
+
+ PSP_INFO_PRINT("grabbed semaphore. Quitting thread\n");
+
+ return 0;
+}
+
+void PspSpeedTests::semaphoreManyThreadSpeed() {
+
+ // create 4 threads
+ for (int i=0; i<4; i++) {
+ int thid = sceKernelCreateThread("my_thread", PspSpeedTests::threadFunc, 0x18, 0x10000, THREAD_ATTR_USER, NULL);
+ sceKernelStartThread(thid, 0, 0);
+ }
+
+ PSP_INFO_PRINT("main thread. created threads\n");
+
+ uint32 threads = _sem.numOfWaitingThreads();
+ while (threads < 4) {
+ threads = _sem.numOfWaitingThreads();
+ PSP_INFO_PRINT("main thread: waiting threads[%d]\n", threads);
+ }
+
+ PSP_INFO_PRINT("main: semaphore value[%d]\n", _sem.getValue());
+ PSP_INFO_PRINT("main thread: waiting threads[%d]\n", _sem.numOfWaitingThreads());
+
+ _sem.give(4);
+}
+
+void PspSpeedTests::fastCopySpecificSize(byte *dst, byte *src, uint32 bytes) {
+ uint32 time1, time2;
+ uint32 fastcopyTime, memcpyTime;
+ const int iterations = 2000;
+ int intc;
+
+ intc = pspSdkDisableInterrupts();
+
+ time1 = PspRtc::instance().getMicros();
+ for (int i=0; i<iterations; i++) {
+ PspMemory::fastCopy(dst, src, bytes);
+ }
+ time2 = PspRtc::instance().getMicros();
+
+ pspSdkEnableInterrupts(intc);
+
+ fastcopyTime = time2-time1;
+
+ intc = pspSdkDisableInterrupts();
+
+ time1 = PspRtc::instance().getMicros();
+ for (int i=0; i<iterations; i++) {
+ memcpy(dst, src, bytes);
+ }
+ time2 = PspRtc::instance().getMicros();
+
+ pspSdkEnableInterrupts(intc);
+
+ memcpyTime = time2-time1;
+
+ PSP_INFO_PRINT("%d bytes. memcpy[%d], fastcopy[%d]\n", bytes, memcpyTime, fastcopyTime);
+}
+
+void PspSpeedTests::fastCopyDifferentSizes(byte *dst, byte *src) {
+ PSP_INFO_PRINT("\nsrc[%p], dst[%p]\n", src, dst);
+ fastCopySpecificSize(dst, src, 1);
+ fastCopySpecificSize(dst, src, 2);
+ fastCopySpecificSize(dst, src, 3);
+ fastCopySpecificSize(dst, src, 4);
+ fastCopySpecificSize(dst, src, 5);
+ fastCopySpecificSize(dst, src, 8);
+ fastCopySpecificSize(dst, src, 10);
+ fastCopySpecificSize(dst, src, 16);
+ fastCopySpecificSize(dst, src, 32);
+ fastCopySpecificSize(dst, src, 50);
+ fastCopySpecificSize(dst, src, 100);
+ fastCopySpecificSize(dst, src, 500);
+ fastCopySpecificSize(dst, src, 1024);
+ fastCopySpecificSize(dst, src, 2048);
+}
+
+void PspSpeedTests::fastCopySpeed() {
+ PSP_INFO_PRINT("running fastCopy speed test\n");
+
+ uint32 *bufferSrc32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE);
+ uint32 *bufferDst32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE);
+
+ // fill buffer 1
+ for (int i=0; i<MEMCPY_BUFFER_SIZE/4; i++)
+ bufferSrc32[i] = i | (((MEMCPY_BUFFER_SIZE/4)-i)<<16);
+
+ // print buffer
+ for (int i=0; i<50; i++)
+ PSP_INFO_PRINT("%x ", bufferSrc32[i]);
+ PSP_INFO_PRINT("\n");
+
+ byte *bufferSrc = ((byte *)bufferSrc32);
+ byte *bufferDst = ((byte *)bufferDst32);
+
+ PSP_INFO_PRINT("\n\ndst and src cached: -----------------\n");
+ fastCopyDifferentSizes(bufferDst, bufferSrc);
+ fastCopyDifferentSizes(bufferDst+1, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst+1, bufferSrc);
+
+ PSP_INFO_PRINT("\n\ndst cached, src uncached: -----------------\n");
+ bufferSrc = UNCACHED(bufferSrc);
+ fastCopyDifferentSizes(bufferDst, bufferSrc);
+ fastCopyDifferentSizes(bufferDst+1, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst+1, bufferSrc);
+
+ PSP_INFO_PRINT("\n\ndst uncached, src uncached: --------------\n");
+ bufferDst = UNCACHED(bufferDst);
+ fastCopyDifferentSizes(bufferDst, bufferSrc);
+ fastCopyDifferentSizes(bufferDst+1, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst+1, bufferSrc);
+
+ PSP_INFO_PRINT("\n\ndst uncached, src cached: -------------------\n");
+ bufferSrc = CACHED(bufferSrc);
+ fastCopyDifferentSizes(bufferDst, bufferSrc);
+ fastCopyDifferentSizes(bufferDst+1, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst+1, bufferSrc);
+
+
+ free(bufferSrc32);
+ free(bufferDst32);
+}
+
+//-------Unit Tests -------------------------------
+
+class PspUnitTests {
+public:
+ void testFastCopy();
+
+private:
+ enum {
+ MEMCPY_BUFFER_SIZE = 8192
+ };
+
+ void fastCopySpecificSize(byte *dst, byte *src, uint32 bytes, bool swap = false);
+ void fastCopyDifferentSizes(byte *dst, byte *src, bool swap = false);
+};
+
+void PspUnitTests::testFastCopy() {
+ PSP_INFO_PRINT("running fastcopy unit test ***********\n");
+ PSP_INFO_PRINT("this test requires the test flag to be on in fastCopy\n\n");
+
+ uint32 *bufferSrc32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE);
+ uint32 *bufferDst32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE);
+
+ // fill buffer 1
+ for (int i=0; i<MEMCPY_BUFFER_SIZE/4; i++)
+ bufferSrc32[i] = i | (((MEMCPY_BUFFER_SIZE/4)-i)<<16);
+
+ // print buffer
+ for (int i=0; i<50; i++)
+ PSP_INFO_PRINT("%x ", bufferSrc32[i]);
+ PSP_INFO_PRINT("\n");
+
+ byte *bufferSrc = ((byte *)bufferSrc32);
+ byte *bufferDst = ((byte *)bufferDst32);
+
+ fastCopyDifferentSizes(bufferDst, bufferSrc, true);
+ fastCopyDifferentSizes(bufferDst+1, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst+2, bufferSrc+2, true);
+ fastCopyDifferentSizes(bufferDst+3, bufferSrc+3);
+ fastCopyDifferentSizes(bufferDst, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst, bufferSrc+2, true);
+ fastCopyDifferentSizes(bufferDst+2, bufferSrc, true);
+ fastCopyDifferentSizes(bufferDst, bufferSrc+3);
+ fastCopyDifferentSizes(bufferDst+1, bufferSrc+2);
+ fastCopyDifferentSizes(bufferDst+1, bufferSrc+3);
+ fastCopyDifferentSizes(bufferDst+2, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst+2, bufferSrc+3);
+ fastCopyDifferentSizes(bufferDst+3, bufferSrc+1);
+ fastCopyDifferentSizes(bufferDst+3, bufferSrc+2);
+
+ free(bufferSrc32);
+ free(bufferDst32);
+}
+
+void PspUnitTests::fastCopyDifferentSizes(byte *dst, byte *src, bool swap) {
+ fastCopySpecificSize(dst, src, 1);
+ fastCopySpecificSize(dst, src, 2, swap);
+ fastCopySpecificSize(dst, src, 4, swap);
+ fastCopySpecificSize(dst, src, 6, swap);
+ fastCopySpecificSize(dst, src, 8, swap);
+ fastCopySpecificSize(dst, src, 9);
+ fastCopySpecificSize(dst, src, 10, swap);
+ fastCopySpecificSize(dst, src, 11);
+ fastCopySpecificSize(dst, src, 12, swap);
+ fastCopySpecificSize(dst, src, 13);
+ fastCopySpecificSize(dst, src, 14, swap);
+ fastCopySpecificSize(dst, src, 15);
+ fastCopySpecificSize(dst, src, 16, swap);
+ fastCopySpecificSize(dst, src, 17);
+ fastCopySpecificSize(dst, src, 18, swap);
+ fastCopySpecificSize(dst, src, 19);
+ fastCopySpecificSize(dst, src, 20, swap);
+ fastCopySpecificSize(dst, src, 32, swap);
+ fastCopySpecificSize(dst, src, 33);
+ fastCopySpecificSize(dst, src, 34, swap);
+ fastCopySpecificSize(dst, src, 35);
+ fastCopySpecificSize(dst, src, 36, swap);
+ fastCopySpecificSize(dst, src, 50, swap);
+ fastCopySpecificSize(dst, src, 100, swap);
+ fastCopySpecificSize(dst, src, 500, swap);
+ fastCopySpecificSize(dst, src, 1000, swap);
+}
+
+void PspUnitTests::fastCopySpecificSize(byte *dst, byte *src, uint32 bytes, bool swap) {
+ memset(dst, 0, bytes);
+ PspMemory::fastCopy(dst, src, bytes);
+
+ if (swap) { // test swap also
+ memset(dst, 0, bytes);
+
+ // pixelformat for swap
+ PSPPixelFormat format;
+ format.set(PSPPixelFormat::Type_4444, true);
+
+ PspMemory::fastSwap(dst, src, bytes, format);
+ }
+}
+
+void psp_tests() {
+ PSP_INFO_PRINT("in tests\n");
+
+#ifdef PSP_ENABLE_SPEED_TESTS
+ // Speed tests
+ PspSpeedTests speedTests;
+ speedTests.tickSpeed();
+ speedTests.getMicrosSpeed();
+ speedTests.msReadSpeed();
+ speedTests.seekSpeed();
+ speedTests.msReadSpeed();
+ speedTests.threadFunctionsSpeed();
+ speedTests.semaphoreSpeed();
+ speedTests.semaphoreManyThreadSpeed();
+ speedTests.fastCopySpeed();
+#endif
+
+#ifdef PSP_ENABLE_UNIT_TESTS
+ // Unit tests
+ PspUnitTests unitTests;
+
+ unitTests.testFastCopy();
+#endif
+}
+
+#endif /* (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS) */ \ No newline at end of file
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formCards.h b/backends/platform/psp/tests.h
index 766c4793b9..1518acfb4c 100644
--- a/backends/platform/PalmOS/Src/launcher/forms/formCards.h
+++ b/backends/platform/psp/tests.h
@@ -18,16 +18,19 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/psp_main.cpp $
+ * $Id: psp_main.cpp 49155 2010-05-23 11:48:21Z Bluddy $
*
*/
-#ifndef __FORMCARDS_H__
-#define __FORMCARDS_H__
+#ifndef _PSP_TESTS_H_
+#define _PSP_TESTS_H_
-UInt16 parseCards();
-void CardSlotFormUpdate();
-void CardSlotCreateDirs();
+//#define PSP_ENABLE_UNIT_TESTS // run unit tests
+//#define PSP_ENABLE_SPEED_TESTS // run speed tests
+#if defined (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS)
+void psp_tests();
#endif
+
+#endif /* _PSP_TESTS_H_ */ \ No newline at end of file
diff --git a/backends/platform/psp/thread.cpp b/backends/platform/psp/thread.cpp
new file mode 100644
index 0000000000..e757c2f575
--- /dev/null
+++ b/backends/platform/psp/thread.cpp
@@ -0,0 +1,234 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 <pspthreadman.h>
+
+#include "backends/platform/psp/thread.h"
+#include "backends/platform/psp/trace.h"
+
+// Class PspThreadable --------------------------------------------------
+// Inherit this to create C++ threads easily
+
+bool PspThreadable::threadCreateAndStart(const char *threadName, int priority, int stackSize, bool useVfpu /*= false*/) {
+ DEBUG_ENTER_FUNC();
+
+ if (_threadId != -1) {
+ PSP_ERROR("thread already created!\n");
+ return false;
+ }
+
+ _threadId = sceKernelCreateThread(threadName, __threadCallback, priority, stackSize, THREAD_ATTR_USER, 0); // add VFPU support
+
+ if (_threadId < 0) {
+ PSP_ERROR("failed to create %s thread. Error code %d\n", threadName, _threadId);
+ return false;
+ }
+
+ // We want to pass the pointer to this, but we'll have to take address of this so use a little trick
+ PspThreadable *_this = this;
+
+ if (sceKernelStartThread(_threadId, sizeof(uint32 *), &_this) < 0) {
+ PSP_ERROR("failed to start %s thread id[%d]\n", threadName, _threadId);
+ return false;
+ }
+
+ PSP_DEBUG_PRINT("Started %s thread with id[%x]\n", threadName, _threadId);
+
+ return true;
+}
+
+// Callback function to be called by PSP kernel
+int PspThreadable::__threadCallback(SceSize, void *__this) {
+ DEBUG_ENTER_FUNC();
+
+ PspThreadable *_this = *(PspThreadable **)__this; // Dereference the copied value which was 'this'
+
+ _this->threadFunction(); // call the virtual function
+
+ return 0;
+}
+
+// PspThread class
+// Utilities to access general thread functions
+
+void PspThread::delayMillis(uint32 ms) {
+ sceKernelDelayThread(ms * 1000);
+}
+
+void PspThread::delayMicros(uint32 us) {
+ sceKernelDelayThread(us);
+}
+
+// Class PspSemaphore ------------------------------------------------
+//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
+//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
+
+#include "backends/platform/psp/trace.h"
+
+PspSemaphore::PspSemaphore(int initialValue, int maxValue/*=255*/) {
+ DEBUG_ENTER_FUNC();
+ _handle = 0;
+ _handle = (uint32)sceKernelCreateSema("ScummVM Sema", 0 /* attr */,
+ initialValue, maxValue,
+ 0 /*option*/);
+ if (!_handle)
+ PSP_ERROR("failed to create semaphore.\n");
+}
+
+PspSemaphore::~PspSemaphore() {
+ DEBUG_ENTER_FUNC();
+ if (_handle)
+ if (sceKernelDeleteSema((SceUID)_handle) < 0)
+ PSP_ERROR("failed to delete semaphore.\n");
+}
+
+int PspSemaphore::numOfWaitingThreads() {
+ DEBUG_ENTER_FUNC();
+ SceKernelSemaInfo info;
+ info.numWaitThreads = 0;
+
+ if (sceKernelReferSemaStatus((SceUID)_handle, &info) < 0)
+ PSP_ERROR("failed to retrieve semaphore info for handle %d\n", _handle);
+
+ return info.numWaitThreads;
+}
+
+int PspSemaphore::getValue() {
+ DEBUG_ENTER_FUNC();
+ SceKernelSemaInfo info;
+ info.currentCount = 0;
+
+ if (sceKernelReferSemaStatus((SceUID)_handle, &info) < 0)
+ PSP_ERROR("failed to retrieve semaphore info for handle %d\n", _handle);
+
+ return info.currentCount;
+}
+
+bool PspSemaphore::pollForValue(int value) {
+ DEBUG_ENTER_FUNC();
+ if (sceKernelPollSema((SceUID)_handle, value) < 0)
+ return false;
+
+ return true;
+}
+
+// false: timeout or error
+bool PspSemaphore::takeWithTimeOut(uint32 timeOut) {
+ DEBUG_ENTER_FUNC();
+
+ uint32 *pTimeOut = 0;
+ if (timeOut)
+ pTimeOut = &timeOut;
+
+ if (sceKernelWaitSema(_handle, 1, pTimeOut) < 0) // we always wait for 1
+ return false;
+ return true;
+}
+
+bool PspSemaphore::give(int num /*=1*/) {
+ DEBUG_ENTER_FUNC();
+
+ if (sceKernelSignalSema((SceUID)_handle, num) < 0)
+ return false;
+ return true;
+}
+
+// Class PspMutex ------------------------------------------------------------
+
+bool PspMutex::lock() {
+ DEBUG_ENTER_FUNC();
+ int threadId = sceKernelGetThreadId();
+ bool ret = true;
+
+ if (_ownerId == threadId) {
+ _recursiveCount++;
+ } else {
+ ret = _semaphore.take();
+ _ownerId = threadId;
+ _recursiveCount = 0;
+ }
+ return ret;
+}
+
+bool PspMutex::unlock() {
+ DEBUG_ENTER_FUNC();
+ int threadId = sceKernelGetThreadId();
+ bool ret = true;
+
+ if (_ownerId != threadId) {
+ PSP_ERROR("attempt to unlock mutex by thread[%x] as opposed to owner[%x]\n",
+ threadId, _ownerId);
+ return false;
+ }
+
+ if (_recursiveCount) {
+ _recursiveCount--;
+ } else {
+ _ownerId = 0;
+ ret = _semaphore.give(1);
+ }
+ return ret;
+}
+
+// Class PspCondition -------------------------------------------------
+
+// Release all threads waiting on the condition
+void PspCondition::releaseAll() {
+ _mutex.lock();
+ if (_waitingThreads > _signaledThreads) { // we have signals to issue
+ int numWaiting = _waitingThreads - _signaledThreads; // threads we haven't signaled
+ _signaledThreads = _waitingThreads;
+
+ _waitSem.give(numWaiting);
+ _mutex.unlock();
+ for (int i=0; i<numWaiting; i++) // wait for threads to tell us they're awake
+ _doneSem.take();
+ } else {
+ _mutex.unlock();
+ }
+}
+
+// Mutex must be taken before entering wait
+void PspCondition::wait(PspMutex &externalMutex) {
+ _mutex.lock();
+ _waitingThreads++;
+ _mutex.unlock();
+
+ externalMutex.unlock(); // must unlock external mutex
+
+ _waitSem.take(); // sleep on the wait semaphore
+
+ // let the signaling thread know we're done
+ _mutex.lock();
+ if (_signaledThreads > 0 ) {
+ _doneSem.give(); // let the thread know
+ _signaledThreads--;
+ }
+ _waitingThreads--;
+ _mutex.unlock();
+
+ externalMutex.lock(); // must lock external mutex here for continuation
+}
+
diff --git a/backends/platform/psp/thread.h b/backends/platform/psp/thread.h
new file mode 100644
index 0000000000..44394af40a
--- /dev/null
+++ b/backends/platform/psp/thread.h
@@ -0,0 +1,112 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef PSP_THREAD_H
+#define PSP_THREAD_H
+
+#include <pspthreadman.h>
+#include "common/scummsys.h"
+
+// class to inherit for creating threads
+class PspThreadable {
+protected:
+ int _threadId;
+ virtual void threadFunction() = 0; // this function will be called when the thread starts
+public:
+ PspThreadable() : _threadId(-1) {} // constructor
+ virtual ~PspThreadable() {} // destructor
+ static int __threadCallback(SceSize, void *__this); // used to get called by sceKernelStartThread() Don't override
+ bool threadCreateAndStart(const char *threadName, int priority, int stackSize, bool useVfpu = false);
+};
+
+// class for thread utils
+class PspThread {
+public:
+ // static functions
+ static void delayMillis(uint32 ms); // delay the current thread
+ static void delayMicros(uint32 us);
+};
+
+class PspSemaphore {
+private:
+ uint32 _handle;
+public:
+ PspSemaphore(int initialValue, int maxValue=255);
+ ~PspSemaphore();
+ bool take() { return takeWithTimeOut(0); }
+ bool takeWithTimeOut(uint32 timeOut);
+ bool give(int num=1);
+ bool pollForValue(int value); // check for a certain value
+ int numOfWaitingThreads();
+ int getValue();
+};
+
+class PspMutex {
+private:
+ PspSemaphore _semaphore;
+ int _recursiveCount;
+ int _ownerId;
+public:
+ PspMutex(bool initialValue) : _semaphore(initialValue ? 1 : 0, 255), _recursiveCount(0), _ownerId(0) {} // initial, max value
+ bool lock();
+ bool unlock();
+ bool poll() { return _semaphore.pollForValue(1); }
+ int numOfWaitingThreads() { return _semaphore.numOfWaitingThreads(); }
+ bool getValue() { return (bool)_semaphore.getValue(); }
+};
+
+class PspCondition {
+private:
+ PspMutex _mutex;
+ int _waitingThreads;
+ int _signaledThreads;
+ PspSemaphore _waitSem;
+ PspSemaphore _doneSem;
+public:
+ PspCondition() : _mutex(true), _waitingThreads(0), _signaledThreads(0),
+ _waitSem(0), _doneSem(0) {}
+ void wait(PspMutex &externalMutex);
+ void releaseAll();
+};
+
+enum ThreadPriority {
+ PRIORITY_MAIN_THREAD = 36,
+ PRIORITY_TIMER_THREAD = 30,
+ PRIORITY_AUDIO_THREAD = 25, // must be higher than timer or we get stuttering
+ PRIORITY_POWER_THREAD = 20, // quite a light thread
+ PRIORITY_DISPLAY_THREAD = 17 // very light thread for callbacks only
+};
+
+enum StackSizes {
+ STACK_DEFAULT = 4 * 1024,
+ STACK_AUDIO_THREAD = 16 * 1024,
+ STACK_TIMER_THREAD = 32 * 1024,
+ STACK_DISPLAY_THREAD = 2 * 1024,
+ STACK_POWER_THREAD = 4 * 1024
+};
+
+#endif /* PSP_THREADS_H */
+
+
diff --git a/backends/platform/psp/trace.cpp b/backends/platform/psp/trace.cpp
index 4bf5450177..7bac6534da 100644
--- a/backends/platform/psp/trace.cpp
+++ b/backends/platform/psp/trace.cpp
@@ -30,8 +30,9 @@
#include <stdio.h>
int psp_debug_indent = 0;
+bool firstWriteToFile = true;
-void PSPDebugTrace(bool alsoToScreen, const char *format, ...) {
+void PspDebugTrace(bool alsoToScreen, const char *format, ...) {
va_list opt;
char buffer[2048];
int bufsz;
@@ -41,8 +42,12 @@ void PSPDebugTrace(bool alsoToScreen, const char *format, ...) {
bufsz = vsnprintf(buffer, (size_t) sizeof(buffer), format, opt);
va_end(opt);
- //fd = fopen("MS0:/SCUMMTRACE.TXT", "ab");
- fd = fopen("SCUMMTRACE.TXT", "ab");
+ if (firstWriteToFile) {
+ fd = fopen("SCUMMTRACE.TXT", "wb"); // erase the file the first time we write
+ firstWriteToFile = false;
+ } else {
+ fd = fopen("SCUMMTRACE.TXT", "ab");
+ }
if (fd == 0)
return;
diff --git a/backends/platform/psp/trace.h b/backends/platform/psp/trace.h
index 1aad0f6781..625aa60772 100644
--- a/backends/platform/psp/trace.h
+++ b/backends/platform/psp/trace.h
@@ -30,17 +30,19 @@
#include "common/str.h"
+#define __PSP_PRINT_TO_FILE_AND_SCREEN__
+
/* Choose to print to file/screen/both */
#ifdef __PSP_PRINT_TO_FILE__
- #define __PSP_PRINT__(format,...) PSPDebugTrace(false, format, ## __VA_ARGS__)
+ #define __PSP_PRINT__(format,...) PspDebugTrace(false, format, ## __VA_ARGS__)
#elif defined __PSP_PRINT_TO_FILE_AND_SCREEN__
- #define __PSP_PRINT__(format,...) PSPDebugTrace(true, format, ## __VA_ARGS__)
+ #define __PSP_PRINT__(format,...) PspDebugTrace(true, format, ## __VA_ARGS__)
#else /* default - print to screen */
#define __PSP_PRINT__(format,...) fprintf(stderr, format, ## __VA_ARGS__)
#endif /* PSP_PRINT_TO_FILE/SCREEN */
-/* Error function */
-#define PSP_ERROR(format,...) __PSP_PRINT__("Error in %s: " format, __PRETTY_FUNCTION__, ## __VA_ARGS__)
+/* Error function - always print to file as well */
+#define PSP_ERROR(format,...) PspDebugTrace(true, "Error in %s: " format, __PRETTY_FUNCTION__, ## __VA_ARGS__)
/* Do the indent */
#define __PSP_INDENT__ for(int _i=psp_debug_indent; _i>0; _i--) \
@@ -52,7 +54,7 @@
#define PSP_INFO_PRINT_INDENT(format,...) { __PSP_INDENT__; \
__PSP_PRINT__(format, ## __VA_ARGS__); }
-void PSPDebugTrace(bool alsoToScreen, const char *format, ...);
+void PspDebugTrace(bool alsoToScreen, const char *format, ...);
extern int psp_debug_indent;
diff --git a/backends/platform/samsungtv/module.mk b/backends/platform/samsungtv/module.mk
index 27e2cfa77d..d7ebe75080 100644
--- a/backends/platform/samsungtv/module.mk
+++ b/backends/platform/samsungtv/module.mk
@@ -5,8 +5,7 @@ MODULE_OBJS := \
main.o \
samsungtv.o
-MODULE_DIRS += \
- backends/platform/samsungtv/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/sdl/events.cpp b/backends/platform/sdl/events.cpp
index 1965cb3031..1c1d82730f 100644
--- a/backends/platform/sdl/events.cpp
+++ b/backends/platform/sdl/events.cpp
@@ -180,6 +180,7 @@ static void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) {
bool OSystem_SDL::pollEvent(Common::Event &event) {
SDL_Event ev;
+ ev.type = SDL_NOEVENT;
handleKbdMouse();
diff --git a/backends/platform/sdl/graphics.cpp b/backends/platform/sdl/graphics.cpp
index 9d0d872c3d..aec90d1352 100644
--- a/backends/platform/sdl/graphics.cpp
+++ b/backends/platform/sdl/graphics.cpp
@@ -25,6 +25,7 @@
#include "backends/platform/sdl/sdl.h"
#include "common/mutex.h"
+#include "common/translation.h"
#include "common/util.h"
#ifdef USE_RGB_COLOR
#include "common/list.h"
@@ -36,7 +37,7 @@
#include "graphics/surface.h"
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
- {"1x", "Normal (no scaling)", GFX_NORMAL},
+ {"1x", _s("Normal (no scaling)"), GFX_NORMAL},
#ifdef USE_SCALERS
{"2x", "2x", GFX_DOUBLESIZE},
{"3x", "3x", GFX_TRIPLESIZE},
@@ -213,45 +214,54 @@ OSystem::TransactionError OSystem_SDL::endGFXTransaction() {
}
#ifdef USE_RGB_COLOR
-const Graphics::PixelFormat RGBList[] = {
+
+Common::List<Graphics::PixelFormat> OSystem_SDL::getSupportedFormats() const {
+ assert(!_supportedFormats.empty());
+ return _supportedFormats;
+}
+
+void OSystem_SDL::detectSupportedFormats() {
+
+ // Clear old list
+ _supportedFormats.clear();
+
+ // Some tables with standard formats that we always list
+ // as "supported". If frontend code tries to use one of
+ // these, we will perform the necessary format
+ // conversion in the background. Of course this incurs a
+ // performance hit, but on desktop ports this should not
+ // matter. We still push the currently active format to
+ // the front, so if frontend code just uses the first
+ // available format, it will get one that is "cheap" to
+ // use.
+ const Graphics::PixelFormat RGBList[] = {
#ifdef ENABLE_32BIT
- // RGBA8888, ARGB8888, RGB888
- Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0),
- Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24),
- Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0),
+ // RGBA8888, ARGB8888, RGB888
+ Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0),
+ Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24),
+ Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0),
#endif
- // RGB565, XRGB1555, RGB555, RGBA4444, ARGB4444
- Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0),
- Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15),
- Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0),
- Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0),
- Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12)
-};
-const Graphics::PixelFormat BGRList[] = {
+ // RGB565, XRGB1555, RGB555, RGBA4444, ARGB4444
+ Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0),
+ Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15),
+ Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0),
+ Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0),
+ Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12)
+ };
+ const Graphics::PixelFormat BGRList[] = {
#ifdef ENABLE_32BIT
- // ABGR8888, BGRA8888, BGR888
- Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24),
- Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0),
- Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0),
+ // ABGR8888, BGRA8888, BGR888
+ Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24),
+ Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0),
+ Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0),
#endif
- // BGR565, XBGR1555, BGR555, ABGR4444, BGRA4444
- Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0),
- Graphics::PixelFormat(2, 5, 5, 5, 1, 0, 5, 10, 15),
- Graphics::PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0),
- Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12),
- Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0)
-};
-
-// TODO: prioritize matching alpha masks
-Common::List<Graphics::PixelFormat> OSystem_SDL::getSupportedFormats() {
- static Common::List<Graphics::PixelFormat> list;
- static bool inited = false;
-
- if (inited)
- return list;
-
- bool BGR = false;
- int listLength = ARRAYSIZE(RGBList);
+ // BGR565, XBGR1555, BGR555, ABGR4444, BGRA4444
+ Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0),
+ Graphics::PixelFormat(2, 5, 5, 5, 1, 0, 5, 10, 15),
+ Graphics::PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0),
+ Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12),
+ Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0)
+ };
Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8();
if (_hwscreen) {
@@ -267,31 +277,32 @@ Common::List<Graphics::PixelFormat> OSystem_SDL::getSupportedFormats() {
format.aLoss = 8;
// Push it first, as the prefered format.
- list.push_back(format);
+ _supportedFormats.push_back(format);
+ }
- if (format.bShift > format.rShift)
- BGR = true;
+ // TODO: prioritize matching alpha masks
+ int i;
- // Mark that we don't need to do this any more.
- inited = true;
+ // Push some RGB formats
+ for (i = 0; i < ARRAYSIZE(RGBList); i++) {
+ if (_hwscreen && (RGBList[i].bytesPerPixel > format.bytesPerPixel))
+ continue;
+ if (RGBList[i] != format)
+ _supportedFormats.push_back(RGBList[i]);
}
- for (int i = 0; i < listLength; i++) {
- if (inited && (RGBList[i].bytesPerPixel > format.bytesPerPixel))
+ // Push some BGR formats
+ for (i = 0; i < ARRAYSIZE(BGRList); i++) {
+ if (_hwscreen && (BGRList[i].bytesPerPixel > format.bytesPerPixel))
continue;
- if (BGR) {
- if (BGRList[i] != format)
- list.push_back(BGRList[i]);
- list.push_back(RGBList[i]);
- } else {
- if (RGBList[i] != format)
- list.push_back(RGBList[i]);
- list.push_back(BGRList[i]);
- }
+ if (BGRList[i] != format)
+ _supportedFormats.push_back(BGRList[i]);
}
- list.push_back(Graphics::PixelFormat::createFormatCLUT8());
- return list;
+
+ // Finally, we always supposed 8 bit palette graphics
+ _supportedFormats.push_back(Graphics::PixelFormat::createFormatCLUT8());
}
+
#endif
bool OSystem_SDL::setGraphicsMode(int mode) {
@@ -573,6 +584,10 @@ bool OSystem_SDL::loadGFXMode() {
_hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
_videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
);
+#ifdef USE_RGB_COLOR
+ detectSupportedFormats();
+#endif
+
if (_hwscreen == NULL) {
// DON'T use error(), as this tries to bring up the debug
// console, which WON'T WORK now that _hwscreen is hosed.
@@ -768,7 +783,8 @@ void OSystem_SDL::internUpdateScreen() {
#endif
// If the shake position changed, fill the dirty area with blackness
- if (_currentShakePos != _newShakePos) {
+ if (_currentShakePos != _newShakePos ||
+ (_mouseNeedsRedraw && _mouseBackup.y <= _currentShakePos)) {
SDL_Rect blackrect = {0, 0, _videoMode.screenWidth * _videoMode.scaleFactor, _newShakePos * _videoMode.scaleFactor};
if (_videoMode.aspectRatioCorrection && !_overlayVisible)
@@ -1377,6 +1393,10 @@ void OSystem_SDL::setMousePos(int x, int y) {
void OSystem_SDL::warpMouse(int x, int y) {
int y1 = y;
+ // Don't change mouse position, when mouse is outside of our window (in case of windowed mode)
+ if (!(SDL_GetAppState( ) & SDL_APPMOUSEFOCUS))
+ return;
+
if (_videoMode.aspectRatioCorrection && !_overlayVisible)
y1 = real2Aspect(y);
@@ -1662,7 +1682,7 @@ void OSystem_SDL::undrawMouse() {
return;
if (_mouseBackup.w != 0 && _mouseBackup.h != 0)
- addDirtyRect(x, y, _mouseBackup.w, _mouseBackup.h);
+ addDirtyRect(x, y - _currentShakePos, _mouseBackup.w, _mouseBackup.h);
}
void OSystem_SDL::drawMouse() {
diff --git a/backends/platform/sdl/main.cpp b/backends/platform/sdl/main.cpp
index b38b815438..ef95a6d256 100644
--- a/backends/platform/sdl/main.cpp
+++ b/backends/platform/sdl/main.cpp
@@ -28,6 +28,7 @@
// otherwise we will get errors about the windows headers redefining
// "ARRAYSIZE" for example.
#if defined(WIN32) && !defined(__SYMBIAN32__)
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// winnt.h defines ARRAYSIZE, but we want our own one...
#undef ARRAYSIZE
diff --git a/backends/platform/sdl/module.mk b/backends/platform/sdl/module.mk
index f6ec769253..43751a57b2 100644
--- a/backends/platform/sdl/module.mk
+++ b/backends/platform/sdl/module.mk
@@ -7,8 +7,7 @@ MODULE_OBJS := \
main.o \
sdl.o
-MODULE_DIRS += \
- backends/platform/sdl/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index e54d70e8b2..5c50a43daf 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -24,6 +24,7 @@
*/
#if defined(WIN32)
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// winnt.h defines ARRAYSIZE, but we want our own one... - this is needed before including util.h
#undef ARRAYSIZE
@@ -95,11 +96,11 @@ AspectRatio::AspectRatio(int w, int h) {
}
#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && defined(USE_SCALERS)
-static const size_t AR_COUNT = 4;
-static const char* desiredAspectRatioAsStrings[AR_COUNT] = { "auto", "4/3", "16/9", "16/10" };
-static const AspectRatio desiredAspectRatios[AR_COUNT] = { AspectRatio(0, 0), AspectRatio(4,3), AspectRatio(16,9), AspectRatio(16,10) };
-
static AspectRatio getDesiredAspectRatio() {
+ const size_t AR_COUNT = 4;
+ const char* desiredAspectRatioAsStrings[AR_COUNT] = { "auto", "4/3", "16/9", "16/10" };
+ const AspectRatio desiredAspectRatios[AR_COUNT] = { AspectRatio(0, 0), AspectRatio(4,3), AspectRatio(16,9), AspectRatio(16,10) };
+
//TODO : We could parse an arbitrary string, if we code enough proper validation
Common::String desiredAspectRatio = ConfMan.get("desired_screen_aspect_ratio");
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index b6baa52391..ace07f349e 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -98,7 +98,7 @@ public:
virtual Graphics::PixelFormat getScreenFormat() const { return _screenFormat; }
// Highest supported
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats();
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
#endif
// Set the size and format of the video bitmap.
@@ -272,6 +272,13 @@ protected:
#ifdef USE_RGB_COLOR
Graphics::PixelFormat _screenFormat;
Graphics::PixelFormat _cursorFormat;
+ Common::List<Graphics::PixelFormat> _supportedFormats;
+
+ /**
+ * Update the list of supported pixel formats.
+ * This method is invoked by loadGFXMode().
+ */
+ void detectSupportedFormats();
#endif
// temporary screen (for scalers)
diff --git a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
index 3543dc8d19..62fcef0275 100644
--- a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
+++ b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
@@ -61,6 +61,7 @@ $ftp_url = "FTP://$FTP_User\@$FTP_Host/$FTP_Dir/";
$ExtraMacros = "MACRO NONSTANDARD_PORT\n";
$ExtraMacros .= "MACRO ENABLE_VKEYBD\n";
$ExtraMacros .= "MACRO DISABLE_FANCY_THEMES\n";
+$ExtraMacros .= "MACRO USE_TRANSLATION\n";
# prep nice list of SDKs
#while( ($SDK, $RootDir) = each(%SDK_RootDirs) )
diff --git a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
index cd107f59ca..a9e7aa562a 100644
--- a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
+++ b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
@@ -42,12 +42,12 @@
'zlib' => 'zlib.lib',
'mad' => 'libmad.lib',
'tremor' => 'libtremor.lib',
- 'mpeg2' => 'libmpeg2.lib'
+ 'flac' => 'libflac.lib'
);
# these are normally enabled for each variation
#$DefaultFeatures = qw(zlib,mad);
- $DefaultFeatures = qw(zlib,mad,tremor);
+ $DefaultFeatures = qw(zlib,mad,tremor,flac);
##################################################################################################################
##
@@ -229,6 +229,45 @@
# now you can add $VariationSets only built on this PC below this line :)
}
+ elsif ($ENV{'COMPUTERNAME'} eq "EMBEDDEV_VAIO1") #################################################################
+ {
+ $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:\\S60v3";
+ #$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!";
diff --git a/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in b/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in
index bd65c3b5e7..99cbb264c2 100644
--- a/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in
+++ b/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in
@@ -110,13 +110,13 @@ SOURCEPATH ..\..\..\..\base
//STOP_AUTO_OBJECTS_BASE_//
-SOURCEPATH ..\..\..\..\
+SOURCEPATH ..\..\..\..
// backend EPOC/SDL/ESDL specific includes
SOURCE backends\platform\sdl\events.cpp
SOURCE backends\platform\sdl\graphics.cpp
-SOURCE backends\platform\sdl\sdl.cpp
SOURCE backends\platform\sdl\hardwarekeys.cpp
+SOURCE backends\platform\sdl\sdl.cpp
SOURCE backends\fs\symbian\symbian-fs-factory.cpp
SOURCE backends\platform\symbian\src\SymbianOS.cpp
SOURCE backends\platform\symbian\src\SymbianActions.cpp
@@ -127,6 +127,9 @@ SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
SOURCE gui\Dialog.cpp
+// Common error
+source common\error.cpp
+
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in
index 34207df5cf..3509714152 100644
--- a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in
+++ b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in
@@ -110,13 +110,13 @@ SOURCEPATH ..\..\..\..\base
//STOP_AUTO_OBJECTS_BASE_//
-SOURCEPATH ..\..\..\..\
+SOURCEPATH ..\..\..\..
// backend EPOC/SDL/ESDL specific includes
SOURCE backends\platform\sdl\events.cpp
SOURCE backends\platform\sdl\graphics.cpp
-SOURCE backends\platform\sdl\sdl.cpp
SOURCE backends\platform\sdl\hardwarekeys.cpp
+SOURCE backends\platform\sdl\sdl.cpp
SOURCE backends\fs\symbian\symbian-fs-factory.cpp
SOURCE backends\platform\symbian\src\SymbianOS.cpp
SOURCE backends\platform\symbian\src\SymbianActions.cpp
@@ -127,6 +127,9 @@ SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
SOURCE gui\Dialog.cpp
+// Common error
+source common\error.cpp
+
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/mmp/scummvm_sci.mmp.in b/backends/platform/symbian/mmp/scummvm_sci.mmp.in
index 2466f0ec2d..1748be29b9 100644
--- a/backends/platform/symbian/mmp/scummvm_sci.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_sci.mmp.in
@@ -58,7 +58,7 @@ SOURCEPATH ..\..\..\..\engines\sci
// *** Include paths
-USERINCLUDE ..\..\..\..\engines ..\..\..\..\engines\sci
+USERINCLUDE ..\..\..\..\engines
USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/src/SymbianActions.cpp b/backends/platform/symbian/src/SymbianActions.cpp
index d925f5f0e7..1a55a68778 100644
--- a/backends/platform/symbian/src/SymbianActions.cpp
+++ b/backends/platform/symbian/src/SymbianActions.cpp
@@ -28,6 +28,7 @@
#include "gui/message.h"
#include "scumm/scumm.h"
#include "common/config-manager.h"
+#include "common/translation.h"
#include <sdl.h>
@@ -37,25 +38,25 @@ namespace GUI {
// or we put them in this file separated by #ifdefs, this one is up to you, AnotherGuest :)
const Common::String actionNames[] = {
- "Up",
- "Down",
- "Left",
- "Right",
- "Left Click",
- "Right Click",
- "Save",
- "Skip",
- "Zone",
- "Multi Function",
- "Swap character",
- "Skip text",
- "Pause",
- "Fast mode",
- "Quit",
- "Debugger",
- "Global menu",
- "Virtual keyboard",
- "Key mapper"
+ _s("Up"),
+ _s("Down"),
+ _s("Left"),
+ _s("Right"),
+ _s("Left Click"),
+ _s("Right Click"),
+ _s("Save"),
+ _s("Skip"),
+ _s("Zone"),
+ _s("Multi Function"),
+ _s("Swap character"),
+ _s("Skip text"),
+ _s("Pause"),
+ _s("Fast mode"),
+ _s("Quit"),
+ _s("Debugger"),
+ _s("Global menu"),
+ _s("Virtual keyboard"),
+ _s("Key mapper")
};
#ifdef UIQ
@@ -75,7 +76,7 @@ void SymbianActions::init() {
Common::String SymbianActions::actionName(ActionType action) {
- return actionNames[action];
+ return _(actionNames[action]);
}
int SymbianActions::size() {
diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp
index 2ae47b07a8..d63c9fe044 100644
--- a/backends/platform/symbian/src/SymbianOS.cpp
+++ b/backends/platform/symbian/src/SymbianOS.cpp
@@ -35,6 +35,7 @@
#include "common/config-manager.h"
#include "common/scummsys.h"
+#include "common/translation.h"
#include "gui/message.h"
@@ -442,7 +443,7 @@ bool OSystem_SDL_Symbian::remapKey(SDL_Event &ev, Common::Event &event) {
case GUI::ACTION_QUIT:
{
- GUI::MessageDialog alert("Do you want to quit ?", "Yes", "No");
+ GUI::MessageDialog alert(_("Do you want to quit ?"), _("Yes"), _("No"));
if (alert.runModal() == GUI::kMessageOK)
quit();
diff --git a/backends/platform/wii/module.mk b/backends/platform/wii/module.mk
index cf55a182c0..88e75fba26 100644
--- a/backends/platform/wii/module.mk
+++ b/backends/platform/wii/module.mk
@@ -8,8 +8,7 @@ MODULE_OBJS := \
osystem_sfx.o \
osystem_events.o
-MODULE_DIRS += \
- backends/platform/wii/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/wii/options.cpp b/backends/platform/wii/options.cpp
index a8f3552313..295856d564 100644
--- a/backends/platform/wii/options.cpp
+++ b/backends/platform/wii/options.cpp
@@ -28,6 +28,8 @@
#include "gui/dialog.h"
#include "backends/fs/wii/wii-fs-factory.h"
+#include "common/translation.h"
+
#include "options.h"
WiiOptionsDialog::WiiOptionsDialog(bool doubleStrike) :
@@ -42,84 +44,84 @@ WiiOptionsDialog::WiiOptionsDialog(bool doubleStrike) :
_strUnderscanY = "wii_video_default_underscan_y";
}
- new ButtonWidget(this, _w - 108 - 16, _h - 24 - 16, 108, 24, "Ok", 'k');
- new ButtonWidget(this, _w - 216 - 32, _h - 24 - 16, 108, 24, "Cancel", 'c');
+ new ButtonWidget(this, _w - 108 - 16, _h - 24 - 16, 108, 24, _("OK"), 0, 'k');
+ new ButtonWidget(this, _w - 216 - 32, _h - 24 - 16, 108, 24, _("Cancel"), 0, 'c');
_tab = new TabWidget(this, 0, 0, _w, _h - 54);
- _tabVideo = _tab->addTab("Video");
+ _tabVideo = _tab->addTab(_("Video"));
new StaticTextWidget(_tab, 16, 16, 128, 16,
- "Current video mode:", Graphics::kTextAlignRight);
+ _("Current video mode:"), Graphics::kTextAlignRight);
new StaticTextWidget(_tab, 160, 16, 128, 16,
- _doubleStrike ? "Double-strike" : "Default",
+ _doubleStrike ? _("Double-strike") : _("Default"),
Graphics::kTextAlignLeft);
new StaticTextWidget(_tab, 16, 48, 128, 16,
- "Horizontal underscan:", Graphics::kTextAlignRight);
- _sliderUnderscanX = new SliderWidget(_tab, 160, 47, 128, 18, 'x');
+ _("Horizontal underscan:"), Graphics::kTextAlignRight);
+ _sliderUnderscanX = new SliderWidget(_tab, 160, 47, 128, 18, 0, 'x');
_sliderUnderscanX->setMinValue(0);
_sliderUnderscanX->setMaxValue(32);
new StaticTextWidget(_tab, 16, 80, 128, 16,
- "Vertical underscan:", Graphics::kTextAlignRight);
- _sliderUnderscanY = new SliderWidget(_tab, 160, 79, 128, 18, 'y');
+ _("Vertical underscan:"), Graphics::kTextAlignRight);
+ _sliderUnderscanY = new SliderWidget(_tab, 160, 79, 128, 18, 0, 'y');
_sliderUnderscanY->setMinValue(0);
_sliderUnderscanY->setMaxValue(32);
- _tabInput = _tab->addTab("Input");
+ _tabInput = _tab->addTab(_("Input"));
new StaticTextWidget(_tab, 16, 16, 128, 16,
- "GC Pad sensitivity:", Graphics::kTextAlignRight);
- _sliderPadSensitivity = new SliderWidget(_tab, 160, 15, 128, 18, 'x');
+ _("GC Pad sensitivity:"), Graphics::kTextAlignRight);
+ _sliderPadSensitivity = new SliderWidget(_tab, 160, 15, 128, 18, 0, 'x');
_sliderPadSensitivity->setMinValue(0);
_sliderPadSensitivity->setMaxValue(64);
new StaticTextWidget(_tab, 16, 44, 128, 16,
- "GC Pad acceleration:", Graphics::kTextAlignRight);
- _sliderPadAcceleration = new SliderWidget(_tab, 160, 43, 128, 18, 'y');
+ _("GC Pad acceleration:"), Graphics::kTextAlignRight);
+ _sliderPadAcceleration = new SliderWidget(_tab, 160, 43, 128, 18, 0, 'y');
_sliderPadAcceleration->setMinValue(0);
_sliderPadAcceleration->setMaxValue(8);
#ifdef USE_WII_DI
- _tabDVD = _tab->addTab("DVD");
+ _tabDVD = _tab->addTab(_("DVD"));
new StaticTextWidget(_tab, 16, 16, 64, 16,
- "Status:", Graphics::kTextAlignRight);
- _textDVDStatus = new StaticTextWidget(_tab, 96, 16, 272, 16, "Unknown",
+ _("Status:"), Graphics::kTextAlignRight);
+ _textDVDStatus = new StaticTextWidget(_tab, 96, 16, 272, 16, _("Unknown"),
Graphics::kTextAlignLeft);
- new ButtonWidget(_tab, 16, 48, 108, 24, "Mount DVD", 'mdvd');
- new ButtonWidget(_tab, 140, 48, 108, 24, "Unmount DVD", 'udvd');
+ new ButtonWidget(_tab, 16, 48, 108, 24, _("Mount DVD"), 0, 'mdvd');
+ new ButtonWidget(_tab, 140, 48, 108, 24, _("Unmount DVD"), 0, 'udvd');
#endif
#ifdef USE_WII_SMB
- _tabSMB = _tab->addTab("SMB");
+ _tabSMB = _tab->addTab(_("SMB"));
new StaticTextWidget(_tab, 16, 16, 64, 16,
- "Status:", Graphics::kTextAlignRight);
- _textSMBStatus = new StaticTextWidget(_tab, 96, 16, 272, 16, "Unknown",
+ _("Status:"), Graphics::kTextAlignRight);
+ _textSMBStatus = new StaticTextWidget(_tab, 96, 16, 272, 16, _("Unknown"),
Graphics::kTextAlignLeft);
new StaticTextWidget(_tab, 16, 52, 64, 16,
- "Server:", Graphics::kTextAlignRight);
+ _("Server:"), Graphics::kTextAlignRight);
_editSMBServer = new EditTextWidget(_tab, 96, 48, _w - 96 - 32, 24, "");
new StaticTextWidget(_tab, 16, 92, 64, 16,
- "Share:", Graphics::kTextAlignRight);
+ _("Share:"), Graphics::kTextAlignRight);
_editSMBShare = new EditTextWidget(_tab, 96, 88, _w - 96 - 32, 24, "");
new StaticTextWidget(_tab, 16, 132, 64, 16,
- "Username:", Graphics::kTextAlignRight);
+ _("Username:"), Graphics::kTextAlignRight);
_editSMBUsername = new EditTextWidget(_tab, 96, 128, _w - 96 - 32, 24, "");
new StaticTextWidget(_tab, 16, 172, 64, 16,
- "Password:", Graphics::kTextAlignRight);
+ _("Password:"), Graphics::kTextAlignRight);
_editSMBPassword = new EditTextWidget(_tab, 96, 168, _w - 96 - 32, 24, "");
- new ButtonWidget(_tab, 16, 208, 108, 24, "Init network", 'net');
+ new ButtonWidget(_tab, 16, 208, 108, 24, _("Init network"), 0, 'net');
- new ButtonWidget(_tab, 140, 208, 108, 24, "Mount SMB", 'msmb');
- new ButtonWidget(_tab, 264, 208, 108, 24, "Unmount SMB", 'usmb');
+ new ButtonWidget(_tab, 140, 208, 108, 24, _("Mount SMB"), 0, 'msmb');
+ new ButtonWidget(_tab, 264, 208, 108, 24, _("Unmount SMB"), 0, 'usmb');
#endif
_tab->setActiveTab(_tabVideo);
@@ -140,12 +142,12 @@ void WiiOptionsDialog::handleTickle() {
#ifdef USE_WII_DI
if (tab == _tabDVD) {
if (fsf.isMounted(WiiFilesystemFactory::kDVD)) {
- _textDVDStatus->setLabel("DVD Mounted successfully");
+ _textDVDStatus->setLabel(_("DVD Mounted successfully"));
} else {
if (fsf.failedToMount(WiiFilesystemFactory::kDVD))
- _textDVDStatus->setLabel("Error while mounting the DVD");
+ _textDVDStatus->setLabel(_("Error while mounting the DVD"));
else
- _textDVDStatus->setLabel("DVD not mounted");
+ _textDVDStatus->setLabel(_("DVD not mounted"));
}
}
#endif
@@ -158,32 +160,32 @@ void WiiOptionsDialog::handleTickle() {
switch (status) {
case 0:
if (fsf.isMounted(WiiFilesystemFactory::kSMB)) {
- label = "Network up, share mounted";
+ label = _("Network up, share mounted");
} else {
- label = "Network up";
+ label = _("Network up");
if (fsf.failedToMount(WiiFilesystemFactory::kSMB))
- label += ", error while mounting the share";
+ label += _(", error while mounting the share");
else
- label += ", share not mounted";
+ label += _(", share not mounted");
}
break;
case -ENETDOWN:
- label = "Network down";
+ label = _("Network down");
break;
case -EBUSY:
- label = "Initialising network";
+ label = _("Initialising network");
break;
case -ETIMEDOUT:
- label = "Timeout while initialising network";
+ label = _("Timeout while initialising network");
break;
default:
- label = String::printf("Network not initialsed (%d)", status);
+ label = String::printf(_("Network not initialsed (%d)"), status);
break;
}
diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h
index d277aa38b1..8180d5727f 100644
--- a/backends/platform/wii/osystem.h
+++ b/backends/platform/wii/osystem.h
@@ -156,7 +156,7 @@ public:
virtual bool setGraphicsMode(int mode);
#ifdef USE_RGB_COLOR
virtual Graphics::PixelFormat getScreenFormat() const;
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats();
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
#endif
virtual int getGraphicsMode() const;
virtual void initSize(uint width, uint height,
diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp
index 3d4e75883b..19190048a0 100644
--- a/backends/platform/wii/osystem_gfx.cpp
+++ b/backends/platform/wii/osystem_gfx.cpp
@@ -209,7 +209,7 @@ Graphics::PixelFormat OSystem_Wii::getScreenFormat() const {
return _pfGame;
}
-Common::List<Graphics::PixelFormat> OSystem_Wii::getSupportedFormats() {
+Common::List<Graphics::PixelFormat> OSystem_Wii::getSupportedFormats() const {
Common::List<Graphics::PixelFormat> res;
res.push_back(_pfRGB565);
res.push_back(Graphics::PixelFormat::createFormatCLUT8());
diff --git a/backends/platform/wince/CEActionsPocket.cpp b/backends/platform/wince/CEActionsPocket.cpp
index ebe6981290..64abd0be3e 100644
--- a/backends/platform/wince/CEActionsPocket.cpp
+++ b/backends/platform/wince/CEActionsPocket.cpp
@@ -31,30 +31,32 @@
#include "common/config-manager.h"
#include "gui/KeysDialog.h"
+#include "common/translation.h"
+
#ifdef _WIN32_WCE
#define KEY_ALL_SKIP 3457
#endif
const String pocketActionNames[] = {
- "Pause",
- "Save",
- "Quit",
- "Skip",
- "Hide Toolbar",
- "Show Keyboard",
- "Sound on/off",
- "Right click",
- "Show/Hide Cursor",
- "Free look",
- "Zoom up",
- "Zoom down",
- "Multi Function",
- "Bind Keys",
- "Cursor Up",
- "Cursor Down",
- "Cursor Left",
- "Cursor Right",
- "Left Click",
+ _s("Pause"),
+ _s("Save"),
+ _s("Quit"),
+ _s("Skip"),
+ _s("Hide Toolbar"),
+ _s("Show Keyboard"),
+ _s("Sound on/off"),
+ _s("Right click"),
+ _s("Show/Hide Cursor"),
+ _s("Free look"),
+ _s("Zoom up"),
+ _s("Zoom down"),
+ _s("Multi Function"),
+ _s("Bind Keys"),
+ _s("Cursor Up"),
+ _s("Cursor Down"),
+ _s("Cursor Left"),
+ _s("Cursor Right"),
+ _s("Left Click")
};
void CEActionsPocket::init() {
@@ -63,7 +65,7 @@ void CEActionsPocket::init() {
String CEActionsPocket::actionName(GUI::ActionType action) {
- return pocketActionNames[action];
+ return _(pocketActionNames[action]);
}
int CEActionsPocket::size() {
@@ -258,7 +260,7 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) {
if (action == POCKET_ACTION_SAVE && ConfMan.get("gameid") == "parallaction") {
// FIXME: This is a temporary solution. The engine should handle its own menus.
// Note that the user can accomplish this via the virtual keyboard as well, this is just for convenience
- GUI::MessageDialog alert("Do you want to load or save the game?", "Load", "Save");
+ GUI::MessageDialog alert(_("Do you want to load or save the game?"), _("Load"), _("Save"));
if (alert.runModal() == GUI::kMessageOK)
_key_action[action].setKey(SDLK_l);
else
@@ -308,7 +310,7 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) {
case POCKET_ACTION_QUIT:
if (!quitdialog) {
quitdialog = true;
- GUI::MessageDialog alert(" Are you sure you want to quit ? ", "Yes", "No");
+ GUI::MessageDialog alert(_(" Are you sure you want to quit ? "), _("Yes"), _("No"));
if (alert.runModal() == GUI::kMessageOK)
_mainSystem->quit();
quitdialog = false;
diff --git a/backends/platform/wince/CEActionsSmartphone.cpp b/backends/platform/wince/CEActionsSmartphone.cpp
index 47733ae317..af80bd2908 100644
--- a/backends/platform/wince/CEActionsSmartphone.cpp
+++ b/backends/platform/wince/CEActionsSmartphone.cpp
@@ -30,23 +30,25 @@
#include "common/config-manager.h"
#include "gui/KeysDialog.h"
+#include "common/translation.h"
+
#define KEY_ALL_SKIP 3457
const String smartphoneActionNames[] = {
- "Up",
- "Down",
- "Left",
- "Right",
- "Left Click",
- "Right Click",
- "Save",
- "Skip",
- "Zone",
- "Multi Function",
- "Bind Keys",
- "Keyboard",
- "Rotate",
- "Quit"
+ _s("Up"),
+ _s("Down"),
+ _s("Left"),
+ _s("Right"),
+ _s("Left Click"),
+ _s("Right Click"),
+ _s("Save"),
+ _s("Skip"),
+ _s("Zone"),
+ _s("Multi Function"),
+ _s("Bind Keys"),
+ _s("Keyboard"),
+ _s("Rotate"),
+ _s("Quit")
};
const int ACTIONS_SMARTPHONE_DEFAULT[] = { SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, SDLK_F1, SDLK_F2, SDLK_F3, SDLK_ESCAPE, SDLK_9, SDLK_8, SDLK_F4, SDLK_RETURN, SDLK_5, SDLK_0 };
@@ -57,7 +59,7 @@ void CEActionsSmartphone::init() {
String CEActionsSmartphone::actionName(GUI::ActionType action) {
- return smartphoneActionNames[action];
+ return _(smartphoneActionNames[action]);
}
int CEActionsSmartphone::size() {
@@ -220,7 +222,7 @@ bool CEActionsSmartphone::perform(GUI::ActionType action, bool pushed) {
if (action == SMARTPHONE_ACTION_SAVE && ConfMan.get("gameid") == "parallaction") {
// FIXME: This is a temporary solution. The engine should handle its own menus.
// Note that the user can accomplish this via the virtual keyboard as well, this is just for convenience
- GUI::MessageDialog alert("Do you want to load or save the game?", "Load", "Save");
+ GUI::MessageDialog alert(_("Do you want to load or save the game?"), _("Load"), _("Save"));
if (alert.runModal() == GUI::kMessageOK)
_key_action[action].setKey(SDLK_l);
else
@@ -267,7 +269,7 @@ bool CEActionsSmartphone::perform(GUI::ActionType action, bool pushed) {
case SMARTPHONE_ACTION_QUIT:
if (!quitdialog) {
quitdialog = true;
- GUI::MessageDialog alert(" Are you sure you want to quit ? ", "Yes", "No");
+ GUI::MessageDialog alert(_(" Are you sure you want to quit ? "), _("Yes"), _("No"));
if (alert.runModal() == GUI::kMessageOK)
_mainSystem->quit();
quitdialog = false;
diff --git a/backends/platform/wince/CELauncherDialog.cpp b/backends/platform/wince/CELauncherDialog.cpp
index 21a967336e..11e4900c2d 100644
--- a/backends/platform/wince/CELauncherDialog.cpp
+++ b/backends/platform/wince/CELauncherDialog.cpp
@@ -38,6 +38,8 @@
#include "common/config-manager.h"
+#include "common/translation.h"
+
using namespace GUI;
using namespace Common;
@@ -51,13 +53,13 @@ public:
// needs fixing, or remove it!
const int buttonWidth = g_gui.xmlEval()->getVar("Globals.Button.Width", 0);
const int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0);
- new ButtonWidget(this, (_w - buttonWidth) / 2, 45, buttonWidth, buttonHeight, "OK", kCloseCmd, '\r'); // Close dialog - FIXME
+ new ButtonWidget(this, (_w - buttonWidth) / 2, 45, buttonWidth, buttonHeight, _("OK"), 0, kCloseCmd, '\r'); // Close dialog - FIXME
- Common::String videoDriver("Using SDL driver ");
+ Common::String videoDriver(_("Using SDL driver "));
SDL_VideoDriverName(tempo, sizeof(tempo));
videoDriver += tempo;
new StaticTextWidget(this, 0, 10, _w, kLineHeight, videoDriver, Graphics::kTextAlignCenter);
- Common::String displayInfos("Display ");
+ Common::String displayInfos(_("Display "));
sprintf(tempo, "%dx%d (real %dx%d)", GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), OSystem_WINCE3::getScreenWidth(), OSystem_WINCE3::getScreenHeight());
displayInfos += tempo;
new StaticTextWidget(this, 0, 20, _w, kLineHeight, displayInfos, Graphics::kTextAlignCenter);
@@ -99,7 +101,7 @@ void CELauncherDialog::automaticScanDirectory(const Common::FSNode &node) {
* returns some illegal paths atm.
*/
void CELauncherDialog::addGame() {
- MessageDialog alert("Do you want to perform an automatic scan ?", "Yes", "No");
+ MessageDialog alert(_("Do you want to perform an automatic scan ?"), _("Yes"), _("No"));
if (alert.runModal() == kMessageOK && _browser->runModal() > 0) {
// Clear existing domains
ConfigManager::DomainMap &domains = (ConfigManager::DomainMap&)ConfMan.getGameDomains();
diff --git a/backends/platform/wince/module.mk b/backends/platform/wince/module.mk
index 6e328b0af4..2d852670f8 100644
--- a/backends/platform/wince/module.mk
+++ b/backends/platform/wince/module.mk
@@ -28,8 +28,7 @@ MODULE_OBJS := \
PocketSCUMM.o \
smartLandScale.o
-MODULE_DIRS += \
- backends/platform/wince/
-
-# We don't use the rules.mk here on purpose
-OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp
index b3480702b5..aef2117bd7 100644
--- a/backends/platform/wince/wince-sdl.cpp
+++ b/backends/platform/wince/wince-sdl.cpp
@@ -30,6 +30,7 @@
#include "common/events.h"
#include "common/util.h"
#include "common/timer.h"
+#include "common/translation.h"
#include "engines/engine.h"
@@ -107,14 +108,14 @@ bool _hasSmartphoneResolution = false;
// Low end devices 240x320
static const OSystem::GraphicsMode s_supportedGraphicsModesLow[] = {
- {"1x", "Normal (no scaling)", GFX_NORMAL},
+ {"1x", _s("Normal (no scaling)"), GFX_NORMAL},
{0, 0, 0}
};
// High end device 480x640
static const OSystem::GraphicsMode s_supportedGraphicsModesHigh[] = {
- {"1x", "Normal (no scaling)", GFX_NORMAL},
+ {"1x", _s("Normal (no scaling)"), GFX_NORMAL},
{"2x", "2x", GFX_DOUBLESIZE},
#ifndef _MSC_VER // EVC breaks template functions, and I'm tired of fixing them :)
{"2xsai", "2xSAI", GFX_2XSAI},
@@ -2263,6 +2264,7 @@ static int mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter) {
bool OSystem_WINCE3::pollEvent(Common::Event &event) {
SDL_Event ev;
+ ev.type = SDL_NOEVENT;
byte b = 0;
DWORD currentTime;
bool keyEvent = false;
diff --git a/backends/plugins/win32/win32-provider.cpp b/backends/plugins/win32/win32-provider.cpp
index a39bdfe76a..65586249e8 100644
--- a/backends/plugins/win32/win32-provider.cpp
+++ b/backends/plugins/win32/win32-provider.cpp
@@ -30,6 +30,7 @@
#include "common/debug.h"
#include "common/fs.h"
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
diff --git a/backends/vkeybd/virtual-keyboard.cpp b/backends/vkeybd/virtual-keyboard.cpp
index bd512fe3ad..2c88322191 100644
--- a/backends/vkeybd/virtual-keyboard.cpp
+++ b/backends/vkeybd/virtual-keyboard.cpp
@@ -90,7 +90,6 @@ bool VirtualKeyboard::openPack(const String &packName, const FSNode &node) {
return true;
}
-#ifdef USE_ZLIB
if (node.getChild(packName + ".zip").exists()) {
// compressed keyboard pack
_fileArchive = makeZipArchive(node.getChild(packName + ".zip"));
@@ -109,7 +108,6 @@ bool VirtualKeyboard::openPack(const String &packName, const FSNode &node) {
return true;
}
-#endif
return false;
}
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 8fa2f54b03..e36ddfca54 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -32,8 +32,6 @@
#include "common/system.h"
#include "common/fs.h"
-#include "sound/mididrv.h"
-
#include "gui/ThemeEngine.h"
#define DETECTOR_TESTING_HACK
@@ -51,7 +49,7 @@ static const char USAGE_STRING[] =
;
// DONT FIXME: DO NOT ORDER ALPHABETICALLY, THIS IS ORDERED BY IMPORTANCE/CATEGORY! :)
-#if defined(PALMOS_MODE) || defined(__SYMBIAN32__) || defined(__GP32__)
+#if defined(__SYMBIAN32__) || defined(__GP32__) || defined(ANDROID)
static const char HELP_STRING[] = "NoUsageString"; // save more data segment space
#else
static const char HELP_STRING[] =
@@ -61,7 +59,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"
+ " --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,8 +362,6 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
END_OPTION
DO_OPTION('e', "music-driver")
- if (MidiDriver::findMusicDriver(option) == 0)
- usage("Unrecognized music driver '%s'", option);
END_OPTION
DO_LONG_OPTION_INT("output-rate")
@@ -941,7 +937,7 @@ bool processSettings(Common::String &command, Common::StringMap &settings) {
// environment variable. This is weaker than a --savepath on the
// command line, but overrides the default savepath, hence it is
// handled here, just before the command line gets parsed.
-#if !defined(MACOS_CARBON) && !defined(_WIN32_WCE) && !defined(PALMOS_MODE) && !defined(__GP32__)
+#if !defined(_WIN32_WCE) && !defined(__GP32__) && !defined(ANDROID)
if (!settings.contains("savepath")) {
const char *dir = getenv("SCUMMVM_SAVEPATH");
if (dir && *dir && strlen(dir) < MAXPATHLEN) {
diff --git a/base/internal_version.h b/base/internal_version.h
index bdd0474c2b..2e6b7a24ad 100644
--- a/base/internal_version.h
+++ b/base/internal_version.h
@@ -2,4 +2,9 @@
#define SCUMMVM_SVN_REVISION
#endif
+#ifdef RELEASE_BUILD
+#undef SCUMMVM_SVN_REVISION
+#define SCUMMVM_SVN_REVISION
+#endif
+
#define SCUMMVM_VERSION "1.2.0svn" SCUMMVM_SVN_REVISION
diff --git a/base/internal_version.h.in b/base/internal_version.h.in
index 1b7e5ed147..4eecf90d87 100644
--- a/base/internal_version.h.in
+++ b/base/internal_version.h.in
@@ -2,4 +2,9 @@
#define SCUMMVM_SVN_REVISION
#endif
+#ifdef RELEASE_BUILD
+#undef SCUMMVM_SVN_REVISION
+#define SCUMMVM_SVN_REVISION
+#endif
+
#define SCUMMVM_VERSION "@VERSION@" SCUMMVM_SVN_REVISION
diff --git a/base/main.cpp b/base/main.cpp
index 8067bd0a26..08d59aafab 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -47,12 +47,14 @@
#include "common/fs.h"
#include "common/system.h"
#include "common/tokenizer.h"
+#include "common/translation.h"
#include "gui/GuiManager.h"
#include "gui/message.h"
#include "gui/error.h"
#include "sound/audiocd.h"
+#include "sound/mididrv.h"
#include "backends/keymapper/keymapper.h"
@@ -102,7 +104,7 @@ static const EnginePlugin *detectPlugin() {
// Query the plugins and find one that will handle the specified gameid
printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActiveDomainName().c_str(), gameid.c_str());
- printf(" Looking for a plugin supporting this gameid... ");
+ printf("%s", " Looking for a plugin supporting this gameid... ");
#if defined(NEW_PLUGIN_DESIGN_FIRST_REFINEMENT) && defined(DYNAMIC_MODULES)
GameDescriptor game = EngineMan.findGameOnePlugAtATime(gameid, &plugin);
@@ -146,7 +148,7 @@ static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const
// Is a separate dialog here still required?
//GUI::displayErrorDialog("ScummVM could not find any game in the specified directory!");
- const char *errMsg = Common::errorToString(err);
+ const char *errMsg = _(Common::errorToString(err));
warning("%s failed to instantiate engine: %s (target '%s', path '%s')",
plugin->getName(),
@@ -205,7 +207,7 @@ static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const
while (!tokenizer.empty()) {
Common::String token = tokenizer.nextToken();
if (!DebugMan.enableDebugChannel(token))
- warning("Engine does not support debug level '%s'", token.c_str());
+ warning(_("Engine does not support debug level '%s'"), token.c_str());
}
// Inform backend that the engine is about to be run
@@ -273,22 +275,22 @@ static void setupKeymapper(OSystem &system) {
mapper->registerHardwareKeySet(keySet);
// Now create the global keymap
- act = new Action(globalMap, "MENU", "Menu", kGenericActionType, kSelectKeyType);
+ act = new Action(globalMap, "MENU", _("Menu"), kGenericActionType, kSelectKeyType);
act->addKeyEvent(KeyState(KEYCODE_F5, ASCII_F5, 0));
- act = new Action(globalMap, "SKCT", "Skip", kGenericActionType, kActionKeyType);
+ act = new Action(globalMap, "SKCT", _("Skip"), kGenericActionType, kActionKeyType);
act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0));
- act = new Action(globalMap, "PAUS", "Pause", kGenericActionType, kStartKeyType);
+ act = new Action(globalMap, "PAUS", _("Pause"), kGenericActionType, kStartKeyType);
act->addKeyEvent(KeyState(KEYCODE_SPACE, ' ', 0));
- act = new Action(globalMap, "SKLI", "Skip line", kGenericActionType, kActionKeyType);
+ act = new Action(globalMap, "SKLI", _("Skip line"), kGenericActionType, kActionKeyType);
act->addKeyEvent(KeyState(KEYCODE_PERIOD, '.', 0));
- act = new Action(globalMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType);
+ act = new Action(globalMap, "VIRT", _("Display keyboard"), kVirtualKeyboardActionType);
act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0));
- act = new Action(globalMap, "REMP", "Remap keys", kKeyRemapActionType);
+ act = new Action(globalMap, "REMP", _("Remap keys"), kKeyRemapActionType);
act->addKeyEvent(KeyState(KEYCODE_F8, ASCII_F8, 0));
mapper->addGlobalKeymap(globalMap);
@@ -324,6 +326,8 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
// Update the config file
ConfMan.set("versioninfo", gScummVMVersion, Common::ConfigManager::kApplicationDomain);
+ // Enable translation
+ TransMan.setLanguage(ConfMan.get("gui_language").c_str());
// Load and setup the debuglevel and the debug flags. We do this at the
// soonest possible moment to ensure debug output starts early on, if
@@ -347,6 +351,16 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
PluginManager::instance().loadPlugins();
#endif
+ // If we received an invalid music parameter via command line we check this here.
+ // We can't check this before loading the music plugins.
+ // On the other hand we cannot load the plugins before we know the file paths (in case of external plugins).
+ if (settings.contains("music-driver")) {
+ if (MidiDriver::getMusicType(MidiDriver::getDeviceHandle(settings["music-driver"])) == MT_INVALID) {
+ warning("Unrecognized music driver '%s'. Switching to default device", settings["music-driver"].c_str());
+ settings["music-driver"] = "auto";
+ }
+ }
+
// Process the remaining command line settings. Must be done after the
// config file and the plugins have been loaded.
if (!Base::processSettings(command, settings))
@@ -394,7 +408,7 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
// Did an error occur ?
if (result != Common::kNoError) {
// Shows an informative error dialog if starting the selected game failed.
- GUI::displayErrorDialog(result, "Error running game:");
+ GUI::displayErrorDialog(result, _("Error running game:"));
}
// Quit unless an error occurred, or Return to launcher was requested
@@ -420,8 +434,8 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
} else {
// A dialog would be nicer, but we don't have any
// screen to draw on yet.
- warning("Could not find any engine capable of running the selected game");
- GUI::displayErrorDialog("Could not find any engine capable of running the selected game");
+ warning("%s", _("Could not find any engine capable of running the selected game"));
+ GUI::displayErrorDialog(_("Could not find any engine capable of running the selected game"));
}
// We will destroy the AudioCDManager singleton here to save some memory.
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 6d9df6a812..61cc747a41 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -167,14 +167,15 @@ public:
// Music plugins
// TODO: Use defines to disable or enable each MIDI driver as a
// static/dynamic plugin, like it's done for the engines
+ LINK_PLUGIN(AUTO)
LINK_PLUGIN(NULL)
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
LINK_PLUGIN(WINDOWS)
#endif
- #if defined(UNIX) && defined(USE_ALSA)
+ #if defined(USE_ALSA)
LINK_PLUGIN(ALSA)
#endif
- #if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__)
+ #if defined(USE_SEQ_MIDI)
LINK_PLUGIN(SEQ)
#endif
#if defined(__MINT__)
@@ -190,13 +191,6 @@ public:
LINK_PLUGIN(COREAUDIO)
LINK_PLUGIN(COREMIDI)
#endif
- #if defined(PALMOS_MODE)
- # if defined(COMPILE_CLIE)
- LINK_PLUGIN(YPA1)
- # elif defined(COMPILE_ZODIAC) && (!defined(ENABLE_SCUMM) || !defined(PALMOS_ARM))
- LINK_PLUGIN(ZODIAC)
- # endif
- #endif
#ifdef USE_FLUIDSYNTH
LINK_PLUGIN(FLUIDSYNTH)
#endif
@@ -204,6 +198,8 @@ public:
LINK_PLUGIN(MT32)
#endif
LINK_PLUGIN(ADLIB)
+ LINK_PLUGIN(PCSPK)
+ LINK_PLUGIN(PCJR)
LINK_PLUGIN(TOWNS)
#if defined (UNIX)
LINK_PLUGIN(TIMIDITY)
diff --git a/base/version.cpp b/base/version.cpp
index ad74c64265..17058d4a03 100644
--- a/base/version.cpp
+++ b/base/version.cpp
@@ -86,6 +86,10 @@ const char *gScummVMFeatures = ""
"ALSA "
#endif
+#ifdef USE_SEQ_MIDI
+ "SEQ "
+#endif
+
#ifdef USE_RGB_COLOR
"RGB "
#endif
diff --git a/common/algorithm.h b/common/algorithm.h
index d3f518b225..9d22af4090 100644
--- a/common/algorithm.h
+++ b/common/algorithm.h
@@ -197,6 +197,21 @@ T sortPartition(T first, T last, T pivot, StrictWeakOrdering &comp) {
/**
* Simple sort function, modeled after std::sort.
* It compares data with the given comparator object comp.
+ *
+ * Like std::sort this is not guaranteed to be stable.
+ *
+ * Two small quotes from wikipedia about stability:
+ *
+ * Stable sorting algorithms maintain the relative order of records with
+ * equal keys.
+ *
+ * Unstable sorting algorithms may change the relative order of records with
+ * equal keys, but stable sorting algorithms never do so.
+ *
+ * For more information on that topic check out:
+ * http://en.wikipedia.org/wiki/Sorting_algorithm#Stability
+ *
+ * NOTE: Actually as the time of writing our implementation is unstable.
*/
template<typename T, class StrictWeakOrdering>
void sort(T first, T last, StrictWeakOrdering comp) {
diff --git a/common/config-file.cpp b/common/config-file.cpp
index cc55ebd6c7..d001a66c9e 100644
--- a/common/config-file.cpp
+++ b/common/config-file.cpp
@@ -125,7 +125,7 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
if (*p == '\0')
error("ConfigFile::loadFromStream: missing ] in line %d", lineno);
else if (*p != ']')
- error("ConfigFile::loadFromStream: Invalid character '%c' occured in section name in line %d", *p, lineno);
+ error("ConfigFile::loadFromStream: Invalid character '%c' occurred in section name in line %d", *p, lineno);
// Previous section is finished now, store it.
if (!section.name.empty())
diff --git a/common/error.cpp b/common/error.cpp
index d51774fd3e..6d1e349287 100644
--- a/common/error.cpp
+++ b/common/error.cpp
@@ -26,6 +26,8 @@
#include "common/error.h"
#include "common/util.h"
+#include "common/translation.h"
+
namespace Common {
/**
@@ -38,24 +40,24 @@ struct ErrorMessage {
};
static const ErrorMessage _errMsgTable[] = {
- { kInvalidPathError, "Invalid Path" },
- { kNoGameDataFoundError, "Game Data not found" },
- { kUnsupportedGameidError, "Game Id not supported" },
- { kUnsupportedColorMode, "Unsupported Color Mode" },
+ { kInvalidPathError, _s("Invalid Path") },
+ { kNoGameDataFoundError, _s("Game Data not found") },
+ { kUnsupportedGameidError, _s("Game Id not supported") },
+ { kUnsupportedColorMode, _s("Unsupported Color Mode") },
- { kReadPermissionDenied, "Read permission denied" },
- { kWritePermissionDenied, "Write permission denied" },
+ { kReadPermissionDenied, _s("Read permission denied") },
+ { kWritePermissionDenied, _s("Write permission denied") },
// The following three overlap a bit with kInvalidPathError and each other. Which to keep?
- { kPathDoesNotExist, "Path not exists" },
- { kPathNotDirectory, "Path not a directory" },
- { kPathNotFile, "Path not a file" },
+ { kPathDoesNotExist, _s("Path not exists") },
+ { kPathNotDirectory, _s("Path not a directory") },
+ { kPathNotFile, _s("Path not a file") },
- { kCreatingFileFailed, "Cannot create file" },
- { kReadingFailed, "Reading failed" },
- { kWritingFailed, "Writing data failed" },
+ { kCreatingFileFailed, _s("Cannot create file") },
+ { kReadingFailed, _s("Reading failed") },
+ { kWritingFailed, _s("Writing data failed") },
- { kUnknownError, "Unknown Error" }
+ { kUnknownError, _s("Unknown Error") }
};
const char *errorToString(Error error) {
@@ -66,7 +68,7 @@ const char *errorToString(Error error) {
}
}
- return "Unknown Error";
+ return _("Unknown Error");
}
} // End of namespace Common
diff --git a/common/error.h b/common/error.h
index c4d383e508..e79b8d0e91 100644
--- a/common/error.h
+++ b/common/error.h
@@ -44,7 +44,7 @@ namespace Common {
* kPathInvalid, kPathIsInvalid, kInvalidPathError
*/
enum Error {
- kNoError = 0, ///< No error occured
+ kNoError = 0, ///< No error occurred
kInvalidPathError, ///< Engine initialization: Invalid game path was passed
kNoGameDataFoundError, ///< Engine initialization: No game data was found in the specified location
kUnsupportedGameidError, ///< Engine initialization: Gameid not supported by this (Meta)Engine
diff --git a/common/events.h b/common/events.h
index 24c9a23728..3c4f6e8d1c 100644
--- a/common/events.h
+++ b/common/events.h
@@ -201,13 +201,14 @@ public:
* Notifies the observer of an incoming event.
*
* An observer is supposed to eat the event, with returning true, when
- * it might want prevent other observers from preventing to receive
- * the event. An usage example here is the keymapper:
+ * it wants to prevent other observers from receiving the event.
+ * An usage example here is the keymapper:
* If it processes an Event, it should 'eat' it and create a new
* event, which the EventDispatcher will then catch.
*
- * @param event the event, which is incoming.
- * @return true if this observer uses this event, false otherwise.
+ * @param event the event, which is incoming.
+ * @return true if the event should not be passed to other observers,
+ * false otherwise.
*/
virtual bool notifyEvent(const Event &event) = 0;
};
diff --git a/common/file.cpp b/common/file.cpp
index 6291aa8855..dec0f2a953 100644
--- a/common/file.cpp
+++ b/common/file.cpp
@@ -51,11 +51,11 @@ bool File::open(const String &filename, Archive &archive) {
SeekableReadStream *stream = 0;
if ((stream = archive.createReadStreamForMember(filename))) {
- debug(3, "Opening hashed: %s", filename.c_str());
+ debug(8, "Opening hashed: %s", filename.c_str());
} else if ((stream = archive.createReadStreamForMember(filename + "."))) {
// WORKAROUND: Bug #1458388: "SIMON1: Game Detection fails"
// sometimes instead of "GAMEPC" we get "GAMEPC." (note trailing dot)
- debug(3, "Opening hashed: %s.", filename.c_str());
+ debug(8, "Opening hashed: %s.", filename.c_str());
}
return open(stream, filename);
diff --git a/common/hashmap.h b/common/hashmap.h
index db80f632ed..0d4d7663f3 100644
--- a/common/hashmap.h
+++ b/common/hashmap.h
@@ -68,9 +68,6 @@ template<class T> class IteratorImpl;
template<class Key, class Val, class HashFunc = Hash<Key>, class EqualFunc = EqualTo<Key> >
class HashMap {
private:
-#if defined (PALMOS_MODE)
-public:
-#endif
typedef HashMap<Key, Val, HashFunc, EqualFunc> HM_t;
diff --git a/common/macresman.cpp b/common/macresman.cpp
index de78cedf61..4b726a183d 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -515,12 +515,10 @@ void MacResManager::convertCrsrCursor(byte *data, int datasize, byte **cursor, i
int i, b;
byte imageByte;
byte *iconData;
- int numBytes;
int pixelsPerByte, bpp;
int ctSize;
byte bitmask;
int iconRowBytes, iconBounds[4];
- int ignored;
int iconDataSize;
dis.readUint16BE(); // type
@@ -606,21 +604,19 @@ void MacResManager::convertCrsrCursor(byte *data, int datasize, byte **cursor, i
dis.readUint16BE(); // colorID[c]
palette[0][c * 4 + 0] = dis.readByte();
- ignored = dis.readByte();
+ dis.readByte();
palette[0][c * 4 + 1] = dis.readByte();
- ignored = dis.readByte();
+ dis.readByte();
palette[0][c * 4 + 2] = dis.readByte();
- ignored = dis.readByte();
+ dis.readByte();
palette[0][c * 4 + 3] = 0;
}
*palSize = ctSize;
- numBytes = (iconBounds[2] - iconBounds[0]) * (iconBounds[3] - iconBounds[1]);
-
pixelsPerByte = (iconBounds[2] - iconBounds[0]) / iconRowBytes;
bpp = 8 / pixelsPerByte;
diff --git a/common/messages.cpp b/common/messages.cpp
new file mode 100644
index 0000000000..b21454d02d
--- /dev/null
+++ b/common/messages.cpp
@@ -0,0 +1,2722 @@
+// generated by po2c 1.0.2-scummvm - Do not modify
+
+static const char * const _messageIds[] = {
+ /* 0 */ "",
+ /* 1 */ " Are you sure you want to quit ? ",
+ /* 2 */ " (Active)",
+ /* 3 */ " (Game)",
+ /* 4 */ " (Global)",
+ /* 5 */ "(built on %s)",
+ /* 6 */ ", error while mounting the share",
+ /* 7 */ ", share not mounted",
+ /* 8 */ "... progress ...",
+ /* 9 */ "11kHz",
+ /* 10 */ "22 kHz",
+ /* 11 */ "44 kHz",
+ /* 12 */ "48 kHz",
+ /* 13 */ "8 kHz",
+ /* 14 */ "<default>",
+ /* 15 */ "About ScummVM",
+ /* 16 */ "AdLib Emulator",
+ /* 17 */ "AdLib emulator:",
+ /* 18 */ "AdLib is used for music in many games",
+ /* 19 */ "Add Game...",
+ /* 20 */ "Antialiased Renderer (16bpp)",
+ /* 21 */ "Aspect ratio correction",
+ /* 22 */ "Associated key : %s",
+ /* 23 */ "Associated key : none",
+ /* 24 */ "Audio",
+ /* 25 */ "Autosave:",
+ /* 26 */ "Available engines:",
+ /* 27 */ "A~b~out...",
+ /* 28 */ "Bind Keys",
+ /* 29 */ "Both",
+ /* 30 */ "Brightness:",
+ /* 31 */ "Cancel",
+ /* 32 */ "Cannot create file",
+ /* 33 */ "Change game options",
+ /* 34 */ "Change global ScummVM options",
+ /* 35 */ "Check if you want to use your real hardware Roland-compatible sound device connected to your computer",
+ /* 36 */ "Choose",
+ /* 37 */ "Choose an action to map",
+ /* 38 */ "Clear value",
+ /* 39 */ "Close",
+ /* 40 */ "Correct aspect ratio for 320x200 games",
+ /* 41 */ "Could not find any engine capable of running the selected game",
+ /* 42 */ "Current video mode:",
+ /* 43 */ "Cursor Down",
+ /* 44 */ "Cursor Left",
+ /* 45 */ "Cursor Right",
+ /* 46 */ "Cursor Up",
+ /* 47 */ "DOSBox OPL emulator",
+ /* 48 */ "DVD",
+ /* 49 */ "DVD Mounted successfully",
+ /* 50 */ "DVD not mounted",
+ /* 51 */ "Date: ",
+ /* 52 */ "Debugger",
+ /* 53 */ "Default",
+ /* 54 */ "Delete",
+ /* 55 */ "Disable power off",
+ /* 56 */ "Disabled GFX",
+ /* 57 */ "Discovered %d new games ...",
+ /* 58 */ "Discovered %d new games.",
+ /* 59 */ "Display ",
+ /* 60 */ "Display keyboard",
+ /* 61 */ "Do you really want to delete this savegame?",
+ /* 62 */ "Do you really want to remove this game configuration?",
+ /* 63 */ "Do you really want to run the mass game detector? This could potentially add a huge number of games.",
+ /* 64 */ "Do you want to load or save the game?",
+ /* 65 */ "Do you want to perform an automatic scan ?",
+ /* 66 */ "Do you want to quit ?",
+ /* 67 */ "Double-strike",
+ /* 68 */ "Down",
+ /* 69 */ "Enable Roland GS Mode",
+ /* 70 */ "Engine does not support debug level '%s'",
+ /* 71 */ "English",
+ /* 72 */ "Error running game:",
+ /* 73 */ "Error while mounting the DVD",
+ /* 74 */ "Extra Path:",
+ /* 75 */ "FM Towns Emulator",
+ /* 76 */ "Fast mode",
+ /* 77 */ "Features compiled in:",
+ /* 78 */ "Free look",
+ /* 79 */ "Full title of the game",
+ /* 80 */ "Fullscreen mode",
+ /* 81 */ "GC Pad acceleration:",
+ /* 82 */ "GC Pad sensitivity:",
+ /* 83 */ "GFX",
+ /* 84 */ "GM Device:",
+ /* 85 */ "GUI Language:",
+ /* 86 */ "GUI Renderer:",
+ /* 87 */ "Game",
+ /* 88 */ "Game Data not found",
+ /* 89 */ "Game Id not supported",
+ /* 90 */ "Game Path:",
+ /* 91 */ "Global menu",
+ /* 92 */ "Go to previous directory level",
+ /* 93 */ "Go up",
+ /* 94 */ "Graphics",
+ /* 95 */ "Graphics mode:",
+ /* 96 */ "Hardware scale (fast, but low quality)",
+ /* 97 */ "Hercules Amber",
+ /* 98 */ "Hercules Green",
+ /* 99 */ "Hide Toolbar",
+ /* 100 */ "High quality audio (slower) (reboot)",
+ /* 101 */ "Higher value specifies better sound quality but may be not supported by your soundcard",
+ /* 102 */ "Hold Shift for Mass Add",
+ /* 103 */ "Horizontal underscan:",
+ /* 104 */ "IBM PCjr Emulator",
+ /* 105 */ "ID:",
+ /* 106 */ "Init network",
+ /* 107 */ "Initial top screen scale:",
+ /* 108 */ "Initialising MT-32 Emulator",
+ /* 109 */ "Initialising network",
+ /* 110 */ "Input",
+ /* 111 */ "Invalid Path",
+ /* 112 */ "Key mapper",
+ /* 113 */ "Keyboard",
+ /* 114 */ "Keymap:",
+ /* 115 */ "Keys",
+ /* 116 */ "Language of ScummVM GUI",
+ /* 117 */ "Language of the game. This will not turn your Spanish game version into English",
+ /* 118 */ "Language:",
+ /* 119 */ "Left",
+ /* 120 */ "Left Click",
+ /* 121 */ "Load",
+ /* 122 */ "Load game:",
+ /* 123 */ "Load savegame for selected game",
+ /* 124 */ "MAME OPL emulator",
+ /* 125 */ "MIDI",
+ /* 126 */ "MIDI gain:",
+ /* 127 */ "MT-32",
+ /* 128 */ "MT-32 Device:",
+ /* 129 */ "MT-32 Emulator",
+ /* 130 */ "Main screen scaling:",
+ /* 131 */ "Map",
+ /* 132 */ "Mass Add...",
+ /* 133 */ "Menu",
+ /* 134 */ "Misc",
+ /* 135 */ "Mixed AdLib/MIDI mode",
+ /* 136 */ "Mount DVD",
+ /* 137 */ "Mount SMB",
+ /* 138 */ "Mouse click",
+ /* 139 */ "Multi Function",
+ /* 140 */ "Music Device:",
+ /* 141 */ "Music volume:",
+ /* 142 */ "Mute All",
+ /* 143 */ "Name:",
+ /* 144 */ "Network down",
+ /* 145 */ "Network not initialsed (%d)",
+ /* 146 */ "Network up",
+ /* 147 */ "Network up, share mounted",
+ /* 148 */ "Never",
+ /* 149 */ "No",
+ /* 150 */ "No date saved",
+ /* 151 */ "No music",
+ /* 152 */ "No playtime saved",
+ /* 153 */ "No time saved",
+ /* 154 */ "None",
+ /* 155 */ "Normal (no scaling)",
+ /* 156 */ "OK",
+ /* 157 */ "Output rate:",
+ /* 158 */ "Override global MIDI settings",
+ /* 159 */ "Override global MT-32 settings",
+ /* 160 */ "Override global audio settings",
+ /* 161 */ "Override global graphic settings",
+ /* 162 */ "Override global volume settings",
+ /* 163 */ "PC Speaker Emulator",
+ /* 164 */ "Password:",
+ /* 165 */ "Path not a directory",
+ /* 166 */ "Path not a file",
+ /* 167 */ "Path not exists",
+ /* 168 */ "Paths",
+ /* 169 */ "Pause",
+ /* 170 */ "Pick the game:",
+ /* 171 */ "Platform the game was originally designed for",
+ /* 172 */ "Platform:",
+ /* 173 */ "Playtime: ",
+ /* 174 */ "Please select an action",
+ /* 175 */ "Plugins Path:",
+ /* 176 */ "Preferred Device:",
+ /* 177 */ "Press the key to associate",
+ /* 178 */ "Quit",
+ /* 179 */ "Quit ScummVM",
+ /* 180 */ "Read permission denied",
+ /* 181 */ "Reading failed",
+ /* 182 */ "Remap keys",
+ /* 183 */ "Remove game from the list. The game data files stay intact",
+ /* 184 */ "Render mode:",
+ /* 185 */ "Right",
+ /* 186 */ "Right Click",
+ /* 187 */ "Right click",
+ /* 188 */ "Rotate",
+ /* 189 */ "SFX volume:",
+ /* 190 */ "SMB",
+ /* 191 */ "Save",
+ /* 192 */ "Save Path:",
+ /* 193 */ "Save Path: ",
+ /* 194 */ "Save game:",
+ /* 195 */ "Scan complete!",
+ /* 196 */ "Scanned %d directories ...",
+ /* 197 */ "ScummVM Main Menu",
+ /* 198 */ "ScummVM could not find any engine capable of running the selected game!",
+ /* 199 */ "ScummVM could not find any game in the specified directory!",
+ /* 200 */ "ScummVM couldn't open the specified directory!",
+ /* 201 */ "Search in game list",
+ /* 202 */ "Search:",
+ /* 203 */ "Select SoundFont",
+ /* 204 */ "Select a Theme",
+ /* 205 */ "Select additional game directory",
+ /* 206 */ "Select an action and click 'Map'",
+ /* 207 */ "Select directory for GUI themes",
+ /* 208 */ "Select directory for extra files",
+ /* 209 */ "Select directory for plugins",
+ /* 210 */ "Select directory for saved games",
+ /* 211 */ "Select directory for savegames",
+ /* 212 */ "Select directory with game data",
+ /* 213 */ "Sensitivity",
+ /* 214 */ "Server:",
+ /* 215 */ "Share:",
+ /* 216 */ "Short game identifier used for referring to savegames and running the game from the command line",
+ /* 217 */ "Show Keyboard",
+ /* 218 */ "Show mouse cursor",
+ /* 219 */ "Show subtitles and play speech",
+ /* 220 */ "Show/Hide Cursor",
+ /* 221 */ "Skip",
+ /* 222 */ "Skip line",
+ /* 223 */ "Skip text",
+ /* 224 */ "Snap to edges",
+ /* 225 */ "Software scale (good quality, but slower)",
+ /* 226 */ "Sound on/off",
+ /* 227 */ "SoundFont is supported by some audio cards, Fluidsynth and Timidity",
+ /* 228 */ "SoundFont:",
+ /* 229 */ "Spch",
+ /* 230 */ "Special dithering modes supported by some games",
+ /* 231 */ "Special sound effects volume",
+ /* 232 */ "Specifies default sound device for General MIDI output",
+ /* 233 */ "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output",
+ /* 234 */ "Specifies output sound device or sound card emulator",
+ /* 235 */ "Specifies path to additional data used by all games or ScummVM",
+ /* 236 */ "Specifies path to additional data used the game",
+ /* 237 */ "Specifies preferred sound device or sound card emulator",
+ /* 238 */ "Specifies where your savegames are put",
+ /* 239 */ "Speech",
+ /* 240 */ "Speech volume:",
+ /* 241 */ "Standard Renderer (16bpp)",
+ /* 242 */ "Start selected game",
+ /* 243 */ "Status:",
+ /* 244 */ "Subs",
+ /* 245 */ "Subtitle speed:",
+ /* 246 */ "Subtitles",
+ /* 247 */ "Swap character",
+ /* 248 */ "Tap for left click, double tap right click",
+ /* 249 */ "Text and Speech:",
+ /* 250 */ "The chosen directory cannot be written to. Please select another one.",
+ /* 251 */ "Theme Path:",
+ /* 252 */ "Theme:",
+ /* 253 */ "This game ID is already taken. Please choose another one.",
+ /* 254 */ "This game does not support loading games from the launcher.",
+ /* 255 */ "Time: ",
+ /* 256 */ "Timeout while initialising network",
+ /* 257 */ "Touch X Offset",
+ /* 258 */ "Touch Y Offset",
+ /* 259 */ "Touchpad mode disabled.",
+ /* 260 */ "Touchpad mode enabled.",
+ /* 261 */ "True Roland MT-32 (disable GM emulation)",
+ /* 262 */ "Turns off General MIDI mapping for games with Roland MT-32 soundtrack",
+ /* 263 */ "Unknown",
+ /* 264 */ "Unknown Error",
+ /* 265 */ "Unmount DVD",
+ /* 266 */ "Unmount SMB",
+ /* 267 */ "Unscaled (you must scroll left and right)",
+ /* 268 */ "Unsupported Color Mode",
+ /* 269 */ "Untitled savestate",
+ /* 270 */ "Up",
+ /* 271 */ "Use both MIDI and AdLib sound generation",
+ /* 272 */ "Use laptop trackpad-style cursor control",
+ /* 273 */ "Username:",
+ /* 274 */ "Using SDL driver ",
+ /* 275 */ "Vertical underscan:",
+ /* 276 */ "Video",
+ /* 277 */ "Virtual keyboard",
+ /* 278 */ "Volume",
+ /* 279 */ "Windows MIDI",
+ /* 280 */ "Write permission denied",
+ /* 281 */ "Writing data failed",
+ /* 282 */ "Yes",
+ /* 283 */ "You have to restart ScummVM to take the effect.",
+ /* 284 */ "Zone",
+ /* 285 */ "Zoom down",
+ /* 286 */ "Zoom up",
+ /* 287 */ "every 10 mins",
+ /* 288 */ "every 15 mins",
+ /* 289 */ "every 30 mins",
+ /* 290 */ "every 5 mins",
+ /* 291 */ "~A~bout",
+ /* 292 */ "~A~dd Game...",
+ /* 293 */ "~C~ancel",
+ /* 294 */ "~C~lose",
+ /* 295 */ "~E~dit Game...",
+ /* 296 */ "~H~elp",
+ /* 297 */ "~I~ndy fight controls",
+ /* 298 */ "~K~eys",
+ /* 299 */ "~L~eft handed mode",
+ /* 300 */ "~L~oad",
+ /* 301 */ "~L~oad...",
+ /* 302 */ "~N~ext",
+ /* 303 */ "~O~K",
+ /* 304 */ "~O~ptions",
+ /* 305 */ "~O~ptions...",
+ /* 306 */ "~P~revious",
+ /* 307 */ "~Q~uit",
+ /* 308 */ "~R~emove Game",
+ /* 309 */ "~R~esume",
+ /* 310 */ "~R~eturn to Launcher",
+ /* 311 */ "~S~ave",
+ /* 312 */ "~S~tart",
+ /* 313 */ "~T~ransitions Enabled",
+ /* 314 */ "~W~ater Effect Enabled",
+ /* 315 */ "~Z~ip Mode Activated",
+ NULL
+};
+
+struct PoMessageEntry {
+ int msgid;
+ const char *msgstr;
+};
+
+static const PoMessageEntry _translation_ru_RU[] = {
+ { 0, "Project-Id-Version: ScummVM VERSION\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-30 22:14+0100\nPO-Revision-Date: 2010-06-13 20:55+0300\nLast-Translator: Eugene Sandulenko <sev@scummvm.org>\nLanguage-Team: Russian\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-5\nContent-Transfer-Encoding: 8bit\nLanguage: Russian\nPlural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" },
+ { 1, " \262\353 \343\322\325\340\325\335\353, \347\342\336 \345\336\342\330\342\325 \322\353\331\342\330? " },
+ { 2, " (\260\332\342\330\322\335\320\357)" },
+ { 3, " (\270\323\340\353)" },
+ { 4, " (\263\333\336\321\320\333\354\335\320\357)" },
+ { 5, "(\341\336\321\340\320\335 %s)" },
+ { 6, ", \336\350\330\321\332\320 \322\336 \322\340\325\334\357 \337\336\324\332\333\356\347\325\335\330\357 \337\320\337\332\330" },
+ { 7, ", \337\320\337\332\320 \335\325 \337\336\324\332\333\356\347\325\335\320" },
+ { 8, "... \330\351\343 ..." },
+ { 9, "11 \332\263\346" },
+ { 10, "22 \332\263\346" },
+ { 11, "44 \332\263\346" },
+ { 12, "48 \332\263\346" },
+ { 13, "8 \332\263\346" },
+ { 14, "<\337\336 \343\334\336\333\347\320\335\330\356>" },
+ { 15, "\276 \337\340\336\323\340\320\334\334\325 ScummVM" },
+ { 16, "\315\334\343\333\357\342\336\340 AdLib" },
+ { 17, "\315\334\343\333\357\342\336\340 AdLib:" },
+ { 18, "\267\322\343\332\336\322\320\357 \332\320\340\342\320 AdLib \330\341\337\336\333\354\327\343\325\342\341\357 \334\335\336\323\330\334\330 \330\323\340\320\334\330" },
+ { 19, "\275\336\322\320\357 \330\323\340\320..." },
+ { 20, "\300\320\341\342\325\340\330\327\320\342\336\340 \341\336 \341\323\333\320\326\330\322\320\335\330\325\334 (16bpp)" },
+ { 21, "\272\336\340\340\325\332\346\330\357 \341\336\336\342\335\336\350\325\335\330\357 \341\342\336\340\336\335" },
+ { 22, "\275\320\327\335\320\347\325\335\335\320\357 \332\333\320\322\330\350\320 : %s" },
+ { 23, "\275\320\327\335\320\347\325\335\335\320\357 \332\333\320\322\330\350\320 : \335\325\342" },
+ { 24, "\260\343\324\330\336" },
+ { 25, "\260\322\342\336\341\336\345\340\320\335\325\335\330\325:" },
+ { 26, "\264\336\341\342\343\337\335\353\325 \324\322\330\326\332\330:" },
+ { 27, "\276 \337~\340~\336\323\340\320\334\334\325..." },
+ { 28, "\275\320\327\335\320\347\330\342\354 \332\333\320\322\330\350\330" },
+ { 29, "\262\341\361" },
+ { 30, "\317\340\332\336\341\342\354:" },
+ { 31, "\276\342\334\325\335\320" },
+ { 32, "\275\325 \334\336\323\343 \341\336\327\324\320\342\354 \344\320\331\333" },
+ { 33, "\270\327\334\325\335\330\342\354 \336\337\346\330\330 \330\323\340\353" },
+ { 34, "\270\327\334\325\335\330\342\354 \323\333\336\321\320\333\354\335\353\325 \336\337\346\330\330 ScummVM" },
+ { 35, "\276\342\334\325\342\354\342\325, \325\341\333\330 \343 \322\320\341 \337\336\324\332\333\356\347\325\335\336 Roland-\341\336\322\334\325\341\342\330\334\336\325 \327\322\343\332\336\322\336\325 \343\341\342\340\336\331\341\342\322\336 \330 \322\353 \345\336\342\330\342\325 \325\323\336 \330\341\337\336\333\354\327\336\322\320\342\354" },
+ { 36, "\262\353\321\340\320\342\354" },
+ { 37, "\262\353\321\325\340\330\342\325 \324\325\331\341\342\322\330\325 \324\333\357 \335\320\327\335\320\347\325\335\330\357" },
+ { 38, "\276\347\330\341\342\330\342\354 \327\335\320\347\325\335\330\325" },
+ { 39, "\267\320\332\340\353\342\354" },
+ { 40, "\272\336\340\340\325\332\342\330\340\336\322\320\342\354 \341\336\336\342\335\336\350\325\335\330\325 \341\342\336\340\336\335 \324\333\357 \330\323\340 \341 \340\320\327\340\325\350\325\335\330\325\334 320x200" },
+ { 41, "\275\325 \334\336\323\343 \335\320\331\342\330 \324\322\330\326\336\332 \324\333\357 \327\320\337\343\341\332\320 \322\353\321\340\320\335\335\336\331 \330\323\340\353" },
+ { 42, "\302\325\332\343\351\330\331 \322\330\324\325\336\340\325\326\330\334:" },
+ { 43, "\272\343\340\341\336\340 \322\335\330\327" },
+ { 44, "\272\343\340\341\336\340 \322\333\325\322\336" },
+ { 45, "\272\343\340\341\336\340 \322\337\340\320\322\336" },
+ { 46, "\272\343\340\341\336\340 \322\322\325\340\345" },
+ { 47, "\315\334\343\333\357\342\336\340 DOSBox OPL" },
+ { 48, "DVD" },
+ { 49, "DVD \337\336\324\332\333\356\347\325\335 \343\341\337\325\350\335\336" },
+ { 50, "DVD \335\325 \337\336\324\332\333\356\347\325\335" },
+ { 51, "\264\320\342\320: " },
+ { 52, "\276\342\333\320\324\347\330\332" },
+ { 53, "\277\336 \343\334\336\333\347\320\335\330\356" },
+ { 54, "\303\324\320\333\330\342\354" },
+ { 55, "\267\320\337\340\325\342\330\342\354 \322\353\332\333\356\347\325\335\330\325" },
+ { 56, "\261\325\327 \323\340\320\344\330\332\330" },
+ { 57, "\275\320\331\324\325\335\336 %d \335\336\322\353\345 \330\323\340 ..." },
+ { 58, "\275\320\331\324\325\335\336 %d \335\336\322\353\345 \330\323\340." },
+ { 59, "\277\336\332\320\327\320\342\354 " },
+ { 60, "\277\336\332\320\327\320\342\354 \332\333\320\322\330\320\342\343\340\343" },
+ { 61, "\262\353 \324\325\331\341\342\322\330\342\325\333\354\335\336 \345\336\342\330\342\325 \343\324\320\333\330\342\354 \355\342\336 \341\336\345\340\320\335\325\335\330\325?" },
+ { 62, "\262\353 \324\325\331\341\342\322\330\342\325\333\354\335\336 \345\336\342\330\342\325 \343\324\320\333\330\342\354 \343\341\342\320\335\336\322\332\330 \324\333\357 \355\342\336\331 \330\323\340\353?" },
+ { 63, "\262\353 \324\325\331\341\342\322\330\342\325\333\354\335\336 \345\336\342\330\342\325 \327\320\337\343\341\342\330\342\354 \324\325\342\325\332\342\336\340 \322\341\325\345 \330\323\340? \315\342\336 \337\336\342\325\335\346\330\320\333\354\335\336 \334\336\326\325\342 \324\336\321\320\322\330\342\354 \321\336\333\354\350\336\325 \332\336\333\330\347\325\341\342\322\336 \330\323\340." },
+ { 64, "\262\353 \345\336\342\330\342\325 \327\320\323\340\343\327\330\342\354 \333\330\321\336 \341\336\345\340\320\335\330\342\354 \330\323\340\343?" },
+ { 65, "\262\353 \345\336\342\330\342\325 \337\340\336\330\327\322\325\341\342\330 \320\322\342\336\334\320\342\330\347\325\341\332\330\331 \337\336\330\341\332?" },
+ { 66, "\262\353 \345\336\342\330\342\325 \322\353\331\342\330?" },
+ { 67, "\264\322\336\331\335\336\331 \343\324\320\340" },
+ { 68, "\262\335\330\327" },
+ { 69, "\262\332\333\356\347\330\342\354 \340\325\326\330\334 Roland GS" },
+ { 70, "\264\322\330\326\336\332 \335\325 \337\336\324\324\325\340\326\330\322\320\325\342 \343\340\336\322\325\335\354 \336\342\333\320\324\332\330 '%s'" },
+ { 71, "English" },
+ { 72, "\276\350\330\321\332\320 \327\320\337\343\341\332\320 \330\323\340\353:" },
+ { 73, "\276\350\330\321\332\320 \322\336 \322\340\325\334\357 \337\336\324\332\333\356\347\325\335\330\357 DVD" },
+ { 74, "\264\336\337. \337\343\342\354:" },
+ { 75, "\315\334\343\333\357\342\336\340 FM Towns" },
+ { 76, "\261\353\341\342\340\353\331 \340\325\326\330\334" },
+ { 77, "\262\332\333\356\347\325\335\335\353\325 \322 \321\330\333\324 \336\337\346\330\330:" },
+ { 78, "\301\322\336\321\336\324\335\353\331 \336\321\327\336\340" },
+ { 79, "\277\336\333\335\336\325 \335\320\327\322\320\335\330\325 \330\323\340\353" },
+ { 80, "\277\336\333\335\336\355\332\340\320\335\335\353\331 \340\325\326\330\334" },
+ { 81, "\303\341\332\336\340\325\335\330\325 GC \337\320\324\320:" },
+ { 82, "\307\343\322\341\342\322\330\342\325\333\354\335\336\341\342\354 GC \337\320\324\320:" },
+ { 83, "\263\340\344" },
+ { 84, "\303\341\342\340\336\331\341\342\322\336 GM:" },
+ { 85, "\317\327\353\332 GUI:" },
+ { 86, "\300\330\341\336\322\320\333\332\320 GUI:" },
+ { 87, "\270\323\340\320" },
+ { 88, "\275\325\342 \344\320\331\333\336\322 \330\323\340\353" },
+ { 89, "Game Id \335\325 \337\336\324\324\325\340\326\330\322\320\325\342\341\357" },
+ { 90, "\263\324\325 \330\323\340\320: " },
+ { 91, "\263\333\336\321\320\333\354\335\336\325 \334\325\335\356" },
+ { 92, "\277\325\340\325\331\342\330 \335\320 \324\330\340\325\332\342\336\340\330\356 \343\340\336\322\335\325\334 \322\353\350\325" },
+ { 93, "\262\322\325\340\345" },
+ { 94, "\263\340\320\344\330\332\320" },
+ { 95, "\263\340\320\344. \340\325\326\330\334:" },
+ { 96, "\305\320\340\324\322\320\340\335\336\325 \334\320\341\350\342\320\321\330\340\336\322\320\335\330\325 (\321\353\341\342\340\336, \335\336 \335\330\327\332\336\323\336 \332\320\347\325\341\342\322\320)" },
+ { 97, "Hercules \317\335\342\320\340\335\353\331" },
+ { 98, "Hercules \267\325\333\325\335\353\331" },
+ { 99, "\301\337\340\357\342\320\342\354 \337\320\335\325\333\354 \330\335\341\342\340\343\334\325\335\342\336\322" },
+ { 100, "\262\353\341\336\332\336\325 \332\320\347\325\341\342\322\336 \327\322\343\332\320 (\334\325\324\333\325\335\335\325\325) (\340\325\321\343\342)" },
+ { 101, "\261\276\333\354\350\330\325 \327\335\320\347\325\335\330\357 \327\320\324\320\356\342 \333\343\347\350\325\325 \332\320\347\325\341\342\322\336 \327\322\343\332\320, \336\324\335\320\332\336 \336\335\330 \334\336\323\343\342 \335\325 \337\336\324\324\325\340\326\330\322\320\342\354\341\357 \322\320\350\325\331 \327\322\343\332\336\322\336\331 \332\320\340\342\336\331" },
+ { 102, "\303\324\325\340\326\330\322\320\331\342\325 \332\333\320\322\330\350\343 Shift \324\333\357 \342\336\323\336, \347\342\336\321\353 \324\336\321\320\322\330\342\354 \335\325\341\332\336\333\354\332\336 \330\323\340" },
+ { 103, "\263\336\340\330\327\336\335\342\320\333\354\335\353\331 underscan:" },
+ { 104, "\315\334\343\333\357\342\336\340 IBM PCjr" },
+ { 105, "ID:" },
+ { 106, "\270\335\330\346\330\320\333\330\327\320\346\330\357 \341\325\342\330" },
+ { 107, "\275\320\347\320\333\354\335\353\331 \334\320\341\350\342\320\321 \322\325\340\345\335\325\323\336 \355\332\340\320\335\320:" },
+ { 108, "\275\320\341\342\340\320\330\322\320\356 \355\334\343\333\357\342\336\340 MT-32" },
+ { 109, "\275\320\341\342\340\320\330\322\320\356 \341\325\342\354" },
+ { 110, "\262\322\336\324" },
+ { 111, "\275\325\322\325\340\335\353\331 \337\343\342\354" },
+ { 112, "\275\320\327\335\320\347\325\335\330\325 \332\333\320\322\330\350" },
+ { 113, "\272\333\320\322\330\320\342\343\340\320" },
+ { 114, "\302\320\321\333\330\346\320 \332\333\320\322\330\350:" },
+ { 115, "\272\333\320\322\330\350\330" },
+ { 116, "\317\327\353\332 \323\340\320\344\330\347\325\341\332\336\323\336 \330\335\342\325\340\344\325\331\341\320 ScummVM" },
+ { 117, "\317\327\353\332 \330\323\340\353. \270\327\334\325\335\325\335\330\325 \355\342\336\323\336 \337\320\340\320\334\325\342\340\320 \335\325 \337\340\325\322\340\320\342\330\342 \330\323\340\343 \335\320 \320\335\323\333\330\331\341\332\336\334 \322 \340\343\341\341\332\343\356" },
+ { 118, "\317\327\353\332:" },
+ { 119, "\262\333\325\322\336" },
+ { 120, "\273\325\322\353\331 \351\325\333\347\336\332" },
+ { 121, "\267\320\323\340\343\327\330\342\354" },
+ { 122, "\267\320\323\340\343\327\330\342\354 \330\323\340\343:" },
+ { 123, "\267\320\323\340\343\327\330\342\354 \341\336\345\340\335\325\335\330\325 \324\333\357 \322\353\321\340\320\335\335\336\331 \330\323\340\353" },
+ { 124, "\315\334\343\333\357\342\336\340 MAME OPL" },
+ { 125, "MIDI" },
+ { 126, "\303\341\330\333\325\335\330\325 MIDI:" },
+ { 127, "MT-32" },
+ { 128, "\303\341\342\340. MT-32:" },
+ { 129, "\315\334\343\333\357\342\336\340 MT-32" },
+ { 130, "\274\320\341\350\342\320\321 \323\333\320\322\335\336\323\336 \355\332\340\320\335\320:" },
+ { 131, "\275\320\327\335\320\347\330\342\354" },
+ { 132, "\274\335\336\323\336 \330\323\340..." },
+ { 133, "\274\325\335\356" },
+ { 134, "\300\320\327\335\336\325" },
+ { 135, "\301\334\325\350\320\335\335\353\331 \340\325\326\330\334 AdLib/MIDI" },
+ { 136, "\277\336\324\332\333\356\347\330\342\354 DVD" },
+ { 137, "\277\336\324\332\333\356\347\330\342\354 SMB" },
+ { 138, "\272\333\330\332 \334\353\350\354\356" },
+ { 139, "\274\343\333\354\342\330\344\343\335\332\346\330\357" },
+ { 140, "\267\322\343\332\336\322\336\325 \343\341\342-\322\336:" },
+ { 141, "\263\340\336\334\332. \334\343\327\353\332\330:" },
+ { 142, "\262\353\332\333. \322\341\361" },
+ { 143, "\275\320\327\322:" },
+ { 144, "\301\325\342\354 \322\353\332\333\356\347\325\335\320" },
+ { 145, "\301\325\342\354 \335\325 \335\320\341\342\340\336\325\335\320 (%d)" },
+ { 146, "\301\325\342\354 \340\320\321\336\342\320\325\342" },
+ { 147, "\301\325\342\354 \340\320\321\336\342\320\325\342, \337\320\337\332\320 \337\336\324\332\333\356\347\325\335\320" },
+ { 148, "\275\330\332\336\323\324\320" },
+ { 149, "\275\325\342" },
+ { 150, "\264\320\342\320 \335\325 \327\320\337\330\341\320\335\320" },
+ { 151, "\261\325\327 \334\343\327\353\332\330" },
+ { 152, "\262\340\325\334\357 \330\323\340\353 \335\325 \327\320\337\330\341\320\335\336" },
+ { 153, "\262\340\325\334\357 \335\325 \327\320\337\330\341\320\335\336" },
+ { 154, "\275\325 \327\320\324\320\335" },
+ { 155, "\261\325\327 \343\322\325\333\330\347\325\335\330\357" },
+ { 156, "OK" },
+ { 157, "\307\320\341\342\336\342\320 \327\322\343\332\320:" },
+ { 158, "\277\325\340\325\332\340\353\342\354 \323\333\336\321\320\333\354\335\353\325 \343\341\342\320\335\336\322\332\330 MIDI" },
+ { 159, "\277\325\340\325\332\340\353\342\354 \323\333\336\321\320\333\354\335\353\325 \343\341\342\320\335\336\322\332\330 MT-32" },
+ { 160, "\277\325\340\325\332\340\353\342\354 \323\333\336\321\320\333\354\335\353\325 \343\341\342\320\335\336\322\332\330 \320\343\324\330\336" },
+ { 161, "\277\325\340\325\332\340\353\342\354 \323\333\336\321\320\333\354\335\353\325 \343\341\342\320\335\336\322\332\330 \323\340\320\344\330\332\330" },
+ { 162, "\277\325\340\325\332\340\353\342\354 \323\333\336\321\320\333\354\335\353\325 \343\341\342\320\335\336\322\332\330 \323\340\336\334\332\336\341\342\330" },
+ { 163, "\315\334\343\333\357\342\336\340 PC \341\337\330\332\325\340\320" },
+ { 164, "\277\320\340\336\333\354:" },
+ { 165, "\277\343\342\354 \335\325 \357\322\333\357\325\342\341\357 \324\330\340\325\332\342\336\340\330\325\331" },
+ { 166, "\277\343\342\354 \335\325 \357\322\333\357\325\342\341\357 \344\320\331\333\336\334" },
+ { 167, "\277\343\342\354 \335\325 \335\320\331\324\325\335" },
+ { 168, "\277\343\342\330" },
+ { 169, "\277\320\343\327\320" },
+ { 170, "\262\353\321\325\340\330\342\325 \330\323\340\343:" },
+ { 171, "\277\333\320\342\344\336\340\334\320, \324\333\357 \332\336\342\336\340\336\331 \330\323\340\320 \321\353\333\320 \330\327\335\320\347\320\333\354\335\336 \340\320\327\340\320\321\336\342\320\335\320" },
+ { 172, "\277\333\320\342\344\336\340\334\320:" },
+ { 173, "\262\340\325\334\357 \330\323\340\353: " },
+ { 174, "\277\336\326\320\333\343\331\341\342\320, \322\353\321\325\340\330\342\325 \324\325\331\341\342\322\330\325" },
+ { 175, "\277\343\342\354 \332 \337\333\320\323\330\335\320\334:" },
+ { 176, "\267\322\343\332\336\322\336\325 \343\341\342-\322\336:" },
+ { 177, "\275\320\326\334\330\342\325 \332\333\320\322\330\350\343 \324\333\357 \335\320\327\335\320\347\325\335\330\357" },
+ { 178, "\262\353\345\336\324" },
+ { 179, "\262\353\345\336\324 \330\327 ScummVM" },
+ { 180, "\275\325\324\336\341\342\320\342\336\347\335\336 \337\340\320\322 \324\333\357 \347\342\325\335\330\357" },
+ { 181, "\276\350\330\321\332\320 \347\342\325\335\330\357" },
+ { 182, "\277\325\340\325\335\320\327\335\320\347\330\342\354 \332\333\320\322\330\350\330" },
+ { 183, "\303\324\320\333\330\342\354 \330\323\340\343 \330\327 \341\337\330\341\332\320. \275\325 \343\324\320\333\357\325\342 \330\323\340\343 \341 \326\325\341\342\332\336\323\336 \324\330\341\332\320" },
+ { 184, "\300\325\326\330\334 \340\320\341\342\340\320:" },
+ { 185, "\262\337\340\320\322\336" },
+ { 186, "\277\340\320\322\353\331 \351\325\333\347\336\332" },
+ { 187, "\277\340\320\322\353\331 \351\325\333\347\336\332" },
+ { 188, "\277\336\322\325\340\335\343\342\354" },
+ { 189, "\263\340\336\334\332. SFX:" },
+ { 190, "SMB" },
+ { 191, "\267\320\337\330\341\320\342\354" },
+ { 192, "\277\343\342\354 \341\336\345\340: " },
+ { 193, "\301\336\345\340\320\335\325\335\330\357 \330\323\340:" },
+ { 194, "\301\336\345\340\320\335\330\342\354 \330\323\340\343: " },
+ { 195, "\277\336\330\341\332 \327\320\332\336\335\347\325\335!" },
+ { 196, "\277\340\336\341\334\336\342\340\325\335\336 %d \324\330\340\325\332\342\336\340\330\331 ..." },
+ { 197, "\263\333\320\322\335\336\325 \334\325\335\356 ScummVM" },
+ { 198, "ScummVM \335\325 \341\334\336\323 \335\320\331\342\330 \324\322\330\326\336\332 \324\333\357 \327\320\337\343\341\332\320 \322\353\321\340\320\335\335\336\331 \330\323\340\353!" },
+ { 199, "ScummVM \335\325 \334\336\326\325\342 \335\320\331\342\330 \330\323\340\343 \322 \343\332\320\327\320\335\335\336\331 \324\330\340\325\332\342\336\340\330\330!" },
+ { 200, "ScummVM \335\325 \334\336\326\325\342 \336\342\332\340\353\342\354 \343\332\320\327\320\335\335\343\356 \324\330\340\325\332\342\336\340\330\356!" },
+ { 201, "\277\336\330\341\332 \322 \341\337\330\341\332\325 \330\323\340" },
+ { 202, "\277\336\330\341\332:" },
+ { 203, "\262\353\321\325\340\330\342\325 SoundFont" },
+ { 204, "\262\353\321\325\340\330\342\325 \342\325\334\343" },
+ { 205, "\262\353\321\325\340\330\342\325 \324\336\337\336\333\335\330\342\325\333\354\335\343\356 \324\330\340\325\332\342\336\340\330\356 \330\323\340\353" },
+ { 206, "\262\353\321\325\340\330\342\325 \324\325\331\341\342\322\330\325 \330 \332\333\330\332\335\330\342\325 '\275\320\327\335\320\347\330\342\354'" },
+ { 207, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \324\333\357 \342\325\334 GUI" },
+ { 208, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \341 \324\336\337\336\333\335\330\342\325\333\354\335\353\334\330 \344\320\331\333\320\334\330" },
+ { 209, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \341 \337\333\320\323\330\335\320\334\330" },
+ { 210, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \324\333\357 \341\336\345\340\320\335\325\335\330\331" },
+ { 211, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \324\333\357 \341\336\345\340\320\335\325\335\330\331" },
+ { 212, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \341 \344\320\331\333\320\334\330 \330\323\340\353" },
+ { 213, "\307\343\322\341\342\322\330\342\325\333\354\335\336\341\342\354" },
+ { 214, "\301\325\340\322\325\340:" },
+ { 215, "\301\325\342\325\322\320\357 \337\320\337\332\320:" },
+ { 216, "\272\336\340\336\342\332\330\331 \330\324\325\335\342\330\344\330\332\320\342\336\340, \330\341\337\336\333\354\327\343\325\334\353\331 \324\333\357 \330\334\325\335 \341\336\345\340\320\335\325\335\330\331 \330\323\340 \330 \324\333\357 \327\320\337\343\341\332\320 \330\327 \332\336\334\320\335\324\335\336\331 \341\342\340\336\332\330" },
+ { 217, "\277\336\332\320\327\320\342\354 \332\333\320\322\330\320\342\343\340\343" },
+ { 218, "\277\336\332\320\327\353\322\320\342\354 \332\343\340\341\336\340 \334\353\350\330" },
+ { 219, "\277\336\332\320\327\353\322\320\342\354 \341\343\321\342\330\342\340\353 \330 \322\336\341\337\340\336\330\327\322\336\324\330\342\354 \340\325\347\354" },
+ { 220, "\277\336\332\320\327\320\342\354/\303\321\340\320\342\354 \332\343\340\341\336\340" },
+ { 221, "\277\340\336\337\343\341\342\330\342\354" },
+ { 222, "\277\340\336\337\343\341\342\330\342\354 \341\342\340\336\332\343" },
+ { 223, "\277\340\336\337\343\341\342\330\342\354 \342\325\332\341\342" },
+ { 224, "\277\340\330\332\340\325\337\330\342\354 \332 \323\340\320\335\330\346\320\334" },
+ { 225, "\277\340\336\323\340\320\334\334\335\336\325 \334\320\341\350\342\320\321\330\340\336\322\320\335\330\325 (\345\336\340\336\350\325\325 \332\320\347\325\341\342\322\336, \335\336 \334\325\324\333\325\335\335\325\325)" },
+ { 226, "\267\322\343\332 \322\332\333/\322\353\332\333" },
+ { 227, "SoundFont\353 \337\336\324\324\325\340\324\326\330\322\320\356\342\341\357 \335\325\332\336\342\336\340\353\334\330 \327\322\343\332\336\322\353\334\330 \332\320\340\342\320\334\330, Fluidsynth \330 Timidity" },
+ { 228, "SoundFont:" },
+ { 229, "\276\327\322" },
+ { 230, "\301\337\325\346\330\320\333\354\335\353\325 \340\325\326\330\334\353 \340\325\335\324\325\340\330\335\323\320, \337\336\324\324\325\340\326\330\322\320\325\334\353\325 \335\325\332\336\342\336\340\353\334\330 \330\323\340\320\334\330" },
+ { 231, "\263\340\336\334\332\336\341\342\354 \341\337\325\346\330\320\333\354\335\353\345 \327\322\343\332\336\322\353\345 \355\344\344\325\332\342\336\322" },
+ { 232, "\303\332\320\327\353\322\320\325\342 \322\353\345\336\324\335\336\325 \327\322\343\332\336\322\336\325 \343\341\342\340\336\331\341\342\322\336 \324\333\357 MIDI" },
+ { 233, "\303\332\320\327\353\322\320\325\342 \327\322\343\332\336\322\336\325 \343\341\342\340\336\331\341\342\322\336 \337\336 \343\334\336\333\347\320\335\330\357 \324\333\357 \322\353\322\336\324\320 \335\320 Roland MT-32/LAPC1/CM32l/CM64" },
+ { 234, "\303\332\320\327\353\322\320\325\342 \322\353\345\336\324\335\336\325 \327\322\343\332\336\322\336\325 \343\341\342\340\336\331\341\342\322\336 \330\333\330 \355\334\343\333\357\342\336\340 \327\322\343\332\336\322\336\331 \332\320\340\342\353" },
+ { 235, "\303\332\320\327\353\322\320\325\342 \337\343\342\354 \332 \324\336\337\336\333\335\330\342\325\333\354\335\353\334 \344\320\331\333\320\334 \324\320\335\335\353\345, \330\341\337\336\333\354\327\343\325\334\353\345 \322\341\325\334\330 \330\323\340\320\334\330, \333\330\321\336 ScummVM" },
+ { 236, "\303\332\320\327\353\322\320\325\342 \337\343\342\354 \332 \324\336\337\336\333\335\330\342\325\333\354\335\353\334 \344\320\331\333\320\334 \324\320\335\335\353\345 \324\333\357 \330\323\340\353" },
+ { 237, "\303\332\320\327\353\322\320\325\342 \322\353\345\336\324\335\336\325 \327\322\343\332\336\322\336\325 \343\341\342\340\336\331\341\342\322\336 \330\333\330 \355\334\343\333\357\342\336\340 \327\322\343\332\336\322\336\331 \332\320\340\342\353" },
+ { 238, "\303\332\320\327\353\322\320\325\342 \337\343\342\354 \332 \341\336\345\340\320\335\325\335\330\357\334 \330\323\340\353" },
+ { 239, "\276\327\322\343\347\332\320" },
+ { 240, "\263\340\336\334\332. \336\327\322\343\347\332\330:" },
+ { 241, "\301\342\320\335\324\320\340\342\335\353\331 \340\320\341\342\325\340\330\327\320\342\336\340 (16bpp)" },
+ { 242, "\267\320\337\343\341\342\330\342\354 \322\353\321\340\320\335\335\343\356 \330\323\340\343" },
+ { 243, "\301\336\341\342\336\357\335\330\325:" },
+ { 244, "\301\343\321" },
+ { 245, "\301\332\336\340\336\341\342\354 \342\330\342\340\336\322:" },
+ { 246, "\301\343\321\342\330\342\340\353" },
+ { 247, "\301\334\325\335\330\342\354 \323\325\340\336\357" },
+ { 248, "\302\320\337 \324\333\357 \333\325\322\336\323\336 \351\325\333\347\332\320, \324\322\336\331\335\336\331 \342\320\337 \324\333\357 \337\340\320\322\336\323\336 \351\325\333\347\332\320" },
+ { 249, "\302\325\332\341\342 \330 \336\327\322\343\347\332\320:" },
+ { 250, "\275\325 \334\336\323\343 \337\330\341\320\342\354 \322 \322\353\321\340\320\335\335\343\356 \324\330\340\325\332\342\336\340\330\356. \277\336\326\320\333\343\331\341\342\320, \343\332\320\326\330\342\325 \324\340\343\323\343\356." },
+ { 251, "\263\324\325 \342\325\334\353:" },
+ { 252, "\302\325\334\320:" },
+ { 253, "\315\342\336\342 ID \330\323\340\353 \343\326\325 \330\341\337\336\333\354\327\343\325\342\341\357. \277\336\326\320\333\343\331\341\342\320, \322\353\321\325\340\330\342\325 \324\340\343\323\336\331." },
+ { 254, "\315\342\320 \330\323\340\320 \335\325 \337\336\324\324\325\340\326\330\322\320\325\342 \327\320\323\340\343\327\332\343 \341\336\345\340\320\335\325\335\330\331 \347\325\340\325\327 \323\333\320\322\335\336\325 \334\325\335\356." },
+ { 255, "\262\340\325\334\357: " },
+ { 256, "\262\340\325\334\357 \337\336\324\332\333\356\347\325\335\330\357 \332 \341\325\342\330 \330\341\342\325\332\333\336" },
+ { 257, "\301\334\325\351\325\335\330\325 \332\320\341\320\335\330\331 \337\336 \336\341\330 X" },
+ { 258, "\301\334\325\351\325\335\330\325 \332\320\341\320\335\330\331 \337\336 \336\341\330 Y" },
+ { 259, "\300\325\326\330\334 \342\320\347\337\320\324\320 \322\353\332\333\356\347\325\335." },
+ { 260, "\300\325\326\330\334 \342\320\347\337\320\324\320 \322\332\333\356\347\325\335." },
+ { 261, "\275\320\341\342\336\357\351\330\331 Roland MT-32 (\327\320\337\340\325\342\330\342\354 \355\334\343\333\357\346\330\356 GM)" },
+ { 262, "\262\353\332\333\356\347\320\325\342 \334\320\337\337\330\335\323 General MIDI \324\333\357 \330\323\340 \341 \327\322\343\332\336\322\336\331 \324\336\340\336\326\332\336\331 \324\333\357 Roland MT-32" },
+ { 263, "\275\325\330\327\322\325\341\342\335\336" },
+ { 264, "\275\325\330\327\322\325\341\342\335\320\357 \336\350\330\321\332\320" },
+ { 265, "\276\342\332\333\356\347\330\342\354 DVD" },
+ { 266, "\276\342\332\333\356\347\342\354 SMB" },
+ { 267, "\261\325\327 \334\320\341\350\342\320\321\330\340\336\322\320\335\330\357 (\335\343\326\335\336 \321\343\324\325\342 \337\340\336\332\340\343\347\330\322\320\342\354 \322\333\325\322\336 \330 \322\337\340\320\322\336)" },
+ { 268, "\275\325\337\336\324\324\325\340\326\330\322\320\325\334\353\331 \340\325\326\330\334 \346\322\325\342\320" },
+ { 269, "\301\336\345\340\320\335\325\335\330\325 \321\325\327 \330\334\325\335\330" },
+ { 270, "\262\322\325\340\345" },
+ { 271, "\270\341\337\336\333\354\327\336\322\320\342\354 \330 MIDI \330 AdLib \324\333\357 \323\325\335\325\340\320\346\330\330 \327\322\343\332\320" },
+ { 272, "\270\341\337\336\333\354\327\336\322\320\342\354 \343\337\340\320\322\333\325\335\330\325 \332\343\340\341\336\340\336\334 \332\320\332 \335\320 \342\340\325\332\337\320\324\325 \333\325\337\342\336\337\336\322" },
+ { 273, "\277\336\333\354\327\336\322\320\342\325\333\354:" },
+ { 274, "\270\341\337\336\333\354\327\343\356 \324\340\320\331\322\325\340 SDL " },
+ { 275, "\262\325\340\342\330\332\320\333\354\335\353\331 underscan:" },
+ { 276, "\262\330\324\325\336" },
+ { 277, "\262\330\340\342\343\320\333\354\335\320\357 \332\333\320\322\330\320\342\343\340\320" },
+ { 278, "\263\340\336\334\332\336\341\342\354" },
+ { 279, "Windows MIDI" },
+ { 280, "\275\325\324\336\341\342\320\342\336\347\335\336 \337\340\320\322 \324\333\357 \327\320\337\330\341\330" },
+ { 281, "\276\350\330\321\332\320 \327\320\337\330\341\330 \324\320\335\335\353\345" },
+ { 282, "\264\320" },
+ { 283, "\262\353 \324\336\333\326\335\353 \337\325\340\325\327\320\337\343\341\342\330\342\354 ScummVM \347\342\336\321\353 \337\340\330\334\325\335\330\342\354 \330\327\334\325\335\325\335\330\357." },
+ { 284, "\267\336\335\320" },
+ { 285, "\303\334\325\335\354\350. \334\320\341\350\342\320\321" },
+ { 286, "\303\322\325\333. \334\320\341\350\342\320\321" },
+ { 287, "\332\320\326\324\353\325 10 \334\330\335\343\342" },
+ { 288, "\332\320\326\324\353\325 15 \334\330\335\343\342" },
+ { 289, "\332\320\326\324\353\325 30 \334\330\335\343\342" },
+ { 290, "\332\320\326\324\353\325 5 \334\330\335\343\342" },
+ { 291, "\276 \337\340\336~\323~\340\320\334\334\325" },
+ { 292, "~\264~\336\321. \330\323\340\343..." },
+ { 293, "\276~\342~\334\325\335\320" },
+ { 294, "~\267~\320\332\340\353\342\354" },
+ { 295, "\276~\337~\346\330\330 \330\323\340\353..." },
+ { 296, "~\277~\336\334\336\351\354" },
+ { 297, "\303\337\340\320\322\333\325\335\330\325 \321\336\357\334\330 \322 Indy" },
+ { 298, "~\272~\333\320\322\330\350\330" },
+ { 299, "\273\325\322\336\340\343\332\330\331 \340\325\326\330\334" },
+ { 300, "~\267~\320\323\340\343\327\330\342\354" },
+ { 301, "~\267~\320\323\340\343\327\330\342\354..." },
+ { 302, "~\301~\333\325\324" },
+ { 303, "~O~K" },
+ { 304, "~\276~\337\346\330\330" },
+ { 305, "~\276~\337\346\330\330..." },
+ { 306, "~\277~\340\325\324" },
+ { 307, "~\262~\353\345\336\324" },
+ { 308, "~\303~\324\320\333\330\342\354 \330\323\340\343" },
+ { 309, "\277\340\336\324\336\333~\326~\330\342\354" },
+ { 310, "~\262~\353\331\342\330 \322 \323\333\320\322\335\336\325 \334\325\335\356" },
+ { 311, "~\267~\320\337\330\341\320\342\354" },
+ { 312, "\277~\343~\341\332" },
+ { 313, "\277\325\340\325\345\336\324\353 \320\332\342\330\322\330\340\336\322\320\335\353" },
+ { 314, "\315\344\344\325\332\342\353 \322\336\324\353 \322\332\333\356\347\325\335\353" },
+ { 315, "\300\325\326\330\334 \321\353\341\342\340\336\323\336 \337\325\340\325\345\336\324\320 \320\332\342\330\322\330\340\336\322\320\335" },
+ { -1, NULL }
+};
+
+static const PoMessageEntry _translation_it_IT[] = {
+ { 0, "Project-Id-Version: ScummVM 1.2.0svn\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-30 22:14+0100\nPO-Revision-Date: 2010-06-30 23:56+0100\nLast-Translator: Maff <matteo.maff at gmail dot com>\nLanguage-Team: Italian\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\nLanguage: Italiano\n" },
+ { 1, " Sei sicuro di voler uscire? " },
+ { 2, " (Attivo)" },
+ { 3, " (Gioco)" },
+ { 4, " (Globale)" },
+ { 5, "(build creata il %s)" },
+ { 6, ", errore nel montare la condivisione" },
+ { 7, ", condivisione non montata" },
+ { 8, "... progresso ..." },
+ { 9, "11kHz" },
+ { 10, "22 kHz" },
+ { 11, "44 kHz" },
+ { 12, "48 kHz" },
+ { 13, "8 kHz" },
+ { 14, "<predefinito>" },
+ { 15, "Informazioni su ScummVM" },
+ { 16, "Emulatore AdLib" },
+ { 17, "Emulatore AdLib:" },
+ { 18, "AdLib \350 utilizzato per la musica in molti giochi" },
+ { 19, "Aggiungi gioco..." },
+ { 20, "Renderer con antialiasing (16bpp)" },
+ { 21, "Correzione proporzioni" },
+ { 22, "Tasto associato: %s" },
+ { 23, "Tasto associato: nessuno" },
+ { 24, "Audio" },
+ { 25, "Autosalva:" },
+ { 26, "Motori disponibili:" },
+ { 27, "~I~nfo..." },
+ { 28, "Associa tasti" },
+ { 29, "Entrambi" },
+ { 30, "Luminosit\340:" },
+ { 31, "Annulla" },
+ { 32, "Impossibile creare il file" },
+ { 33, "Modifica le opzioni di gioco" },
+ { 34, "Modifica le opzioni globali di ScummVM" },
+ { 35, "Seleziona se vuoi usare il dispositivo hardware audio compatibile con Roland che \350 connesso al tuo computer" },
+ { 36, "Scegli" },
+ { 37, "Scegli un'azione da mappare" },
+ { 38, "Cancella" },
+ { 39, "Chiudi" },
+ { 40, "Corregge le proporzioni dei giochi 320x200" },
+ { 41, "Impossibile trovare un motore in grado di eseguire il gioco selezionato" },
+ { 42, "Modalit\340 video attuale:" },
+ { 43, "Cursore gi\371" },
+ { 44, "Cursore a sinistra" },
+ { 45, "Cursore a destra" },
+ { 46, "Cursore su" },
+ { 47, "Emulatore OPL DOSBox" },
+ { 48, "DVD" },
+ { 49, "DVD montato con successo" },
+ { 50, "DVD non montato" },
+ { 51, "Data: " },
+ { 52, "Debugger" },
+ { 53, "Predefinito" },
+ { 54, "Elimina" },
+ { 55, "Disattiva spegnimento in chiusura" },
+ { 56, "Grafica disattivata" },
+ { 57, "Rilevati %d nuovi giochi..." },
+ { 58, "Rilevati %d nuovi giochi." },
+ { 59, "Visualizza " },
+ { 60, "Mostra tastiera" },
+ { 61, "Sei sicuro di voler eliminare questo salvataggio?" },
+ { 62, "Sei sicuro di voler rimuovere questa configurazione di gioco?" },
+ { 63, "Vuoi davvero eseguire il rilevatore di giochi in massa? Potrebbe aggiungere un numero enorme di giochi." },
+ { 64, "Vuoi caricare o salvare il gioco?" },
+ { 65, "Vuoi eseguire una scansione automatica?" },
+ { 66, "Sei sicuro di voler uscire?" },
+ { 67, "Double-strike" },
+ { 68, "Gi\371" },
+ { 69, "Attiva la modalit\340 Roland GS" },
+ { 70, "Il motore non supporta il livello di debug '%s'" },
+ { 71, "Inglese" },
+ { 72, "Errore nell'esecuzione del gioco:" },
+ { 73, "Errore nel montare il DVD" },
+ { 74, "Percorso extra:" },
+ { 75, "Emulatore FM Towns" },
+ { 76, "Modalit\340 veloce" },
+ { 77, "Funzionalit\340 compilate in:" },
+ { 78, "Osservazione libera" },
+ { 79, "Titolo completo del gioco" },
+ { 80, "Modalit\340 a schermo intero" },
+ { 81, "Accelerazione pad GC:" },
+ { 82, "Sensibilit\340 pad GC:" },
+ { 83, "Grafica" },
+ { 84, "Dispositivo GM:" },
+ { 85, "Lingua GUI:" },
+ { 86, "Renderer GUI:" },
+ { 87, "Gioco" },
+ { 88, "Dati di gioco non trovati" },
+ { 89, "ID di gioco non supportato" },
+ { 90, "Percorso gioco:" },
+ { 91, "Menu globale" },
+ { 92, "Vai alla cartella superiore" },
+ { 93, "Cartella superiore" },
+ { 94, "Grafica" },
+ { 95, "Modalit\340:" },
+ { 96, "Ridimensionamento hardware (veloce, ma di bassa qualit\340)" },
+ { 97, "Hercules ambra" },
+ { 98, "Hercules verde" },
+ { 99, "Nascondi la barra degli strumenti" },
+ { 100, "Audio ad alta qualit\340 (pi\371 lento) (riavviare)" },
+ { 101, "Valori pi\371 alti restituiscono un suono di maggior qualit\340, ma potrebbero non essere supportati dalla tua scheda audio" },
+ { 102, "Tieni premuto Shift per l'aggiunta in massa" },
+ { 103, "Underscan orizzontale:" },
+ { 104, "Emulatore IBM PCjr" },
+ { 105, "ID:" },
+ { 106, "Avvia rete" },
+ { 107, "Schermo in primo piano:" },
+ { 108, "Avvio in corso dell'emulatore MT-32" },
+ { 109, "Avvio rete in corso" },
+ { 110, "Input" },
+ { 111, "Percorso non valido" },
+ { 112, "Programmatore tasti" },
+ { 113, "Tastiera" },
+ { 114, "Mappa tasti:" },
+ { 115, "Tasti" },
+ { 116, "Lingua dell'interfaccia grafica di ScummVM" },
+ { 117, "Lingua del gioco. Un gioco inglese non potr\340 risultare tradotto in italiano" },
+ { 118, "Lingua:" },
+ { 119, "Sinistra" },
+ { 120, "Clic sinistro" },
+ { 121, "Carica" },
+ { 122, "Carica gioco:" },
+ { 123, "Carica un salvataggio del gioco selezionato" },
+ { 124, "Emulatore OPL MAME" },
+ { 125, "MIDI" },
+ { 126, "Guadagno MIDI:" },
+ { 128, "Disposit. MT32:" },
+ { 129, "Emulatore MT-32" },
+ { 130, "Schermo principale:" },
+ { 131, "Mappa" },
+ { 132, "Agg. in massa..." },
+ { 133, "Menu" },
+ { 134, "Varie" },
+ { 135, "Modalit\340 mista AdLib/MIDI" },
+ { 136, "Monta DVD" },
+ { 137, "Monta SMB" },
+ { 138, "Clic del mouse" },
+ { 139, "Multifunzione" },
+ { 140, "Dispositivo GM:" },
+ { 141, "Volume musica:" },
+ { 142, "Disattiva audio" },
+ { 143, "Nome:" },
+ { 144, "Rete disattivata" },
+ { 145, "Rete non avviata (%d)" },
+ { 146, "Rete attiva" },
+ { 147, "Rete attiva, condivisione montata" },
+ { 148, "Mai" },
+ { 149, "No" },
+ { 150, "Nessuna data salvata" },
+ { 151, "Nessuna musica" },
+ { 152, "Nessun tempo salvato" },
+ { 153, "Nessun orario salvato" },
+ { 154, "Nessuno" },
+ { 155, "Normale (nessun ridimensionamento)" },
+ { 156, "OK" },
+ { 157, "Frequenza:" },
+ { 158, "Ignora le impostazioni MIDI globali" },
+ { 159, "Ignora le impostazioni MIDI globali" },
+ { 160, "Ignora le impostazioni audio globali" },
+ { 161, "Ignora le impostazioni grafiche globali" },
+ { 162, "Ignora le impostazioni globali di volume" },
+ { 163, "Emulatore PC Speaker" },
+ { 164, "Password:" },
+ { 165, "Il percorso non \350 una cartella" },
+ { 166, "Il percorso non \350 un file" },
+ { 167, "Il percorso non esiste" },
+ { 168, "Percorsi" },
+ { 169, "Pausa" },
+ { 170, "Scegli il gioco:" },
+ { 171, "La piattaforma per la quale il gioco \350 stato concepito" },
+ { 172, "Piattaforma:" },
+ { 173, "Tempo di gioco: " },
+ { 174, "Seleziona un'azione" },
+ { 175, "Percorso plugin:" },
+ { 176, "Disp. preferito:" },
+ { 177, "Premi il tasto da associare" },
+ { 178, "Esci" },
+ { 179, "Chiudi ScummVM" },
+ { 180, "Autorizzazione di lettura negata" },
+ { 181, "Lettura fallita" },
+ { 182, "Riprogramma tasti" },
+ { 183, "Rimuove il gioco dalla lista. I file del gioco rimarranno intatti" },
+ { 184, "Resa grafica:" },
+ { 185, "Destra" },
+ { 186, "Clic destro" },
+ { 187, "Clic destro" },
+ { 188, "Rotazione" },
+ { 189, "Volume effetti:" },
+ { 190, "SMB" },
+ { 191, "Salva" },
+ { 192, "Salvataggi:" },
+ { 193, "Salvataggi:" },
+ { 194, "Salva gioco:" },
+ { 195, "Scansione completa!" },
+ { 196, "%d cartelle analizzate..." },
+ { 197, "Menu principale di ScummVM" },
+ { 198, "ScummVM non ha potuto trovare un motore in grado di eseguire il gioco selezionato!" },
+ { 199, "ScummVM non ha potuto trovare nessun gioco nella cartella specificata!" },
+ { 200, "ScummVM non ha potuto aprire la cartella specificata!" },
+ { 201, "Cerca nella lista dei giochi" },
+ { 202, "Cerca:" },
+ { 203, "Seleziona SoundFont" },
+ { 204, "Seleziona un tema" },
+ { 205, "Seleziona la cartella di gioco aggiuntiva" },
+ { 206, "Seleziona un'azione e clicca 'Mappa'" },
+ { 207, "Seleziona la cartella dei temi dell'interfaccia" },
+ { 208, "Seleziona la cartella dei file aggiuntivi" },
+ { 209, "Seleziona la cartella dei plugin" },
+ { 210, "Seleziona la cartella dei salvataggi" },
+ { 211, "Seleziona la cartella per i salvataggi" },
+ { 212, "Seleziona la cartella contenente i file di gioco" },
+ { 213, "Sensibilit\340" },
+ { 214, "Server:" },
+ { 215, "Condivisione:" },
+ { 216, "Breve identificatore di gioco utilizzato per il riferimento a salvataggi e per l'esecuzione del gioco dalla riga di comando" },
+ { 217, "Mostra tastiera" },
+ { 218, "Mostra cursore del mouse" },
+ { 219, "Mostra i sottotitoli e attiva le voci" },
+ { 220, "Mostra/nascondi cursore" },
+ { 221, "Salta" },
+ { 222, "Salta battuta" },
+ { 223, "Salta testo" },
+ { 224, "Aggancia ai bordi" },
+ { 225, "Ridimensionamento software (di buona qualit\340, ma pi\371 lento)" },
+ { 226, "Suono on/off" },
+ { 227, "SoundFont \350 supportato da alcune schede audio, Fluidsynth e Timidity" },
+ { 228, "SoundFont:" },
+ { 229, "Voci" },
+ { 230, "Modalit\340 di resa grafica speciali supportate da alcuni giochi" },
+ { 231, "Volume degli effetti sonori" },
+ { 232, "Specifica il dispositivo audio predefinito per l'output General MIDI" },
+ { 233, "Specifica il dispositivo audio predefinito per l'output Roland MT-32/LAPC1/CM32l/CM64" },
+ { 234, "Specifica il dispositivo di output audio o l'emulatore della scheda audio" },
+ { 235, "Specifica il percorso di ulteriori dati usati dai giochi o da ScummVM" },
+ { 236, "Specifica il percorso di ulteriori dati usati dal gioco" },
+ { 237, "Specifica il dispositivo audio o l'emulatore della scheda audio preferiti" },
+ { 238, "Specifica dove archiviare i salvataggi" },
+ { 239, "Voci" },
+ { 240, "Volume voci:" },
+ { 241, "Renderer standard (16bpp)" },
+ { 242, "Esegue il gioco selezionato" },
+ { 243, "Stato:" },
+ { 244, "Sub" },
+ { 245, "Velocit\340 testo:" },
+ { 246, "Sottotitoli" },
+ { 247, "Cambia personaggio" },
+ { 248, "Un tocco per il clic sinistro, doppio tocco per il clic destro" },
+ { 249, "Testo e voci:" },
+ { 250, "La cartella scelta \350 in sola lettura. Si prega di sceglierne un'altra." },
+ { 251, "Percorso tema:" },
+ { 252, "Tema:" },
+ { 253, "Questo ID di gioco \350 gi\340 in uso. Si prega di sceglierne un'altro." },
+ { 254, "Questo gioco non supporta il caricamento di salvataggi dalla schermata di avvio." },
+ { 255, "Ora: " },
+ { 256, "Attesa per l'avvio della rete" },
+ { 257, "Compensa X del tocco" },
+ { 258, "Compensa Y del tocco" },
+ { 259, "Modalit\340 touchpad disattivata." },
+ { 260, "Modalit\340 touchpad attivata." },
+ { 261, "Roland MT-32 effettivo (disattiva emulazione GM)" },
+ { 262, "Disattiva la mappatura General MIDI per i giochi con colonna sonora Roland MT-32" },
+ { 263, "Sconosciuto" },
+ { 264, "Errore sconosciuto" },
+ { 265, "Smonta DVD" },
+ { 266, "Smonta SMB" },
+ { 267, "Non ridimensionato (devi scorrere a sinistra e a destra)" },
+ { 268, "Modalit\340 colore non supportata" },
+ { 269, "Salvataggio senza titolo" },
+ { 270, "Su" },
+ { 271, "Utilizza generazione di suono sia MIDI che AdLib" },
+ { 272, "Utilizza il controllo del cursore stile trackpad del portatile" },
+ { 273, "Nome utente:" },
+ { 274, "Utilizzo del driver SDL " },
+ { 275, "Underscan verticale:" },
+ { 276, "Video" },
+ { 277, "Tastiera virtuale" },
+ { 278, "Volume" },
+ { 279, "MIDI Windows" },
+ { 280, "Autorizzazione di scrittura negata" },
+ { 281, "Scrittura dati fallita" },
+ { 282, "S\354" },
+ { 283, "Devi riavviare ScummVM affinch\351 le modifiche abbiano effetto." },
+ { 284, "Zona" },
+ { 285, "Zoom indietro" },
+ { 286, "Zoom avanti" },
+ { 287, "ogni 10 minuti" },
+ { 288, "ogni 15 minuti" },
+ { 289, "ogni 30 minuti" },
+ { 290, "ogni 5 minuti" },
+ { 291, "~I~nfo" },
+ { 292, "~A~ggiungi gioco..." },
+ { 293, "~A~nnulla" },
+ { 294, "~C~hiudi" },
+ { 295, "~M~odifica gioco..." },
+ { 296, "~A~iuto" },
+ { 297, "Controlli combattimento di ~I~ndy" },
+ { 298, "~T~asti" },
+ { 299, "~M~odalit\340 mancini" },
+ { 300, "~C~arica" },
+ { 301, "~C~arica..." },
+ { 302, "~S~uccessivi" },
+ { 303, "~O~K" },
+ { 304, "~O~pzioni" },
+ { 305, "~O~pzioni..." },
+ { 306, "~P~recedenti" },
+ { 307, "C~h~iudi" },
+ { 308, "~R~imuovi gioco" },
+ { 309, "~R~ipristina" },
+ { 310, "~V~ai a schermata di avvio" },
+ { 311, "~S~alva" },
+ { 312, "~G~ioca" },
+ { 313, "~T~ransizioni attive" },
+ { 314, "~E~ffetto acqua attivo" },
+ { 315, "Modalit\340 ~Z~ip attivata" },
+ { -1, NULL }
+};
+
+static const PoMessageEntry _translation_hu_HU[] = {
+ { 0, "Project-Id-Version: ScummVM VERSION\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-30 22:14+0100\nPO-Revision-Date: 2009-11-25 07:42-0500\nLast-Translator: Alex Bevilacqua <alexbevi@gmail.com>\nLanguage-Team: Hungarian\nMIME-Version: 1.0\nContent-Type: text/plain; charset=cp1250\nContent-Transfer-Encoding: 8bit\nLanguage: \nPlural-Forms: nplurals=2; plural=(n != 1);\n" },
+ { 14, "<alap\351rtelmezett>" },
+ { 16, "AdLib vezet :" },
+ { 17, "AdLib vezet :" },
+ { 21, "Aspect adag korrekci\363" },
+ { 24, "Hang" },
+ { 25, "Automatikus ment\351s:" },
+ { 28, "Kulcsok" },
+ { 42, "Renderel\351si m\363d:" },
+ { 53, "<alap\351rtelmezett>" },
+ { 69, "K\351pess\351 Roland GS Mode" },
+ { 74, "Extra \332tvonal:" },
+ { 76, "Grafikus m\363d:" },
+ { 80, "Teljes k\351perny s m\363d:" },
+ { 86, "Lek\351pez eszk\366z GUI:" },
+ { 90, "Extra \332tvonal:" },
+ { 94, "Grafik\341val" },
+ { 95, "Grafikus m\363d:" },
+ { 115, "Kulcsok" },
+ { 124, "AdLib vezet :" },
+ { 126, "MIDI nyeres\351g:" },
+ { 128, "Zene mennyis\351g:" },
+ { 135, "Vegyes AdLib/MIDI m\363d" },
+ { 140, "Zene mennyis\351g:" },
+ { 141, "Zene mennyis\351g:" },
+ { 142, "Muta \326sszes" },
+ { 148, "Soha" },
+ { 149, "Semmi" },
+ { 154, "Semmi" },
+ { 156, "Igen" },
+ { 157, "Kimeneti teljes\355tm\351ny:" },
+ { 168, "\326sv\351nyek" },
+ { 169, "\326sv\351nyek" },
+ { 184, "Renderel\351si m\363d:" },
+ { 189, "SFX mennyis\351ge" },
+ { 192, "Extra \332tvonal:" },
+ { 214, "Soha" },
+ { 239, "Csak a besz\351d" },
+ { 240, "Besz\351d mennyis\351g:" },
+ { 245, "Felirat sebess\351g:" },
+ { 246, "Csak feliratok" },
+ { 249, "Sz\366veg \351s besz\351d:" },
+ { 252, "T\351ma:" },
+ { 255, "T\351ma:" },
+ { 261, "Igaz Roland MT-32 (megb\351n\355t GM emul\341ci\363)" },
+ { 274, "Zenei vezet :" },
+ { 278, "Volumene" },
+ { 284, "Semmi" },
+ { 287, "10 percenk\351nt" },
+ { 288, "15 percenk\351nt" },
+ { 289, "30 percenk\351nt" },
+ { 290, "5 percenk\351nt" },
+ { 298, "Kulcsok" },
+ { 299, "Renderel\351si m\363d:" },
+ { 303, "Igen" },
+ { -1, NULL }
+};
+
+static const PoMessageEntry _translation_fr_FR[] = {
+ { 0, "Project-Id-Version: ScummVM 1.2.0svn\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-30 22:14+0100\nPO-Revision-Date: 2010-07-30 22:18+0100\nLast-Translator: Thierry Crozat <criezy@scummvm.org>\nLanguage-Team: French <scummvm-devel@lists.sf.net>\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\nLanguage: Francais\nPlural-Forms: nplurals=2; plural=n>1;\n" },
+ { 1, "Voulez-vous vraiment quitter?" },
+ { 2, "(Actif)" },
+ { 3, "(Jeu)" },
+ { 4, "(Global)" },
+ { 5, "(compil\351 sur %s)" },
+ { 6, ", \351chec du montage du disque partag\351" },
+ { 7, ", disque partag\351 non mont\351" },
+ { 8, "... en cours ..." },
+ { 9, "11 kHz" },
+ { 10, "22 kHz" },
+ { 11, "44 kHz" },
+ { 12, "48 kHz" },
+ { 13, "8 kHz" },
+ { 14, "<defaut>" },
+ { 15, "\300 propos de ScummVM" },
+ { 16, "\311mulateur AdLib" },
+ { 17, "\311mulateur AdLib:" },
+ { 18, "AdLib est utilis\351 pour la musique dans de nombreux jeux" },
+ { 19, "Ajouter..." },
+ { 20, "Anti-cr\351nel\351 (16 bpp)" },
+ { 21, "Correction du rapport d'aspect" },
+ { 22, "Touche associ\351e: %s" },
+ { 23, "Touche associ\351e: aucune" },
+ { 24, "Audio" },
+ { 25, "Sauvegarde auto:" },
+ { 26, "Moteurs disponibles:" },
+ { 27, "\300 ~P~ropos..." },
+ { 28, "Affecter les touches" },
+ { 29, "Les deux" },
+ { 30, "Luminosit\351:" },
+ { 31, "Annuler" },
+ { 32, "Impossible de cr\351er le fichier" },
+ { 33, "Change les options du jeu" },
+ { 34, "Change les options globales de ScummVM" },
+ { 35, "V\351rifie si vous voulez utiliser un p\351riph\351rique audio compatible Roland connect\351 \340 l'ordinateur" },
+ { 36, "Choisir" },
+ { 37, "S\351lectionnez une action \340 affecter" },
+ { 38, "Effacer la valeur" },
+ { 39, "Fermer" },
+ { 40, "Corrige le rapport d'aspect pour les jeu 320x200" },
+ { 41, "Impossible de trouver un moteur pour ex\351cuter le jeu s\351lectionn\351" },
+ { 42, "Mode vid\351o actuel" },
+ { 43, "Bas" },
+ { 44, "Gauche" },
+ { 45, "Droit" },
+ { 46, "Haut" },
+ { 47, "\311mulateur DOSBox OPL" },
+ { 48, "DVD" },
+ { 49, "DVD mont\351 avec succ\350s" },
+ { 50, "DVD non mont\351" },
+ { 51, "Date:" },
+ { 52, "Debugger" },
+ { 53, "D\351faut" },
+ { 54, "Supprimer" },
+ { 55, "D\351sactiv\351 l'extinction" },
+ { 56, "GFX d\351sactiv\351" },
+ { 57, "%d nouveaux jeux trouv\351s ..." },
+ { 58, "%d nouveaux jeux trouv\351s." },
+ { 59, "Affichage" },
+ { 60, "Afficher le clavier" },
+ { 61, "Voulez-vous vraiment supprimer cette sauvegarde?" },
+ { 62, "Voulez-vous vraiment supprimer ce jeu?" },
+ { 63, "Voulez-vous vraiment lancer la d\351tection automatique des jeux? Cela peut potentiellement ajouter un grand nombre de jeux." },
+ { 64, "Voulez-vous charger ou sauver le jeu?" },
+ { 65, "Voulez-vous ex\351cuter une recherche automatique?" },
+ { 66, "Voulez-vous quitter?" },
+ { 67, "Coup double" },
+ { 68, "Bas" },
+ { 69, "Activer le mode Roland GS" },
+ { 70, "Le niveau de debug '%s' n'est pas support\351 par ce moteur de jeu" },
+ { 71, "Anglais" },
+ { 72, "Erreur lors de l'\351x\351cution du jeu:" },
+ { 73, "\311chec du montage du DVD" },
+ { 74, "Extra:" },
+ { 75, "\311mulateur FM Towns" },
+ { 76, "Mode rapide" },
+ { 77, "Options incluses:" },
+ { 78, "Regarder autour" },
+ { 79, "Nom complet du jeu" },
+ { 80, "Plein \351cran" },
+ { 81, "Acceleration du pad GC:" },
+ { 82, "Sensibilit\351 du pad GC:" },
+ { 83, "GFX" },
+ { 84, "Sortie GM:" },
+ { 85, "Langue:" },
+ { 86, "Interface:" },
+ { 87, "Jeu" },
+ { 88, "Fichier de don\351es introuvable" },
+ { 89, "ID de jeu non support\351" },
+ { 90, "Chemin du Jeu:" },
+ { 91, "Menu global" },
+ { 92, "Remonte d'un niveau dans la hi\351rarchie de r\351pertoire" },
+ { 93, "Remonter" },
+ { 94, "Graphique" },
+ { 95, "Mode graphique:" },
+ { 96, "Mise \340 l'echelle mat\351rielle (rapide mais qualit\351 faible)" },
+ { 97, "Hercules Ambre" },
+ { 98, "Hercules Vert" },
+ { 99, "Cach\351 la barre d'outils" },
+ { 100, "Audio haute qualit\351 (plus lent) (red\351marrer)" },
+ { 101, "Une valeur plus \351lev\351e donne une meilleure qualit\351 audio mais peut ne pas \352tre support\351 par votre carte son" },
+ { 102, "Ajoute un jeu \340 la Liste. Maintenez Shift enfonc\351e pour un Ajout Massif" },
+ { 103, "Underscan horizontal:" },
+ { 104, "\311mulateur IBM PCjr" },
+ { 105, "ID:" },
+ { 106, "Initialiser le r\351seau" },
+ { 107, "\311chelle initiale de l'\351cran du haut" },
+ { 108, "Initialisation de l'\311mulateur MT-32" },
+ { 109, "Initialisation du r\351seau" },
+ { 110, "Entr\351e" },
+ { 111, "Chemin Invalide" },
+ { 112, "Affectation des touches" },
+ { 113, "Clavier" },
+ { 114, "Affectation des touches:" },
+ { 115, "Touches" },
+ { 116, "Langue de l'interface graphique de ScummVM" },
+ { 117, "Langue du jeu. Cela ne traduira pas en anglais par magie votre version espagnole du jeu." },
+ { 118, "Langue:" },
+ { 119, "Gauche" },
+ { 120, "Clic Gauche" },
+ { 121, "Charger" },
+ { 122, "Charger le jeu:" },
+ { 123, "Charge une sauvegarde pour le jeu s\351lectionn\351" },
+ { 124, "\311mulateur MAME OPL" },
+ { 125, "MIDI" },
+ { 126, "Gain MIDI:" },
+ { 127, "MT-32" },
+ { 128, "Sortie MT-32:" },
+ { 129, "\311mulateur MT-32" },
+ { 130, "\311chelle de l'\351cran principal" },
+ { 131, "Affecter" },
+ { 132, "Ajout Massif..." },
+ { 133, "Menu" },
+ { 134, "Divers" },
+ { 135, "Mode mixe AdLib/MIDI" },
+ { 136, "Monter le DVD" },
+ { 137, "Monter SMB" },
+ { 138, "Clic de souris" },
+ { 139, "Fonction Multiple" },
+ { 140, "Sortie Audio:" },
+ { 141, "Volume Musique:" },
+ { 142, "Silence" },
+ { 143, "Nom:" },
+ { 144, "R\351seau d\351connect\351" },
+ { 145, "R\351seau non initialis\351 (%d)" },
+ { 146, "R\351seau connect\351" },
+ { 147, "R\351seau connect\351, disque partag\351 mont\351" },
+ { 148, "Jamais" },
+ { 149, "Non" },
+ { 150, "Date non sauv\351e" },
+ { 151, "Pas de musique" },
+ { 152, "Dur\351e de jeu non sauv\351e" },
+ { 153, "Heure non sauv\351e" },
+ { 154, "Aucun" },
+ { 155, "Normal (\351chelle d'origine)" },
+ { 156, "OK" },
+ { 157, "Fr\351quence:" },
+ { 158, "Utiliser des r\351glages MIDI sp\351cifiques \340 ce jeux" },
+ { 159, "Utiliser des r\351glages MT-32 sp\351cifiques \340 ce jeux" },
+ { 160, "Utiliser des r\351glages audio sp\351cifiques \340 ce jeux" },
+ { 161, "Utiliser des r\351glages graphiques sp\351cifiques \340 ce jeux" },
+ { 162, "Utiliser des r\351glages de volume sonore sp\351cifiques \340 ce jeux" },
+ { 163, "\311mulateur Haut Parleur PC" },
+ { 164, "Mot de passe:" },
+ { 165, "Chemin n'est pas un r\351pertoire" },
+ { 166, "Chemin n'est pas un fichier" },
+ { 167, "Chemin inexistant" },
+ { 168, "Chemins" },
+ { 169, "Mettre en pause" },
+ { 170, "Choisissez le jeu:" },
+ { 171, "Plateforme pour laquelle votre jeu a \351t\351 con\347u" },
+ { 172, "Plateforme:" },
+ { 173, "Dur\351e de jeu:" },
+ { 174, "Selectionnez une action" },
+ { 175, "Plugins:" },
+ { 176, "Sortie Pr\351f\351r\351:" },
+ { 177, "Appuyez sur la touche \340 associer" },
+ { 178, "Quitter" },
+ { 179, "Quitter ScummVM" },
+ { 180, "V\351roulli\351 en lecture" },
+ { 181, "Echec de la lecture" },
+ { 182, "Changer l'affectation des touches" },
+ { 183, "Supprime le jeu de la liste. Les fichiers sont conserv\351s" },
+ { 184, "Mode de rendu:" },
+ { 185, "Droite" },
+ { 186, "Clic Droit" },
+ { 187, "Clic droit" },
+ { 188, "Pivoter" },
+ { 189, "Volume Bruitage:" },
+ { 190, "SMB" },
+ { 191, "Sauver" },
+ { 192, "Sauvegardes:" },
+ { 193, "Sauvegardes:" },
+ { 194, "Sauvegarde:" },
+ { 195, "Examen termin\351!" },
+ { 196, "%d r\351pertoires examin\351s ..." },
+ { 197, "Menu Principal ScummVM" },
+ { 198, "ScummVM n'a pas pu trouv\351 de moteur pour lancer le jeu s\351lectionn\351." },
+ { 199, "ScummVM n'a pas trouv\351 de jeux dans le r\351pertoire s\351lectionn\351." },
+ { 200, "ScummVM n'a pas pu ouvrir le r\351pertoire s\351lectionn\351." },
+ { 201, "Recherche dans la liste de jeux" },
+ { 202, "Filtre:" },
+ { 203, "Choisir une banque de sons" },
+ { 204, "S\351lectionnez un Th\350me" },
+ { 205, "S\351lectionner un r\351pertoire suppl\351mentaire" },
+ { 206, "Selectionez une action et cliquez 'Affecter'" },
+ { 207, "S\351lectionner le r\351pertoire des th\350mes d'interface" },
+ { 208, "S\351lectionner le r\351pertoire pour les fichiers supl\351mentaires" },
+ { 209, "S\351lectionner le r\351pertoire des plugins" },
+ { 210, "S\351lectionner le r\351pertoire pour les sauvegardes" },
+ { 211, "S\351lectionner le r\351pertoire pour les sauvegardes" },
+ { 212, "S\351lectionner le r\351pertoire contenant les donn\351es du jeu" },
+ { 213, "Sensibilit\351" },
+ { 214, "Serveur:" },
+ { 215, "Disque partag\351:" },
+ { 216, "ID compact du jeu utilis\351 pour identifier les sauvegardes et d\351marrer le jeu depuis la ligne de commande" },
+ { 217, "Afficher le clavier" },
+ { 218, "Afficher le curseur de la souris" },
+ { 219, "Affiche les sous-titres et joue les dialogues audio" },
+ { 220, "Afficher/Cacher le curseur" },
+ { 221, "Passer" },
+ { 222, "Passer la phrase" },
+ { 223, "Sauter le texte" },
+ { 224, "Aligner sur les bords" },
+ { 225, "Mise \340 l'\351chelle logicielle (bonne qualit\351 mais plus lent)" },
+ { 226, "Audio marche/arr\352t" },
+ { 227, "La banque de sons est utilis\351e par certaines cartes audio, Fluidsynth et Timidity" },
+ { 228, "Banque de sons:" },
+ { 229, "Audio" },
+ { 230, "Mode sp\351cial de tramage support\351 par certains jeux" },
+ { 231, "Volume des effets sp\351ciaux sonores" },
+ { 232, "Sp\351cifie le p\351riph\351rique audio par d\351faut pour la sortie General MIDI" },
+ { 233, "Sp\351cifie le p\351riph\351rique audio par d\351faut pour la sortie Roland MT-32/LAPC1/CM32l/CM64" },
+ { 234, "Sp\351cifie le p\351riph\351rique de sortie audio ou l'\351mulateur de carte audio" },
+ { 235, "Sp\351cifie un chemin vers des donn\351es suppl\351mentaires utilis\351es par tous les jeux ou ScummVM" },
+ { 236, "D\351finie un chemin vers des donn\351es supl\351mentaires utilis\351es par le jeu" },
+ { 237, "Sp\351cifie le p\351riph\351rique de sortie audio ou l'\351mulateur de carte audio pr\351f\351r\351" },
+ { 238, "D\351finie l'emplacement o\371 les fichiers de sauvegarde sont cr\351\351s" },
+ { 239, "Audio" },
+ { 240, "Volume Dialogues:" },
+ { 241, "Standard (16bpp)" },
+ { 242, "D\351marre le jeu s\351lectionn\351" },
+ { 243, "Status:" },
+ { 244, "Subs" },
+ { 245, "Vitesse des ST:" },
+ { 246, "Sous-titres" },
+ { 247, "Changement de personnage" },
+ { 248, "Toucher pour un clic gauche, toucher deux fois pour un clic droit" },
+ { 249, "Dialogue:" },
+ { 250, "Le r\351pertoire s\351lectionn\351 est v\351rouill\351 en \351criture. S\351lectionnez un autre r\351pertoire." },
+ { 251, "Th\350mes:" },
+ { 252, "Th\350me:" },
+ { 253, "Cet ID est d\351j\340 utilis\351 par un autre jeu. Choisissez en un autre svp." },
+ { 254, "Le chargement de sauvegarde depuis le lanceur n'est pas support\351 pour ce jeu." },
+ { 255, "Heure:" },
+ { 256, "D\351passement du d\351lai lors de l'initialisation du r\351seau" },
+ { 257, "D\351calage X du toucher" },
+ { 258, "D\351callage Y du toucher" },
+ { 259, "Mode touchpad d\351sactiv\351" },
+ { 260, "Mode touchpad activ\351" },
+ { 261, "Roland MT-32 exacte (d\351sactive l'\351mulation GM)" },
+ { 262, "D\351sactiver la conversion des pistes MT-32 en General MIDI" },
+ { 263, "Inconue" },
+ { 264, "Erreur inconnue" },
+ { 265, "D\351monter le DVD" },
+ { 266, "D\351monter SMB" },
+ { 267, "Sans changement d'\351chelle (vous devez faire d\351filer l'\351cran)" },
+ { 268, "Mode de couleurs non support\351" },
+ { 269, "Sauvegarde sans nom" },
+ { 270, "Haut" },
+ { 271, "Utiliser \340 la fois MIDI et AdLib" },
+ { 272, "Activer le contr\364le du curseur de type trackpad" },
+ { 273, "Nom d'utilisateur:" },
+ { 274, "Utilise le pilote SDL" },
+ { 275, "Underscan vertical:" },
+ { 276, "Vid\351o" },
+ { 277, "Clavier virtuel" },
+ { 278, "Volume" },
+ { 279, "MIDI Windows" },
+ { 280, "Verrouill\351 en \351criture" },
+ { 281, "Echec de l'\351criture des donn\351es" },
+ { 282, "Oui" },
+ { 283, "Vous devez relancer ScummVM pour que le changement soit pris en compte." },
+ { 284, "Zone" },
+ { 285, "Zoomer" },
+ { 286, "D\351zoomer" },
+ { 287, "Toutes les 10 mins" },
+ { 288, "Toutes les 15 mins" },
+ { 289, "Toutes les 30 mins" },
+ { 290, "Toutes les 5 mins" },
+ { 291, "\300 ~P~ropos" },
+ { 292, "~A~jouter..." },
+ { 293, "~A~nnuler" },
+ { 294, "~F~ermer" },
+ { 295, "~E~diter..." },
+ { 296, "~A~ide" },
+ { 297, "Contr\364le des combats d'~I~ndy" },
+ { 298, "~T~ouches" },
+ { 299, "Mode ~G~aucher" },
+ { 300, "~C~harger" },
+ { 301, "~C~harger" },
+ { 302, "~S~uivant" },
+ { 303, "~O~K" },
+ { 304, "~O~ptions" },
+ { 305, "~O~ptions..." },
+ { 306, "~P~r\351c\351dent" },
+ { 307, "~Q~uitter" },
+ { 308, "~S~upprimer" },
+ { 309, "~R~eprendre" },
+ { 310, "Retour au ~L~anceur" },
+ { 311, "~S~auver" },
+ { 312, "~D~\351marrer" },
+ { 313, "T~r~ansitions activ\351" },
+ { 314, "~E~ffets de l'Eau Activ\351s" },
+ { 315, "Mode ~Z~ip Activ\351" },
+ { -1, NULL }
+};
+
+static const PoMessageEntry _translation_uk_UA[] = {
+ { 0, "Project-Id-Version: ScummVM VERSION\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-30 22:14+0100\nPO-Revision-Date: 2010-07-30 22:19+0100\nLast-Translator: Lubomyr Lisen\nLanguage-Team: Ukrainian\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-5\nContent-Transfer-Encoding: 8bit\nLanguage: Ukrainian\nPlural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" },
+ { 1, " \262\330 \343\337\325\322\335\325\335\366, \351\336 \345\336\347\325\342\325 \322\330\331\342\330? " },
+ { 2, " (\260\332\342\330\322\335\320)" },
+ { 3, " (\246\323\340\330)" },
+ { 4, " (\263\333\336\321\320\333\354\335\320)" },
+ { 5, "(\327\366\321\340\320\335\330\331 %s)" },
+ { 6, ", \337\336\334\330\333\332\320 \337\366\324 \347\320\341 \337\366\324\332\333\356\347\325\335\335\357 \337\320\337\332\330" },
+ { 7, ", \337\320\337\332\320 \335\325 \337\366\324\332\333\356\347\325\335\320" },
+ { 8, "... \337\336\350\343\332 ..." },
+ { 9, "11 \332\263\346" },
+ { 10, "22 \332\263\346" },
+ { 11, "44 \332\263\346" },
+ { 12, "48 \332\263\346" },
+ { 13, "8 \332\263\346" },
+ { 14, "<\327\320 \343\334\336\322\347\320\335\335\357\334>" },
+ { 15, "\277\340\336 ScummVM" },
+ { 16, "\265\334\343\333\357\342\336\340 AdLib" },
+ { 17, "\265\334\343\333\357\342\336\340 AdLib:" },
+ { 18, "\267\322\343\332\336\322\320 \332\320\340\342\320 AdLib \322\330\332\336\340\330\341\342\336\322\343\364\342\354\341\357 \321\320\323\320\342\354\334\320 \366\323\340\320\334\330" },
+ { 19, "\264\336\324. \323\340\343..." },
+ { 20, "\300\320\341\342\325\340\330\327\320\342\336\340 \327\366 \327\323\333\320\324\326\343\322\320\335\335\357\334 (16bpp)" },
+ { 21, "\272\336\340\325\332\346\366\357 \341\337\366\322\322\366\324\335\336\350\325\335\335\357 \341\342\336\340\366\335" },
+ { 22, "\277\340\330\327\335\320\347\325\335\320 \332\333\320\322\366\350\320 : %s" },
+ { 23, "\277\340\330\327\335\320\347\325\335\320 \332\333\320\322\366\350\320 : \335\325\334\320\364" },
+ { 24, "\260\343\324\366\336" },
+ { 25, "\260\322\342\336\327\321\325\340\325\326\325\335\335\357:" },
+ { 26, "\264\336\341\342\343\337\335\366 \324\322\330\326\332\330:" },
+ { 27, "\277\340\336 \337~\340~\336\323\340\320\334\343..." },
+ { 28, "\337\340\330\327\335\320\347\330\342\330 \332\333\320\322\366\350\366" },
+ { 29, "\262\341\325" },
+ { 30, "\317\341\332\340\320\322\366\341\342\354:" },
+ { 31, "\262\366\324\334\366\335\320" },
+ { 32, "\275\325 \334\336\326\343 \341\342\322\336\340\330\342\330 \344\320\331\333" },
+ { 33, "\267\334\366\335\330\342\330 \336\337\346\366\367 \323\340\330" },
+ { 34, "\267\334\366\335\330\342\330 \323\333\336\321\320\333\354\335\366 \336\337\346\366\367 ScummVM" },
+ { 35, "\262\366\324\334\366\342\354\342\325, \357\332\351\336 \343 \322\320\341 \337\366\324\332\333\356\347\325\335\330\331 Roland-\341\343\334\366\341\335\330\331 \327\322\343\332\336\322\330\331 \337\340\330\341\342\340\366\331 \366 \322\330 \345\336\347\325\342\325 \331\336\323\336 \322\330\332\336\340\330\341\342\320\342\330" },
+ { 36, "\262\330\321\340\320\342\330" },
+ { 37, "\262\330\321\325\340\366\342\354 \324\366\356 \324\333\357 \337\340\330\327\335\320\347\325\335\335\357" },
+ { 38, "\276\347\330\341\342\330\342\330 \327\335\320\347\325\335\335\357" },
+ { 39, "\267\320\332\340\330\342\330" },
+ { 40, "\272\336\340\330\323\343\322\320\342\330 \341\337\366\322\322\366\324\335\336\350\325\335\335\357 \341\342\336\340\366\335 \324\333\357 \366\323\336\340 \327 \323\340\320\344\366\332\336\356 320x200" },
+ { 41, "\275\325 \334\336\326\343 \327\335\320\331\342\330 \324\322\330\326\336\332 \324\333\357 \327\320\337\343\341\332\343 \322\330\321\340\320\335\336\367 \323\340\330" },
+ { 42, "\302\325\332\343\347\330\331 \322\366\324\325\336\340\325\326\330\334:" },
+ { 43, "\272\343\340\341\336\340 \322\335\330\327" },
+ { 44, "\272\343\340\341\336\340 \322\333\366\322\336" },
+ { 45, "\272\343\340\341\336\340 \322\337\340\320\322\336" },
+ { 46, "\272\343\340\341\336\340 \322\322\325\340\345" },
+ { 47, "\265\334\343\333\357\342\336\340 DOSBox OPL" },
+ { 48, "DVD" },
+ { 49, "DVD \337\366\324\332\333\356\347\325\335\330\331 \343\341\337\366\350\335\336" },
+ { 50, "DVD \335\325 \337\366\324\332\333\356\347\325\335\330\331" },
+ { 51, "\264\320\342\320: " },
+ { 52, "\262\366\324\333\320\324\347\330\332" },
+ { 53, "\267\320 \343\334\336\322\347\320\335\335\357\334" },
+ { 54, "\262\330\324\320\333\330\342\330" },
+ { 55, "\267\320\321\336\340\336\335\330\342\330 \322\330\334\332\335\325\335\335\357" },
+ { 56, "\261\325\327 \323\340\320\344\366\332\330" },
+ { 57, "\267\335\320\331\324\325\335\336 %d \335\336\322\330\345 \366\323\336\340 ..." },
+ { 58, "\267\335\320\331\324\325\335\336 %d \335\336\322\330\345 \366\323\336\340." },
+ { 59, "\277\336\332\320\327\320\342\330 " },
+ { 60, "\277\336\332\320\327\320\342\330 \332\333\320\322\366\320\342\343\340\343" },
+ { 61, "\262\330 \324\366\331\341\335\336 \345\336\347\325\342\325 \322\330\324\320\333\330\342\330 \346\325 \327\321\325\340\325\326\325\335\335\357?" },
+ { 62, "\262\330 \324\366\331\341\335\336 \345\336\347\325\342\325 \322\330\324\320\333\330\342\330 \343\341\342\320\335\336\322\332\330 \324\333\357 \346\366\364\367 \323\340\330?" },
+ { 63, "\262\330 \324\366\331\341\335\336 \345\336\347\325\342\325 \327\320\337\343\341\342\330\342\330 \324\325\342\325\332\342\336\340 \343\341\366\345 \366\323\336\340? \306\325 \337\336\342\325\335\346\366\331\335\336 \334\336\326\325 \324\336\324\320\342\330 \322\325\333\330\332\343 \332\366\333\354\332\366\341\342\354 \366\323\336\340." },
+ { 64, "\262\330 \345\336\347\325\342\325 \327\320\322\320\335\342\320\326\330\342\330 \320\321\336 \327\321\325\340\325\323\342\330 \323\340\343?" },
+ { 65, "\262\330 \345\336\347\325\342\325 \327\324\366\331\341\335\330\342\330 \320\322\342\336\334\320\342\330\347\335\330\331 \337\336\350\343\332?" },
+ { 66, "\262\330 \345\336\347\330\342\325 \322\330\331\342\330?" },
+ { 67, "\277\336\324\322\366\331\335\330\331 \343\324\320\340" },
+ { 68, "\262\335\330\327" },
+ { 69, "\303\322\366\334\332\335\343\342\330 \340\325\326\330\334 Roland GS" },
+ { 70, "\264\322\330\326\336\332 \335\325 \337\366\324\342\340\330\334\343\364 \340\366\322\325\335\354 \322\366\324\333\320\324\332\330 '%s'" },
+ { 71, "English" },
+ { 72, "\277\336\334\330\333\332\320 \327\320\337\343\341\332\343 \323\340\330:" },
+ { 73, "\277\336\334\330\333\332\320 \337\366\324 \347\320\341 \337\366\324\332\333\356\347\325\335\335\357 DVD" },
+ { 74, "\264\336\324. \350\333\357\345:" },
+ { 75, "\265\334\343\333\357\342\336\340 FM Towns" },
+ { 76, "\310\322\330\324\332\330\331 \340\325\326\330\334" },
+ { 77, "\262\332\333\356\347\325\335\366 \322 \321\366\333\324 \336\337\346\366\367:" },
+ { 78, "\262\366\333\354\335\330\331 \336\323\333\357\324" },
+ { 79, "\277\336\322\335\320 \335\320\327\322\320 \323\340\330" },
+ { 80, "\277\336\322\335\336\325\332\340\320\335\335\330\331 \340\325\326\330\334" },
+ { 81, "\277\340\330\341\332\336\340\325\335\335\357 GC \337\320\324\343:" },
+ { 82, "\307\343\342\333\330\322\366\341\342\354 GC \337\320\324\343:" },
+ { 83, "\263\340\344" },
+ { 84, "\277\340\330\341\342\340\366\331 GM:" },
+ { 85, "\274\336\322\320 \366\335\342\325\340\344\325\331\341\343:" },
+ { 86, "\300\320\341\342\325\340\330\327\320\342\336\340 GUI:" },
+ { 87, "\263\340\320" },
+ { 88, "\275\325\334\320\364 \344\320\331\333\366\322 \323\340\330" },
+ { 89, "Game Id \335\325 \337\366\324\342\340\330\334\343\364\342\354\341\357" },
+ { 90, "\310\333\357\345 \324\336 \323\340\330: " },
+ { 91, "\263\333\336\321\320\333\354\335\325 \334\325\335\356" },
+ { 92, "\277\325\340\325\331\342\330 \335\320 \337\320\337\332\343 \340\366\322\335\325\334 \322\330\351\325" },
+ { 93, "\262\322\325\340\345" },
+ { 94, "\263\340\320\344\366\332\320" },
+ { 95, "\263\340\320\344\366\347\335\330\331 \340\325\326\330\334:" },
+ { 96, "\305\320\340\324\322\320\340\335\336\325 \334\320\341\350\342\320\321\343\322\320\335\335\357 (\350\322\330\324\332\336, \320\333\325 \335\330\327\354\332\336\367 \357\332\336\341\342\366)" },
+ { 97, "Hercules \317\335\342\320\340\335\330\331" },
+ { 98, "Hercules \267\325\333\325\335\330\331" },
+ { 99, "\267\320\345\336\322\320\342\330 \337\320\335\325\333\354 \366\335\341\342\340\343\334\325\335\342\366\322" },
+ { 100, "\262\330\341\336\332\320 \357\332\366\341\342\354 \327\322\343\332\343 (\337\336\322\366\333\354\335\366\350\325) (\340\325\321\343\342)" },
+ { 101, "\262\325\333\330\332\366 \327\335\320\347\325\335\335\357 \327\320\324\320\356\342\354 \332\340\320\351\343 \357\332\366\341\342\354 \327\322\343\332\343, \337\340\336\342\325 \322\336\335\330 \334\336\326\343\342\354 \335\325 \337\366\324\342\340\330\334\343\322\320\342\330\341\357 \322\320\350\336\356 \327\322\343\332\336\322\336\356 \332\320\340\342\336\356" },
+ { 102, "\303\342\340\330\334\343\331\342\325 \332\333\320\322\366\350\343 Shift \324\333\357 \342\336\323\336, \351\336\321 \324\336\324\320\342\330 \324\325\332\366\333\354\332\320 \366\323\336\340" },
+ { 103, "\263\336\340\330\327\336\335\342\320\333\354\335\330\331 underscan:" },
+ { 104, "\265\334\343\333\357\342\336\340 IBM PCjr" },
+ { 105, "ID:" },
+ { 106, "\246\335\366\346\366\320\333\366\327\320\346\366\357 \334\325\340\325\326\366" },
+ { 107, "\277\336\347\320\342\332\336\322\330\331 \334\320\341\350\342\320\321 \322\325\340\345\335\354\336\323\336 \325\332\340\320\335\343:" },
+ { 108, "\275\320\341\342\340\336\356\356 \325\334\343\333\357\342\336\340 MT-32" },
+ { 109, "\275\320\333\320\350\342\336\322\343\356 \334\325\340\325\326\343" },
+ { 110, "\262\322\366\324" },
+ { 111, "\275\325\337\340\320\322\330\333\354\335\330\331 \350\333\357\345" },
+ { 112, "\277\340\330\327\335\320\347\325\335\335\357 \332\333\320\322\366\350" },
+ { 113, "\272\333\320\322\366\320\342\343\340\320" },
+ { 114, "\302\320\321\333\330\346\357 \332\333\320\322\366\350:" },
+ { 115, "\272\333\320\322\366\350\366" },
+ { 116, "\274\336\322\320 \323\340\320\344\366\347\335\336\323\336 \366\335\342\325\340\344\325\331\341\343 ScummVM" },
+ { 117, "\274\336\322\320 \323\340\330. \267\334\366\335\320 \346\354\336\323\336 \337\320\340\320\334\325\342\340\343 \335\325 \337\325\340\325\342\322\336\340\330\342\354 \323\340\343 \335\320 \320\335\323\333\366\331\341\354\332\366\331 \322 \343\332\340\320\367\335\341\354\332\343" },
+ { 118, "\274\336\322\320:" },
+ { 119, "\262\333\366\322\336" },
+ { 120, "\273\366\322\330\331 \332\333\366\332" },
+ { 121, "\267\320\322\320\335\342\320\326\330\342\330" },
+ { 122, "\267\320\322\320\335\342\320\326\330\342\330 \323\340\343:" },
+ { 123, "\267\320\322\320\335\342\320\326\330\342\330 \327\321\325\340\325\326\325\335\335\357 \324\333\357 \322\330\321\340\320\335\336\367 \323\340\330" },
+ { 124, "\265\334\343\333\357\342\336\340 MAME OPL:" },
+ { 125, "MIDI" },
+ { 126, "\277\336\341\330\333\325\335\335\357 MIDI:" },
+ { 127, "MT-32" },
+ { 128, "\277\340\330\341\342\340\366\331 MT-32:" },
+ { 129, "\265\334\343\333\357\342\336\340 MT-32" },
+ { 130, "\274\320\341\350\342\320\321 \323\336\333\336\322\335\336\323\336 \325\332\340\320\335\343:" },
+ { 131, "\277\340\330\327\335\320\347\330\342\330" },
+ { 132, "\264\336\324. \321\320\323\320\342\336..." },
+ { 133, "\274\325\335\356" },
+ { 134, "\300\366\327\335\325" },
+ { 135, "\267\334\366\350\320\335\330\331 \340\325\326\330\334 AdLib/MIDI" },
+ { 136, "\277\366\324\332\333\356\347\330\342\330 DVD" },
+ { 137, "\277\366\324\332\333\356\347\330\342\330 SMB" },
+ { 138, "\272\333\366\332 \334\330\350\332\336\356" },
+ { 139, "\274\343\333\354\342\366\344\343\335\332\346\366\357" },
+ { 140, "\274\343\327\330\347\335\330\331 \277\340\330\341\342\340\366\331:" },
+ { 141, "\263\343\347\335\366\341\342\354 \334\343\327\330\332\330:" },
+ { 142, "\262\330\334\332\335\343\342\330 \343\341\325" },
+ { 143, "\275\320\327\322\320:" },
+ { 144, "\274\325\340\325\326\320 \322\330\334\332\335\325\335\320" },
+ { 145, "\274\325\340\325\326\320 \335\325 \335\320\333\320\323\336\324\326\325\335\320 (%d)" },
+ { 146, "\274\325\340\325\326\320 \337\340\320\346\356\364" },
+ { 147, "\274\325\340\325\326\320 \337\340\320\346\356\364, \337\320\337\332\320 \337\366\324\332\333\356\347\325\335\320" },
+ { 148, "\275\366\332\336\333\330" },
+ { 149, "\275\366" },
+ { 150, "\264\320\342\320 \335\325 \327\320\337\330\341\320\335\320" },
+ { 151, "\261\325\327 \334\343\327\330\332\330" },
+ { 152, "\307\320\341 \323\340\330 \335\325 \327\320\337\330\341\320\335\336" },
+ { 153, "\307\320\341 \335\325 \327\320\337\330\341\320\335\330\331" },
+ { 154, "\275\325 \327\320\324\320\335\330\331" },
+ { 155, "\261\325\327 \327\321\366\333\354\350\325\335\335\357" },
+ { 156, "OK" },
+ { 157, "\262\330\345\366\324\335\320 \347\320\341\342\336\342\320:" },
+ { 158, "\277\325\340\325\332\340\330\342\330 \323\333\336\321\320\333\354\335\366 \343\341\342\320\335\336\322\332\330 MIDI" },
+ { 159, "\277\325\340\325\332\340\330\342\330 \323\333\336\321\320\333\354\335\366 \343\341\342\320\335\336\322\332\330 MT-32" },
+ { 160, "\277\325\340\325\332\340\330\342\330 \323\333\336\321\320\333\354\335\366 \343\341\342\320\335\336\322\332\330 \320\343\324\366\336" },
+ { 161, "\277\325\340\325\332\340\330\342\330 \323\333\336\321\320\333\354\335\366 \343\341\342\320\335\336\322\332\330 \323\340\320\344\366\332\330" },
+ { 162, "\277\325\340\325\332\340\330\342\330 \323\333\336\321\320\333\354\335\366 \343\341\342\320\335\336\322\332\330 \323\343\347\335\336\341\342\366" },
+ { 163, "\265\334\343\333\357\342\336\340 PC \341\337\366\332\325\340\320" },
+ { 164, "\277\320\340\336\333\354:" },
+ { 165, "\310\333\357\345 \335\325 \364 \337\320\337\332\336\356" },
+ { 166, "\310\333\357\345 \335\325 \364 \344\320\331\333\336\334" },
+ { 167, "\310\333\357\345 \335\325 \327\335\320\331\324\325\335\330\331" },
+ { 168, "\310\333\357\345\330" },
+ { 169, "\277\320\343\327\320" },
+ { 170, "\262\330\321\325\340\366\342\354 \323\340\343:" },
+ { 171, "\277\333\320\342\344\336\340\334\320, \324\333\357 \357\332\336\367 \323\340\320 \321\343\333\320 \341\337\336\347\320\342\332\343 \340\336\327\340\336\321\333\325\335\320" },
+ { 172, "\277\333\320\342\344\336\340\334\320:" },
+ { 173, "\307\320\341 \323\340\330: " },
+ { 174, "\261\343\324\354 \333\320\341\332\320, \322\330\321\325\340\366\342\354 \324\366\356" },
+ { 175, "\310\333\357\345 \324\336 \337\333\320\323\366\335\366\322:" },
+ { 176, "\277\340\330\341\342\340\366\331 \357\332\336\334\343 \322\366\324\324\320\364\342\354\341\357 \337\325\340\325\322\320\323\320:" },
+ { 177, "\275\320\342\330\341\335\366\342\354 \332\333\320\322\366\350\343 \324\333\357 \337\340\330\327\335\320\347\325\335\335\357" },
+ { 178, "\262\330\345\366\324" },
+ { 179, "\262\330\345\366\324 \327 ScummVM" },
+ { 180, "\275\325\324\336\341\342\320\342\335\354\336 \337\340\320\322 \324\333\357 \347\330\342\320\335\335\357" },
+ { 181, "\277\336\334\330\333\332\320 \347\330\342\320\335\335\357" },
+ { 182, "\277\325\340\325\337\340\330\327\335\320\347\330\342\330 \332\333\320\322\366\350\366" },
+ { 183, "\262\330\324\320\333\330\342\330 \323\340\343 \327\366 \341\337\330\341\332\343. \275\325 \322\330\324\320\333\357\364 \323\340\343 \327 \326\336\340\341\342\332\336\323\336 \324\330\341\332\320" },
+ { 184, "\300\325\326\330\334 \340\320\341\342\340\343\322\320\335\335\357:" },
+ { 185, "\262\337\340\320\322\336" },
+ { 186, "\277\340\320\322\330\331 \332\333\366\332" },
+ { 187, "\277\340\320\322\330\331 \332\333\366\332" },
+ { 188, "\277\336\322\325\340\335\343\342\330" },
+ { 189, "\263\343\347\335\366\341\342\354 \325\344\325\332\342\366\322:" },
+ { 190, "SMB" },
+ { 191, "\267\320\337\330\341\320\342\330" },
+ { 192, "\310\333\357\345 \327\321\325\340.: " },
+ { 193, "\310\333\357\345 \324\333\357 \327\321\325\340\325\326\325\335\354: " },
+ { 194, "\267\321\325\340\325\323\342\330 \323\340\343: " },
+ { 195, "\277\336\350\343\332 \327\320\332\366\335\347\325\335\330\331!" },
+ { 196, "\277\340\336\323\333\357\335\343\342\336 %d \337\320\337\336\332 ..." },
+ { 197, "\263\336\333\336\322\335\325 \334\325\335\356 ScummVM" },
+ { 198, "ScummVM \335\325 \327\334\366\323 \327\335\320\331\342\330 \324\322\330\326\336\332 \324\333\357 \327\320\337\343\341\332\343 \322\330\321\340\320\335\336\367 \323\340\330!" },
+ { 199, "ScummVM \335\325 \334\336\326\325 \327\335\320\331\342\330 \323\340\343 \343 \322\332\320\327\320\335\366\331 \337\320\337\346\366!" },
+ { 200, "ScummVM \335\325 \334\336\326\325 \322\366\324\332\340\330\342\330 \322\332\320\327\320\335\343 \337\320\337\332\343!" },
+ { 201, "\277\336\350\343\332 \322 \341\337\330\341\332\343 \366\323\336\340" },
+ { 202, "\277\336\350\343\332:" },
+ { 203, "\262\330\321\325\340\366\342\354 SoundFont" },
+ { 204, "\262\330\321\325\340\366\342\354 \342\325\334\343" },
+ { 205, "\262\330\321\325\340\366\342\354 \324\336\324\320\342\332\336\322\343 \337\320\337\332\343 \323\340\330" },
+ { 206, "\262\330\321\325\340\366\342\354 \324\366\356 \366 \332\333\366\332\335\366\342\354 '\277\340\330\327\335\320\347\330\342\330'" },
+ { 207, "\262\330\321\325\340\366\342\354 \337\320\337\332\343 \324\333\357 \342\325\334 GUI" },
+ { 208, "\262\330\321\325\340\366\342\354 \337\320\337\332\343 \327 \324\336\324\320\342\332\336\322\330\334\330 \344\320\331\333\320\334\330" },
+ { 209, "\262\330\321\325\340\366\342\354 \337\320\337\332\343 \327 \337\333\320\323\330\335\320\334\330" },
+ { 210, "\262\330\321\325\340\366\342\354 \337\320\337\332\343 \324\333\357 \327\321\325\340\325\326\325\335\354" },
+ { 211, "\262\330\321\325\340\366\342\354 \337\320\337\332\343 \324\333\357 \327\321\325\340\325\326\325\335\354" },
+ { 212, "\262\330\321\325\340\366\342\354 \337\320\337\332\343 \327 \344\320\331\333\320\334\330 \323\340\330" },
+ { 213, "\307\343\342\333\330\322\366\341\342\354" },
+ { 214, "\301\325\340\322\325\340:" },
+ { 215, "\274\325\340\325\326\325\322\320 \337\320\337\332\320:" },
+ { 216, "\272\336\340\336\342\332\330\331 \366\324\325\335\342\330\344\366\332\320\342\336\340, \357\332\330\331 \322\330\332\336\340\330\341\342\336\322\343\364\342\354\341\357 \324\333\357 \335\320\327\322 \327\321\325\340\325\326\325\335\330\345 \366\323\336\340 \366 \324\333\357 \327\320\337\343\341\332\343 \327 \332\336\334\320\335\324\335\336\367 \341\342\340\366\347\332\330" },
+ { 217, "\277\336\332\320\327\320\342\330 \332\333\320\322\366\320\342\343\340\343" },
+ { 218, "\277\336\332\320\327\343\322\320\342\330 \332\343\340\341\336\340 \334\330\350\366" },
+ { 219, "\277\336\332\320\327\343\322\320\342\330 \341\343\321\342\330\342\340\330 \366 \322\366\324\342\322\336\340\356\322\320\342\330 \334\336\322\343" },
+ { 220, "\277\336\332\320\327\320\342\330/\301\345\336\322\320\342\330 \332\343\340\341\336\340" },
+ { 221, "\277\340\336\337\343\341\342\330\342\330" },
+ { 222, "\277\340\336\337\343\341\342\330\342\330 \340\357\324\336\332" },
+ { 223, "\277\340\336\337\343\341\342\330\342\330 \342\325\332\341\342" },
+ { 224, "\277\340\330\332\340\366\337\330\342\330 \324\336 \332\340\320\367\322" },
+ { 225, "\277\340\336\323\340\320\334\335\325 \334\320\341\350\342\320\321\343\322\320\335\335\357 (\345\336\340\336\350\320 \357\332\366\341\342\354, \320\333\325 \337\336\322\366\333\354\335\366\350\325)" },
+ { 226, "\267\322\343\332 \343\322\366\334/\322\330\334\332" },
+ { 227, "SoundFont \337\366\324\342\340\330\334\343\364\342\354\341\357 \324\325\357\332\330\334\330 \327\322\343\332\336\322\330\334\330 \332\320\340\342\320\334\330, Fluidsynth \366 Timidity" },
+ { 228, "SoundFont:" },
+ { 229, "\276\327\322" },
+ { 230, "\301\337\325\346\366\320\333\354\335\366 \340\325\326\330\334\330 \340\325\335\324\325\340\330\335\323\343, \357\332\366 \337\366\324\342\340\330\334\343\356\342\354 \324\325\357\332\366 \366\323\340\330" },
+ { 231, "\263\343\347\335\366\341\342\354 \341\337\325\346\366\320\333\354\335\330\345 \327\322\343\332\336\322\330\345 \325\344\325\332\342\366\322" },
+ { 232, "\262\332\320\327\343\364 \322\330\345\366\324\335\330\331 \327\322\343\332\336\322\330\331 \337\340\330\341\342\340\366\331 \324\333\357 MIDI" },
+ { 233, "\262\332\320\327\343\364 \327\322\343\332\336\322\330\331 \337\340\330\341\342\340\366\331 \337\336 \343\334\336\322\347\320\335\335\356 \324\333\357 \322\330\322\336\324\343 \335\320 Roland MT-32/LAPC1/CM32l/CM64" },
+ { 234, "\262\332\320\327\343\364 \322\330\345\366\324\335\330\331 \327\322\343\332\336\322\330\331 \337\340\330\341\342\340\366\331 \320\321\336 \325\334\343\333\357\342\336\340 \327\322\343\332\336\322\336\367 \332\320\340\342\330" },
+ { 235, "\262\332\320\327\343\364 \350\333\357\345 \324\336 \324\336\324\320\342\332\336\322\330\345 \344\320\331\333\366\322 \324\320\335\330\345, \322\330\332\336\340\330\341\342\336\322\343\322\320\335\330\345 \343\341\366\334\320 \366\323\340\320\334\330, \320\321\336 ScummVM" },
+ { 236, "\262\332\320\327\343\364 \350\333\357\345 \324\336 \324\336\324\320\342\332\336\322\330\345 \344\320\331\333\366\322 \324\320\335\330\345 \324\333\357 \323\340\330" },
+ { 237, "\262\332\320\327\343\364 \322\330\345\366\324\335\330\331 \327\322\343\332\336\322\330\331 \337\340\330\341\342\340\366\331 \320\321\336 \325\334\343\333\357\342\336\340 \327\322\343\332\336\322\336\367 \332\320\340\342\330" },
+ { 238, "\262\332\320\327\343\364 \350\333\357\345 \324\336 \327\321\325\340\325\326\325\335\354 \323\340\330" },
+ { 239, "\276\327\322\343\347\325\335\335\357" },
+ { 240, "\263\343\347\335\366\341\342\354 \336\327\322\343\347\325\335\335\357:" },
+ { 241, "\301\342\320\335\324\320\340\342\335\330\331 \340\320\341\342\325\340\330\327\320\342\336\340 (16bpp)" },
+ { 242, "\267\320\337\343\341\342\330\342\330 \322\330\321\340\320\335\343 \323\340\343" },
+ { 243, "\301\342\320\335:" },
+ { 244, "\301\343\321" },
+ { 245, "\310\322\330\324\332\366\341\342\354 \341\343\321\342\330\342\340\366\322:" },
+ { 246, "\301\343\321\342\330\342\340\330" },
+ { 247, "\267\334\366\335\330\342\330 \323\325\340\336\357" },
+ { 248, "\302\320\337 \324\333\357 \333\366\322\336\323\336 \332\333\320\346\320\335\335\357, \337\336\324\322\366\331\335\330\331 \342\320\337 \324\333\357 \337\340\320\322\336\323\336 \332\333\320\346\320\335\335\357" },
+ { 249, "\302\325\332\341\342 \366 \336\327\322\343\347\325\335\335\357:" },
+ { 250, "\275\325 \334\336\326\343 \337\330\341\320\342\330 \343 \322\330\321\340\320\335\343 \337\320\337\332\343. \261\343\324\354 \333\320\341\332\320, \322\332\320\326\366\342\354 \366\335\350\343." },
+ { 251, "\310\333\357\345 \324\336 \342\325\334:" },
+ { 252, "\302\325\334\320:" },
+ { 253, "\306\325\331 ID \323\340\330 \322\326\325 \322\330\332\336\340\330\341\342\336\322\343\364\342\354\341\357. \261\343\324\354 \333\320\341\332\320, \322\330\321\325\340\366\342\354 \366\335\350\330\331." },
+ { 254, "\306\357 \323\340\320 \335\325 \337\366\324\342\340\330\334\343\364 \327\320\322\320\335\342\320\326\325\335\335\357 \327\321\325\340\325\326\325\335\354 \347\325\340\325\327 \323\336\333\336\322\335\325 \334\325\335\356." },
+ { 255, "\307\320\341: " },
+ { 256, "\307\320\341 \337\366\324\332\333\356\347\325\335\335\357 \324\336 \334\325\340\325\326\366 \322\330\342\366\332" },
+ { 257, "\267\334\366\351\325\335\335\357 \342\336\340\332\320\335\354 \337\336 \336\341\366 X" },
+ { 258, "\267\334\366\351\325\335\335\357 \342\336\340\332\320\335\354 \337\336 \336\341\366 Y" },
+ { 259, "\300\325\326\330\334 \342\320\347\337\320\324\343 \322\330\334\332\335\325\335\330\331." },
+ { 260, "\300\325\326\330\334 \342\320\347\337\320\324\343 \343\322\366\334\332\335\325\335\330\331." },
+ { 261, "\301\337\340\320\322\326\335\366\331 Roland MT-32 (\322\330\334\332\335\343\342\330 \325\334\343\333\357\346\330\356 GM)" },
+ { 262, "\262\330\334\330\332\320\364 \334\320\337\337\366\335\323 General MIDI \324\333\357 \366\323\336\340 \366\327 \327\322\343\332\336\322\336\356 \324\336\340\366\326\332\336\356 \324\333\357 Roland MT-32" },
+ { 263, "\275\325\322\366\324\336\334\336" },
+ { 264, "\275\325\322\366\324\336\334\320 \337\336\334\330\333\332\320" },
+ { 265, "\262\366\324\332\333\356\347\330\342\330 DVD" },
+ { 266, "\262\366\324\332\333\356\347\342\330 SMB" },
+ { 267, "\261\325\327 \334\320\341\350\342\320\321\343\322\320\335\335\357 (\342\340\325\321\320 \321\343\324\325 \337\340\336\332\340\343\347\343\322\320\342\330 \335\320\333\366\322\336 \366 \335\320\337\340\320\322\336)" },
+ { 268, "\300\325\326\330\334 \272\336\333\354\336\340\343 \335\325 \337\366\324\342\340\330\334\343\364\342\354\341\357" },
+ { 269, "\267\321\325\340\325\326\325\335\335\357 \321\325\327 \366\334\325\335\366" },
+ { 270, "\262\322\325\340\345" },
+ { 271, "\262\330\332\336\340\330\341\342\336\322\343\322\320\342\330 \366 MIDI \366 AdLib \324\333\357 \323\325\335\325\340\320\346\366\367 \327\322\343\332\343" },
+ { 272, "\262\330\332\336\340\330\341\342\336\322\343\322\320\342\330 \343\337\340\320\322\333\366\335\335\357 \332\343\340\341\336\340\336\334 \357\332 \335\320 \342\340\325\332\337\320\324\366 \333\320\337\342\336\337\366\322" },
+ { 273, "\272\336\340\330\341\342\343\322\320\347:" },
+ { 274, "\262\330\332\336\340\330\341\342\336\322\343\356 \324\340\320\331\322\325\340 SDL " },
+ { 275, "\262\325\340\342\330\332\320\333\354\335\330\331 underscan:" },
+ { 276, "\262\366\324\325\336" },
+ { 277, "\262\366\340\342\343\320\333\354\335\320 \332\333\320\322\366\320\342\343\340\320" },
+ { 278, "\263\343\347\335\366\341\342\354" },
+ { 279, "Windows MIDI" },
+ { 280, "\275\325\324\336\341\342\320\342\335\354\336 \337\340\320\322 \324\333\357 \327\320\337\330\341\343" },
+ { 281, "\277\336\334\330\333\332\320 \327\320\337\330\341\343 \324\320\335\330\345" },
+ { 282, "\302\320\332" },
+ { 283, "\262\330 \337\336\322\330\335\335\366 \337\325\340\325\327\320\337\343\341\342\330\342\330 ScummVM \351\336\321 \327\320\341\342\336\341\343\322\320\342\330 \327\334\366\335\330." },
+ { 284, "\267\336\335\320" },
+ { 285, "\267\334\335\350. \334\320\350\342\320\321" },
+ { 286, "\267\321\366\333. \334\320\350\342\320\321" },
+ { 287, "\332\336\326\335\366 10 \345\322" },
+ { 288, "\332\336\326\335\366 15 \345\322" },
+ { 289, "\332\336\326\335\366 30 \345\322" },
+ { 290, "\332\336\326\335\366 5 \345\322" },
+ { 291, "\277\340\336 \337\340\336~\323~\340\320\334\343" },
+ { 292, "~\264~\336\324. \323\340\343..." },
+ { 293, "\262\366~\324~\334\366\335\320" },
+ { 294, "~\267~\320\332\340\330\342\330" },
+ { 295, "\300\325\324\320~\323~. \323\340\343..." },
+ { 296, "~\264~\336\337\336\334\336\323\320" },
+ { 297, "\272\325\340\343\322\320\335\335\357 \321\336\357\334\330 \322 Indy" },
+ { 298, "~\272~\333\320\322\366\350\366" },
+ { 299, "\273\366\322\336\340\343\332\330\331 \340\325\326\330\334" },
+ { 300, "~\267~\320\322\320\335\342\320\326\330\342\330" },
+ { 301, "~\267~\320\322\320\335..." },
+ { 302, "~\275~\320\341\342" },
+ { 303, "~O~K" },
+ { 304, "~\276~\337\346\366\367" },
+ { 305, "~\276~\337\346\366\367..." },
+ { 306, "~\277~\336\337\325\340" },
+ { 307, "~\262~\330\345\366\324" },
+ { 308, "~\262~\330\324\320\333\330\342\330 \323\340\343" },
+ { 309, "\277\340\336\324\336\322~\326~\330\342\330" },
+ { 310, "~\277~\336\322\325\340\335\343\342\330\341\354 \322 \323\336\333\336\322\335\325 \334\325\335\356" },
+ { 311, "~\267~\320\337\330\341\320\342\330" },
+ { 312, "\267~\320~\337\343\341\332" },
+ { 313, "\277\325\340\325\345\336\324\330 \320\332\342\330\322\336\322\320\335\366" },
+ { 314, "\265\344\325\332\342\330 \322\336\324\330 \322\332\333\356\347\325\335\366" },
+ { 315, "\300\325\326\330\334 \350\322\330\324\332\336\323\336 \337\325\340\325\345\336\324\343 \320\332\342\330\322\336\322\320\335\330\331" },
+ { -1, NULL }
+};
+
+static const PoMessageEntry _translation_ca_ES[] = {
+ { 0, "Project-Id-Version: ScummVM 1.2.0svn\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-30 22:14+0100\nPO-Revision-Date: 2010-06-26 16:45+0100\nLast-Translator: Jordi Vilalta Prat <jvprat@gmail.com>\nLanguage-Team: Catalan <scummvm-devel@lists.sf.net>\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\nLanguage: Catalan\n" },
+ { 2, " (Actiu)" },
+ { 3, " (Joc)" },
+ { 4, " (Global)" },
+ { 5, "(compilat el %s)" },
+ { 6, ", error al muntar la compartici\363" },
+ { 7, ", compartici\363 no muntada" },
+ { 8, "... progr\351s ..." },
+ { 9, "11kHz" },
+ { 10, "22 kHz" },
+ { 11, "44 kHz" },
+ { 12, "48 kHz" },
+ { 13, "8 kHz" },
+ { 14, "<per defecte>" },
+ { 15, "Quant a ScummVM" },
+ { 16, "Emulador d'AdLib" },
+ { 17, "Emulador d'AdLib:" },
+ { 18, "AdLib s'utilitza per la m\372sica de molts jocs" },
+ { 19, "Afegeix Joc..." },
+ { 20, "Pintat amb antialias (16bpp)" },
+ { 21, "Correcci\363 del rati d'aspecte" },
+ { 22, "Tecla associada : %s" },
+ { 23, "Tecla associada : cap" },
+ { 24, "\300udio" },
+ { 25, "Desat autom\340tic:" },
+ { 26, "Motors disponibles:" },
+ { 27, "~Q~uant a..." },
+ { 28, "Mapeja tecles" },
+ { 29, "Ambd\363s" },
+ { 30, "Brillantor:" },
+ { 31, "Cancel\267la" },
+ { 32, "No s'ha pogut crear el fitxer" },
+ { 33, "Canvia les opcions del joc" },
+ { 34, "Canvia les opcions globals de ScummVM" },
+ { 35, "Marqueu si voleu utilitzar el vostre dispositiu hardware real de so compatible amb Roland connectat al vostre ordinador" },
+ { 36, "Escull" },
+ { 37, "Sel\267leccioneu una acci\363 per mapejar" },
+ { 38, "Neteja el valor" },
+ { 39, "Tanca" },
+ { 40, "Corregeix la relaci\363 d'aspecte per jocs de 320x200" },
+ { 41, "No s'ha pogut trobar cap motor capa\347 d'executar el joc seleccionat" },
+ { 42, "Mode de v\355deo actual:" },
+ { 43, "Cursor Avall" },
+ { 44, "Cursor Esquerra" },
+ { 45, "Cursor Dreta" },
+ { 46, "Cursor Amunt" },
+ { 47, "Emulador OPL de DOSBox" },
+ { 48, "DVD" },
+ { 49, "El DVD s'ha muntat satisfact\362riament" },
+ { 50, "El DVD no est\340 muntat" },
+ { 51, "Data: " },
+ { 52, "Depurador" },
+ { 53, "Per defecte" },
+ { 54, "Suprimeix" },
+ { 55, "Desactiva l'apagat autom\340tic" },
+ { 56, "GFX desactivats" },
+ { 57, "S'han descobert %d jocs nous ..." },
+ { 58, "S'han descobert %d jocs nous." },
+ { 59, "Pantalla" },
+ { 60, "Mostra el teclat" },
+ { 61, "Realment voleu suprimir aquesta partida?" },
+ { 62, "Realment voleu suprimir la configuraci\363 d'aquest joc?" },
+ { 63, "Esteu segur que voleu executar el detector massiu de jocs? Aix\362 pot afegir una gran quantitat de jocs." },
+ { 64, "Voleu carregar o desar el joc?" },
+ { 65, "Voleu fer una cerca autom\340tica?" },
+ { 66, "Vols sortir?" },
+ { 68, "Avall" },
+ { 69, "Activa el Mode Roland GS" },
+ { 70, "El motor no suporta el nivell de depuraci\363 '%s'" },
+ { 71, "Angl\350s" },
+ { 72, "Error al executar el joc:" },
+ { 73, "Error al muntar el DVD" },
+ { 74, "Cam\355 Extra:" },
+ { 75, "Emulador de FM Towns" },
+ { 76, "Mode r\340pid" },
+ { 77, "Caracter\355stiques compilades:" },
+ { 78, "Vista lliure" },
+ { 79, "T\355tol complet del joc" },
+ { 80, "Mode pantalla completa" },
+ { 81, "Acceleraci\363 del Pad GC:" },
+ { 82, "Sensibilitat del Pad GC:" },
+ { 83, "GFX" },
+ { 84, "Dispositiu GM:" },
+ { 85, "Idioma de la interf\355cie d'usuari:" },
+ { 86, "Mode de pintat de la interf\355cie d'usuari:" },
+ { 87, "Joc" },
+ { 88, "No s'han trobat les dades del joc" },
+ { 89, "Identificador de joc no suportat" },
+ { 90, "Cam\355 del Joc:" },
+ { 91, "Men\372 global" },
+ { 92, "Torna al nivell de directoris anterior" },
+ { 93, "Amunt" },
+ { 94, "Gr\340fics" },
+ { 95, "Mode gr\340fic:" },
+ { 96, "Escalat per hardware (r\340pid, per\362 de baixa qualitat)" },
+ { 97, "Hercules \300mbar" },
+ { 98, "Hercules Verd" },
+ { 99, "Oculta la barra d'eines" },
+ { 100, "Alta qualitat d'\340udio (m\351s lent) (reiniciar)" },
+ { 101, "Valors m\351s alts especifiquen millor qualitat de so per\362 pot ser que la vostra tarja de so no ho suporti" },
+ { 102, "Mantingueu premut Shift per a l'Addici\363 Massiva" },
+ { 104, "Emulador d'IBM PCjr" },
+ { 105, "Identificador:" },
+ { 106, "Inicia la xarxa" },
+ { 107, "Escalat inicial de la pantalla superior:" },
+ { 108, "Iniciant l'Emulador de MT-32" },
+ { 109, "Iniciant la xarxa" },
+ { 110, "Entrada" },
+ { 111, "Cam\355 incorrecte" },
+ { 112, "Mapejador de tecles" },
+ { 113, "Teclat" },
+ { 114, "Mapa de teclat:" },
+ { 115, "Tecles" },
+ { 116, "Idioma de la interf\355cie d'usuari de ScummVM" },
+ { 117, "Idioma del joc. Aix\362 no convertir\340 la vostra versi\363 Espanyola del joc a Angl\350s" },
+ { 118, "Idioma:" },
+ { 119, "Esquerra" },
+ { 120, "Clic esquerre" },
+ { 121, "Carrega" },
+ { 122, "Carrega partida:" },
+ { 123, "Carrega una partida pel joc seleccionat" },
+ { 124, "Emulador OPL de MAME" },
+ { 125, "MIDI" },
+ { 126, "Guany MIDI:" },
+ { 128, "Dispositiu MT32:" },
+ { 129, "Emulador de MT-32" },
+ { 130, "Escalat de la pantalla principal:" },
+ { 131, "Mapeja" },
+ { 132, "Addici\363 Massiva..." },
+ { 133, "Men\372" },
+ { 134, "Misc" },
+ { 135, "Mode combinat AdLib/MIDI" },
+ { 136, "Munta el DVD" },
+ { 137, "Munta SMB" },
+ { 138, "Clic del ratol\355" },
+ { 139, "Funci\363 M\372ltiple" },
+ { 140, "Dispositiu GM:" },
+ { 141, "Volum de la m\372sica:" },
+ { 142, "Silenciar tot" },
+ { 143, "Nom:" },
+ { 144, "Xarxa inactiva" },
+ { 145, "Xarxa no iniciada (%d)" },
+ { 146, "Xarxa activa" },
+ { 147, "Xarxa activa, compartici\363 muntada" },
+ { 148, "Mai" },
+ { 149, "No" },
+ { 150, "No hi ha data desada" },
+ { 151, "Sense m\372sica" },
+ { 152, "No hi ha temps de joc desat" },
+ { 153, "No hi ha hora desada" },
+ { 154, "Cap" },
+ { 155, "Normal (sense escalar)" },
+ { 156, "D'acord" },
+ { 157, "Freq\374\350ncia de sortida:" },
+ { 158, "Fer canvis sobre les opcions globals de MIDI" },
+ { 159, "Fer canvis sobre les opcions globals de MIDI" },
+ { 160, "Fer canvis sobre les opcions globals d'\340udio" },
+ { 161, "Fer canvis sobre les opcions globals de gr\340fics" },
+ { 162, "Fer canvis sobre les opcions globals de volum" },
+ { 163, "Emulador d'Altaveu de PC" },
+ { 164, "Contrasenya:" },
+ { 165, "El cam\355 no \351s un directori" },
+ { 166, "El cam\355 no \351s un fitxer" },
+ { 167, "El cam\355 no existeix" },
+ { 168, "Camins" },
+ { 169, "Pausa" },
+ { 170, "Seleccioneu el joc:" },
+ { 171, "Plataforma per la que el joc es va dissenyar originalment" },
+ { 172, "Plataforma:" },
+ { 173, "Temps de joc: " },
+ { 174, "Seleccioneu una acci\363" },
+ { 175, "Cam\355 dels connectors:" },
+ { 176, "Dispositiu Preferit:" },
+ { 177, "Premeu la tecla a associar" },
+ { 178, "Surt" },
+ { 179, "Surt de ScummVM" },
+ { 180, "S'ha denegat el perm\355s de lectura" },
+ { 181, "Ha fallat la lectura" },
+ { 182, "Remapeja les tecles" },
+ { 183, "Elimina un joc de la llista. Els fitxers de dades del joc es mantenen intactes" },
+ { 184, "Mode de pintat:" },
+ { 185, "Dreta" },
+ { 186, "Clic dret" },
+ { 187, "Clic dret" },
+ { 188, "Rotar" },
+ { 189, "Volum dels efectes:" },
+ { 190, "SMB" },
+ { 191, "Desa" },
+ { 192, "Cam\355 de les Partides:" },
+ { 193, "Cam\355 de les Partides: " },
+ { 194, "Desa la partida:" },
+ { 195, "S'ha acabat la cerca!" },
+ { 196, "S'han cercat %d directoris ..." },
+ { 197, "Men\372 Principal de ScummVM" },
+ { 198, "ScummVM no ha pogut trobar cap motor capa\347 d'executar el joc seleccionat!" },
+ { 199, "ScummVM no ha pogut trobar cap joc al directori especificat!" },
+ { 200, "ScummVM no ha pogut obrir el directori especificat!" },
+ { 201, "Cerca a la llista de jocs" },
+ { 202, "Cerca:" },
+ { 203, "Seleccioneu el fitxer SoundFont" },
+ { 204, "Seleccioneu un Tema" },
+ { 205, "Seleccioneu el directori addicional del joc" },
+ { 206, "Seleccioneu una acci\363 i cliqueu 'Mapeja'" },
+ { 207, "Seleccioneu el directori dels temes de la Interf\355cie d'Usuari" },
+ { 208, "Seleccioneu el directori dels fitxers extra" },
+ { 209, "Seleccioneu el directori dels connectors" },
+ { 210, "Seleccioneu el directori de les partides desades" },
+ { 211, "Seleccioneu el directori de les partides desades" },
+ { 212, "Seleccioneu el directori amb les dades del joc" },
+ { 213, "Sensibilitat" },
+ { 214, "Servidor:" },
+ { 215, "Compartici\363:" },
+ { 216, "Identificador de joc curt utilitzat per referir-se a les partides i per executar el joc des de la l\355nia de comandes" },
+ { 217, "Mostra el teclat" },
+ { 218, "Mostra el cursor del ratol\355" },
+ { 219, "Mostra els subt\355tols i reprodueix la veu" },
+ { 220, "Mostra/Oculta el cursor" },
+ { 221, "Salta" },
+ { 222, "Salta la l\355nia" },
+ { 223, "Salta el text" },
+ { 225, "Escalat per software (bona qualitat, per\362 m\351s lent)" },
+ { 226, "So engegat/parat" },
+ { 227, "Algunes targes de so, Fluidsynth i Timidity suporten SoundFont" },
+ { 228, "Fitxer SoundFont:" },
+ { 229, "Veus" },
+ { 230, "Modes de dispersi\363 especials suportats per alguns jocs" },
+ { 231, "Volum dels sons d'efectes especials" },
+ { 232, "Especifica el dispositiu de so per defecte per a la sortida General MIDI" },
+ { 233, "Especifica el dispositiu de so per defecte per a la sortida de Roland MT-32/LAPC1/CM32l/CM64" },
+ { 234, "Especifica el dispositiu de so o l'emulador de tarja de so de sortida" },
+ { 235, "Especifica el cam\355 de les dades addicionals utilitzades per tots els jocs o pel ScummVM" },
+ { 236, "Especifica el cam\355 de dades addicionals utilitzades pel joc" },
+ { 237, "Especifica el dispositiu de so o l'emulador de tarja de so preferit" },
+ { 238, "Especifica on es desaran les partides" },
+ { 239, "Veus" },
+ { 240, "Volum de la veu:" },
+ { 241, "Pintat est\340ndard (16bpp)" },
+ { 242, "Iniciant el joc seleccionat" },
+ { 243, "Estat:" },
+ { 244, "Subt" },
+ { 245, "Velocitat dels subt\355tols:" },
+ { 246, "Subt\355tols" },
+ { 247, "Commuta el personatge" },
+ { 248, "Toc per a clic esquerre, doble toc per a clic dret" },
+ { 249, "Text i Veus:" },
+ { 250, "No es pot escriure al directori seleccionat. Si us plau, escolliu-ne un altre." },
+ { 251, "Cam\355 dels Temes:" },
+ { 252, "Tema:" },
+ { 253, "Aquest identificador de joc ja est\340 usat. Si us plau, trieu-ne un altre." },
+ { 254, "Aquest joc no suporta la c\340rrega de partides des del llan\347ador." },
+ { 255, "Hora: " },
+ { 257, "Despla\347ament X del toc" },
+ { 258, "Despla\347ament Y del toc" },
+ { 259, "Mode Touchpad desactivat." },
+ { 260, "Mode Touchpad activat." },
+ { 261, "Roland MT-32 real (desactiva l'emulaci\363 GM)" },
+ { 262, "Desactiva la conversi\363 General MIDI pels jocs que tenen banda sonora per a Roland MT-32" },
+ { 263, "Desconegut" },
+ { 264, "Error desconegut" },
+ { 265, "Desmunta el DVD" },
+ { 266, "Desmunta SMB" },
+ { 267, "Sense escalar (haureu de despla\347ar-vos a esquerra i dreta)" },
+ { 268, "Mode de color no suportat" },
+ { 269, "Partida sense t\355tol" },
+ { 270, "Amunt" },
+ { 271, "Utilitza MIDI i la generaci\363 de so AdLib alhora" },
+ { 272, "Utilitza el control del cursor a l'estil del trackpad dels port\340tils" },
+ { 273, "Nom d'usuari:" },
+ { 274, "Utilitzant el controlador SDL " },
+ { 276, "V\355deo" },
+ { 277, "Teclat virtual" },
+ { 278, "Volum" },
+ { 279, "MIDI de Windows" },
+ { 280, "S'ha denegat el perm\355s d'escriptura" },
+ { 281, "Ha fallat l'escriptura de dades" },
+ { 282, "S\355" },
+ { 283, "Heu de reiniciar ScummVM perqu\350 tots els canvis tingui efecte." },
+ { 284, "Zona" },
+ { 285, "Redueix" },
+ { 286, "Amplia" },
+ { 287, "cada 10 minuts" },
+ { 288, "cada 15 minuts" },
+ { 289, "cada 30 minuts" },
+ { 290, "cada 5 minuts" },
+ { 291, "~Q~uant a" },
+ { 292, "~A~fegeix Joc..." },
+ { 293, "~C~ancel\267la" },
+ { 294, "~T~anca" },
+ { 295, "~E~dita Joc..." },
+ { 296, "~A~juda" },
+ { 297, "Controls de lluita de l'~I~ndy" },
+ { 298, "~T~ecles" },
+ { 299, "Mode ~e~squerr\340" },
+ { 300, "C~a~rrega" },
+ { 301, "~C~arrega..." },
+ { 302, "~S~eg\374ent" },
+ { 303, "~D~'acord" },
+ { 304, "~O~pcions" },
+ { 305, "~O~pcions..." },
+ { 306, "~A~nterior" },
+ { 307, "~T~anca" },
+ { 308, "~S~uprimeix Joc" },
+ { 309, "~C~ontinua" },
+ { 310, "~R~etorna al Llan\347ador" },
+ { 311, "~D~esa" },
+ { 312, "~I~nicia" },
+ { 313, "~T~ransicions activades" },
+ { 314, "~E~fecte de l'aigua activat" },
+ { 315, "Mode ~Z~ip activat" },
+ { -1, NULL }
+};
+
+static const PoMessageEntry _translation_es_ES[] = {
+ { 0, "Project-Id-Version: ScummVM 1.2.0svn\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-30 22:14+0100\nPO-Revision-Date: 2010-07-30 22:17+0100\nLast-Translator: Tom\341s Maidagan\nLanguage-Team: \nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\nLanguage: Espanol\n" },
+ { 1, "\277Seguro que quieres salir?" },
+ { 2, "(Activa)" },
+ { 3, "(Juego)" },
+ { 4, "(General)" },
+ { 5, "(compilado el %s)" },
+ { 6, ", error al montar el disco compartido" },
+ { 7, ", disco compartido no montado" },
+ { 8, "... progreso..." },
+ { 9, "11kHz" },
+ { 10, "22 kHz" },
+ { 11, "44 kHz" },
+ { 12, "48 kHz" },
+ { 13, "8 kHz" },
+ { 14, "<por defecto>" },
+ { 15, "Acerca de ScummVM" },
+ { 16, "Emulador de AdLib" },
+ { 17, "Emulador de AdLib:" },
+ { 18, "AdLib se usa para la m\372sica en muchos juegos" },
+ { 19, "A\361adir juego..." },
+ { 20, "Antialiasing (16bpp)" },
+ { 21, "Correcci\363n de aspecto" },
+ { 22, "Tecla asociada: %s" },
+ { 23, "Tecla asociada: ninguna" },
+ { 24, "Sonido" },
+ { 25, "Autoguardado:" },
+ { 26, "Motores disponibles:" },
+ { 27, "Acerca ~d~e" },
+ { 28, "Asignar teclas" },
+ { 29, "Ambos" },
+ { 30, "Brillo:" },
+ { 31, "Cancelar" },
+ { 32, "Imposible crear el archivo" },
+ { 33, "Cambiar opciones de juego" },
+ { 34, "Cambiar opciones generales de ScummVM" },
+ { 35, "Marcar si se quiere usar un dispositivo de sonido real conectado al ordenador y compatible con Roland" },
+ { 36, "Elegir" },
+ { 37, "Elige la acci\363n a asociar" },
+ { 38, "Eliminar valor" },
+ { 39, "Cerrar" },
+ { 40, "Corregir relaci\363n de aspecto en juegos 320x200" },
+ { 41, "No se ha podido encontrar ning\372n motor capaz de ejecutar el juego" },
+ { 42, "Modo de v\355deo actual:" },
+ { 43, "Abajo" },
+ { 44, "Izquierda" },
+ { 45, "Derecha" },
+ { 46, "Arriba" },
+ { 47, "Emulador de DOSBox OPL" },
+ { 48, "DVD" },
+ { 49, "DVD montado con \351xito" },
+ { 50, "DVD no montado" },
+ { 51, "Fecha:" },
+ { 52, "Debugger" },
+ { 53, "Por defecto" },
+ { 54, "Borrar" },
+ { 55, "Desactivar apagado" },
+ { 56, "GFX desactivados" },
+ { 57, "Se han encontrado %d juegos nuevos..." },
+ { 58, "Se han encontrado %d juegos nuevos." },
+ { 59, "Pantalla" },
+ { 60, "Mostrar el teclado" },
+ { 61, "\277Seguro que quieres borrar esta partida?" },
+ { 62, "\277Seguro que quieres eliminar la configuraci\363n de este juego?" },
+ { 63, "\277Seguro que quieres ejecutar la detecci\363n masiva? Puede que se a\361ada un gran n\372mero de juegos." },
+ { 64, "\277Quieres cargar o guardar el juego?" },
+ { 65, "\277Quieres realizar una b\372squeda autom\341tica?" },
+ { 66, "\277Quieres salir?" },
+ { 67, "Doble golpe" },
+ { 68, "Abajo" },
+ { 69, "Activar modo Roland GS" },
+ { 70, "El motor no soporta el nivel de debug '%s'" },
+ { 71, "Ingl\351s" },
+ { 72, "Error al ejecutar el juego:" },
+ { 73, "Error al montar el DVD" },
+ { 74, "Adicional:" },
+ { 75, "Emulador de FM Towns" },
+ { 76, "Modo r\341pido" },
+ { 77, "Caracter\355sticas compiladas:" },
+ { 78, "Vista libre" },
+ { 79, "T\355tulo completo del juego" },
+ { 80, "Pantalla completa" },
+ { 81, "Aceleraci\363n del pad GC:" },
+ { 82, "Sensibilidad del pad GC:" },
+ { 83, "GFX" },
+ { 84, "Dispositivo GM:" },
+ { 85, "Idioma de la interfaz:" },
+ { 86, "Render de la interfaz" },
+ { 87, "Juego" },
+ { 88, "No se han encontrado datos de juego" },
+ { 89, "ID del juego no soportada" },
+ { 90, "Juego:" },
+ { 91, "Men\372 general" },
+ { 92, "Ir al directorio anterior" },
+ { 93, "Arriba" },
+ { 94, "Gr\341ficos" },
+ { 95, "Modo gr\341fico:" },
+ { 96, "Escalado por hardware (r\341pido, pero de baja calidad)" },
+ { 97, "Hercules \341mbar" },
+ { 98, "Hercules verde" },
+ { 99, "Ocultar barra de tareas" },
+ { 100, "Sonido de alta calidad (m\341s lento) (reinicio)" },
+ { 101, "Los valores m\341s altos ofrecen mayor calidad, pero puede que tu tarjeta de sonido no sea compatible" },
+ { 102, "Mant\351n pulsado May\372s para a\361adir varios" },
+ { 103, "Underscan horizontal" },
+ { 104, "Emulador de IBM PCjr" },
+ { 105, "ID:" },
+ { 106, "Inicializar red" },
+ { 107, "Escalado de la pantalla inicial superior:" },
+ { 108, "Iniciando emulador de MT-32" },
+ { 109, "Inicializando red" },
+ { 110, "Entrada" },
+ { 111, "Ruta no v\341lida" },
+ { 112, "Asignaci\363n de teclas" },
+ { 113, "Teclado" },
+ { 114, "Asignaci\363n de teclas:" },
+ { 115, "Teclas" },
+ { 116, "Idioma de la interfaz de ScummVM" },
+ { 117, "Idioma del juego. No sirve para pasar al ingl\351s la versi\363n espa\361ola de un juego" },
+ { 118, "Idioma:" },
+ { 119, "Izquierda" },
+ { 120, "Clic izquierdo" },
+ { 121, "Cargar" },
+ { 122, "Cargar juego:" },
+ { 123, "Cargar partida del juego seleccionado" },
+ { 124, "Emulador de MAME OPL" },
+ { 125, "MIDI" },
+ { 126, "Ganancia MIDI:" },
+ { 127, "MT-32" },
+ { 128, "Dispositivo MT-32:" },
+ { 129, "Emulador de MT-32" },
+ { 130, "Escalado de la pantalla principal:" },
+ { 131, "Asignar" },
+ { 132, "A\361adir varios..." },
+ { 133, "Men\372" },
+ { 134, "Otros" },
+ { 135, "Modo AdLib/MIDI" },
+ { 136, "Montar DVD" },
+ { 137, "Montar SMB" },
+ { 138, "Clic de rat\363n" },
+ { 139, "Multifunci\363n" },
+ { 140, "Dispositivo de m\372sica:" },
+ { 141, "Volumen de la m\372sica:" },
+ { 142, "Silenciar" },
+ { 143, "Nombre:" },
+ { 144, "Red desconectada" },
+ { 145, "Red no inicializada (%d)" },
+ { 146, "Red conectada" },
+ { 147, "Red conectada, disco compartido montado" },
+ { 148, "Nunca" },
+ { 149, "No" },
+ { 150, "No hay fecha guardada" },
+ { 151, "Sin m\372sica" },
+ { 152, "No hay tiempo de juego guardado" },
+ { 153, "No hay hora guardada" },
+ { 154, "Ninguno" },
+ { 155, "Normal (sin escalado)" },
+ { 156, "De acuerdo" },
+ { 157, "Frecuencia de salida:" },
+ { 158, "Ignorar opciones MIDI generales" },
+ { 159, "Ignorar opciones MT-32 generales" },
+ { 160, "Ignorar opciones de sonido generales" },
+ { 161, "Ignorar opciones gr\341ficas generales" },
+ { 162, "Ignorar opciones de volumen generales" },
+ { 163, "Emulador del altavoz de PC" },
+ { 164, "Contrase\361a:" },
+ { 165, "La ruta no es un directorio" },
+ { 166, "La ruta no es un archivo" },
+ { 167, "La ruta no existe" },
+ { 168, "Rutas" },
+ { 169, "Pausar" },
+ { 170, "Elige el juego:" },
+ { 171, "Plataforma para la que se dise\361\363 el juego" },
+ { 172, "Plataforma:" },
+ { 173, "Tiempo de juego:" },
+ { 174, "Por favor, selecciona una acci\363n" },
+ { 175, "Plugins:" },
+ { 176, "Dispositivo preferido:" },
+ { 177, "Pulsa la tecla a asignar" },
+ { 178, "Salir" },
+ { 179, "Cerrar ScummVM" },
+ { 180, "Permiso de lectura denegado" },
+ { 181, "Lectura fallida" },
+ { 182, "Asignar teclas" },
+ { 183, "Elimina el juego de la lista. Los archivos no se borran" },
+ { 184, "Modo de renderizado:" },
+ { 185, "Derecha" },
+ { 186, "Clic derecho" },
+ { 187, "Clic derecho" },
+ { 188, "Rotar" },
+ { 189, "Volumen de los efectos" },
+ { 190, "SMB" },
+ { 191, "Guardar" },
+ { 192, "Partidas:" },
+ { 193, "Partidas:" },
+ { 194, "Guardar partida" },
+ { 195, "\241B\372squeda completada!" },
+ { 196, "Se ha buscado en %d directorios..." },
+ { 197, "Men\372 principal de ScummVM" },
+ { 198, "\241ScummVM no ha podido encontrar ning\372n motor capaz de ejecutar el juego!" },
+ { 199, "\241ScummVM no ha encontrado ning\372n juego en el directorio!" },
+ { 200, "\241ScummVM no ha podido abrir el directorio!" },
+ { 201, "Buscar en la lista de juegos" },
+ { 202, "Buscar:" },
+ { 203, "Seleccionar SoundFont" },
+ { 204, "Selecciona un tema" },
+ { 205, "Seleccionar directorio de juego adicional" },
+ { 206, "Selecciona una acci\363n y pulsa \"Asignar\"" },
+ { 207, "Selecciona el directorio para temas de interfaz" },
+ { 208, "Selecciona el directorio para archivos adicionales" },
+ { 209, "Selecciona el directorio para plugins" },
+ { 210, "Seleccionar directorio para partidas guardadas" },
+ { 211, "Selecciona el directorio para partidas guardadas." },
+ { 212, "Seleccionar directorio con los archivos del juego" },
+ { 213, "Sensibilidad" },
+ { 214, "Servidor:" },
+ { 215, "Disco compartido:" },
+ { 216, "Identificador usado para las partidas guardadas y para ejecutar el juego desde la l\355nea de comando" },
+ { 217, "Mostrar teclado" },
+ { 218, "Mostrar el cursor" },
+ { 219, "Reproducir voces y subt\355tulos" },
+ { 220, "Mostrar/ocultar cursor" },
+ { 221, "Saltar" },
+ { 222, "Saltar frase" },
+ { 223, "Saltar texto" },
+ { 224, "Pegar a los bordes" },
+ { 225, "Escalado por software (buena calidad, pero m\341s lento)" },
+ { 226, "Sonido activado/desactivado" },
+ { 227, "Algunas tarjetas de sonido, Fluidsynth y Timidity soportan SoundFont" },
+ { 228, "SoundFont:" },
+ { 229, "Voces" },
+ { 230, "Modos especiales de expansi\363n soportados por algunos juegos" },
+ { 231, "Volumen de los efectos de sonido" },
+ { 232, "Especifica el dispositivo de salida General MIDI por defecto" },
+ { 233, "Especifica el dispositivo de sonido para la salida Roland MT-32/LAPC1/CM32l/CM64 por defecto" },
+ { 234, "Especifica el dispositivo de sonido o emulador de tarjeta de sonido de salida" },
+ { 235, "Especifica el directorio adicional usado por los juegos y ScummVM" },
+ { 236, "Especifica un directorio para datos adicionales del juego" },
+ { 237, "Especifica qu\351 dispositivo de sonido o emulador de tarjeta de sonido prefieres" },
+ { 238, "Especifica d\363nde guardar tus partidas" },
+ { 239, "Voces" },
+ { 240, "Volumen de las voces" },
+ { 241, "Est\341ndar (16bpp)" },
+ { 242, "Jugar al juego seleccionado" },
+ { 243, "Estado:" },
+ { 244, "Subt." },
+ { 245, "Velocidad de los subt\355tulos:" },
+ { 246, "Subt\355tulos" },
+ { 247, "Cambiar personaje" },
+ { 248, "Un toque para clic izquierdo, dos para clic derecho" },
+ { 249, "Texto y voces:" },
+ { 250, "No se puede escribir en el directorio elegido. Por favor, selecciona otro." },
+ { 251, "Temas:" },
+ { 252, "Tema:" },
+ { 253, "Esta ID ya est\341 siendo usada. Por favor, elige otra." },
+ { 254, "Este juego no permite cargar partidas desde el lanzador." },
+ { 255, "Hora:" },
+ { 256, "Se ha excedido el tiempo de inicializaci\363n de red" },
+ { 257, "Compensaci\363n X del toque" },
+ { 258, "Compensaci\363n Y del toque" },
+ { 259, "Modo Touchpad desactivado." },
+ { 260, "Modo Touchpad activado." },
+ { 261, "Roland MT-32 aut\351ntica (desactivar emulaci\363n GM)" },
+ { 262, "Desactiva la conversi\363n General MIDI en juegos con sonido Roland MT-32" },
+ { 263, "Desconocido" },
+ { 264, "Error desconocido" },
+ { 265, "Desmontar DVD" },
+ { 266, "Desmontar SMB" },
+ { 267, "Sin escalado (debes desplazar la pantalla a los lados)" },
+ { 268, "Modo de color no soportado" },
+ { 269, "Partida sin nombre" },
+ { 270, "Arriba" },
+ { 271, "Usar tanto MIDI como AdLib en la generaci\363n de sonido" },
+ { 272, "Activar el sistema de control tipo trackpad de los port\341tiles" },
+ { 273, "Usuario:" },
+ { 274, "Usando driver SDL" },
+ { 275, "Underscan vertical:" },
+ { 276, "V\355deo" },
+ { 277, "Teclado virtual" },
+ { 278, "Volumen" },
+ { 279, "Windows MIDI" },
+ { 280, "Permiso de escritura denegado" },
+ { 281, "Escritura de datos fallida" },
+ { 282, "S\355" },
+ { 283, "Tienes que reiniciar ScummVM para aplicar los cambios." },
+ { 284, "Zona" },
+ { 285, "Disminuir zoom" },
+ { 286, "Aumentar zoom" },
+ { 287, "cada 10 minutos" },
+ { 288, "cada 15 minutos" },
+ { 289, "cada 30 minutos" },
+ { 290, "cada 5 minutos" },
+ { 291, "Acerca ~d~e" },
+ { 292, "~A~\361adir juego..." },
+ { 293, "~C~ancelar" },
+ { 294, "Cerra~r~" },
+ { 295, "~E~ditar juego..." },
+ { 296, "~A~yuda" },
+ { 297, "Controles para pelear de ~I~ndy" },
+ { 298, "~T~eclas" },
+ { 299, "Modo para ~z~urdos" },
+ { 300, "~C~argar" },
+ { 301, "~C~argar..." },
+ { 302, "Si~g~uiente" },
+ { 303, "~S~\355" },
+ { 304, "~O~opciones" },
+ { 305, "~O~opciones..." },
+ { 306, "~A~nterior" },
+ { 307, "~S~alir" },
+ { 308, "E~l~iminar juego" },
+ { 309, "~R~eanudar" },
+ { 310, "~V~olver al lanzador" },
+ { 311, "~G~uardar" },
+ { 312, "~J~ugar" },
+ { 313, "Tra~n~siciones activadas" },
+ { 314, "Efecto ag~u~a activado" },
+ { 315, "Modo ~Z~ip activado" },
+ { -1, NULL }
+};
+
+static const PoMessageEntry _translation_de_DE[] = {
+ { 0, "Project-Id-Version: ScummVM 1.2.0svn\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-30 22:14+0100\nPO-Revision-Date: 2010-07-09 20:37+0100\nLast-Translator: Simon Sawatzki\nLanguage-Team: Lothar Serra Mari <Lothar@Windowsbase.de> & Simon Sawatzki <SimSaw@gmx.de>\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\nLanguage: Deutsch\nPlural-Forms: nplurals=2; plural=n != 1;\n" },
+ { 1, " M\366chten Sie wirklich beenden? " },
+ { 2, " (Aktiv)" },
+ { 3, " (Spiel)" },
+ { 4, " (Global)" },
+ { 5, "(erstellt am %s)" },
+ { 6, ", Fehler beim Einbinden des \366ffentlichen Verzeichnisses" },
+ { 7, ", \366ffentliches Verzeichnis nicht eingebunden" },
+ { 8, "... l\344uft..." },
+ { 9, "11 kHz" },
+ { 10, "22 kHz" },
+ { 11, "44 kHz" },
+ { 12, "48 kHz" },
+ { 13, "8 kHz" },
+ { 14, "<Standard>" },
+ { 15, "\334ber ScummVM" },
+ { 16, "AdLib-Emulator" },
+ { 17, "AdLib-Emulator" },
+ { 18, "AdLib wird f\374r die Musik in vielen Spielen verwendet." },
+ { 19, "Spiel hinzuf\374gen" },
+ { 20, "Kantengl\344ttung (16bpp)" },
+ { 21, "Seitenverh\344ltnis korrigieren" },
+ { 22, "Zugewiesene Taste: %s" },
+ { 23, "Zugewiesene Taste: keine" },
+ { 24, "Audio" },
+ { 25, "Autom. Speichern:" },
+ { 26, "Verf\374gbare Spiele-Engines:" },
+ { 27, "\334be~r~" },
+ { 28, "Tasten zuweisen" },
+ { 29, "Beides" },
+ { 30, "Helligkeit:" },
+ { 31, "Abbrechen" },
+ { 32, "Kann Datei nicht erstellen." },
+ { 33, "Spieloptionen \344ndern" },
+ { 34, "Globale ScummVM-Einstellungen bearbeiten" },
+ { 35, "W\344hlen Sie dies aus, wenn Sie Ihre echte Hardware, die mit einer Roland-kompatiblen Soundkarte verbunden ist, verwenden m\366chten." },
+ { 36, "Ausw\344hlen" },
+ { 37, "Eine Aktion zum Zuweisen ausw\344hlen" },
+ { 38, "Wert l\366schen" },
+ { 39, "Schlie\337en" },
+ { 40, "Seitenverh\344ltnis f\374r Spiele mit der Aufl\366sung 320x200 korrigieren" },
+ { 41, "Kann keine Spiel-Engine finden, die dieses Spiel starten kann." },
+ { 42, "Aktueller Videomodus:" },
+ { 43, "Zeiger runter" },
+ { 44, "Zeiger nach links" },
+ { 45, "Zeiger nach rechts" },
+ { 46, "Zeiger hoch" },
+ { 47, "DOSBox-OPL-Emulator" },
+ { 48, "DVD" },
+ { 49, "DVD erfolgreich eingebunden" },
+ { 50, "DVD nicht eingebunden" },
+ { 51, "Datum: " },
+ { 52, "Debugger" },
+ { 53, "Standard" },
+ { 54, "L\366schen" },
+ { 55, "Stromsparmodus abschalten" },
+ { 56, "GFX ausgeschalten" },
+ { 57, "%d neue Spiele gefunden..." },
+ { 58, "%d neue Spiele gefunden." },
+ { 59, "Anzeige" },
+ { 60, "Tastatur anzeigen" },
+ { 61, "Diesen Spielstand wirklich l\366schen?" },
+ { 62, "M\366chten Sie wirklich diese Spielkonfiguration entfernen?" },
+ { 63, "M\366chten Sie wirklich den PC nach Spielen durchsuchen? M\366glicherweise wird dabei eine gr\366\337ere Menge an Spielen hinzugef\374gt." },
+ { 64, "M\366chten Sie ein Spiel laden oder speichern?" },
+ { 65, "M\366chten Sie eine automatische Durchsuchung vornehmen?" },
+ { 66, "M\366chten Sie beenden?" },
+ { 67, "Doppelzeilen (kein Zeilensprungverfahren)" },
+ { 68, "Runter" },
+ { 69, "Roland-GS-Modus" },
+ { 70, "Engine unterst\374tzt den Debug-Level \"%s\" nicht" },
+ { 71, "English" },
+ { 72, "Fehler beim Ausf\374hren des Spiels:" },
+ { 73, "Fehler beim Einbinden der DVD" },
+ { 74, "Extrapfad:" },
+ { 75, "FM-Towns-Emulator" },
+ { 76, "Schneller Modus" },
+ { 77, "Verwendete Funktionen:" },
+ { 78, "Freie Ansicht" },
+ { 79, "Voller Name des Spiels" },
+ { 80, "Vollbildmodus" },
+ { 81, "GC-Pad-Beschleunigung:" },
+ { 82, "GC-Pad-Empfindlichkeit:" },
+ { 83, "GFX" },
+ { 84, "GM-Ger\344t:" },
+ { 85, "GUI-Sprache:" },
+ { 86, "GUI-Renderer:" },
+ { 87, "Spiel" },
+ { 88, "Spieldaten nicht gefunden" },
+ { 89, "Spielkennung nicht unterst\374tzt" },
+ { 90, "Spielpfad:" },
+ { 91, "Hauptmen\374" },
+ { 92, "Zu h\366herer Pfadebene wechseln" },
+ { 93, "Pfad hoch" },
+ { 94, "Grafik" },
+ { 95, "Grafikmodus:" },
+ { 96, "Hardware-Skalierung (schnell, aber schlechte Qualit\344t)" },
+ { 97, "Hercules Bernsteingelb" },
+ { 98, "Hercules-Gr\374n" },
+ { 99, "Werkzeugleiste verbergen" },
+ { 100, "Hohe Audioqualit\344t (lansamer) (erfordert Neustart)" },
+ { 101, "H\366here Werte bewirken eine bessere Soundqualit\344t, werden aber m\366glicherweise nicht von jeder Soundkarte unterst\374tzt." },
+ { 102, "Umschalttaste (Shift) gedr\374ckt halten, um Verzeichnisse nach Spielen zu durchsuchen" },
+ { 103, "Horizontale Bildverkleinerung:" },
+ { 104, "IBM-PCjr-Emulator" },
+ { 105, "Kennung:" },
+ { 106, "Netzwerk starten" },
+ { 107, "Verg\366\337erung des oberen Bildschirms:" },
+ { 108, "MT-32-Emulator wird gestartet..." },
+ { 109, "Netzwerk wird gestartet..." },
+ { 110, "Eingabe" },
+ { 111, "Ung\374ltiges Verzeichnis" },
+ { 112, "Tasten zuordnen" },
+ { 113, "Tastatur" },
+ { 114, "Tasten-Layout:" },
+ { 115, "Tasten" },
+ { 116, "Sprache der ScummVM-Oberfl\344che" },
+ { 117, "Sprache des Spiels. Diese Funktion wird nicht eine spanische Version des Spiels in eine deutsche verwandeln." },
+ { 118, "Sprache:" },
+ { 119, "Links" },
+ { 120, "Linksklick" },
+ { 121, "Laden" },
+ { 122, "Spiel laden:" },
+ { 123, "Spielstand f\374r ausgew\344hltes Spiel laden" },
+ { 124, "MAME-OPL-Emulator" },
+ { 125, "MIDI" },
+ { 126, "MIDI-Lautst\344rke:" },
+ { 128, "MT32-Ger\344t:" },
+ { 129, "MT-32-Emulation" },
+ { 130, "Hauptbildschirm-Skalierung:" },
+ { 131, "Zuweisen" },
+ { 132, "Durchsuchen" },
+ { 133, "Men\374" },
+ { 134, "Sonstiges" },
+ { 135, "AdLib-/MIDI-Modus" },
+ { 136, "DVD einbinden" },
+ { 137, "SMB einbinden" },
+ { 138, "Mausklick" },
+ { 139, "Multifunktion" },
+ { 140, "Musikger\344t:" },
+ { 141, "Musiklautst\344rke:" },
+ { 142, "Alles aus" },
+ { 143, "Name:" },
+ { 144, "Netzwerk ist aus." },
+ { 145, "Netzwerk nicht gestartet (%d)" },
+ { 146, "Netzwerk gestartet" },
+ { 147, "Netzwerk gestartet, \366ffentliches Verzeichnis eingebunden" },
+ { 148, "Niemals" },
+ { 149, "Nein" },
+ { 150, "Kein Datum gespeichert" },
+ { 151, "Keine Musik" },
+ { 152, "Keine Spielzeit gespeichert" },
+ { 153, "Keine Zeit gespeichert" },
+ { 154, "-" },
+ { 155, "Normal (keine Skalierung)" },
+ { 156, "OK" },
+ { 157, "Ausgabefrequenz:" },
+ { 158, "Globale MIDI-Einstellungen \374bergehen" },
+ { 159, "Globale MIDI-Einstellungen \374bergehen" },
+ { 160, "Globale Audioeinstellungen \374bergehen" },
+ { 161, "Globale Grafikeinstellungen \374bergehen" },
+ { 162, "Globale Lautst\344rke-Einstellungen \374bergehen" },
+ { 163, "PC-Lautsprecher-Emulator" },
+ { 164, "Passwort:" },
+ { 165, "Ung\374ltiges Verzeichnis" },
+ { 166, "Pfad ist keine Datei." },
+ { 167, "Verzeichnis existiert nicht." },
+ { 168, "Pfade" },
+ { 169, "Pause" },
+ { 170, "Spiel ausw\344hlen:" },
+ { 171, "Plattform, f\374r die das Spiel urspr\374nglich erstellt wurde" },
+ { 172, "Plattform:" },
+ { 173, "Spieldauer: " },
+ { 174, "Bitte eine Aktion ausw\344hlen" },
+ { 175, "Plugin-Pfad:" },
+ { 176, "Standard-Ger\344t:" },
+ { 177, "Taste dr\374cken, um sie zuzuweisen" },
+ { 178, "Beenden" },
+ { 179, "ScummVM beenden" },
+ { 180, "Lese-Berechtigung nicht vorhanden" },
+ { 181, "Lesefehler aufgetreten" },
+ { 182, "Tasten neu zuweisen" },
+ { 183, "Spiel aus der Liste entfernen. Die Spieldateien bleiben erhalten." },
+ { 184, "Render-Modus:" },
+ { 185, "Rechts" },
+ { 186, "Rechtsklick" },
+ { 187, "Rechtsklick" },
+ { 188, "Drehen" },
+ { 189, "Effektlautst\344rke:" },
+ { 190, "SMB" },
+ { 191, "Speichern" },
+ { 192, "Spielst\344nde:" },
+ { 193, "Spielst\344nde: " },
+ { 194, "Speichern:" },
+ { 195, "Suchlauf abgeschlossen!" },
+ { 196, "%d Ordner durchsucht..." },
+ { 197, "ScummVM-Hauptmen\374" },
+ { 198, "ScummVM konnte keine Engine finden, um das Spiel zu starten!" },
+ { 199, "ScummVM kann in dem gew\344hlten Verzeichnis kein Spiel finden!" },
+ { 200, "ScummVM kann das gew\344hlte Verzeichnis nicht \366ffnen!" },
+ { 201, "In Spieleliste suchen" },
+ { 202, "Suchen:" },
+ { 203, "SoundFont ausw\344hlen" },
+ { 204, "Thema ausw\344hlen" },
+ { 205, "Verzeichnis mit zus\344tzlichen Dateien ausw\344hlen" },
+ { 206, "Aktion ausw\344hlen und \"Zuweisen\" klicken" },
+ { 207, "Verzeichnis f\374r Oberfl\344chen-Themen" },
+ { 208, "Verzeichnis f\374r zus\344tzliche Dateien ausw\344hlen" },
+ { 209, "Verzeichnis f\374r Erweiterungen ausw\344hlen" },
+ { 210, "Verzeichnis f\374r Spielst\344nde ausw\344hlen" },
+ { 211, "Verzeichnis f\374r Spielst\344nde ausw\344hlen" },
+ { 212, "Verzeichnis mit Spieldateien ausw\344hlen" },
+ { 213, "Empfindlichkeit" },
+ { 214, "Server:" },
+ { 215, "\326ffentliches Verzeichnis:" },
+ { 216, "Kurzer Spielname, um die Spielst\344nde zuzuordnen und das Spiel von der Kommandozeile aus starten zu k\366nnen" },
+ { 217, "Tastatur zeigen" },
+ { 218, "Mauszeiger anzeigen" },
+ { 219, "Untertitel anzeigen und Sprachausgabe aktivieren" },
+ { 220, "Cursor zeigen/verbergen" },
+ { 221, "\334berspringen" },
+ { 222, "Zeile \374berspringen" },
+ { 223, "Text \374berspringen" },
+ { 224, "An Ecken anheften" },
+ { 225, "Software-Skalierung (gute Qualit\344t, aber langsamer)" },
+ { 226, "Ton ein/aus" },
+ { 227, "SoundFont wird von einigen Soundkarten, Fluidsynth und Timidity unterst\374tzt." },
+ { 228, "SoundFont:" },
+ { 229, "Spr." },
+ { 230, "Spezielle Farbmischungsmethoden werden von manchen Spielen unterst\374tzt." },
+ { 231, "Lautst\344rke spezieller Soundeffekte" },
+ { 232, "Legt das standardm\344\337ige Musikwiedergabe-Ger\344t f\374r General-MIDI-Ausgabe fest." },
+ { 233, "Legt das standardm\344\337ige Tonwiedergabe-Ger\344t f\374r die Ausgabe von Roland MT-32/LAPC1/CM32l/CM64 fest." },
+ { 234, "Legt das Musikwiedergabe-Ger\344t oder den Soundkarten-Emulator fest." },
+ { 235, "Legt das Verzeichnis f\374r zus\344tzliche Spieldateien f\374r alle Spiele in ScummVM fest." },
+ { 236, "Legt das Verzeichnis f\374r zus\344tzliche Spieldateien fest." },
+ { 237, "Legt das bevorzugte Tonwiedergabe-Ger\344t oder den Soundkarten-Emulator fest." },
+ { 238, "Legt fest, wo die Spielst\344nde abgelegt werden." },
+ { 239, "Sprache" },
+ { 240, "Sprachlautst\344rke:" },
+ { 241, "Standard-Renderer (16bpp)" },
+ { 242, "Ausgew\344hltes Spiel starten" },
+ { 243, "Status:" },
+ { 244, "Untert." },
+ { 245, "Untertitel-Tempo:" },
+ { 246, "Untertitel" },
+ { 247, "Figur wechseln" },
+ { 248, "Tippen f\374r Linksklick, Doppeltippen f\374r Rechtsklick" },
+ { 249, "Text und Sprache:" },
+ { 250, "In das gew\344hlte Verzeichnis kann nicht geschrieben werden. Bitte ein anderes ausw\344hlen." },
+ { 251, "Themenpfad:" },
+ { 252, "Thema:" },
+ { 253, "Diese Spielkennung ist schon vergeben. Bitte eine andere w\344hlen." },
+ { 254, "F\374r dieses Spiel wird das Laden aus der Spieleliste heraus nicht unterst\374tzt." },
+ { 255, "Zeit: " },
+ { 256, "Zeit\374berschreitung beim Starten des Netzwerks" },
+ { 257, "Zu X-Position gehen" },
+ { 258, "Zu Y-Position gehen" },
+ { 259, "Touchpad-Modus ausgeschaltet." },
+ { 260, "Touchpad-Modus aktiviert." },
+ { 261, "Echte Roland-MT-32-Emulation (GM-Emulation deaktiviert)" },
+ { 262, "Schaltet die General-MIDI-Zuweisung f\374r Spiele mit Roland-MT-32-Audiospur aus." },
+ { 263, "Unbekannt" },
+ { 264, "Unbekannter Fehler" },
+ { 265, "DVD aush\344ngen" },
+ { 266, "SMB aush\344ngen" },
+ { 267, "Nicht skalieren (Sie m\374ssen nach links und nach rechts scrollen)" },
+ { 268, "Farbmodus nicht unterst\374tzt" },
+ { 269, "Unbenannt" },
+ { 270, "Hoch" },
+ { 271, "Benutzt MIDI und AdLib zur Sounderzeugung." },
+ { 272, "Den Trackpad-Style f\374r Maussteuerung benutzen" },
+ { 273, "Benutzername:" },
+ { 274, "SDL-Treiber verwenden" },
+ { 275, "Vertikale Bildverkleinerung:" },
+ { 276, "Video" },
+ { 277, "Virtuelle Tastatur" },
+ { 278, "Lautst\344rke" },
+ { 279, "Windows MIDI" },
+ { 280, "Schreib-Berechtigung nicht vorhanden" },
+ { 281, "Daten konnten nicht geschrieben werden." },
+ { 282, "Ja" },
+ { 283, "Sie m\374ssen ScummVM neustarten, um die Einstellungen zu \374bernehmen." },
+ { 284, "Zone" },
+ { 285, "Hineinzoomen" },
+ { 286, "Herauszoomen" },
+ { 287, "alle 10 Minuten" },
+ { 288, "alle 15 Minuten" },
+ { 289, "alle 30 Minuten" },
+ { 290, "alle 5 Minuten" },
+ { 291, "\334be~r~" },
+ { 292, "Spiel ~h~inzuf\374gen" },
+ { 293, "~A~bbrechen" },
+ { 294, "~S~chlie\337en" },
+ { 295, "Spielo~p~tionen" },
+ { 296, "~H~ilfe" },
+ { 297, "~K~ampfsteuerung f\374r Indiana Jones" },
+ { 298, "~T~asten" },
+ { 299, "~L~inke-Hand-Modus" },
+ { 300, "~L~aden" },
+ { 301, "~L~aden..." },
+ { 302, "~W~eiter" },
+ { 303, "~O~K" },
+ { 304, "~O~ptionen" },
+ { 305, "~O~ptionen" },
+ { 306, "~Z~ur\374ck" },
+ { 307, "~B~eenden" },
+ { 308, "Spiel ~e~ntfernen" },
+ { 309, "~F~ortsetzen" },
+ { 310, "Zur Spiele~l~iste zur\374ck" },
+ { 311, "~S~peichern" },
+ { 312, "~S~tarten" },
+ { 313, "\334ber~g~\344nge aktiviert" },
+ { 314, "~W~assereffekt aktiviert" },
+ { 315, "~Z~ip-Modus aktiviert" },
+ { -1, NULL }
+};
+
+struct PoLangEntry {
+ const char *lang;
+ const char *charset;
+ const char *langname;
+ const PoMessageEntry *msgs;
+};
+
+const PoLangEntry _translations[] = {
+ { "ru_RU", "iso-8859-5", "Russian", _translation_ru_RU },
+ { "it_IT", "iso-8859-1", "Italiano", _translation_it_IT },
+ { "hu_HU", "cp1250", NULL, _translation_hu_HU },
+ { "fr_FR", "iso-8859-1", "Francais", _translation_fr_FR },
+ { "uk_UA", "iso-8859-5", "Ukrainian", _translation_uk_UA },
+ { "ca_ES", "iso-8859-1", "Catalan", _translation_ca_ES },
+ { "es_ES", "iso-8859-1", "Espanol", _translation_es_ES },
+ { "de_DE", "iso-8859-1", "Deutsch", _translation_de_DE },
+ { NULL, NULL, NULL, NULL }
+};
+
+// code
+
+static const PoMessageEntry *_currentTranslation = NULL;
+static int _currentTranslationMessageEntryCount = 0;
+static const char *_currentTranslationCharset = NULL;
+
+void po2c_setlang(const char *lang) {
+ _currentTranslation = NULL;
+ _currentTranslationMessageEntryCount = 0;
+ _currentTranslationCharset = NULL;
+
+ // if lang is NULL or "", deactivate it
+ if (lang == NULL || *lang == '\0')
+ return;
+
+ // searches for a valid language array
+ for (int i = 0; _currentTranslation == NULL && _translations[i].lang != NULL; ++i) {
+ if (strcmp(lang, _translations[i].lang) == 0) {
+ _currentTranslation = _translations[i].msgs;
+ _currentTranslationCharset = _translations[i].charset;
+ }
+ }
+
+ // try partial searches
+ for (int i = 0; _currentTranslation == NULL && _translations[i].lang != NULL; ++i) {
+ if (strncmp(lang, _translations[i].lang, 2) == 0) {
+ _currentTranslation = _translations[i].msgs;
+ _currentTranslationCharset = _translations[i].charset;
+ }
+ }
+
+ // if found, count entries
+ if (_currentTranslation != NULL) {
+ for (const PoMessageEntry *m = _currentTranslation; m->msgid != -1; ++m)
+ ++_currentTranslationMessageEntryCount;
+ }
+}
+
+const char *po2c_gettext(const char *msgid) {
+ // if no language is set or msgid is empty, return msgid as is
+ if (_currentTranslation == NULL || *msgid == '\0')
+ return msgid;
+
+ // binary-search for the msgid
+ int leftIndex = 0;
+ int rightIndex = _currentTranslationMessageEntryCount - 1;
+
+ while (rightIndex >= leftIndex) {
+ const int midIndex = (leftIndex + rightIndex) / 2;
+ const PoMessageEntry * const m = &_currentTranslation[midIndex];
+
+ const int compareResult = strcmp(msgid, _messageIds[m->msgid]);
+
+ if (compareResult == 0)
+ return m->msgstr;
+ else if (compareResult < 0)
+ rightIndex = midIndex - 1;
+ else
+ leftIndex = midIndex + 1;
+ }
+
+ return msgid;
+}
+
+const char *po2c_getcharset(void) {
+ if (_currentTranslationCharset)
+ return _currentTranslationCharset;
+ else
+ return "ASCII";
+}
+
+int po2c_getnumlangs(void) {
+ return ARRAYSIZE(_translations) - 1;
+}
+
+const char *po2c_getlang(const int num) {
+ assert(num < ARRAYSIZE(_translations));
+ return _translations[num].lang;
+}
+
+const char *po2c_getlangname(const int num) {
+ assert(num < ARRAYSIZE(_translations));
+ if (_translations[num].langname != NULL)
+ return _translations[num].langname;
+ return _translations[num].lang;
+}
diff --git a/common/module.mk b/common/module.mk
index 83d30f0a9b..239f8e9ccf 100644
--- a/common/module.mk
+++ b/common/module.mk
@@ -22,6 +22,7 @@ MODULE_OBJS := \
system.o \
textconsole.o \
tokenizer.o \
+ translation.o \
unarj.o \
unzip.o \
util.o \
diff --git a/common/ptr.h b/common/ptr.h
index 25ce6dcd64..7307038936 100644
--- a/common/ptr.h
+++ b/common/ptr.h
@@ -242,7 +242,7 @@ public:
*/
operator bool() const { return _pointer != 0; }
- ~ScopedPtr() {
+ ~ScopedPtr() {
delete _pointer;
}
@@ -255,14 +255,14 @@ public:
}
/**
- * Returns the plain pointer value.
+ * Returns the plain pointer value.
*
* @return the pointer the ScopedPtr manages
*/
PointerType get() const { return _pointer; }
/**
- * Returns the plain pointer value and releases ScopedPtr.
+ * Returns the plain pointer value and releases ScopedPtr.
* After release() call you need to delete object yourself
*
* @return the pointer the ScopedPtr manages
diff --git a/common/savefile.h b/common/savefile.h
index 39be661b45..16b0fdbfbe 100644
--- a/common/savefile.h
+++ b/common/savefile.h
@@ -109,14 +109,14 @@ public:
/**
* Open the savefile with the specified name in the given directory for saving.
* @param name the name of the savefile
- * @return pointer to an OutSaveFile, or NULL if an error occured.
+ * @return pointer to an OutSaveFile, or NULL if an error occurred.
*/
virtual OutSaveFile *openForSaving(const String &name) = 0;
/**
* Open the file with the specified name in the given directory for loading.
* @param name the name of the savefile
- * @return pointer to an InSaveFile, or NULL if an error occured.
+ * @return pointer to an InSaveFile, or NULL if an error occurred.
*/
virtual InSaveFile *openForLoading(const String &name) = 0;
diff --git a/common/scummsys.h b/common/scummsys.h
index 98dd47e171..96639716ea 100644
--- a/common/scummsys.h
+++ b/common/scummsys.h
@@ -243,27 +243,6 @@
#define SCUMM_NEED_ALIGNMENT
#endif
-#elif defined(__PALMOS_TRAPS__) || defined (__PALMOS_ARMLET__)
-
-#ifdef __PALMOS_ARMLET__
- #include <extras_string.h>
-#endif
- #define SCUMM_LITTLE_ENDIAN
-
- #define scumm_stricmp stricmp
- #define scumm_strnicmp strnicmp
-
- #define SCUMM_NEED_ALIGNMENT
- #define STRINGBUFLEN 256
-
- extern const char *SCUMMVM_SAVEPATH;
-
- #if !defined(COMPILE_ZODIAC) && !defined(COMPILE_OS5)
- # define NEWGUI_256
- #else
- # undef UNUSED
- #endif
-
#elif defined(__DC__)
#define scumm_stricmp strcasecmp
diff --git a/common/singleton.h b/common/singleton.h
index d66fb84cc2..2f721a65f7 100644
--- a/common/singleton.h
+++ b/common/singleton.h
@@ -95,7 +95,7 @@ protected:
* Note that you need to use this macro from the global namespace.
*
* This is because C++ requires initial explicit specialization
- * to be placed in the same namespace as the template.
+ * to be placed in the same namespace as the template.
* It has to be put in the global namespace to assure the correct
* namespace Common is referenced.
*/
diff --git a/common/str.cpp b/common/str.cpp
index 5e771c8b4d..744ba46ec7 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -105,8 +105,6 @@ String::String(char c)
_storage[0] = c;
_storage[1] = 0;
- // TODO/FIXME: There is no reason for the following check -- we *do*
- // allow strings to contain 0 bytes!
_size = (c == 0) ? 0 : 1;
}
@@ -151,7 +149,11 @@ void String::ensureCapacity(uint32 new_size, bool keep_old) {
// We need to allocate storage on the heap!
// Compute a suitable new capacity limit
- newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1));
+ // If the current capacity is sufficient we use the same capacity
+ if (new_size < curCapacity)
+ newCapacity = curCapacity;
+ else
+ newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1));
// Allocate new storage
newStorage = new char[newCapacity];
@@ -252,9 +254,11 @@ String &String::operator=(const String &str) {
String &String::operator=(char c) {
decRefCount(_extern._refCount);
_str = _storage;
- _size = 1;
+
_str[0] = c;
_str[1] = 0;
+
+ _size = (c == 0) ? 0 : 1;
return *this;
}
diff --git a/common/str.h b/common/str.h
index 12e2b0d2d3..46e721a746 100644
--- a/common/str.h
+++ b/common/str.h
@@ -39,6 +39,9 @@ namespace Common {
* Instead, small strings are stored 'inside' the string object (i.e. on
* the stack, for stack allocated objects), and only for strings exceeding
* a certain length do we allocate a buffer on the heap.
+ *
+ * The presence of \0 characters in the string will cause undefined
+ * behaviour in some operations.
*/
class String {
protected:
diff --git a/common/stream.cpp b/common/stream.cpp
index 6737eafc9c..84b712a562 100644
--- a/common/stream.cpp
+++ b/common/stream.cpp
@@ -152,7 +152,7 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
len++;
}
- // We always terminate the buffer if no error occured
+ // We always terminate the buffer if no error occurred
*p = 0;
return buf;
}
@@ -303,4 +303,29 @@ bool BufferedSeekableReadStream::seek(int32 offset, int whence) {
return true; // FIXME: STREAM REWRITE
}
+bool MemoryWriteStreamDynamic::seek(int32 offs, int whence) {
+ // Pre-Condition
+ assert(_pos <= _size);
+ switch (whence) {
+ case SEEK_END:
+ // SEEK_END works just like SEEK_SET, only 'reversed',
+ // i.e. from the end.
+ offs = _size + offs;
+ // Fall through
+ case SEEK_SET:
+ _ptr = _data + offs;
+ _pos = offs;
+ break;
+
+ case SEEK_CUR:
+ _ptr += offs;
+ _pos += offs;
+ break;
+ }
+ // Post-Condition
+ assert(_pos <= _size);
+
+ return true; // FIXME: STREAM REWRITE
+}
+
} // End of namespace Common
diff --git a/common/stream.h b/common/stream.h
index b6afcd85a9..5c81063a7e 100644
--- a/common/stream.h
+++ b/common/stream.h
@@ -687,6 +687,8 @@ public:
uint32 size() const { return _size; }
byte *getData() { return _data; }
+
+ bool seek(int32 offset, int whence = SEEK_SET);
};
} // End of namespace Common
diff --git a/common/system.h b/common/system.h
index 60cea49f87..0ff841e441 100644
--- a/common/system.h
+++ b/common/system.h
@@ -383,7 +383,7 @@ public:
* @note Backends supporting RGB color should accept game data in RGB color
* order, even if hardware uses BGR or some other color order.
*/
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats() = 0;
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0;
#else
inline Graphics::PixelFormat getScreenFormat() const {
return Graphics::PixelFormat::createFormatCLUT8();
@@ -879,7 +879,7 @@ public:
/**
* Create a new mutex.
- * @return the newly created mutex, or 0 if an error occured.
+ * @return the newly created mutex, or 0 if an error occurred.
*/
virtual MutexRef createMutex() = 0;
diff --git a/common/textconsole.cpp b/common/textconsole.cpp
index eef58fa39c..0d0b0aead9 100644
--- a/common/textconsole.cpp
+++ b/common/textconsole.cpp
@@ -43,6 +43,14 @@ extern bool isSmartphone();
#define fputs(str, file) DS::std_fwrite(str, strlen(str), 1, file)
#endif
+#ifdef ANDROID
+ #include <android/log.h>
+#endif
+
+#ifdef __PSP__
+ #include "backends/platform/psp/trace.h"
+#endif
+
namespace Common {
static OutputFormatter s_errorOutputFormatter = 0;
@@ -71,7 +79,9 @@ void warning(const char *s, ...) {
vsnprintf(buf, STRINGBUFLEN, s, va);
va_end(va);
-#if !defined (__SYMBIAN32__)
+#if defined( ANDROID )
+ __android_log_write(ANDROID_LOG_WARN, "ScummVM", buf);
+#elif !defined (__SYMBIAN32__)
fputs("WARNING: ", stderr);
fputs(buf, stderr);
fputs("!\n", stderr);
@@ -141,14 +151,18 @@ void NORETURN_PRE error(const char *s, ...) {
#endif
#endif
-#ifdef PALMOS_MODE
- extern void PalmFatalError(const char *err);
- PalmFatalError(buf_output);
+#ifdef ANDROID
+ __android_log_assert("Fatal error", "ScummVM", "%s", buf_output);
#endif
#ifdef __SYMBIAN32__
Symbian::FatalError(buf_output);
#endif
+
+#ifdef __PSP__
+ PspDebugTrace(false, "%s", buf_output); // write to file
+#endif
+
// Finally exit. quit() will terminate the program if g_system is present
if (g_system)
g_system->quit();
diff --git a/common/translation.cpp b/common/translation.cpp
new file mode 100644
index 0000000000..b52aad0d1f
--- /dev/null
+++ b/common/translation.cpp
@@ -0,0 +1,217 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+// winnt.h defines ARRAYSIZE, but we want our own one... - this is needed before including util.h
+#undef ARRAYSIZE
+#endif
+
+#include "translation.h"
+
+DECLARE_SINGLETON(Common::TranslationManager)
+
+#ifdef USE_DETECTLANG
+#ifndef WIN32
+#include <locale.h>
+#endif // !WIN32
+#endif
+
+#ifdef USE_TRANSLATION
+#include "messages.cpp"
+#endif
+
+namespace Common {
+
+
+#ifdef USE_TRANSLATION
+
+// Translation enabled
+
+TranslationManager::TranslationManager() {
+#ifdef USE_DETECTLANG
+#ifdef WIN32
+ // We can not use "setlocale" (at least not for MSVC builds), since it
+ // will return locales like: "English_USA.1252", thus we need a special
+ // way to determine the locale string for Win32.
+ char langName[9];
+ char ctryName[9];
+
+ const LCID languageIdentifier = GetThreadLocale();
+
+ // GetLocalInfo is only supported starting from Windows 2000, according to this:
+ // http://msdn.microsoft.com/en-us/library/dd318101%28VS.85%29.aspx
+ // On the other hand the locale constants used, seem to exist on Windows 98 too,
+ // check this for that: http://msdn.microsoft.com/en-us/library/dd464799%28v=VS.85%29.aspx
+ //
+ // I am not exactly sure what is the truth now, it might be very well that this breaks
+ // support for systems older than Windows 2000....
+ //
+ // TODO: Check whether this (or ScummVM at all ;-) works on a system with Windows 98 for
+ // example and if it does not and we still want Windows 9x support, we should definitly
+ // think of another solution.
+ if (GetLocaleInfo(languageIdentifier, LOCALE_SISO639LANGNAME, langName, sizeof(langName)) != 0 &&
+ GetLocaleInfo(languageIdentifier, LOCALE_SISO3166CTRYNAME, ctryName, sizeof(ctryName)) != 0) {
+ _syslang = langName;
+ _syslang += "_";
+ _syslang += ctryName;
+ } else {
+ _syslang = "C";
+ }
+#else // WIN32
+ // Activating current locale settings
+ const char *locale = setlocale(LC_ALL, "");
+
+ // Detect the language from the locale
+ if (!locale) {
+ _syslang = "C";
+ } else {
+ int length = 0;
+
+ // Strip out additional information, like
+ // ".UTF-8" or the like. We do this, since
+ // our translation languages are usually
+ // specified without any charset information.
+ for (int i = 0; locale[i]; ++i) {
+ // TODO: Check whether "@" should really be checked
+ // here.
+ if (locale[i] == '.' || locale[i] == ' ' || locale[i] == '@') {
+ length = i;
+ break;
+ }
+
+ length = i;
+ }
+
+ _syslang = String(locale, length);
+ }
+#endif // WIN32
+#else // USE_DETECTLANG
+ _syslang = "C";
+#endif // USE_DETECTLANG
+
+ // Set the default language
+ setLanguage("");
+}
+
+TranslationManager::~TranslationManager() {
+}
+
+void TranslationManager::setLanguage(const char *lang) {
+ if (*lang == '\0')
+ po2c_setlang(_syslang.c_str());
+ else
+ po2c_setlang(lang);
+}
+
+const char *TranslationManager::getTranslation(const char *message) {
+ return po2c_gettext(message);
+}
+
+const char *TranslationManager::getCurrentCharset() {
+ return po2c_getcharset();
+}
+
+String TranslationManager::getTranslation(const String &message) {
+ return po2c_gettext(message.c_str());
+}
+
+const TLangArray TranslationManager::getSupportedLanguageNames() const {
+ TLangArray languages;
+
+ int total = po2c_getnumlangs();
+ for (int i = 0; i < total; i++) {
+ TLanguage lng(po2c_getlangname(i), i + 1);
+ languages.push_back(lng);
+ }
+
+ //sort(languages.begin(), languages.end());
+
+ return languages;
+}
+
+int TranslationManager::parseLanguage(const String lang) {
+ int total = po2c_getnumlangs();
+
+ for (int i = 0; i < total; i++) {
+ if (lang == po2c_getlang(i))
+ return i + 1;
+ }
+
+ return kTranslationBuiltinId;
+}
+
+
+const char *TranslationManager::getLangById(int id) {
+ switch (id) {
+ case kTranslationAutodetectId:
+ return "";
+ case kTranslationBuiltinId:
+ return "C";
+ default:
+ if (id >= 0 && id - 1 < po2c_getnumlangs())
+ return po2c_getlang(id - 1);
+ }
+
+ // In case an invalid ID was specified, we will output a warning
+ // and return the same value as the auto detection id.
+ warning("Invalid language id %d passed to TranslationManager::getLangById", id);
+ return "";
+}
+
+#else // USE_TRANSLATION
+
+// Translation disabled
+
+
+TranslationManager::TranslationManager() {}
+
+TranslationManager::~TranslationManager() {}
+
+void TranslationManager::setLanguage(const char *lang) {}
+
+const char *TranslationManager::getLangById(int id) {
+ return "";
+}
+
+int TranslationManager::parseLanguage(const String lang) {
+ return kTranslationBuiltinId;
+}
+
+const char *TranslationManager::getTranslation(const char *message) {
+ return message;
+}
+
+String TranslationManager::getTranslation(const String &message) {
+ return message;
+}
+
+const TLangArray TranslationManager::getSupportedLanguageNames() const {
+ return TLangArray();
+}
+
+#endif // USE_TRANSLATION
+
+} // End of namespace Common
diff --git a/common/translation.h b/common/translation.h
new file mode 100644
index 0000000000..ccdd0f3500
--- /dev/null
+++ b/common/translation.h
@@ -0,0 +1,145 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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_TRANSLATION_H
+#define COMMON_TRANSLATION_H
+
+#include "common/singleton.h"
+#include "common/str-array.h"
+
+namespace Common {
+
+enum TranslationIDs {
+ kTranslationAutodetectId = 0,
+ kTranslationBuiltinId = 1000
+};
+
+struct TLanguage {
+ const char *name;
+ int id;
+
+ TLanguage() {
+ name = 0;
+ id = 0;
+ }
+
+ TLanguage(const char *n, int i) {
+ name = n;
+ id = i;
+ }
+};
+
+typedef Array<TLanguage> TLangArray;
+
+/**
+ * Message translation manager.
+ */
+class TranslationManager : public Singleton<TranslationManager> {
+public:
+ /**
+ * The constructor detects the system language and sets default
+ * language to English.
+ */
+ TranslationManager();
+ ~TranslationManager();
+
+ /**
+ * Retrieves the language string to the given id.
+ *
+ * @param id Id of the language
+ * @return the matching string description of the language
+ */
+ const char *getLangById(int id);
+
+ /**
+ * Sets the current translation language to the one specified in the
+ * parameter. If the parameter is an empty string, it sets the default
+ * system language.
+ *
+ * @param lang Language to setup.
+ */
+ void setLanguage(const char *lang);
+
+ /**
+ * Sets the current translation language to the one specified by the
+ * id parameter.
+ *
+ * @param id The id of the language.
+ */
+ void setLanguage(int id) {
+ setLanguage(getLangById(id));
+ }
+
+ /**
+ * Parses a language string and returns an id instead.
+ *
+ * @param lang Language string
+ * @return id of the language or kTranslationBuiltinId in case the
+ * language could not be found.
+ */
+ int parseLanguage(const String lang);
+
+ /**
+ * Returns the translation into the current language of the parameter
+ * message. In case the message isn't found in the translation catalog,
+ * it returns the original untranslated message.
+ */
+ const char *getTranslation(const char *message);
+
+ /**
+ * Returns the translation into the current language of the parameter
+ * message. In case the message isn't found in the translation catalog,
+ * it returns the original untranslated message.
+ */
+ String getTranslation(const String &message);
+
+ /**
+ * Returns a list of supported languages.
+ *
+ * @return The list of supported languages in a user readable form.
+ */
+ const TLangArray getSupportedLanguageNames() const;
+
+ /**
+ * Returns charset specified by selected translation language
+ */
+ const char *getCurrentCharset();
+
+private:
+ Common::String _syslang;
+};
+
+} // End of namespace Common
+
+#define TransMan Common::TranslationManager::instance()
+
+#ifdef USE_TRANSLATION
+#define _(str) TransMan.getTranslation(str)
+#else
+#define _(str) str
+#endif
+
+#define _s(str) str
+
+#endif
diff --git a/common/unarj.cpp b/common/unarj.cpp
index c130533dc1..2b2af3c54f 100644
--- a/common/unarj.cpp
+++ b/common/unarj.cpp
@@ -738,7 +738,7 @@ ArjArchive::ArjArchive(const String &filename) : _arjFilename(filename) {
warning("ArjArchive::ArjArchive(): Could not find the archive file");
return;
}
-
+
int32 firstHeaderOffset = findHeader(arjFile);
if (firstHeaderOffset < 0) {
@@ -828,7 +828,7 @@ SeekableReadStream *ArjArchive::createReadStreamForMember(const String &name) co
delete decoder;
}
- return new Common::MemoryReadStream(uncompressedData, hdr->origSize, DisposeAfterUse::YES);
+ return new Common::MemoryReadStream(uncompressedData, hdr->origSize, DisposeAfterUse::YES);
}
Archive *makeArjArchive(const String &name) {
diff --git a/common/unzip.cpp b/common/unzip.cpp
index a83f70d671..eda42fd107 100644
--- a/common/unzip.cpp
+++ b/common/unzip.cpp
@@ -79,6 +79,30 @@
#include <zlib.h>
#endif
+#else // !USE_ZLIB
+
+// Even when zlib is not linked in, we can still open ZIP archives and read
+// uncompressed files from them. Attempted decompression of compressed files
+// will result in an error.
+//
+// Define the constants and types used by zlib.
+#define Z_ERRNO -1
+#define Z_OK 0
+#define Z_DEFLATED 8
+typedef void *voidp;
+typedef unsigned int uInt;
+typedef unsigned long uLong;
+typedef long z_off_t;
+typedef unsigned char Byte;
+typedef Byte Bytef;
+typedef struct {
+ Bytef *next_in, *next_out;
+ uInt avail_in, avail_out;
+ uLong total_out;
+} z_stream;
+
+#endif // !USE_ZLIB
+
#include "common/fs.h"
#include "common/unzip.h"
#include "common/file.h"
@@ -1044,6 +1068,7 @@ int unzOpenCurrentFile (unzFile file) {
pfile_in_zip_read_info->stream.total_out = 0;
if (!Store) {
+#ifdef USE_ZLIB
pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
pfile_in_zip_read_info->stream.zfree = (free_func)0;
pfile_in_zip_read_info->stream.opaque = (voidpf)0;
@@ -1058,6 +1083,9 @@ int unzOpenCurrentFile (unzFile file) {
* In unzip, i don't wait absolutely Z_STREAM_END because I known the
* size of both compressed and uncompressed data
*/
+#else
+ err=UNZ_BADZIPFILE;
+#endif
}
pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size;
pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size;
@@ -1068,9 +1096,8 @@ int unzOpenCurrentFile (unzFile file) {
pfile_in_zip_read_info->stream.avail_in = (uInt)0;
-
s->pfile_in_zip_read = pfile_in_zip_read_info;
- return UNZ_OK;
+ return err;
}
@@ -1143,9 +1170,11 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
for (i=0;i<uDoCopy;i++)
*(pfile_in_zip_read_info->stream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i);
+#ifdef USE_ZLIB
pfile_in_zip_read_info->crc32_data = crc32(pfile_in_zip_read_info->crc32_data,
pfile_in_zip_read_info->stream.next_out,
uDoCopy);
+#endif // otherwise leave crc32_data as is and it won't be verified at the end
pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
@@ -1154,6 +1183,7 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
pfile_in_zip_read_info->stream.total_out += uDoCopy;
iRead += uDoCopy;
} else {
+#ifdef USE_ZLIB
uLong uTotalOutBefore,uTotalOutAfter;
const Bytef *bufBefore;
uLong uOutThis;
@@ -1184,6 +1214,11 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
return (iRead==0) ? UNZ_EOF : iRead;
if (err!=Z_OK)
break;
+#else
+ // Cannot decompress the file without zlib.
+ err = UNZ_BADZIPFILE;
+ break;
+#endif
}
}
@@ -1302,16 +1337,20 @@ int unzCloseCurrentFile(unzFile file) {
return UNZ_PARAMERROR;
+#ifdef USE_ZLIB
+ // Only verify crc32_data when zlib is linked in, because otherwise crc32() is
+ // not defined.
if (pfile_in_zip_read_info->rest_read_uncompressed == 0) {
if (pfile_in_zip_read_info->crc32_data != pfile_in_zip_read_info->crc32_wait)
err=UNZ_CRCERROR;
}
+ if (pfile_in_zip_read_info->stream_initialised)
+ inflateEnd(&pfile_in_zip_read_info->stream);
+#endif
free(pfile_in_zip_read_info->read_buffer);
pfile_in_zip_read_info->read_buffer = NULL;
- if (pfile_in_zip_read_info->stream_initialised)
- inflateEnd(&pfile_in_zip_read_info->stream);
pfile_in_zip_read_info->stream_initialised = 0;
free(pfile_in_zip_read_info);
@@ -1466,5 +1505,3 @@ Archive *makeZipArchive(SeekableReadStream *stream) {
}
} // End of namespace Common
-
-#endif
diff --git a/common/unzip.h b/common/unzip.h
index 2f87a96d2b..c460840f12 100644
--- a/common/unzip.h
+++ b/common/unzip.h
@@ -25,8 +25,6 @@
#ifndef COMMON_UNZIP_H
#define COMMON_UNZIP_H
-#ifdef USE_ZLIB
-
namespace Common {
class Archive;
@@ -62,6 +60,4 @@ Archive *makeZipArchive(SeekableReadStream *stream);
} // End of namespace Common
-#endif // USE_ZLIB
-
#endif
diff --git a/common/util.cpp b/common/util.cpp
index 742eb0035d..9e36e0f161 100644
--- a/common/util.cpp
+++ b/common/util.cpp
@@ -24,6 +24,7 @@
#include "common/util.h"
#include "common/system.h"
+#include "common/translation.h"
#include "common/config-manager.h"
namespace Common {
@@ -31,7 +32,7 @@ namespace Common {
//
// Print hexdump of the data passed in
//
-void hexdump(const byte * data, int len, int bytesPerLine, int startOffset) {
+void hexdump(const byte *data, int len, int bytesPerLine, int startOffset) {
assert(1 <= bytesPerLine && bytesPerLine <= 32);
int i;
byte c;
@@ -106,29 +107,29 @@ bool parseBool(const Common::String &val, bool &valAsBool) {
const LanguageDescription g_languages[] = {
- {"zh-cn", "Chinese (China)", ZH_CNA},
- {"zh", "Chinese (Taiwan)", ZH_TWN},
- {"cz", "Czech", CZ_CZE},
- {"nl", "Dutch", NL_NLD},
- {"en", "English", EN_ANY}, // Generic English (when only one game version exist)
- {"gb", "English (GB)", EN_GRB},
- {"us", "English (US)", EN_USA},
- {"fr", "French", FR_FRA},
- {"de", "German", DE_DEU},
- {"gr", "Greek", GR_GRE},
- {"he", "Hebrew", HE_ISR},
- {"hb", "Hebrew", HE_ISR}, // Deprecated
- {"hu", "Hungarian", HU_HUN},
- {"it", "Italian", IT_ITA},
- {"jp", "Japanese", JA_JPN},
- {"kr", "Korean", KO_KOR},
- {"nb", "Norwegian Bokm\xE5l", NB_NOR},
- {"pl", "Polish", PL_POL},
- {"br", "Portuguese", PT_BRA},
- {"ru", "Russian", RU_RUS},
- {"es", "Spanish", ES_ESP},
- {"se", "Swedish", SE_SWE},
- {0, 0, UNK_LANG}
+ { "zh-cn", "Chinese (China)", ZH_CNA },
+ { "zh", "Chinese (Taiwan)", ZH_TWN },
+ { "cz", "Czech", CZ_CZE },
+ { "nl", "Dutch", NL_NLD },
+ { "en", "English", EN_ANY }, // Generic English (when only one game version exist)
+ { "gb", "English (GB)", EN_GRB },
+ { "us", "English (US)", EN_USA },
+ { "fr", "French", FR_FRA },
+ { "de", "German", DE_DEU },
+ { "gr", "Greek", GR_GRE },
+ { "he", "Hebrew", HE_ISR },
+ { "hb", "Hebrew", HE_ISR }, // Deprecated
+ { "hu", "Hungarian", HU_HUN },
+ { "it", "Italian", IT_ITA },
+ { "jp", "Japanese", JA_JPN },
+ { "kr", "Korean", KO_KOR },
+ { "nb", "Norwegian Bokm\xE5l", NB_NOR },
+ { "pl", "Polish", PL_POL },
+ { "br", "Portuguese", PT_BRA },
+ { "ru", "Russian", RU_RUS },
+ { "es", "Spanish", ES_ESP },
+ { "se", "Swedish", SE_SWE },
+ { 0, 0, UNK_LANG }
};
Language parseLanguage(const String &str) {
@@ -167,32 +168,32 @@ const char *getLanguageDescription(Language id) {
const PlatformDescription g_platforms[] = {
- {"2gs", "2gs", "2gs", "Apple IIgs", kPlatformApple2GS},
- {"3do", "3do", "3do", "3DO", kPlatform3DO},
- {"acorn", "acorn", "acorn", "Acorn", kPlatformAcorn},
- {"amiga", "ami", "amiga", "Amiga", kPlatformAmiga},
- {"atari", "atari-st", "st", "Atari ST", kPlatformAtariST},
- {"c64", "c64", "c64", "Commodore 64", kPlatformC64},
- {"pc", "dos", "ibm", "DOS", kPlatformPC},
- {"pc98", "pc98", "pc98", "PC-98", kPlatformPC98},
- {"wii", "wii", "wii", "Nintendo Wii", kPlatformWii},
- {"coco3", "coco3", "coco3", "CoCo3", kPlatformCoCo3},
+ { "2gs", "2gs", "2gs", "Apple IIgs", kPlatformApple2GS },
+ { "3do", "3do", "3do", "3DO", kPlatform3DO },
+ { "acorn", "acorn", "acorn", "Acorn", kPlatformAcorn },
+ { "amiga", "ami", "amiga", "Amiga", kPlatformAmiga },
+ { "atari", "atari-st", "st", "Atari ST", kPlatformAtariST },
+ { "c64", "c64", "c64", "Commodore 64", kPlatformC64 },
+ { "pc", "dos", "ibm", "DOS", kPlatformPC },
+ { "pc98", "pc98", "pc98", "PC-98", kPlatformPC98 },
+ { "wii", "wii", "wii", "Nintendo Wii", kPlatformWii },
+ { "coco3", "coco3", "coco3", "CoCo3", kPlatformCoCo3 },
// 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",
// "FM TOWNS", "FmTowns", etc.
- {"fmtowns", "towns", "fm", "FM-TOWNS", kPlatformFMTowns},
-
- {"linux", "linux", "linux", "Linux", kPlatformLinux},
- {"macintosh", "mac", "mac", "Macintosh", kPlatformMacintosh},
- {"pce", "pce", "pce", "PC-Engine", kPlatformPCEngine},
- {"nes", "nes", "nes", "NES", kPlatformNES},
- {"segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD},
- {"windows", "win", "win", "Windows", kPlatformWindows},
- {"playstation", "psx", "psx", "Sony PlayStation", kPlatformPSX},
- {"cdi", "cdi", "cdi", "Phillips CD-i", kPlatformCDi},
-
- {0, 0, 0, "Default", kPlatformUnknown}
+ { "fmtowns", "towns", "fm", "FM-TOWNS", kPlatformFMTowns },
+
+ { "linux", "linux", "linux", "Linux", kPlatformLinux },
+ { "macintosh", "mac", "mac", "Macintosh", kPlatformMacintosh },
+ { "pce", "pce", "pce", "PC-Engine", kPlatformPCEngine },
+ { "nes", "nes", "nes", "NES", kPlatformNES },
+ { "segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD },
+ { "windows", "win", "win", "Windows", kPlatformWindows },
+ { "playstation", "psx", "psx", "Sony PlayStation", kPlatformPSX },
+ { "cdi", "cdi", "cdi", "Phillips CD-i", kPlatformCDi },
+
+ { 0, 0, 0, "Default", kPlatformUnknown }
};
Platform parsePlatform(const String &str) {
@@ -250,11 +251,11 @@ const char *getPlatformDescription(Platform id) {
const RenderModeDescription g_renderModes[] = {
- {"hercGreen", "Hercules Green", kRenderHercG},
- {"hercAmber", "Hercules Amber", kRenderHercA},
- {"cga", "CGA", kRenderCGA},
- {"ega", "EGA", kRenderEGA},
- {"amiga", "Amiga", kRenderAmiga},
+ { "hercGreen", _s("Hercules Green"), kRenderHercG },
+ { "hercAmber", _s("Hercules Amber"), kRenderHercA },
+ { "cga", "CGA", kRenderCGA },
+ { "ega", "EGA", kRenderEGA },
+ { "amiga", "Amiga", kRenderAmiga },
{0, 0, kRenderDefault}
};
@@ -293,12 +294,23 @@ const struct GameOpt {
uint32 option;
const char *desc;
} g_gameOptions[] = {
- { GUIO_NOSUBTITLES, "sndNoSubs" },
- { GUIO_NOMUSIC, "sndNoMusic" },
- { GUIO_NOSPEECH, "sndNoSpeech" },
- { GUIO_NOSFX, "sndNoSFX" },
- { GUIO_NOMIDI, "sndNoMIDI" },
+ { GUIO_NOSUBTITLES, "sndNoSubs" },
+ { GUIO_NOMUSIC, "sndNoMusic" },
+ { GUIO_NOSPEECH, "sndNoSpeech" },
+ { GUIO_NOSFX, "sndNoSFX" },
+ { GUIO_NOMIDI, "sndNoMIDI" },
+
{ GUIO_NOLAUNCHLOAD, "launchNoLoad" },
+
+ { GUIO_MIDIPCSPK, "midiPCSpk" },
+ { GUIO_MIDICMS, "midiCMS" },
+ { GUIO_MIDIPCJR, "midiPCJr" },
+ { GUIO_MIDIADLIB, "midiAdLib" },
+ { GUIO_MIDITOWNS, "midiTowns" },
+ { GUIO_MIDIPC98, "midiPC98" },
+ { GUIO_MIDIMT32, "midiMt32" },
+ { GUIO_MIDIGM, "midiGM" },
+
{ GUIO_NONE, 0 }
};
@@ -314,6 +326,23 @@ bool checkGameGUIOption(GameGUIOption option, const String &str) {
return false;
}
+bool checkGameGUIOptionLanguage(Language lang, const String &str) {
+ if (!str.contains("lang_")) // If no languages are specified
+ return true;
+
+ if (str.contains(getGameGUIOptionsDescriptionLanguage(lang)))
+ return true;
+
+ return false;
+}
+
+const String getGameGUIOptionsDescriptionLanguage(Language lang) {
+ if (lang == UNK_LANG)
+ return "";
+
+ return String(String("lang_") + getLanguageDescription(lang));
+}
+
uint32 parseGameGUIOptions(const String &str) {
uint32 res = 0;
@@ -324,7 +353,7 @@ uint32 parseGameGUIOptions(const String &str) {
return res;
}
-String getGameGUIOptionsDescription(uint32 options) {
+const String getGameGUIOptionsDescription(uint32 options) {
String res = "";
for (int i = 0; g_gameOptions[i].desc; i++)
@@ -336,12 +365,15 @@ String getGameGUIOptionsDescription(uint32 options) {
return res;
}
-void updateGameGUIOptions(const uint32 options) {
+void updateGameGUIOptions(const uint32 options, const String &langOption) {
+ const String newOptionString = getGameGUIOptionsDescription(options) + " " + langOption;
+
if ((options && !ConfMan.hasKey("guioptions")) ||
- (ConfMan.hasKey("guioptions") && options != parseGameGUIOptions(ConfMan.get("guioptions")))) {
- ConfMan.set("guioptions", getGameGUIOptionsDescription(options));
+ (ConfMan.hasKey("guioptions") && ConfMan.get("guioptions") != newOptionString)) {
+ ConfMan.set("guioptions", newOptionString);
ConfMan.flushToDisk();
}
}
-} // End of namespace Common
+} // End of namespace Common
+
diff --git a/common/util.h b/common/util.h
index 0b7a44f5b3..7a9cf4fb2d 100644
--- a/common/util.h
+++ b/common/util.h
@@ -215,21 +215,32 @@ enum GameGUIOption {
GUIO_NOSUBTITLES = (1 << 0),
GUIO_NOMUSIC = (1 << 1),
GUIO_NOSPEECH = (1 << 2),
- GUIO_NOSFX = (1 << 3),
- GUIO_NOMIDI = (1 << 4),
- GUIO_NOLAUNCHLOAD = (1 << 5)
+ GUIO_NOSFX = (1 << 3),
+ GUIO_NOMIDI = (1 << 4),
+ GUIO_NOLAUNCHLOAD = (1 << 5),
+
+ GUIO_MIDIPCSPK = (1 << 6),
+ GUIO_MIDICMS = (1 << 7),
+ GUIO_MIDIPCJR = (1 << 8),
+ GUIO_MIDIADLIB = (1 << 9),
+ GUIO_MIDITOWNS = (1 << 10),
+ GUIO_MIDIPC98 = (1 << 11),
+ GUIO_MIDIMT32 = (1 << 12),
+ GUIO_MIDIGM = (1 << 13)
};
bool checkGameGUIOption(GameGUIOption option, const String &str);
+bool checkGameGUIOptionLanguage(Language lang, const String &str);
uint32 parseGameGUIOptions(const String &str);
-String getGameGUIOptionsDescription(uint32 options);
+const String getGameGUIOptionsDescription(uint32 options);
+const String getGameGUIOptionsDescriptionLanguage(Language lang);
/**
* Updates the GUI options of the current config manager
* domain, when they differ to the ones passed as
* parameter.
*/
-void updateGameGUIOptions(const uint32 options);
+void updateGameGUIOptions(const uint32 options, const String &langOption);
} // End of namespace Common
diff --git a/configure b/configure
index 6ec3c0dc4f..5bfeba769d 100755
--- a/configure
+++ b/configure
@@ -119,6 +119,7 @@ _tremor=auto
_flac=auto
_mad=auto
_alsa=auto
+_seq_midi=auto
_zlib=auto
_mpeg2=no
_fluidsynth=auto
@@ -133,9 +134,12 @@ _build_scalers=yes
_build_hq_scalers=yes
_indeo3=auto
_enable_prof=no
+_unix=no
# Default vkeybd/keymapper options
_vkeybd=no
_keymapper=no
+# GUI translation options
+_translation=yes
# Default platform settings
_backend=sdl
_endian=unknown
@@ -265,6 +269,10 @@ add_line_to_config_h() {
'"$1"
}
+# Conditionally add a line of data to config.h. Takes two parameters:
+# The first one can be set to 'no' to "comment out" the line, i.e.
+# make it ineffective, use 'yes' otherwise.
+# The second param is the line to insert.
add_to_config_h_if_yes() {
if test "$1" = yes ; then
add_line_to_config_h "$2"
@@ -285,15 +293,28 @@ add_to_config_mk_if_yes() {
fi
}
-# Conditionally add a line of data to config.mk. Takes two parameters:
-# The first one can be set to 'yes' to "comment out" the line, i.e.
-# make it ineffective, use 'no' otherwise.
-# The second param is the line to insert.
-add_to_config_mk_if_no() {
- if test "$1" = no ; then
- add_line_to_config_mk "$2"
+# Conditionally add a '#define' line to config.h. Takes two parameters:
+# The first one can be set to 'yes' or 'no'. If 'yes' is used, then
+# the line "#define $2" is added to config.h, otherwise "#undef $2".
+define_in_config_h_if_yes() {
+ if test "$1" = yes ; then
+ add_line_to_config_h "#define $2"
else
- add_line_to_config_mk "# $2"
+ add_line_to_config_h "#undef $2"
+ fi
+}
+
+# Conditionally add definitions to config.h and config.mk. Takes two parameters:
+# The first one can be set to 'yes' or 'no'. If 'yes' is used, then
+# the line "#define $2" is added to config.h and "$2 = 1" to config.mk.
+# Otherwise "#undef $2" is added to config.h and "# $2 = 1" to config.mk
+define_in_config_if_yes() {
+ if test "$1" = yes ; then
+ add_line_to_config_h "#define $2"
+ add_line_to_config_mk "$2 = 1"
+ else
+ add_line_to_config_h "#undef $2"
+ add_line_to_config_mk "# $2 = 1"
fi
}
@@ -341,7 +362,7 @@ get_system_exe_extension() {
arm-riscos)
_exeext=",ff8"
;;
- dreamcast | gamecube | nds | ps2 | psp | wii)
+ dreamcast | ds | gamecube | n64 | ps2 | psp | wii)
_exeext=".elf"
;;
gp2x-linux)
@@ -625,7 +646,7 @@ Usage: $0 [OPTIONS]...
Configuration:
-h, --help display this help and exit
--backend=BACKEND backend to build (dc, gp2x, gp2xwiz, iphone,
- linuxmoto, nds, null, ps2, psp, sdl, wii, wince)
+ linuxmoto, ds, null, ps2, psp, sdl, wii, wince)
[sdl]
Installation directories:
@@ -655,7 +676,7 @@ Special configuration feature:
gamecube for Nintendo GameCube
iphone for Apple iPhone
linupy for Yopy PDA
- nds for Nintendo DS
+ ds for Nintendo DS
ps2 for PlayStation 2
psp for PlayStation Portable
wii for Nintendo Wii
@@ -676,6 +697,7 @@ Optional Features:
--disable-16bit don't enable 16bit color support
--disable-scalers exclude scalers
--disable-hq-scalers exclude HQ2x and HQ3x scalers
+ --disable-translation don't build support for translated messages
--enable-text-console use text console instead of graphical console
--enable-verbose-build enable regular echoing of commands during build process
@@ -737,6 +759,8 @@ for ac_option in $@; do
--disable-hq-scalers) _build_hq_scalers=no ;;
--enable-alsa) _alsa=yes ;;
--disable-alsa) _alsa=no ;;
+ --enable-seq-midi) _seq_midi=yes ;;
+ --disable-seq-midi) _seq_midi=no ;;
--enable-vorbis) _vorbis=yes ;;
--disable-vorbis) _vorbis=no ;;
--enable-tremor) _tremor=yes ;;
@@ -760,6 +784,8 @@ for ac_option in $@; do
--default-dynamic) _plugins_default=dynamic ;;
--enable-mt32emu) _mt32emu=yes ;;
--disable-mt32emu) _mt32emu=no ;;
+ --enable-translation) _translation=yes ;;
+ --disable-translation) _translation=no ;;
--enable-vkeybd) _vkeybd=yes ;;
--disable-vkeybd) _vkeybd=no ;;
--enable-keymapper) _keymapper=yes ;;
@@ -895,6 +921,11 @@ get_system_exe_extension $guessed_host
NATIVEEXEEXT=$_exeext
case $_host in
+android)
+ _host_os=android
+ _host_cpu=arm
+ _host_alias=arm-oe-linux-androideabi
+ ;;
arm-riscos)
_host_os=riscos
_host_cpu=arm
@@ -906,6 +937,11 @@ dreamcast)
CXXFLAGS="$CXXFLAGS -ml -m4-single-only"
LDFLAGS="$LDFLAGS -ml -m4-single-only"
;;
+ds)
+ _host_os=ds
+ _host_cpu=arm
+ _host_alias=arm-eabi
+ ;;
gamecube)
_host_os=gamecube
_host_cpu=ppc
@@ -944,10 +980,10 @@ motomagx)
_host_cpu=arm
_host_alias=arm-linux-gnueabi
;;
-nds)
- _host_os=nds
- _host_cpu=arm
- _host_alias=arm-eabi
+n64)
+ _host_os=n64
+ _host_cpu=mips
+ _host_alias=mips64
;;
neuros)
_host_os=linux
@@ -1032,7 +1068,9 @@ fi
if test "$_release_build" = yes; then
# Release mode enabled: enable optimizations. This also
# makes it possible to use -Wuninitialized, so let's do that.
- CXXFLAGS="$CXXFLAGS -O2 -Wuninitialized"
+ # We will also add a define, which indicates we are doing
+ # an build for a release version.
+ CXXFLAGS="$CXXFLAGS -O2 -Wuninitialized -DRELEASE_BUILD"
fi
@@ -1058,12 +1096,24 @@ esac
# Platform specific sanity checks
#
case $_host_os in
-gamecube | nds | wii)
+android)
+ if test -z "$ANDROID_SDK"; then
+ echo "Please set ANDROID_SDK in your environment. export ANDROID_SDK=<path to Android SDK>"
+ exit 1
+ fi
+ ;;
+ds | gamecube | wii)
if test -z "$DEVKITPRO"; then
echo "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to devkitPRO>"
exit 1
fi
;;
+n64)
+ if test -z "$N64SDK"; then
+ echo "Please set N64SDK in your environment. export N64SDK=<path to n64 sdk>"
+ exit 1
+ fi
+ ;;
ps2)
if test -z "$PS2SDK"; then
echo "Please set PS2SDK in your environment. export PS2SDK=<path to ps2 sdk>"
@@ -1120,9 +1170,12 @@ else
CXX=
for compiler in $compilers; do
if test_compiler $compiler; then
+ echo "success testing compiler: $1" >> "$TMPLOG"
CXX=$compiler
echo $CXX
break
+ else
+ echo "failure testing compiler: $1" >> "$TMPLOG"
fi
done
fi
@@ -1302,55 +1355,78 @@ echo $_host_os
case $_host_os in
amigaos*)
CXXFLAGS="$CXXFLAGS -mcrt=newlib -mstrict-align -mcpu=750 -mtune=7400"
- LDFLAGS="$LDFLAGS -mcrt=newlib -use-dynld -Lsobjs:"
+ LDFLAGS="$LDFLAGS -mcrt=newlib -use-dynld -LSDK:Local/newib/lib"
# We have to use 'long' for our 4 byte typedef because AmigaOS already typedefs (u)int32
# as (unsigned) long, and consequently we'd get a compiler error otherwise.
type_4_byte='long'
;;
+ android)
+ CXXFLAGS="$CXXFLAGS -Os -msoft-float -mtune=xscale -march=armv5te -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5TE__"
+ add_line_to_config_mk "ANDROID_SDK = $ANDROID_SDK"
+ _unix=yes
+ _seq_midi=no
+ ;;
beos*)
- DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
+ DEFINES="$DEFINES -DSYSTEM_NOT_SUPPORTING_D_TYPE"
# Needs -lbind -lsocket for the timidity MIDI driver
LDFLAGS="-L/boot/home/config/lib"
CFLAGS="-I/boot/home/config/include"
CXXFLAGS="$CXXFLAGS -fhuge-objects"
LIBS="$LIBS -lbind -lsocket"
+ _unix=yes
+ _seq_midi=no
;;
bsd* | hpux* | netbsd* | openbsd* | sunos*)
- DEFINES="$DEFINES -DUNIX"
+ _unix=yes
;;
cygwin*)
echo ERROR: Cygwin building is not supported by ScummVM anymore. Consider using MinGW.
exit 1
;;
darwin*)
- DEFINES="$DEFINES -DUNIX -DMACOSX"
+ DEFINES="$DEFINES -DMACOSX"
LIBS="$LIBS -framework AudioUnit -framework AudioToolbox -framework Carbon -framework CoreMIDI"
add_line_to_config_mk 'MACOSX = 1'
+ _unix=yes
;;
dreamcast)
DEFINES="$DEFINES -D__DC__ -DNONSTANDARD_PORT"
;;
+ ds)
+ # TODO Nintendo DS
+ DEFINES="$DEFINES -D__DS__ -DNDS -DARM9 -DARM -DNONSTANDARD_PORT"
+ CXXFLAGS="$CXXFLAGS -isystem $DEVKITPRO/libnds/include -isystem $DEVKITPRO/devkitARM/arm-eabi/include"
+ CXXFLAGS="$CXXFLAGS -mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer -mthumb-interwork"
+ CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fno-strict-aliasing"
+ LDFLAGS="$LDFLAGS -specs=ds_arm9.specs -mthumb-interwork -mno-fpu -Wl,-Map,map.txt -Wl,--gc-sections"
+ LDFLAGS="$LDFLAGS -L$DEVKITPRO/libnds/lib"
+ LIBS="$LIBS -lnds9"
+ ;;
freebsd*)
- DEFINES="$DEFINES -DUNIX"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+ _unix=yes
;;
gamecube)
CXXFLAGS="$CXXFLAGS -Os -mogc -mcpu=750 -meabi -mhard-float"
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fmodulo-sched"
CXXFLAGS="$CXXFLAGS -I$DEVKITPRO/libogc/include -I$DEVKITPRO/cube/include"
- LDFLAGS="$LDFLAGS -mogc -mcpu=750 -L$DEVKITPRO/libogc/lib/cube -L$DEVKITPRO/cube/lib"
+ # libogc is required to link the cc tests (includes _start())
+ LDFLAGS="$LDFLAGS -mogc -mcpu=750 -L$DEVKITPRO/libogc/lib/cube -L$DEVKITPRO/cube/lib -logc"
;;
haiku*)
- DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
+ DEFINES="$DEFINES -DSYSTEM_NOT_SUPPORTING_D_TYPE"
# Needs -lnetwork for the timidity MIDI driver
LIBS="$LIBS -lnetwork"
CXXFLAGS="$CXXFLAGS -fhuge-objects"
+ _unix=yes
+ _seq_midi=no
;;
irix*)
- DEFINES="$DEFINES -DUNIX -DIRIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
+ DEFINES="$DEFINES -DIRIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
LIBS="$LIBS -lmd -lfastm -lm"
_ranlib=:
+ _unix=yes
;;
linux* | uclinux*)
# When not cross-compiling, enable large file support, but don't
@@ -1358,7 +1434,7 @@ case $_host_os in
if test -z "$_host"; then
CXXFLAGS="$CXXFLAGS $(getconf LFS_CFLAGS 2>/dev/null)"
fi
- DEFINES="$DEFINES -DUNIX"
+ _unix=yes
;;
mingw*)
DEFINES="$DEFINES -DWIN32 -D__USE_MINGW_ANSI_STDIO=0"
@@ -1366,14 +1442,16 @@ case $_host_os in
OBJS="$OBJS scummvmico.o"
;;
mint*)
- DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
+ DEFINES="$DEFINES -DSYSTEM_NOT_SUPPORTING_D_TYPE"
+ _unix=yes
;;
- nds)
- # TODO nds
- DEFINES="$DEFINES -D__DS__ -DNDS -DARM9 -DARM -DNONSTANDARD_PORT"
+ n64)
+ DEFINES="$DEFINES -D__N64__ -DLIMIT_FPS -DNONSTANDARD_PORT"
+ DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER -DDISABLE_COMMAND_LINE"
+ DEFINES="$DEFINES -DDISABLE_FANCY_THEMES -DDISABLE_DOSBOX_OPL -DDISABLE_SID -DDISABLE_NES_APU"
;;
os2-emx*)
- DEFINES="$DEFINES -DUNIX"
+ _unix=yes # FIXME??? Why??
;;
ps2)
# TODO ps2
@@ -1384,15 +1462,17 @@ case $_host_os in
CXXFLAGS="$CXXFLAGS -O3 -I$PSPSDK/include -D_PSP_FW_VERSION=150"
;;
solaris*)
- DEFINES="$DEFINES -DUNIX -DSOLARIS -DSYSTEM_NOT_SUPPORTING_D_TYPE"
+ DEFINES="$DEFINES -DSOLARIS -DSYSTEM_NOT_SUPPORTING_D_TYPE"
# Needs -lbind -lsocket for the timidity MIDI driver
LIBS="$LIBS -lnsl -lsocket"
+ _unix=yes
;;
wii)
CXXFLAGS="$CXXFLAGS -Os -mrvl -mcpu=750 -meabi -mhard-float"
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fmodulo-sched"
CXXFLAGS="$CXXFLAGS -I$DEVKITPRO/libogc/include -I$DEVKITPRO/wii/include"
- LDFLAGS="$LDFLAGS -mrvl -mcpu=750 -L$DEVKITPRO/libogc/lib/wii -L$DEVKITPRO/wii/lib"
+ # libogc is required to link the cc tests (includes _start())
+ LDFLAGS="$LDFLAGS -mrvl -mcpu=750 -L$DEVKITPRO/libogc/lib/wii -L$DEVKITPRO/wii/lib -logc"
;;
wince)
CXXFLAGS="$CXXFLAGS -O3 -march=armv4 -mtune=xscale"
@@ -1402,7 +1482,7 @@ case $_host_os in
# given this is a shell script assume some type of unix
*)
echo "WARNING: could not establish system type, assuming unix like"
- DEFINES="$DEFINES -DUNIX"
+ _unix=yes
;;
esac
@@ -1410,8 +1490,21 @@ if test -n "$_host"; then
# Cross-compiling mode - add your target here if needed
echo "Cross-compiling to $_host"
case "$_host" in
+ android)
+ DEFINES="$DEFINES -DANDROID -DUSE_ARM_SMUSH_ASM"
+ _unix=yes
+ _need_memalign=yes
+ add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_GFX_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
+ _backend="android"
+ _port_mk="backends/platform/android/android.mk"
+ _seq_midi=no
+ ;;
arm-linux|arm*-linux-gnueabi|arm-*-linux)
- DEFINES="$DEFINES -DUNIX"
+ _unix=yes
_need_memalign=yes
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
@@ -1420,7 +1513,8 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
;;
arm-riscos|linupy)
- DEFINES="$DEFINES -DUNIX -DLINUPY"
+ DEFINES="$DEFINES -DLINUPY"
+ _unix=yes
_need_memalign=yes
;;
bfin*)
@@ -1435,18 +1529,36 @@ if test -n "$_host"; then
CXXFLAGS="$CXXFLAGS -O3 -funroll-loops -fschedule-insns2 -fomit-frame-pointer -fdelete-null-pointer-checks"
_need_memalign=yes
_backend="dc"
- _build_scalers="no"
- _mad="yes"
- _zlib="yes"
+ _build_scalers=no
+ _mad=yes
+ _zlib=yes
add_line_to_config_mk 'ronindir = /usr/local/ronin'
_port_mk="backends/platform/dc/dreamcast.mk"
;;
+ ds)
+ # TODO: complete this
+ DEFINES="$DEFINES -DDISABLE_FANCY_THEMES -DVECTOR_RENDERER_FORMAT=1555"
+ DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER"
+ DEFINES="$DEFINES -DREDUCE_MEMORY_USAGE -DSTREAM_AUDIO_FROM_DISK"
+ DEFINES="$DEFINES -DDISABLE_DOSBOX_OPL -DDISABLE_SID -DDISABLE_NES_APU"
+ DEFINES="$DEFINES -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE"
+ _need_memalign=yes
+ add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_GFX_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
+ _backend="ds"
+ _build_scalers=no
+ _mt32emu=no
+ _port_mk="backends/platform/ds/ds.mk"
+ ;;
gamecube)
_endian=big
_need_memalign=yes
_backend="wii"
- _build_scalers="no"
- _mt32emu="no"
+ _build_scalers=no
+ _mt32emu=no
_port_mk="backends/platform/wii/wii.mk"
add_line_to_config_mk 'GAMECUBE = 1'
add_line_to_config_h '#define GAMECUBE'
@@ -1455,10 +1567,11 @@ if test -n "$_host"; then
add_line_to_config_h "/* #define DEBUG_WII_GDB */"
;;
gp2x)
- DEFINES="$DEFINES -DUNIX -DGP2X -DNDEBUG"
+ DEFINES="$DEFINES -DGP2X -DNDEBUG"
CXXFLAGS="$CXXFLAGS -march=armv4t"
ASFLAGS="$ASFLAGS -mfloat-abi=soft"
LDFLAGS="$LDFLAGS -static"
+ _unix=yes
_need_memalign=yes
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
@@ -1466,14 +1579,17 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
_backend="gp2x"
- _build_hq_scalers="no"
- _mt32emu="no"
- _vkeybd="yes"
+ _build_hq_scalers=no
+ _mt32emu=no
+ _vkeybd=yes
+ _seq_midi=no
+ _port_mk="backends/platform/gp2x/gp2x-bundle.mk"
;;
gp2xwiz)
- DEFINES="$DEFINES -DUNIX -DGP2XWIZ -DNDEBUG"
+ DEFINES="$DEFINES -DGP2XWIZ -DNDEBUG"
CXXFLAGS="$CXXFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s"
ASFLAGS="$ASFLAGS -mfloat-abi=soft"
+ _unix=yes
_need_memalign=yes
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
@@ -1481,24 +1597,30 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
_backend="gp2xwiz"
- _build_hq_scalers="no"
- _mt32emu="no"
- _vkeybd="yes"
+ _build_hq_scalers=no
+ _mt32emu=no
+ _vkeybd=yes
+ _seq_midi=no
+ _port_mk="backends/platform/gp2xwiz/gp2xwiz-bundle.mk"
;;
iphone)
- DEFINES="$DEFINES -DIPHONE -DUNIX"
+ DEFINES="$DEFINES -DIPHONE"
+ _unix=yes
_need_memalign=yes
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
_backend="iphone"
- _build_hq_scalers="no"
+ _build_hq_scalers=no
+ _seq_midi=no
;;
m68k-atari-mint)
- DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
+ DEFINES="$DEFINES -DSYSTEM_NOT_SUPPORTING_D_TYPE"
+ _unix=yes
_endian=big
_need_memalign=yes
_ranlib=m68k-atari-mint-ranlib
_ar="m68k-atari-mint-ar cru"
+ _seq_midi=no
;;
*mingw32*)
_sdlconfig=$_host-sdl-config
@@ -1507,8 +1629,9 @@ if test -n "$_host"; then
_ranlib=$_host-ranlib
;;
motoezx)
- DEFINES="$DEFINES -DUNIX -DMOTOEZX"
+ DEFINES="$DEFINES -DMOTOEZX"
ASFLAGS="$ASFLAGS -mfpu=vfp"
+ _unix=yes
_need_memalign=yes
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
@@ -1516,14 +1639,16 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
_backend="linuxmoto"
- _build_hq_scalers="no"
- _mt32emu="no"
- _vkeybd="yes"
+ _build_hq_scalers=no
+ _mt32emu=no
+ _vkeybd=yes
+ _seq_midi=no
_port_mk="backends/platform/linuxmoto/linuxmoto.mk"
;;
motomagx)
- DEFINES="$DEFINES -DUNIX -DMOTOMAGX"
+ DEFINES="$DEFINES -DMOTOMAGX"
ASFLAGS="$ASFLAGS -mfpu=vfp"
+ _unix=yes
_need_memalign=yes
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
@@ -1531,36 +1656,42 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
_backend="linuxmoto"
- _build_hq_scalers="no"
- _mt32emu="no"
- _vkeybd="yes"
+ _build_hq_scalers=no
+ _mt32emu=no
+ _vkeybd=yes
+ _seq_midi=no
_port_mk="backends/platform/linuxmoto/linuxmoto.mk"
;;
- nds)
- # TODO: complete this
- # TODO: Maybe rename nds -> ds (would be more consistent with other backends)
- DEFINES="$DEFINES -DDISABLE_FANCY_THEMES -DVECTOR_RENDERER_FORMAT=1555"
- DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER"
- DEFINES="$DEFINES -DREDUCE_MEMORY_USAGE"
- DEFINES="$DEFINES -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE"
+ n64)
+ CXXFLAGS="$CXXFLAGS -mno-extern-sdata --param max-inline-insns-auto=20 -fomit-frame-pointer"
+ CXXFLAGS="$CXXFLAGS -march=vr4300 -mtune=vr4300 -mhard-float"
+ LDFLAGS="$LDFLAGS -march=vr4300 -mtune=vr4300 -nodefaultlibs -nostartfiles -mno-crt0"
+ LDFLAGS="$LDFLAGS -L$N64SDK/hkz-libn64 -L$N64SDK/lib"
+ LDFLAGS="$LDFLAGS -T n64ld_cpp.x -Xlinker -Map -Xlinker scummvm.map"
+ _backend="n64"
_need_memalign=yes
- _backend="nds"
- _build_hq_scalers="no"
- _mt32emu="no"
- _port_mk="backends/platform/ds/ds.mk"
- # TODO: Enable more ARM optimizations -- requires testing!
- add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
- add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
- #add_line_to_config_mk 'USE_ARM_GFX_ASM = 1'
- #add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
- #add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
+ _mt32emu=no
+ _vkeybd=yes
+ _build_scalers=no
+ _indeo3=no
+ _translation=no
+ _keymapper=no
+ _text_console=no
+ _vkeybd=yes
+ _dynamic_modules=no
+ _plugins_default=static
+ # Force use of libmad, libtremor and zlib
+ _mad=yes
+ _tremor=yes
+ _zlib=yes
;;
neuros)
- DEFINES="$DEFINES -DUNIX -DNEUROS"
+ DEFINES="$DEFINES -DNEUROS"
+ _unix=yes
_need_memalign=yes
_backend='null'
- _build_hq_scalers="no"
- _mt32emu="no"
+ _build_hq_scalers=no
+ _mt32emu=no
;;
ppc-amigaos)
_endian=big
@@ -1569,16 +1700,17 @@ if test -n "$_host"; then
ps2)
# TODO: complete this
DEFINES="$DEFINES -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DDISABLE_DOSBOX_OPL"
+ DEFINES="$DEFINES -DDISABLE_SID -DDISABLE_NES_APU"
_need_memalign=yes
_backend="ps2"
- _build_scalers="no"
- _mt32emu="no"
+ _build_scalers=no
+ _mt32emu=no
# HACK to enable mad & zlib (they are not properly detected due to linker issues).
# This trick doesn't work for tremor right now, as the PS2 port the resulting library
# libtremor, while our code later on expects it to be called libvorbisidec.
# TODO: Enable tremor, e.g. by adding -ltremor or by renaming the lib.
- _mad="yes"
- _zlib="yes"
+ _mad=yes
+ _zlib=yes
# HACK to fix compilation of C source files for now.
add_line_to_config_mk 'CC = ee-gcc'
# HACK to fix linking for now. It seems ee-g++ does not handle linking correctly.
@@ -1598,14 +1730,15 @@ if test -n "$_host"; then
psp)
_need_memalign=yes
_backend="psp"
- _build_scalers="no"
- _mt32emu="no"
+ _build_scalers=no
+ _mt32emu=no
_port_mk="backends/platform/psp/psp.mk"
;;
samsungtv)
- DEFINES="$DEFINES -DUNIX -DSAMSUNGTV -DDISABLE_COMMAND_LINE"
+ DEFINES="$DEFINES -DSAMSUNGTV -DDISABLE_COMMAND_LINE"
ASFLAGS="$ASFLAGS -mfpu=vfp"
HOSTEXEEXT=".so"
+ _unix=yes
_need_memalign=yes
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
@@ -1613,14 +1746,14 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
_backend="samsungtv"
- _mt32emu="no"
- _vkeybd="yes"
+ _mt32emu=no
+ _vkeybd=yes
;;
wii)
_endian=big
_need_memalign=yes
_backend="wii"
- _build_scalers="no"
+ _build_scalers=no
_port_mk="backends/platform/wii/wii.mk"
add_line_to_config_mk 'GAMECUBE = 0'
add_line_to_config_h "#define DEBUG_WII_USBGECKO"
@@ -1640,7 +1773,7 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
_backend="wince"
- _mt32emu="no"
+ _mt32emu=no
_port_mk="backends/platform/wince/wince.mk"
;;
*)
@@ -1719,21 +1852,25 @@ esac
#
case $_endian in
big)
- add_line_to_config_h '/* #define SCUMM_LITTLE_ENDIAN */'
+ add_line_to_config_h '#undef SCUMM_LITTLE_ENDIAN'
add_line_to_config_h '#define SCUMM_BIG_ENDIAN'
;;
little)
add_line_to_config_h '#define SCUMM_LITTLE_ENDIAN'
- add_line_to_config_h '/* #define SCUMM_BIG_ENDIAN */'
+ add_line_to_config_h '#undef SCUMM_BIG_ENDIAN'
;;
*)
exit 1
;;
esac
-add_to_config_h_if_yes $_have_x86 '#define HAVE_X86'
+define_in_config_h_if_yes $_have_x86 'HAVE_X86'
+
+define_in_config_h_if_yes $_need_memalign 'SCUMM_NEED_ALIGNMENT'
-add_to_config_h_if_yes $_need_memalign '#define SCUMM_NEED_ALIGNMENT'
+if test "$_unix" = yes ; then
+ DEFINES="$DEFINES -DUNIX"
+fi
#
# Check whether to enable a verbose build
@@ -1821,7 +1958,7 @@ POST_OBJS_FLAGS := -Wl,-no-whole-archive
LIBS += -ldl
'
;;
- linux*)
+ linux*|android)
_def_plugin='
#define PLUGIN_PREFIX "lib"
#define PLUGIN_SUFFIX ".so"
@@ -1884,7 +2021,7 @@ PLUGIN_SUFFIX := .plg
PLUGIN_EXTRA_DEPS = $(EXECUTABLE)
CXXFLAGS += -DDYNAMIC_MODULES
LDFLAGS += -Wl,-T$(srcdir)/backends/platform/psp/main_prog.ld
-PLUGIN_LDFLAGS = -nostartfiles -Wl,-q,--just-symbols,$(EXECUTABLE),--retain-symbols-file,$(srcdir)/backends/platform/psp/plugin.syms,-T$(srcdir)/backends/platform/psp/plugin.ld -lstdc++ -lc -lm
+PLUGIN_LDFLAGS = -nostartfiles -Wl,-q,--just-symbols,$(EXECUTABLE),--retain-symbols-file,$(srcdir)/backends/platform/psp/plugin.syms,-T$(srcdir)/backends/platform/psp/plugin.ld -lstdc++ -lc -lm -Wl,--wrap,memcpy
PRE_OBJS_FLAGS := -Wl,--whole-archive
POST_OBJS_FLAGS := -Wl,--no-whole-archive
'
@@ -1902,40 +2039,22 @@ fi
#
# Check whether integrated MT-32 emulator support is requested
#
-if test "$_mt32emu" = no ; then
- _def_mt32emu='#undef USE_MT32EMU'
-else
- _def_mt32emu='#define USE_MT32EMU'
-fi
-add_to_config_mk_if_yes "$_mt32emu" 'USE_MT32EMU = 1'
+define_in_config_if_yes "$_mt32emu" 'USE_MT32EMU'
#
# Check whether 16bit color support is requested
#
-if test "$_16bit" = no ; then
- _def_16bit='#undef USE_RGB_COLOR'
-else
- _def_16bit='#define USE_RGB_COLOR'
-fi
-add_to_config_mk_if_yes "$_16bit" 'USE_RGB_COLOR = 1'
+define_in_config_if_yes "$_16bit" 'USE_RGB_COLOR'
#
# Check whether to enable the (hq) scalers
#
if test "$_build_scalers" = no ; then
_build_hq_scalers=no
- _def_scalers='#undef USE_SCALERS'
-else
- _def_scalers='#define USE_SCALERS'
fi
-add_to_config_mk_if_yes "$_build_scalers" 'USE_SCALERS = 1'
+define_in_config_if_yes "$_build_scalers" 'USE_SCALERS'
-if test "$_build_hq_scalers" = no ; then
- _def_hq_scalers='#undef USE_HQ_SCALERS'
-else
- _def_hq_scalers='#define USE_HQ_SCALERS'
-fi
-add_to_config_mk_if_yes "$_build_hq_scalers" 'USE_HQ_SCALERS = 1'
+define_in_config_if_yes "$_build_hq_scalers" 'USE_HQ_SCALERS'
#
# Check whether to compile the Indeo3 decoder
@@ -1943,17 +2062,12 @@ add_to_config_mk_if_yes "$_build_hq_scalers" 'USE_HQ_SCALERS = 1'
if test "$_indeo3" = auto ; then
# Autodetect. Build if either the gob engine or plugins are enabled
if test `get_engine_build gob` = yes || test "$_dynamic_modules" = yes ; then
- _indeo3="yes"
+ _indeo3=yes
else
- _indeo3="no"
+ _indeo3=no
fi
fi
-if test "$_indeo3" = no ; then
- _def_indeo3='#undef USE_INDEO3'
-else
- _def_indeo3='#define USE_INDEO3'
-fi
-add_to_config_mk_if_yes "$_indeo3" 'USE_INDEO3 = 1'
+define_in_config_if_yes "$_indeo3" 'USE_INDEO3'
#
# Check for math lib
@@ -1961,7 +2075,7 @@ add_to_config_mk_if_yes "$_indeo3" 'USE_INDEO3 = 1'
cat > $TMPC << EOF
int main(void) { return 0; }
EOF
-cc_check -lm && LDFLAGS="$LDFLAGS -lm"
+cc_check -lm && LIBS="$LIBS -lm"
#
# Check for Ogg Vorbis
@@ -1977,13 +2091,10 @@ EOF
-lvorbisfile -lvorbis -logg && _vorbis=yes
fi
if test "$_vorbis" = yes ; then
- _def_vorbis='#define USE_VORBIS'
LIBS="$LIBS $OGG_LIBS $VORBIS_LIBS -lvorbisfile -lvorbis -logg"
INCLUDES="$INCLUDES $OGG_CFLAGS $VORBIS_CFLAGS"
-else
- _def_vorbis='#undef USE_VORBIS'
fi
-add_to_config_mk_if_yes "$_vorbis" 'USE_VORBIS = 1'
+define_in_config_if_yes "$_vorbis" 'USE_VORBIS'
echo "$_vorbis"
#
@@ -2000,15 +2111,15 @@ EOF
_tremor=yes
fi
if test "$_tremor" = yes && test "$_vorbis" = no; then
- _def_tremor='#define USE_TREMOR'
- _def_vorbis='#define USE_VORBIS'
+ add_line_to_config_h '#define USE_TREMOR'
+ add_line_to_config_h '#define USE_VORBIS'
LIBS="$LIBS $TREMOR_LIBS -lvorbisidec"
INCLUDES="$INCLUDES $TREMOR_CFLAGS"
else
if test "$_vorbis" = yes; then
_tremor="no (Ogg Vorbis/Tremor support is mutually exclusive)"
fi
- _def_tremor='#undef USE_TREMOR'
+ add_line_to_config_h '#undef USE_TREMOR'
fi
add_to_config_mk_if_yes "$_tremor" 'USE_TREMOR = 1'
echo "$_tremor"
@@ -2032,17 +2143,14 @@ EOF
fi
fi
if test "$_flac" = yes ; then
- _def_flac='#define USE_FLAC'
if test "$_vorbis" = yes ; then
LIBS="$LIBS $FLAC_LIBS $OGG_LIBS -lFLAC -logg"
else
LIBS="$LIBS $FLAC_LIBS -lFLAC"
fi
INCLUDES="$INCLUDES $FLAC_CFLAGS"
-else
- _def_flac='#undef USE_FLAC'
fi
-add_to_config_mk_if_yes "$_flac" 'USE_FLAC = 1'
+define_in_config_if_yes "$_flac" 'USE_FLAC'
echo "$_flac"
#
@@ -2058,13 +2166,10 @@ EOF
cc_check $MAD_CFLAGS $MAD_LIBS -lmad && _mad=yes
fi
if test "$_mad" = yes ; then
- _def_mad='#define USE_MAD'
LIBS="$LIBS $MAD_LIBS -lmad"
INCLUDES="$INCLUDES $MAD_CFLAGS"
-else
- _def_mad='#undef USE_MAD'
fi
-add_to_config_mk_if_yes "$_mad" 'USE_MAD = 1'
+define_in_config_if_yes "$_mad" 'USE_MAD'
echo "$_mad"
#
@@ -2080,15 +2185,26 @@ EOF
cc_check $ALSA_CFLAGS $ALSA_LIBS -lasound && _alsa=yes
fi
if test "$_alsa" = yes ; then
- _def_alsa='#define USE_ALSA'
LIBS="$LIBS $ALSA_LIBS -lasound"
INCLUDES="$INCLUDES $ALSA_CFLAGS"
-else
- _def_alsa='#undef USE_ALSA'
fi
+define_in_config_h_if_yes "$_alsa" 'USE_ALSA'
echo "$_alsa"
#
+# Check for SEQ MIDI
+#
+echocheck "SEQ MIDI"
+if test "$_seq_midi" = auto ; then
+ # TODO: Test for /dev/sequencer presence? Or maybe just for /dev ?
+ # For now, we just always enable it when "unix" mode is on (backends
+ # that do not want it can disable it by setting _seq_midi=no).
+ _seq_midi="$_unix"
+fi
+define_in_config_h_if_yes "$_seq_midi" 'USE_SEQ_MIDI'
+echo "$_seq_midi"
+
+#
# Check for ZLib
#
echocheck "zlib"
@@ -2102,13 +2218,10 @@ EOF
cc_check $ZLIB_CFLAGS $ZLIB_LIBS -lz && _zlib=yes
fi
if test "$_zlib" = yes ; then
- _def_zlib='#define USE_ZLIB'
LIBS="$LIBS $ZLIB_LIBS -lz"
INCLUDES="$INCLUDES $ZLIB_CFLAGS"
-else
- _def_zlib='#undef USE_ZLIB'
fi
-add_to_config_mk_if_yes "$_zlib" 'USE_ZLIB = 1'
+define_in_config_if_yes "$_zlib" 'USE_ZLIB'
echo "$_zlib"
#
@@ -2148,13 +2261,10 @@ EOF
fi
fi
if test "$_mpeg2" = yes ; then
- _def_mpeg2='#define USE_MPEG2'
INCLUDES="$INCLUDES $MPEG2_CFLAGS"
LIBS="$LIBS $MPEG2_LIBS -lmpeg2"
-else
- _def_mpeg2='#undef USE_MPEG2'
fi
-add_to_config_mk_if_yes "$_mpeg2" 'USE_MPEG2 = 1'
+define_in_config_if_yes "$_mpeg2" 'USE_MPEG2'
echo "$_mpeg2"
#
@@ -2170,7 +2280,6 @@ EOF
cc_check $FLUIDSYNTH_CFLAGS $FLUIDSYNTH_LIBS -lfluidsynth && _fluidsynth=yes
fi
if test "$_fluidsynth" = yes ; then
- _def_fluidsynth='#define USE_FLUIDSYNTH'
case $_host_os in
mingw*)
LIBS="$LIBS $FLUIDSYNTH_LIBS -lfluidsynth -ldsound -lwinmm"
@@ -2180,9 +2289,8 @@ if test "$_fluidsynth" = yes ; then
;;
esac
INCLUDES="$INCLUDES $FLUIDSYNTH_CFLAGS"
-else
- _def_fluidsynth='#undef USE_FLUIDSYNTH'
fi
+define_in_config_h_if_yes "$_fluidsynth" 'USE_FLUIDSYNTH'
echo "$_fluidsynth"
#
@@ -2202,12 +2310,13 @@ int main(void) {
char *x = readline("");
}
EOF
- cc_check $READLINE_CFLAGS $READLINE_LIBS $_READLINE_LIBS && _readline=yes
+ cc_check_no_clean $READLINE_CFLAGS $READLINE_LIBS $_READLINE_LIBS && _readline=yes
if test "$_readline" = no ; then
_READLINE_LIBS="-lreadline -ltermcap"
- cc_check $READLINE_CFLAGS $READLINE_LIBS $_READLINE_LIBS && _readline=yes
+ cc_check_no_clean $READLINE_CFLAGS $READLINE_LIBS $_READLINE_LIBS && _readline=yes
fi
fi
+ cc_check_clean
echo "$_readline"
else
_readline=no
@@ -2215,18 +2324,12 @@ else
fi
if test "$_readline" = yes ; then
- _def_readline='#define USE_READLINE'
LIBS="$LIBS $READLINE_LIBS $_READLINE_LIBS"
INCLUDES="$INCLUDES $READLINE_CFLAGS"
-else
- _def_readline='#undef USE_READLINE'
fi
+define_in_config_h_if_yes "$_readline" 'USE_READLINE'
-if test "$_text_console" = yes ; then
- _def_text_console='#define USE_TEXT_CONSOLE'
-else
- _def_text_console='#undef USE_TEXT_CONSOLE'
-fi
+define_in_config_h_if_yes "$_text_console" 'USE_TEXT_CONSOLE'
#
# Check for nasm
@@ -2284,8 +2387,7 @@ if test "$_have_x86" = yes ; then
fi
fi
-add_to_config_h_if_yes $_nasm '#define USE_NASM'
-add_to_config_mk_if_yes $_nasm 'USE_NASM = 1'
+define_in_config_if_yes $_nasm 'USE_NASM'
#
# Enable vkeybd / keymapper
@@ -2297,6 +2399,30 @@ if test "$_keymapper" = yes ; then
DEFINES="$DEFINES -DENABLE_KEYMAPPER"
fi
+# Check whether to build translation support
+#
+echo_n "Building translation support... "
+define_in_config_if_yes $_translation 'USE_TRANSLATION'
+if test "$_translation" = no ; then
+ echo "no"
+else
+ echo_n "yes ("
+
+ cat > $TMPC << EOF
+#include <locale.h>
+int main(void) { setlocale(LC_ALL, ""); return 0; }
+EOF
+ _detectlang=no
+ cc_check $LDFLAGS $CXXFLAGS && _detectlang=yes
+
+ define_in_config_h_if_yes $_detectlang 'USE_DETECTLANG'
+ if test "$_detectlang" = yes ; then
+ echo "with runtime language detection)"
+ else
+ echo "without runtime language detection)"
+ fi
+fi
+
#
# Figure out installation directories
#
@@ -2362,11 +2488,49 @@ fi
# Backend related stuff
#
case $_backend in
+ android)
+ static_libs=''
+ system_libs=''
+ for lib in $LIBS; do
+ case $lib in
+ -lz|-lm)
+ system_libs="$system_libs $lib"
+ ;;
+ *)
+ static_libs="$static_libs $lib"
+ ;;
+ esac
+ done
+
+ # -lgcc is carefully placed here - we want to catch
+ # all toolchain symbols in *our* libraries rather
+ # than pick up anything unhygenic from the Android libs.
+ LIBS="-Wl,-Bstatic $static_libs -Wl,-Bdynamic -lgcc $system_libs -lstdc++ -llog -lGLESv1_CM"
+ DEFINES="$DEFINES -D__ANDROID__ -DANDROID_BACKEND -DREDUCE_MEMORY_USAGE"
+ add_line_to_config_mk 'PLUGIN_LDFLAGS += $(LDFLAGS) -Wl,-shared,-Bsymbolic'
+
+ # Work around an Android 2.0+ run-time linker bug:
+ # The linker doesn't actually look in previously
+ # loaded libraries when trying to resolve symbols -
+ # effectively turning all dlopen(RTLD_GLOBAL) calls
+ # into dlopen(RTLD_LOCAL). It *does* look in
+ # DT_NEEDED libraries, so the workaround is to add an
+ # (otherwise unnecessary) dependency from plugins back
+ # to the main libscummvm.so.
+ add_line_to_config_mk 'PLUGIN_LDFLAGS += -Lbuild.tmp -lscummvm'
+ add_line_to_config_mk 'PLUGIN_EXTRA_DEPS += build.tmp/libscummvm.so'
+ ;;
dc)
INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/dc -isystem $(ronindir)/include'
LDFLAGS="$LDFLAGS -Wl,-Ttext,0x8c010000 -nostartfiles "'$(ronindir)/lib/crt0.o -L$(ronindir)/lib'
LIBS="$LIBS -lronin -lm"
;;
+ ds)
+ # TODO ds
+ INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/ds/arm9/source'
+ INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/ds/commoninclude'
+ INCLUDES="$INCLUDES "'-Ibackends/platform/ds/arm9/data'
+ ;;
gp2x)
find_sdlconfig
INCLUDES="$INCLUDES `$_sdlconfig --prefix="$_sdlpath" --cflags`"
@@ -2391,8 +2555,12 @@ case $_backend in
LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`"
DEFINES="$DEFINES -DSDL_BACKEND -DLINUXMOTO"
;;
- nds)
- # TODO nds
+ n64)
+ INCLUDES="$INCLUDES "'-I$(N64SDK)/include'
+ INCLUDES="$INCLUDES "'-I$(N64SDK)/mips64/include'
+ INCLUDES="$INCLUDES "'-I$(N64SDK)/hkz-libn64'
+ INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/n64'
+ LIBS="$LIBS -lpakfs -lframfs -ln64 -ln64utils -lromfs -lm -lstdc++ -lc -lgcc -lz -lnosys"
;;
null)
DEFINES="$DEFINES -DUSE_NULL_DRIVER"
@@ -2407,14 +2575,8 @@ case $_backend in
;;
psp)
DEFINES="$DEFINES -D__PSP__ -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DDISABLE_DOSBOX_OPL"
- INCLUDES="$INCLUDES -I$PSPDEV/psp/include/SDL"
- LIBS="$LIBS -lpng -lSDL -Wl,-Map,mapfile.txt"
- SDLLIBS=`$PSPDEV/psp/bin/sdl-config --libs`
-
- if `echo "$SDLLIBS" | grep ".*-lGL.*" 1>/dev/null 2>&1`
- then
- LIBS="$LIBS -lGL"
- fi
+ LIBS="$LIBS -lpng -Wl,-Map,mapfile.txt"
+ LDFLAGS="$LDFLAGS -Wl,--wrap,memcpy"
;;
samsungtv)
find_sdlconfig
@@ -2460,7 +2622,7 @@ if test "$have_gcc" = yes ; then
case $_host_os in
# newlib-based system include files suppress non-C89 function
# declarations under __STRICT_ANSI__
- mingw* | dreamcast | wii | gamecube | psp | wince | amigaos*)
+ amigaos* | android | ds | dreamcast | gamecube | mingw* | n64 | psp | wii | wince )
CXXFLAGS="$CXXFLAGS -W -Wno-unused-parameter"
;;
*)
@@ -2481,7 +2643,7 @@ fi;
# Some platforms use certain GNU extensions in header files
case $_host_os in
-gamecube | psp | wii)
+android | gamecube | psp | wii)
;;
*)
CXXFLAGS="$CXXFLAGS -pedantic"
@@ -2589,25 +2751,6 @@ typedef signed $type_1_byte int8;
typedef signed $type_2_byte int16;
typedef signed $type_4_byte int32;
-/* Libs */
-$_def_vorbis
-$_def_tremor
-$_def_flac
-$_def_mad
-$_def_alsa
-$_def_zlib
-$_def_mpeg2
-$_def_fluidsynth
-$_def_readline
-
-/* Options */
-$_def_text_console
-$_def_mt32emu
-$_def_indeo3
-$_def_16bit
-$_def_scalers
-$_def_hq_scalers
-
/* Plugin settings */
$_def_plugin
diff --git a/dists/android/AndroidManifest.xml b/dists/android/AndroidManifest.xml
new file mode 100644
index 0000000000..55e3bf2f38
--- /dev/null
+++ b/dists/android/AndroidManifest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?> <!-- -*- xml -*- -->
+<!-- NB: android:versionCode needs to be bumped for formal releases -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.inodes.gus.scummvm"
+ android:versionCode="6" android:versionName="1.2.0svn"
+ android:installLocation="preferExternal">
+
+ <!-- This version is built against a cupcake (and newer?) ABI.
+ It works on Android 1.5 (SDK 3) and newer.
+ -->
+ <uses-sdk android:minSdkVersion="3"
+ android:targetSdkVersion="8" />
+
+ <application android:name=".ScummVMApplication"
+ android:label="@string/app_name"
+ android:description="@string/app_desc"
+ android:icon="@drawable/scummvm"
+ android:persistent="true">
+ <activity android:name=".ScummVMActivity"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:screenOrientation="landscape"
+ android:configChanges="orientation|keyboardHidden"
+ android:windowSoftInputMode="adjustResize">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".Unpacker"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:screenOrientation="landscape"
+ android:configChanges="orientation|keyboardHidden">
+ <meta-data android:name="org.inodes.gus.unpacker.nextActivity"
+ android:value="org.inodes.gus.scummvm/.ScummVMActivity" />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <permission android:name="org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN"
+ android:label="@string/scummvm_perm_plugin_label"
+ android:description="@string/scummvm_perm_plugin_desc"
+ android:protectionLevel="signature" />
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+
+ <!-- Always needs some sort of qwerty keyboard.
+ Can work with a D-pad / trackball -->
+ <uses-configuration android:reqFiveWayNav="true"
+ android:reqKeyboardType="qwerty"/>
+ <!-- .. or touchscreen -->
+ <uses-configuration android:reqTouchScreen="finger"
+ android:reqKeyboardType="qwerty"/>
+ <uses-configuration android:reqTouchScreen="stylus"
+ android:reqKeyboardType="qwerty"/>
+</manifest>
diff --git a/dists/android/AndroidManifest.xml.in b/dists/android/AndroidManifest.xml.in
new file mode 100644
index 0000000000..26a94f957b
--- /dev/null
+++ b/dists/android/AndroidManifest.xml.in
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?> <!-- -*- xml -*- -->
+<!-- NB: android:versionCode needs to be bumped for formal releases -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.inodes.gus.scummvm"
+ android:versionCode="6" android:versionName="@VERSION@"
+ android:installLocation="preferExternal">
+
+ <!-- This version works on Android 1.5 (SDK 3) and newer, but we
+ want Android 2.2 (SDK 8) defaults and features.
+ -->
+ <uses-sdk android:minSdkVersion="3"
+ android:targetSdkVersion="8" />
+
+ <application android:name=".ScummVMApplication"
+ android:label="@string/app_name"
+ android:description="@string/app_desc"
+ android:icon="@drawable/scummvm"
+ android:persistent="true">
+ <activity android:name=".ScummVMActivity"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:screenOrientation="landscape"
+ android:configChanges="orientation|keyboardHidden"
+ android:windowSoftInputMode="adjustResize">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".Unpacker"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:screenOrientation="landscape"
+ android:configChanges="orientation|keyboardHidden">
+ <meta-data android:name="org.inodes.gus.unpacker.nextActivity"
+ android:value="org.inodes.gus.scummvm/.ScummVMActivity" />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <permission android:name="org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN"
+ android:label="@string/scummvm_perm_plugin_label"
+ android:description="@string/scummvm_perm_plugin_desc"
+ android:protectionLevel="signature" />
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+
+ <!-- Always needs some sort of qwerty keyboard.
+ Can work with a D-pad / trackball -->
+ <uses-configuration android:reqFiveWayNav="true"
+ android:reqKeyboardType="qwerty"/>
+ <!-- .. or touchscreen -->
+ <uses-configuration android:reqTouchScreen="finger"
+ android:reqKeyboardType="qwerty"/>
+ <uses-configuration android:reqTouchScreen="stylus"
+ android:reqKeyboardType="qwerty"/>
+</manifest>
diff --git a/dists/android/mkmanifest.pl b/dists/android/mkmanifest.pl
new file mode 100755
index 0000000000..62caa64a55
--- /dev/null
+++ b/dists/android/mkmanifest.pl
@@ -0,0 +1,170 @@
+#!/usr/bin/perl
+
+use File::Basename qw(dirname);
+use File::Path qw(mkpath);
+use IO::File;
+use XML::Writer;
+use XML::Parser;
+use Getopt::Long;
+
+use warnings;
+use strict;
+
+use constant ANDROID => 'http://schemas.android.com/apk/res/android';
+
+my $id;
+my $package_versionName;
+my $package_versionCode;
+my $configure = 'configure';
+my $stringres = 'res/string/values.xml';
+my $manifest = 'AndroidManifest.xml';
+my $master_manifest;
+my @unpack_libs;
+GetOptions('id=s' => \$id,
+ 'version-name=s' => \$package_versionName,
+ 'version-code=i' => \$package_versionCode,
+ 'configure=s' => \$configure,
+ 'stringres=s' => \$stringres,
+ 'manifest=s' => \$manifest,
+ 'master-manifest=s' => \$master_manifest,
+ 'unpacklib=s' => \@unpack_libs,
+ ) or die;
+die "Missing required arg"
+ unless $id and $package_versionName and $package_versionCode;
+
+
+sub grope_engine_info {
+ my $configure = shift;
+ my @ret;
+ while (<$configure>) {
+ m/^add_engine \s+ (\w+) \s+ "(.*?)" \s+ \w+ (?:\s+ "([\w\s]*)")?/x
+ or next;
+ my $subengines = $3 || '';
+ my %info = (id => $1, name => $2,
+ subengines => [split / /, $subengines]);
+ push @ret, \%info;
+ }
+ return @ret;
+}
+
+sub read_constraints {
+ my $manifest = shift;
+ my @constraints;
+ my $parser = new XML::Parser Handlers => {
+ Start => sub {
+ my $expat = shift;
+ my $elem = shift;
+ return if $elem !~
+ /^(uses-configuration|supports-screens|uses-sdk)$/;
+ my @constraint = ($elem);
+ while (@_) {
+ my $attr = shift;
+ my $value = shift;
+ $attr = [ANDROID, $attr] if $attr =~ s/^android://;
+ push @constraint, $attr, $value;
+ }
+ push @constraints, \@constraint;
+ },
+ };
+ $parser->parse($manifest);
+ return @constraints;
+}
+
+sub print_stringres {
+ my $output = shift;
+ my $info = shift;
+
+ my $writer = new XML::Writer(OUTPUT => $output, ENCODING => 'utf-8',
+ DATA_MODE => 1, DATA_INDENT => 2);
+
+ $writer->xmlDecl();
+ $writer->startTag('resources');
+
+ while (my ($k,$v) = each %$info) {
+ $writer->dataElement('string', $v, name => $k);
+ }
+
+ $writer->endTag('resources');
+ $writer->end();
+}
+
+sub print_manifest {
+ my $output = shift;
+ my $info = shift;
+ my $constraints = shift;
+
+ my $writer = new XML::Writer(OUTPUT => $output, ENCODING => 'utf-8',
+ DATA_MODE => 1, DATA_INDENT => 2,
+ NAMESPACES => 1,
+ PREFIX_MAP => {ANDROID, 'android'});
+
+ $writer->xmlDecl();
+
+ $writer->startTag(
+ 'manifest',
+ 'package' => "org.inodes.gus.scummvm.plugin.$info->{name}",
+ [ANDROID, 'versionCode'] => $package_versionCode,
+ [ANDROID, 'versionName'] => $package_versionName,
+ [ANDROID, 'installLocation'] => 'preferExternal',
+ );
+
+ $writer->startTag(
+ 'application',
+ [ANDROID, 'label'] => '@string/app_name',
+ [ANDROID, 'description'] => '@string/app_desc',
+ [ANDROID, 'icon'] => '@drawable/scummvm',
+ );
+
+ $writer->startTag(
+ 'receiver',
+ [ANDROID, 'name'] => 'org.inodes.gus.scummvm.PluginProvider',
+ [ANDROID, 'process'] => 'org.inodes.gus.scummvm');
+
+ $writer->startTag('intent-filter');
+ $writer->emptyTag('action', [ANDROID, 'name'] =>
+ 'org.inodes.gus.scummvm.action.PLUGIN_QUERY');
+ $writer->emptyTag('category', [ANDROID, 'name'] =>
+ 'android.intent.category.INFO');
+ $writer->endTag('intent-filter');
+ $writer->emptyTag(
+ 'meta-data',
+ [ANDROID, 'name'] => 'org.inodes.gus.scummvm.meta.UNPACK_LIB',
+ [ANDROID, 'value'] => $_)
+ for @{$info->{unpack_libs}};
+
+ $writer->endTag('receiver');
+ $writer->endTag('application');
+
+ $writer->emptyTag('uses-permission', [ANDROID, 'name'] =>
+ 'org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN');
+
+ $writer->emptyTag(@$_) foreach @$constraints;
+
+ $writer->endTag('manifest');
+ $writer->end();
+}
+
+
+my %engines;
+for my $engine (grope_engine_info(new IO::File $configure, 'r')) {
+ $engines{$engine->{id}} = $engine;
+}
+
+my @games = ($id, @{$engines{$id}{subengines}});
+my $games_desc = join('; ', map $engines{$_}{name}, @games);
+
+my @constraints = read_constraints(new IO::File $master_manifest, 'r');
+
+print "Writing $stringres ...\n";
+mkpath(dirname($stringres));
+print_stringres(IO::File->new($stringres, 'w'),
+ {app_name => qq{ScummVM plugin: "$id"},
+ app_desc => "Game engine for: $games_desc",
+ });
+
+print "Writing $manifest ...\n";
+mkpath(dirname($manifest));
+print_manifest(IO::File->new($manifest, 'w'),
+ {name => $id, unpack_libs => \@unpack_libs}, \@constraints);
+
+exit 0;
diff --git a/dists/android/res/drawable/gradient.xml b/dists/android/res/drawable/gradient.xml
new file mode 100644
index 0000000000..dbfd9b5b34
--- /dev/null
+++ b/dists/android/res/drawable/gradient.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <gradient
+ android:startColor="#e9bb8b"
+ android:endColor="#d16e09"
+ android:angle="315" />
+</shape>
diff --git a/dists/android/res/drawable/scummvm.png b/dists/android/res/drawable/scummvm.png
new file mode 100644
index 0000000000..d48cf7f6e8
--- /dev/null
+++ b/dists/android/res/drawable/scummvm.png
Binary files differ
diff --git a/dists/android/res/drawable/scummvm_big.png b/dists/android/res/drawable/scummvm_big.png
new file mode 100644
index 0000000000..2c7a8c932d
--- /dev/null
+++ b/dists/android/res/drawable/scummvm_big.png
Binary files differ
diff --git a/dists/android/res/layout/main.xml b/dists/android/res/layout/main.xml
new file mode 100644
index 0000000000..f5276ce41b
--- /dev/null
+++ b/dists/android/res/layout/main.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<org.inodes.gus.scummvm.EditableSurfaceView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:id="@+id/main_surface"
+ android:gravity="center"
+ android:keepScreenOn="true"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+/>
diff --git a/dists/android/res/layout/splash.xml b/dists/android/res/layout/splash.xml
new file mode 100644
index 0000000000..e9fd5f70e7
--- /dev/null
+++ b/dists/android/res/layout/splash.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:background="@drawable/gradient"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:adjustViewBounds="true"
+ android:scaleType="fitCenter"
+ android:src="@drawable/scummvm_big" />
+ <ProgressBar android:id="@+id/progress"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="300dip"
+ android:layout_height="wrap_content"
+ android:padding="20dip"/>
+</LinearLayout>
diff --git a/dists/android/res/values/strings.xml b/dists/android/res/values/strings.xml
new file mode 100644
index 0000000000..e06509d3ed
--- /dev/null
+++ b/dists/android/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">ScummVM</string>
+ <string name="app_desc">Graphic adventure game engine</string>
+ <string name="quit">Quit</string>
+ <string name="scummvm_perm_plugin_label">ScummVM plugin</string>
+ <string name="scummvm_perm_plugin_desc">Allows the application to
+ provide a ScummVM loadable plugin: code that will be executed in the
+ ScummVM application. Malicious plugins may do anything ScummVM
+ itself could do: write to your SD card, delete your savegames,
+ change the ScummVM background to puce, replace menu labels with rude
+ words, etc.</string>
+ <string name="no_sdcard_title">No SD card?</string>
+ <string name="no_sdcard">Unable to read your SD card. This usually
+ means you still have it mounted on your PC. Unmount, reinsert,
+ whatever and then try again.</string>
+ <string name="no_plugins_title">No plugins found</string>
+ <string name="no_plugins_found">ScummVM requires at least one <i>game
+ engine</i> to be useful. Engines are available as separate plugin
+ packages, from wherever you found ScummVM.</string>
+ <string name="to_market">To Market</string>
+</resources>
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat
index 3fba5780f4..d8cb28076a 100644
--- a/dists/engine-data/kyra.dat
+++ b/dists/engine-data/kyra.dat
Binary files differ
diff --git a/dists/iphone/Info.plist b/dists/iphone/Info.plist
index 9618eb00f3..a042504b9f 100644
--- a/dists/iphone/Info.plist
+++ b/dists/iphone/Info.plist
@@ -24,6 +24,11 @@
<string>svn</string>
<key>CFBundleIconFile</key>
<string>icon.png</string>
+ <key>CFBundleIconFiles</key>
+ <array>
+ <string>icon.png</string>
+ <string>icon-72.png</string>
+ </array>
<key>UIPrerenderedIcon</key>
<true/>
<key>UIDeviceFamily</key>
diff --git a/dists/iphone/icon-72.png b/dists/iphone/icon-72.png
new file mode 100644
index 0000000000..9b424b4018
--- /dev/null
+++ b/dists/iphone/icon-72.png
Binary files differ
diff --git a/dists/iphone/scummvm.xcodeproj/project.pbxproj b/dists/iphone/scummvm.xcodeproj/project.pbxproj
index 032470cf25..5512318918 100755
--- a/dists/iphone/scummvm.xcodeproj/project.pbxproj
+++ b/dists/iphone/scummvm.xcodeproj/project.pbxproj
@@ -782,7 +782,6 @@
DF0941C20F63CB26002D821E /* staticres.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFD0D0F4870E50006E566 /* staticres.cpp */; };
DF0941C30F63CB26002D821E /* tucker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFD0E0F4870E50006E566 /* tucker.cpp */; };
DF0941C40F63CB26002D821E /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301A0F48AF18005EF03C /* detection.cpp */; };
- DF0941C50F63CB26002D821E /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301D0F48AF18005EF03C /* game.cpp */; };
DF0941C60F63CB26002D821E /* gc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301E0F48AF18005EF03C /* gc.cpp */; };
DF0941C80F63CB26002D821E /* kernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830230F48AF18005EF03C /* kernel.cpp */; };
DF0941C90F63CB26002D821E /* kevent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830260F48AF18005EF03C /* kevent.cpp */; };
@@ -960,7 +959,6 @@
DF45B1CE116628A5009B85CC /* coordadjuster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B17E116628A5009B85CC /* coordadjuster.cpp */; };
DF45B1CF116628A5009B85CC /* cursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B180116628A5009B85CC /* cursor.cpp */; };
DF45B1D0116628A5009B85CC /* font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B182116628A5009B85CC /* font.cpp */; };
- DF45B1D2116628A5009B85CC /* gui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B186116628A5009B85CC /* gui.cpp */; };
DF45B1D4116628A5009B85CC /* menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18B116628A5009B85CC /* menu.cpp */; };
DF45B1D5116628A5009B85CC /* paint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18D116628A5009B85CC /* paint.cpp */; };
DF45B1D6116628A5009B85CC /* paint16.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18F116628A5009B85CC /* paint16.cpp */; };
@@ -979,13 +977,9 @@
DF45B1E4116628A5009B85CC /* vocabulary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1A9116628A5009B85CC /* vocabulary.cpp */; };
DF45B1E5116628A5009B85CC /* audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1AC116628A5009B85CC /* audio.cpp */; };
DF45B1E6116628A5009B85CC /* adlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1AF116628A5009B85CC /* adlib.cpp */; };
- DF45B1E7116628A5009B85CC /* amiga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B0116628A5009B85CC /* amiga.cpp */; };
DF45B1E8116628A5009B85CC /* fb01.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B1116628A5009B85CC /* fb01.cpp */; };
DF45B1E9116628A5009B85CC /* midi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B3116628A5009B85CC /* midi.cpp */; };
DF45B1EA116628A5009B85CC /* pcjr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B5116628A5009B85CC /* pcjr.cpp */; };
- DF45B1EB116628A5009B85CC /* core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B7116628A5009B85CC /* core.cpp */; };
- DF45B1EC116628A5009B85CC /* iterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B9116628A5009B85CC /* iterator.cpp */; };
- DF45B1ED116628A5009B85CC /* songlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1BC116628A5009B85CC /* songlib.cpp */; };
DF45B1EF116628A5009B85CC /* midiparser_sci.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1BF116628A5009B85CC /* midiparser_sci.cpp */; };
DF45B1F0116628A5009B85CC /* music.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C1116628A5009B85CC /* music.cpp */; };
DF45B1F1116628A5009B85CC /* soundcmd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C3116628A5009B85CC /* soundcmd.cpp */; };
@@ -998,7 +992,6 @@
DF45B1F8116628A5009B85CC /* coordadjuster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B17E116628A5009B85CC /* coordadjuster.cpp */; };
DF45B1F9116628A5009B85CC /* cursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B180116628A5009B85CC /* cursor.cpp */; };
DF45B1FA116628A5009B85CC /* font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B182116628A5009B85CC /* font.cpp */; };
- DF45B1FC116628A5009B85CC /* gui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B186116628A5009B85CC /* gui.cpp */; };
DF45B1FE116628A5009B85CC /* menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18B116628A5009B85CC /* menu.cpp */; };
DF45B1FF116628A5009B85CC /* paint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18D116628A5009B85CC /* paint.cpp */; };
DF45B200116628A5009B85CC /* paint16.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18F116628A5009B85CC /* paint16.cpp */; };
@@ -1017,13 +1010,9 @@
DF45B20E116628A5009B85CC /* vocabulary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1A9116628A5009B85CC /* vocabulary.cpp */; };
DF45B20F116628A5009B85CC /* audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1AC116628A5009B85CC /* audio.cpp */; };
DF45B210116628A5009B85CC /* adlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1AF116628A5009B85CC /* adlib.cpp */; };
- DF45B211116628A5009B85CC /* amiga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B0116628A5009B85CC /* amiga.cpp */; };
DF45B212116628A5009B85CC /* fb01.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B1116628A5009B85CC /* fb01.cpp */; };
DF45B213116628A5009B85CC /* midi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B3116628A5009B85CC /* midi.cpp */; };
DF45B214116628A5009B85CC /* pcjr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B5116628A5009B85CC /* pcjr.cpp */; };
- DF45B215116628A5009B85CC /* core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B7116628A5009B85CC /* core.cpp */; };
- DF45B216116628A5009B85CC /* iterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B9116628A5009B85CC /* iterator.cpp */; };
- DF45B217116628A5009B85CC /* songlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1BC116628A5009B85CC /* songlib.cpp */; };
DF45B219116628A5009B85CC /* midiparser_sci.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1BF116628A5009B85CC /* midiparser_sci.cpp */; };
DF45B21A116628A5009B85CC /* music.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C1116628A5009B85CC /* music.cpp */; };
DF45B21B116628A5009B85CC /* soundcmd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C3116628A5009B85CC /* soundcmd.cpp */; };
@@ -1036,7 +1025,6 @@
DF45B222116628A5009B85CC /* coordadjuster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B17E116628A5009B85CC /* coordadjuster.cpp */; };
DF45B223116628A5009B85CC /* cursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B180116628A5009B85CC /* cursor.cpp */; };
DF45B224116628A5009B85CC /* font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B182116628A5009B85CC /* font.cpp */; };
- DF45B226116628A5009B85CC /* gui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B186116628A5009B85CC /* gui.cpp */; };
DF45B228116628A5009B85CC /* menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18B116628A5009B85CC /* menu.cpp */; };
DF45B229116628A5009B85CC /* paint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18D116628A5009B85CC /* paint.cpp */; };
DF45B22A116628A5009B85CC /* paint16.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18F116628A5009B85CC /* paint16.cpp */; };
@@ -1055,13 +1043,9 @@
DF45B238116628A5009B85CC /* vocabulary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1A9116628A5009B85CC /* vocabulary.cpp */; };
DF45B239116628A5009B85CC /* audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1AC116628A5009B85CC /* audio.cpp */; };
DF45B23A116628A5009B85CC /* adlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1AF116628A5009B85CC /* adlib.cpp */; };
- DF45B23B116628A5009B85CC /* amiga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B0116628A5009B85CC /* amiga.cpp */; };
DF45B23C116628A5009B85CC /* fb01.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B1116628A5009B85CC /* fb01.cpp */; };
DF45B23D116628A5009B85CC /* midi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B3116628A5009B85CC /* midi.cpp */; };
DF45B23E116628A5009B85CC /* pcjr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B5116628A5009B85CC /* pcjr.cpp */; };
- DF45B23F116628A5009B85CC /* core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B7116628A5009B85CC /* core.cpp */; };
- DF45B240116628A5009B85CC /* iterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1B9116628A5009B85CC /* iterator.cpp */; };
- DF45B241116628A5009B85CC /* songlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1BC116628A5009B85CC /* songlib.cpp */; };
DF45B243116628A5009B85CC /* midiparser_sci.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1BF116628A5009B85CC /* midiparser_sci.cpp */; };
DF45B244116628A5009B85CC /* music.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C1116628A5009B85CC /* music.cpp */; };
DF45B245116628A5009B85CC /* soundcmd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C3116628A5009B85CC /* soundcmd.cpp */; };
@@ -1249,6 +1233,45 @@
DF7E8C110ED5FCC2001CB19F /* xmlparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7E8C0F0ED5FCC2001CB19F /* xmlparser.cpp */; };
DF7E8C530ED60067001CB19F /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7E8C510ED60067001CB19F /* game.cpp */; };
DF7E8C810ED60271001CB19F /* scummmodern.zip in Resources */ = {isa = PBXBuildFile; fileRef = DF7E8C7A0ED601E5001CB19F /* scummmodern.zip */; };
+ DF7F285D11FF23B700159131 /* frameout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F285C11FF23B700159131 /* frameout.cpp */; };
+ DF7F285E11FF23B700159131 /* frameout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F285C11FF23B700159131 /* frameout.cpp */; };
+ DF7F285F11FF23B700159131 /* frameout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F285C11FF23B700159131 /* frameout.cpp */; };
+ DF7F286111FF23D500159131 /* amigamac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286011FF23D500159131 /* amigamac.cpp */; };
+ DF7F286211FF23D500159131 /* amigamac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286011FF23D500159131 /* amigamac.cpp */; };
+ DF7F286311FF23D500159131 /* amigamac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286011FF23D500159131 /* amigamac.cpp */; };
+ DF7F286711FF23EF00159131 /* kvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286411FF23EF00159131 /* kvideo.cpp */; };
+ DF7F286811FF23EF00159131 /* workarounds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286511FF23EF00159131 /* workarounds.cpp */; };
+ DF7F286911FF23EF00159131 /* kvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286411FF23EF00159131 /* kvideo.cpp */; };
+ DF7F286A11FF23EF00159131 /* workarounds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286511FF23EF00159131 /* workarounds.cpp */; };
+ DF7F286B11FF23EF00159131 /* kvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286411FF23EF00159131 /* kvideo.cpp */; };
+ DF7F286C11FF23EF00159131 /* workarounds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286511FF23EF00159131 /* workarounds.cpp */; };
+ DF7F287A11FF243B00159131 /* sound_2gs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287011FF243A00159131 /* sound_2gs.cpp */; };
+ DF7F287B11FF243B00159131 /* sound_coco3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287211FF243B00159131 /* sound_coco3.cpp */; };
+ DF7F287C11FF243B00159131 /* sound_midi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287411FF243B00159131 /* sound_midi.cpp */; };
+ DF7F287D11FF243B00159131 /* sound_pcjr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287611FF243B00159131 /* sound_pcjr.cpp */; };
+ DF7F287E11FF243B00159131 /* sound_sarien.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287811FF243B00159131 /* sound_sarien.cpp */; };
+ DF7F287F11FF243B00159131 /* sound_2gs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287011FF243A00159131 /* sound_2gs.cpp */; };
+ DF7F288011FF243B00159131 /* sound_coco3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287211FF243B00159131 /* sound_coco3.cpp */; };
+ DF7F288111FF243B00159131 /* sound_midi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287411FF243B00159131 /* sound_midi.cpp */; };
+ DF7F288211FF243B00159131 /* sound_pcjr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287611FF243B00159131 /* sound_pcjr.cpp */; };
+ DF7F288311FF243B00159131 /* sound_sarien.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287811FF243B00159131 /* sound_sarien.cpp */; };
+ DF7F288411FF243B00159131 /* sound_2gs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287011FF243A00159131 /* sound_2gs.cpp */; };
+ DF7F288511FF243B00159131 /* sound_coco3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287211FF243B00159131 /* sound_coco3.cpp */; };
+ DF7F288611FF243B00159131 /* sound_midi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287411FF243B00159131 /* sound_midi.cpp */; };
+ DF7F288711FF243B00159131 /* sound_pcjr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287611FF243B00159131 /* sound_pcjr.cpp */; };
+ DF7F288811FF243B00159131 /* sound_sarien.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F287811FF243B00159131 /* sound_sarien.cpp */; };
+ DF7F288B11FF244F00159131 /* Tooltip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F288911FF244F00159131 /* Tooltip.cpp */; };
+ DF7F288C11FF244F00159131 /* Tooltip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F288911FF244F00159131 /* Tooltip.cpp */; };
+ DF7F288D11FF244F00159131 /* Tooltip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F288911FF244F00159131 /* Tooltip.cpp */; };
+ DF7F289311FF247300159131 /* translation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F289111FF247300159131 /* translation.cpp */; };
+ DF7F289511FF247300159131 /* translation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F289111FF247300159131 /* translation.cpp */; };
+ DF7F289711FF247300159131 /* translation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F289111FF247300159131 /* translation.cpp */; };
+ DF7F28A011FF24B000159131 /* mac_snd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F289E11FF24B000159131 /* mac_snd.cpp */; };
+ DF7F28A111FF24B000159131 /* mac_snd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F289E11FF24B000159131 /* mac_snd.cpp */; };
+ DF7F28A211FF24B000159131 /* mac_snd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F289E11FF24B000159131 /* mac_snd.cpp */; };
+ DF7F28A511FF24C400159131 /* console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F28A311FF24C400159131 /* console.cpp */; };
+ DF7F28A611FF24C400159131 /* console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F28A311FF24C400159131 /* console.cpp */; };
+ DF7F28A711FF24C400159131 /* console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F28A311FF24C400159131 /* console.cpp */; };
DF841FDD0E7BA61800F5680E /* iphone_keyboard.m in Sources */ = {isa = PBXBuildFile; fileRef = DF841FD90E7BA61800F5680E /* iphone_keyboard.m */; };
DF841FDE0E7BA61800F5680E /* iphone_video.m in Sources */ = {isa = PBXBuildFile; fileRef = DF841FDB0E7BA61800F5680E /* iphone_video.m */; };
DF84250A0E7BA6AC00F5680E /* agi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF841FF70E7BA6A600F5680E /* agi.cpp */; };
@@ -1881,11 +1904,8 @@
DF89C2880F62D55C00D756B6 /* sprites_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2870F62D55C00D756B6 /* sprites_lol.cpp */; };
DF89C2A40F62D79E00D756B6 /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2A30F62D79E00D756B6 /* script.cpp */; };
DF89C2BB0F62D91000D756B6 /* timestamp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2B80F62D91000D756B6 /* timestamp.cpp */; };
- DF90E9BE10AEDA9B00C8F93F /* kernel32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF90E9BC10AEDA9B00C8F93F /* kernel32.cpp */; };
DF90E9BF10AEDA9B00C8F93F /* selector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF90E9BD10AEDA9B00C8F93F /* selector.cpp */; };
- DF90E9C010AEDA9B00C8F93F /* kernel32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF90E9BC10AEDA9B00C8F93F /* kernel32.cpp */; };
DF90E9C110AEDA9B00C8F93F /* selector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF90E9BD10AEDA9B00C8F93F /* selector.cpp */; };
- DF90E9C210AEDA9B00C8F93F /* kernel32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF90E9BC10AEDA9B00C8F93F /* kernel32.cpp */; };
DF90E9C310AEDA9B00C8F93F /* selector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF90E9BD10AEDA9B00C8F93F /* selector.cpp */; };
DF90EAA410B0234300C8F93F /* draw_playtoons.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF90EAA310B0234300C8F93F /* draw_playtoons.cpp */; };
DF90EAA510B0234300C8F93F /* draw_playtoons.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF90EAA310B0234300C8F93F /* draw_playtoons.cpp */; };
@@ -1941,7 +1961,6 @@
DFB0579911B7549C0015AE65 /* cinepak.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0579611B7549C0015AE65 /* cinepak.cpp */; };
DFB0579A11B7549C0015AE65 /* cinepak.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0579611B7549C0015AE65 /* cinepak.cpp */; };
DFC831210F48AF19005EF03C /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301A0F48AF18005EF03C /* detection.cpp */; };
- DFC831230F48AF19005EF03C /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301D0F48AF18005EF03C /* game.cpp */; };
DFC831240F48AF19005EF03C /* gc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301E0F48AF18005EF03C /* gc.cpp */; };
DFC831270F48AF19005EF03C /* kernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830230F48AF18005EF03C /* kernel.cpp */; };
DFC831280F48AF19005EF03C /* kevent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830260F48AF18005EF03C /* kevent.cpp */; };
@@ -2868,7 +2887,6 @@
DFF95C560FB22D5700A3EC78 /* staticres.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFD0D0F4870E50006E566 /* staticres.cpp */; };
DFF95C570FB22D5700A3EC78 /* tucker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFD0E0F4870E50006E566 /* tucker.cpp */; };
DFF95C580FB22D5700A3EC78 /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301A0F48AF18005EF03C /* detection.cpp */; };
- DFF95C590FB22D5700A3EC78 /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301D0F48AF18005EF03C /* game.cpp */; };
DFF95C5A0FB22D5700A3EC78 /* gc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301E0F48AF18005EF03C /* gc.cpp */; };
DFF95C5C0FB22D5700A3EC78 /* kernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830230F48AF18005EF03C /* kernel.cpp */; };
DFF95C5D0FB22D5700A3EC78 /* kevent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830260F48AF18005EF03C /* kevent.cpp */; };
@@ -3125,9 +3143,6 @@
DF45B182116628A5009B85CC /* font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font.cpp; sourceTree = "<group>"; };
DF45B183116628A5009B85CC /* font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = font.h; sourceTree = "<group>"; };
DF45B185116628A5009B85CC /* frameout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = frameout.h; sourceTree = "<group>"; };
- DF45B186116628A5009B85CC /* gui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gui.cpp; sourceTree = "<group>"; };
- DF45B187116628A5009B85CC /* gui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gui.h; sourceTree = "<group>"; };
- DF45B189116628A5009B85CC /* gui32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gui32.h; sourceTree = "<group>"; };
DF45B18A116628A5009B85CC /* helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = helpers.h; sourceTree = "<group>"; };
DF45B18B116628A5009B85CC /* menu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = menu.cpp; sourceTree = "<group>"; };
DF45B18C116628A5009B85CC /* menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu.h; sourceTree = "<group>"; };
@@ -3162,19 +3177,11 @@
DF45B1AC116628A5009B85CC /* audio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audio.cpp; sourceTree = "<group>"; };
DF45B1AD116628A5009B85CC /* audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio.h; sourceTree = "<group>"; };
DF45B1AF116628A5009B85CC /* adlib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = adlib.cpp; sourceTree = "<group>"; };
- DF45B1B0116628A5009B85CC /* amiga.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = amiga.cpp; sourceTree = "<group>"; };
DF45B1B1116628A5009B85CC /* fb01.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fb01.cpp; sourceTree = "<group>"; };
DF45B1B2116628A5009B85CC /* map-mt32-to-gm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "map-mt32-to-gm.h"; sourceTree = "<group>"; };
DF45B1B3116628A5009B85CC /* midi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = midi.cpp; sourceTree = "<group>"; };
DF45B1B4116628A5009B85CC /* mididriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mididriver.h; sourceTree = "<group>"; };
DF45B1B5116628A5009B85CC /* pcjr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pcjr.cpp; sourceTree = "<group>"; };
- DF45B1B7116628A5009B85CC /* core.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = core.cpp; sourceTree = "<group>"; };
- DF45B1B8116628A5009B85CC /* core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core.h; sourceTree = "<group>"; };
- DF45B1B9116628A5009B85CC /* iterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = iterator.cpp; sourceTree = "<group>"; };
- DF45B1BA116628A5009B85CC /* iterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iterator.h; sourceTree = "<group>"; };
- DF45B1BB116628A5009B85CC /* iterator_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iterator_internal.h; sourceTree = "<group>"; };
- DF45B1BC116628A5009B85CC /* songlib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = songlib.cpp; sourceTree = "<group>"; };
- DF45B1BD116628A5009B85CC /* songlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = songlib.h; sourceTree = "<group>"; };
DF45B1BF116628A5009B85CC /* midiparser_sci.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = midiparser_sci.cpp; sourceTree = "<group>"; };
DF45B1C0116628A5009B85CC /* midiparser_sci.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = midiparser_sci.h; sourceTree = "<group>"; };
DF45B1C1116628A5009B85CC /* music.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = music.cpp; sourceTree = "<group>"; };
@@ -3308,6 +3315,29 @@
DF7E8C510ED60067001CB19F /* game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game.cpp; sourceTree = "<group>"; };
DF7E8C520ED60067001CB19F /* game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = game.h; sourceTree = "<group>"; };
DF7E8C7A0ED601E5001CB19F /* scummmodern.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = scummmodern.zip; sourceTree = "<group>"; };
+ DF7F285C11FF23B700159131 /* frameout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = frameout.cpp; sourceTree = "<group>"; };
+ DF7F286011FF23D500159131 /* amigamac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = amigamac.cpp; sourceTree = "<group>"; };
+ DF7F286411FF23EF00159131 /* kvideo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kvideo.cpp; sourceTree = "<group>"; };
+ DF7F286511FF23EF00159131 /* workarounds.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = workarounds.cpp; sourceTree = "<group>"; };
+ DF7F286611FF23EF00159131 /* workarounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = workarounds.h; sourceTree = "<group>"; };
+ DF7F286F11FF243A00159131 /* detection_tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = detection_tables.h; sourceTree = "<group>"; };
+ DF7F287011FF243A00159131 /* sound_2gs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound_2gs.cpp; sourceTree = "<group>"; };
+ DF7F287111FF243A00159131 /* sound_2gs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sound_2gs.h; sourceTree = "<group>"; };
+ DF7F287211FF243B00159131 /* sound_coco3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound_coco3.cpp; sourceTree = "<group>"; };
+ DF7F287311FF243B00159131 /* sound_coco3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sound_coco3.h; sourceTree = "<group>"; };
+ DF7F287411FF243B00159131 /* sound_midi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound_midi.cpp; sourceTree = "<group>"; };
+ DF7F287511FF243B00159131 /* sound_midi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sound_midi.h; sourceTree = "<group>"; };
+ DF7F287611FF243B00159131 /* sound_pcjr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound_pcjr.cpp; sourceTree = "<group>"; };
+ DF7F287711FF243B00159131 /* sound_pcjr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sound_pcjr.h; sourceTree = "<group>"; };
+ DF7F287811FF243B00159131 /* sound_sarien.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound_sarien.cpp; sourceTree = "<group>"; };
+ DF7F287911FF243B00159131 /* sound_sarien.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sound_sarien.h; sourceTree = "<group>"; };
+ DF7F288911FF244F00159131 /* Tooltip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Tooltip.cpp; sourceTree = "<group>"; };
+ DF7F288A11FF244F00159131 /* Tooltip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Tooltip.h; sourceTree = "<group>"; };
+ DF7F289111FF247300159131 /* translation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = translation.cpp; sourceTree = "<group>"; };
+ DF7F289E11FF24B000159131 /* mac_snd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mac_snd.cpp; sourceTree = "<group>"; };
+ DF7F289F11FF24B000159131 /* mac_snd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mac_snd.h; sourceTree = "<group>"; };
+ DF7F28A311FF24C400159131 /* console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = console.cpp; sourceTree = "<group>"; };
+ DF7F28A411FF24C400159131 /* console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = console.h; sourceTree = "<group>"; };
DF841FD90E7BA61800F5680E /* iphone_keyboard.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = iphone_keyboard.m; sourceTree = "<group>"; };
DF841FDA0E7BA61800F5680E /* iphone_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iphone_video.h; sourceTree = "<group>"; };
DF841FDB0E7BA61800F5680E /* iphone_video.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = iphone_video.m; sourceTree = "<group>"; };
@@ -4358,7 +4388,6 @@
DF89C2B80F62D91000D756B6 /* timestamp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timestamp.cpp; sourceTree = "<group>"; };
DF89C2B90F62D91000D756B6 /* timestamp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timestamp.h; sourceTree = "<group>"; };
DF90E9B410AEDA5300C8F93F /* detection_tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = detection_tables.h; sourceTree = "<group>"; };
- DF90E9BC10AEDA9B00C8F93F /* kernel32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kernel32.cpp; sourceTree = "<group>"; };
DF90E9BD10AEDA9B00C8F93F /* selector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = selector.cpp; sourceTree = "<group>"; };
DF90EAA310B0234300C8F93F /* draw_playtoons.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = draw_playtoons.cpp; sourceTree = "<group>"; };
DF90EAAB10B0236F00C8F93F /* staticres.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = staticres.cpp; sourceTree = "<group>"; };
@@ -4399,11 +4428,9 @@
DFB0579611B7549C0015AE65 /* cinepak.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cinepak.cpp; sourceTree = "<group>"; };
DFB0579711B7549C0015AE65 /* cinepak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cinepak.h; sourceTree = "<group>"; };
DFC8301A0F48AF18005EF03C /* detection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detection.cpp; sourceTree = "<group>"; };
- DFC8301D0F48AF18005EF03C /* game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game.cpp; sourceTree = "<group>"; };
DFC8301E0F48AF18005EF03C /* gc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gc.cpp; sourceTree = "<group>"; };
DFC8301F0F48AF18005EF03C /* gc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gc.h; sourceTree = "<group>"; };
DFC830230F48AF18005EF03C /* kernel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kernel.cpp; sourceTree = "<group>"; };
- DFC830250F48AF18005EF03C /* kernel_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel_types.h; sourceTree = "<group>"; };
DFC830260F48AF18005EF03C /* kevent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kevent.cpp; sourceTree = "<group>"; };
DFC830270F48AF18005EF03C /* kfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kfile.cpp; sourceTree = "<group>"; };
DFC830280F48AF18005EF03C /* kgraphics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kgraphics.cpp; sourceTree = "<group>"; };
@@ -4444,9 +4471,7 @@
DFD518AA0DF34BA600854012 /* 2xsai.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 2xsai.cpp; sourceTree = "<group>"; };
DFD518AB0DF34BA600854012 /* aspect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = aspect.cpp; sourceTree = "<group>"; };
DFD518AD0DF34BA600854012 /* hq2x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hq2x.cpp; sourceTree = "<group>"; };
- DFD518AE0DF34BA600854012 /* hq2x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hq2x.h; sourceTree = "<group>"; };
DFD518B10DF34BA600854012 /* hq3x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hq3x.cpp; sourceTree = "<group>"; };
- DFD518B20DF34BA600854012 /* hq3x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hq3x.h; sourceTree = "<group>"; };
DFD518B50DF34BA600854012 /* scale2x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scale2x.cpp; sourceTree = "<group>"; };
DFD518B60DF34BA600854012 /* scale2x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scale2x.h; sourceTree = "<group>"; };
DFD518B80DF34BA600854012 /* scale3x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scale3x.cpp; sourceTree = "<group>"; };
@@ -4550,7 +4575,7 @@
DFE4778A0D81F4E900B6D1FB /* about.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = about.h; sourceTree = "<group>"; };
DFE4778B0D81F4E900B6D1FB /* Actions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Actions.cpp; sourceTree = "<group>"; };
DFE4778C0D81F4E900B6D1FB /* Actions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Actions.h; sourceTree = "<group>"; };
- DFE4778D0D81F4E900B6D1FB /* browser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = browser.cpp; sourceTree = "<group>"; };
+ DFE4778D0D81F4E900B6D1FB /* browser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = browser.cpp; sourceTree = "<group>"; };
DFE4778E0D81F4E900B6D1FB /* browser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = browser.h; sourceTree = "<group>"; };
DFE4778F0D81F4E900B6D1FB /* chooser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = chooser.cpp; sourceTree = "<group>"; };
DFE477900D81F4E900B6D1FB /* chooser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chooser.h; sourceTree = "<group>"; };
@@ -4901,6 +4926,8 @@
DF45B0EB116627D9009B85CC /* decoders */ = {
isa = PBXGroup;
children = (
+ DF7F289E11FF24B000159131 /* mac_snd.cpp */,
+ DF7F289F11FF24B000159131 /* mac_snd.h */,
DF45B0F7116627DA009B85CC /* adpcm.cpp */,
DF45B0F8116627DA009B85CC /* adpcm.h */,
DF45B0FA116627DA009B85CC /* aiff.cpp */,
@@ -4928,6 +4955,7 @@
DF45B175116628A5009B85CC /* graphics */ = {
isa = PBXGroup;
children = (
+ DF7F285C11FF23B700159131 /* frameout.cpp */,
DFB0578811B754570015AE65 /* maciconbar.cpp */,
DFB0578911B754570015AE65 /* maciconbar.h */,
DF9B924F118E46A00069C19D /* fontsjis.cpp */,
@@ -4947,9 +4975,6 @@
DF45B182116628A5009B85CC /* font.cpp */,
DF45B183116628A5009B85CC /* font.h */,
DF45B185116628A5009B85CC /* frameout.h */,
- DF45B186116628A5009B85CC /* gui.cpp */,
- DF45B187116628A5009B85CC /* gui.h */,
- DF45B189116628A5009B85CC /* gui32.h */,
DF45B18A116628A5009B85CC /* helpers.h */,
DF45B18B116628A5009B85CC /* menu.cpp */,
DF45B18C116628A5009B85CC /* menu.h */,
@@ -5012,8 +5037,8 @@
DF45B1AE116628A5009B85CC /* drivers */ = {
isa = PBXGroup;
children = (
+ DF7F286011FF23D500159131 /* amigamac.cpp */,
DF45B1AF116628A5009B85CC /* adlib.cpp */,
- DF45B1B0116628A5009B85CC /* amiga.cpp */,
DF45B1B1116628A5009B85CC /* fb01.cpp */,
DF45B1B2116628A5009B85CC /* map-mt32-to-gm.h */,
DF45B1B3116628A5009B85CC /* midi.cpp */,
@@ -5026,13 +5051,6 @@
DF45B1B6116628A5009B85CC /* iterator */ = {
isa = PBXGroup;
children = (
- DF45B1B7116628A5009B85CC /* core.cpp */,
- DF45B1B8116628A5009B85CC /* core.h */,
- DF45B1B9116628A5009B85CC /* iterator.cpp */,
- DF45B1BA116628A5009B85CC /* iterator.h */,
- DF45B1BB116628A5009B85CC /* iterator_internal.h */,
- DF45B1BC116628A5009B85CC /* songlib.cpp */,
- DF45B1BD116628A5009B85CC /* songlib.h */,
);
path = iterator;
sourceTree = "<group>";
@@ -5128,6 +5146,17 @@
DF841FF60E7BA6A600F5680E /* agi */ = {
isa = PBXGroup;
children = (
+ DF7F286F11FF243A00159131 /* detection_tables.h */,
+ DF7F287011FF243A00159131 /* sound_2gs.cpp */,
+ DF7F287111FF243A00159131 /* sound_2gs.h */,
+ DF7F287211FF243B00159131 /* sound_coco3.cpp */,
+ DF7F287311FF243B00159131 /* sound_coco3.h */,
+ DF7F287411FF243B00159131 /* sound_midi.cpp */,
+ DF7F287511FF243B00159131 /* sound_midi.h */,
+ DF7F287611FF243B00159131 /* sound_pcjr.cpp */,
+ DF7F287711FF243B00159131 /* sound_pcjr.h */,
+ DF7F287811FF243B00159131 /* sound_sarien.cpp */,
+ DF7F287911FF243B00159131 /* sound_sarien.h */,
DF841FF70E7BA6A600F5680E /* agi.cpp */,
DF841FF80E7BA6A600F5680E /* agi.h */,
DF841FF90E7BA6A600F5680E /* checks.cpp */,
@@ -5366,6 +5395,8 @@
DF8421040E7BA6A700F5680E /* drascula */ = {
isa = PBXGroup;
children = (
+ DF7F28A311FF24C400159131 /* console.cpp */,
+ DF7F28A411FF24C400159131 /* console.h */,
DFCDC6F611662AAB00A7D2A0 /* resource.cpp */,
DF8421050E7BA6A700F5680E /* actors.cpp */,
DF8421060E7BA6A700F5680E /* animation.cpp */,
@@ -6490,11 +6521,13 @@
DFC8301B0F48AF18005EF03C /* engine */ = {
isa = PBXGroup;
children = (
+ DF7F286411FF23EF00159131 /* kvideo.cpp */,
+ DF7F286511FF23EF00159131 /* workarounds.cpp */,
+ DF7F286611FF23EF00159131 /* workarounds.h */,
DFCDC6D5116629CE00A7D2A0 /* features.cpp */,
DFCDC6D6116629CE00A7D2A0 /* features.h */,
DFCDC6D7116629CE00A7D2A0 /* kparse.cpp */,
DFCDC6D8116629CE00A7D2A0 /* selector.h */,
- DF90E9BC10AEDA9B00C8F93F /* kernel32.cpp */,
DF90E9BD10AEDA9B00C8F93F /* selector.cpp */,
DF7585F6100CB75800CC3324 /* static_selectors.cpp */,
DF6118380FE3A8080042AD3F /* kmisc.cpp */,
@@ -6509,11 +6542,9 @@
DF573C020F5A81EA00961A72 /* state.h */,
DF573C030F5A81EA00961A72 /* vm.h */,
DF573C040F5A81EA00961A72 /* vm_types.h */,
- DFC8301D0F48AF18005EF03C /* game.cpp */,
DFC8301E0F48AF18005EF03C /* gc.cpp */,
DFC8301F0F48AF18005EF03C /* gc.h */,
DFC830230F48AF18005EF03C /* kernel.cpp */,
- DFC830250F48AF18005EF03C /* kernel_types.h */,
DFC830260F48AF18005EF03C /* kevent.cpp */,
DFC830270F48AF18005EF03C /* kfile.cpp */,
DFC830280F48AF18005EF03C /* kgraphics.cpp */,
@@ -6542,9 +6573,7 @@
DFD518AA0DF34BA600854012 /* 2xsai.cpp */,
DFD518AB0DF34BA600854012 /* aspect.cpp */,
DFD518AD0DF34BA600854012 /* hq2x.cpp */,
- DFD518AE0DF34BA600854012 /* hq2x.h */,
DFD518B10DF34BA600854012 /* hq3x.cpp */,
- DFD518B20DF34BA600854012 /* hq3x.h */,
DFD518B50DF34BA600854012 /* scale2x.cpp */,
DFD518B60DF34BA600854012 /* scale2x.h */,
DFD518B80DF34BA600854012 /* scale3x.cpp */,
@@ -6736,6 +6765,7 @@
DFE473950D81F4E800B6D1FB /* common */ = {
isa = PBXGroup;
children = (
+ DF7F289111FF247300159131 /* translation.cpp */,
DFB0577311B753DA0015AE65 /* debug-channels.h */,
DFB0577411B753DA0015AE65 /* rational.cpp */,
DFB0577511B753DA0015AE65 /* rational.h */,
@@ -6877,6 +6907,8 @@
DFE477880D81F4E900B6D1FB /* gui */ = {
isa = PBXGroup;
children = (
+ DF7F288911FF244F00159131 /* Tooltip.cpp */,
+ DF7F288A11FF244F00159131 /* Tooltip.h */,
DF9B9246118E46730069C19D /* error.cpp */,
DF9B9247118E46730069C19D /* error.h */,
DF2EC3E410E6490800765801 /* browser_osx.mm */,
@@ -7937,7 +7969,6 @@
DF2FFD170F4870E50006E566 /* staticres.cpp in Sources */,
DF2FFD180F4870E50006E566 /* tucker.cpp in Sources */,
DFC831210F48AF19005EF03C /* detection.cpp in Sources */,
- DFC831230F48AF19005EF03C /* game.cpp in Sources */,
DFC831240F48AF19005EF03C /* gc.cpp in Sources */,
DFC831270F48AF19005EF03C /* kernel.cpp in Sources */,
DFC831280F48AF19005EF03C /* kevent.cpp in Sources */,
@@ -8035,7 +8066,6 @@
DF6BF4FF10529F140069811F /* EventRecorder.cpp in Sources */,
DF6BF50810529F540069811F /* maxtrax.cpp in Sources */,
DF6BF50910529F540069811F /* tfmx.cpp in Sources */,
- DF90E9C210AEDA9B00C8F93F /* kernel32.cpp in Sources */,
DF90E9C310AEDA9B00C8F93F /* selector.cpp in Sources */,
DF90EAA610B0234300C8F93F /* draw_playtoons.cpp in Sources */,
DF90EAAF10B0236F00C8F93F /* staticres.cpp in Sources */,
@@ -8066,7 +8096,6 @@
DF45B1CE116628A5009B85CC /* coordadjuster.cpp in Sources */,
DF45B1CF116628A5009B85CC /* cursor.cpp in Sources */,
DF45B1D0116628A5009B85CC /* font.cpp in Sources */,
- DF45B1D2116628A5009B85CC /* gui.cpp in Sources */,
DF45B1D4116628A5009B85CC /* menu.cpp in Sources */,
DF45B1D5116628A5009B85CC /* paint.cpp in Sources */,
DF45B1D6116628A5009B85CC /* paint16.cpp in Sources */,
@@ -8085,13 +8114,9 @@
DF45B1E4116628A5009B85CC /* vocabulary.cpp in Sources */,
DF45B1E5116628A5009B85CC /* audio.cpp in Sources */,
DF45B1E6116628A5009B85CC /* adlib.cpp in Sources */,
- DF45B1E7116628A5009B85CC /* amiga.cpp in Sources */,
DF45B1E8116628A5009B85CC /* fb01.cpp in Sources */,
DF45B1E9116628A5009B85CC /* midi.cpp in Sources */,
DF45B1EA116628A5009B85CC /* pcjr.cpp in Sources */,
- DF45B1EB116628A5009B85CC /* core.cpp in Sources */,
- DF45B1EC116628A5009B85CC /* iterator.cpp in Sources */,
- DF45B1ED116628A5009B85CC /* songlib.cpp in Sources */,
DF45B1EF116628A5009B85CC /* midiparser_sci.cpp in Sources */,
DF45B1F0116628A5009B85CC /* music.cpp in Sources */,
DF45B1F1116628A5009B85CC /* soundcmd.cpp in Sources */,
@@ -8119,6 +8144,19 @@
DFB0578B11B754570015AE65 /* maciconbar.cpp in Sources */,
DFB0579211B7547D0015AE65 /* pict.cpp in Sources */,
DFB0579911B7549C0015AE65 /* cinepak.cpp in Sources */,
+ DF7F285E11FF23B700159131 /* frameout.cpp in Sources */,
+ DF7F286211FF23D500159131 /* amigamac.cpp in Sources */,
+ DF7F286911FF23EF00159131 /* kvideo.cpp in Sources */,
+ DF7F286A11FF23EF00159131 /* workarounds.cpp in Sources */,
+ DF7F287F11FF243B00159131 /* sound_2gs.cpp in Sources */,
+ DF7F288011FF243B00159131 /* sound_coco3.cpp in Sources */,
+ DF7F288111FF243B00159131 /* sound_midi.cpp in Sources */,
+ DF7F288211FF243B00159131 /* sound_pcjr.cpp in Sources */,
+ DF7F288311FF243B00159131 /* sound_sarien.cpp in Sources */,
+ DF7F288C11FF244F00159131 /* Tooltip.cpp in Sources */,
+ DF7F289511FF247300159131 /* translation.cpp in Sources */,
+ DF7F28A111FF24B000159131 /* mac_snd.cpp in Sources */,
+ DF7F28A611FF24C400159131 /* console.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -8892,7 +8930,6 @@
DF0941C20F63CB26002D821E /* staticres.cpp in Sources */,
DF0941C30F63CB26002D821E /* tucker.cpp in Sources */,
DF0941C40F63CB26002D821E /* detection.cpp in Sources */,
- DF0941C50F63CB26002D821E /* game.cpp in Sources */,
DF0941C60F63CB26002D821E /* gc.cpp in Sources */,
DF0941C80F63CB26002D821E /* kernel.cpp in Sources */,
DF0941C90F63CB26002D821E /* kevent.cpp in Sources */,
@@ -8993,7 +9030,6 @@
DF6BF50110529F140069811F /* EventRecorder.cpp in Sources */,
DF6BF50A10529F540069811F /* maxtrax.cpp in Sources */,
DF6BF50B10529F540069811F /* tfmx.cpp in Sources */,
- DF90E9BE10AEDA9B00C8F93F /* kernel32.cpp in Sources */,
DF90E9BF10AEDA9B00C8F93F /* selector.cpp in Sources */,
DF90EAA410B0234300C8F93F /* draw_playtoons.cpp in Sources */,
DF90EAAD10B0236F00C8F93F /* staticres.cpp in Sources */,
@@ -9025,7 +9061,6 @@
DF45B1F8116628A5009B85CC /* coordadjuster.cpp in Sources */,
DF45B1F9116628A5009B85CC /* cursor.cpp in Sources */,
DF45B1FA116628A5009B85CC /* font.cpp in Sources */,
- DF45B1FC116628A5009B85CC /* gui.cpp in Sources */,
DF45B1FE116628A5009B85CC /* menu.cpp in Sources */,
DF45B1FF116628A5009B85CC /* paint.cpp in Sources */,
DF45B200116628A5009B85CC /* paint16.cpp in Sources */,
@@ -9044,13 +9079,9 @@
DF45B20E116628A5009B85CC /* vocabulary.cpp in Sources */,
DF45B20F116628A5009B85CC /* audio.cpp in Sources */,
DF45B210116628A5009B85CC /* adlib.cpp in Sources */,
- DF45B211116628A5009B85CC /* amiga.cpp in Sources */,
DF45B212116628A5009B85CC /* fb01.cpp in Sources */,
DF45B213116628A5009B85CC /* midi.cpp in Sources */,
DF45B214116628A5009B85CC /* pcjr.cpp in Sources */,
- DF45B215116628A5009B85CC /* core.cpp in Sources */,
- DF45B216116628A5009B85CC /* iterator.cpp in Sources */,
- DF45B217116628A5009B85CC /* songlib.cpp in Sources */,
DF45B219116628A5009B85CC /* midiparser_sci.cpp in Sources */,
DF45B21A116628A5009B85CC /* music.cpp in Sources */,
DF45B21B116628A5009B85CC /* soundcmd.cpp in Sources */,
@@ -9078,6 +9109,19 @@
DFB0578C11B754570015AE65 /* maciconbar.cpp in Sources */,
DFB0579311B7547D0015AE65 /* pict.cpp in Sources */,
DFB0579A11B7549C0015AE65 /* cinepak.cpp in Sources */,
+ DF7F285F11FF23B700159131 /* frameout.cpp in Sources */,
+ DF7F286311FF23D500159131 /* amigamac.cpp in Sources */,
+ DF7F286B11FF23EF00159131 /* kvideo.cpp in Sources */,
+ DF7F286C11FF23EF00159131 /* workarounds.cpp in Sources */,
+ DF7F288411FF243B00159131 /* sound_2gs.cpp in Sources */,
+ DF7F288511FF243B00159131 /* sound_coco3.cpp in Sources */,
+ DF7F288611FF243B00159131 /* sound_midi.cpp in Sources */,
+ DF7F288711FF243B00159131 /* sound_pcjr.cpp in Sources */,
+ DF7F288811FF243B00159131 /* sound_sarien.cpp in Sources */,
+ DF7F288D11FF244F00159131 /* Tooltip.cpp in Sources */,
+ DF7F289711FF247300159131 /* translation.cpp in Sources */,
+ DF7F28A211FF24B000159131 /* mac_snd.cpp in Sources */,
+ DF7F28A711FF24C400159131 /* console.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -9856,7 +9900,6 @@
DFF95C560FB22D5700A3EC78 /* staticres.cpp in Sources */,
DFF95C570FB22D5700A3EC78 /* tucker.cpp in Sources */,
DFF95C580FB22D5700A3EC78 /* detection.cpp in Sources */,
- DFF95C590FB22D5700A3EC78 /* game.cpp in Sources */,
DFF95C5A0FB22D5700A3EC78 /* gc.cpp in Sources */,
DFF95C5C0FB22D5700A3EC78 /* kernel.cpp in Sources */,
DFF95C5D0FB22D5700A3EC78 /* kevent.cpp in Sources */,
@@ -9954,7 +9997,6 @@
DF6BF4FD10529F140069811F /* EventRecorder.cpp in Sources */,
DF6BF50610529F540069811F /* maxtrax.cpp in Sources */,
DF6BF50710529F540069811F /* tfmx.cpp in Sources */,
- DF90E9C010AEDA9B00C8F93F /* kernel32.cpp in Sources */,
DF90E9C110AEDA9B00C8F93F /* selector.cpp in Sources */,
DF90EAA510B0234300C8F93F /* draw_playtoons.cpp in Sources */,
DF90EAAE10B0236F00C8F93F /* staticres.cpp in Sources */,
@@ -9985,7 +10027,6 @@
DF45B222116628A5009B85CC /* coordadjuster.cpp in Sources */,
DF45B223116628A5009B85CC /* cursor.cpp in Sources */,
DF45B224116628A5009B85CC /* font.cpp in Sources */,
- DF45B226116628A5009B85CC /* gui.cpp in Sources */,
DF45B228116628A5009B85CC /* menu.cpp in Sources */,
DF45B229116628A5009B85CC /* paint.cpp in Sources */,
DF45B22A116628A5009B85CC /* paint16.cpp in Sources */,
@@ -10004,13 +10045,9 @@
DF45B238116628A5009B85CC /* vocabulary.cpp in Sources */,
DF45B239116628A5009B85CC /* audio.cpp in Sources */,
DF45B23A116628A5009B85CC /* adlib.cpp in Sources */,
- DF45B23B116628A5009B85CC /* amiga.cpp in Sources */,
DF45B23C116628A5009B85CC /* fb01.cpp in Sources */,
DF45B23D116628A5009B85CC /* midi.cpp in Sources */,
DF45B23E116628A5009B85CC /* pcjr.cpp in Sources */,
- DF45B23F116628A5009B85CC /* core.cpp in Sources */,
- DF45B240116628A5009B85CC /* iterator.cpp in Sources */,
- DF45B241116628A5009B85CC /* songlib.cpp in Sources */,
DF45B243116628A5009B85CC /* midiparser_sci.cpp in Sources */,
DF45B244116628A5009B85CC /* music.cpp in Sources */,
DF45B245116628A5009B85CC /* soundcmd.cpp in Sources */,
@@ -10038,6 +10075,19 @@
DFB0578A11B754570015AE65 /* maciconbar.cpp in Sources */,
DFB0579111B7547D0015AE65 /* pict.cpp in Sources */,
DFB0579811B7549C0015AE65 /* cinepak.cpp in Sources */,
+ DF7F285D11FF23B700159131 /* frameout.cpp in Sources */,
+ DF7F286111FF23D500159131 /* amigamac.cpp in Sources */,
+ DF7F286711FF23EF00159131 /* kvideo.cpp in Sources */,
+ DF7F286811FF23EF00159131 /* workarounds.cpp in Sources */,
+ DF7F287A11FF243B00159131 /* sound_2gs.cpp in Sources */,
+ DF7F287B11FF243B00159131 /* sound_coco3.cpp in Sources */,
+ DF7F287C11FF243B00159131 /* sound_midi.cpp in Sources */,
+ DF7F287D11FF243B00159131 /* sound_pcjr.cpp in Sources */,
+ DF7F287E11FF243B00159131 /* sound_sarien.cpp in Sources */,
+ DF7F288B11FF244F00159131 /* Tooltip.cpp in Sources */,
+ DF7F289311FF247300159131 /* translation.cpp in Sources */,
+ DF7F28A011FF24B000159131 /* mac_snd.cpp in Sources */,
+ DF7F28A511FF24C400159131 /* console.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -10181,6 +10231,7 @@
SCUMM_LITTLE_ENDIAN,
UNIX,
IPHONE,
+ ENABLE_SCI32,
ENABLE_HE,
);
GCC_THUMB_SUPPORT = NO;
@@ -10198,7 +10249,8 @@
PREBINDING = NO;
PROVISIONING_PROFILE = "";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
- SDKROOT = iphoneos3.0;
+ SDKROOT = iphonesimulator3.2;
+ TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
@@ -10210,6 +10262,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
FRAMEWORK_SEARCH_PATHS = "";
+ GCC_C_LANGUAGE_STANDARD = c99;
GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_ENABLE_CPP_RTTI = NO;
GCC_INPUT_FILETYPE = automatic;
@@ -10250,6 +10303,7 @@
SCUMM_LITTLE_ENDIAN,
UNIX,
IPHONE,
+ ENABLE_SCI32,
ENABLE_HE,
);
GCC_THUMB_SUPPORT = NO;
@@ -10259,12 +10313,14 @@
../../,
);
LIBRARY_SEARCH_PATHS = "";
+ ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "-lz";
PREBINDING = NO;
PROVISIONING_PROFILE = "";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
- SDKROOT = iphoneos3.0;
+ SDKROOT = iphonesimulator3.2;
+ TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
@@ -10338,6 +10394,7 @@
"\\\"$(SRCROOT)/../../engines/m4\\\"",
"\\\"$(SRCROOT)/lib\\\"",
);
+ ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = (
"-lSDLmain",
@@ -10351,6 +10408,8 @@
);
PREBINDING = NO;
PRODUCT_NAME = ScummVM;
+ SDKROOT = macosx10.6;
+ VALID_ARCHS = "i386 ppc ppc64 ppc7400 ppc970 x86_64 arm7 arm6";
};
name = Debug;
};
@@ -10422,6 +10481,7 @@
"\\\"$(SRCROOT)/../../engines/m4\\\"",
"\\\"$(SRCROOT)/lib\\\"",
);
+ ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = (
"-lSDLmain",
@@ -10435,6 +10495,8 @@
);
PREBINDING = NO;
PRODUCT_NAME = ScummVM;
+ SDKROOT = macosx10.6;
+ VALID_ARCHS = "i386 ppc ppc64 ppc7400 ppc970 x86_64 arm7 arm6";
WRAPPER_EXTENSION = app;
};
name = Release;
@@ -10454,43 +10516,13 @@
GCC_OPTIMIZATION_LEVEL = 3;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_PREFIX_HEADER = "";
- GCC_PREPROCESSOR_DEFINITIONS = (
- XCODE,
- IPHONE_OFFICIAL,
- USE_ZLIB,
- SCUMMVM,
- ENABLE_SCI,
- ENABLE_TUCKER,
- ENABLE_TOUCHE,
- ENABLE_TINSEL,
- ENABLE_SWORD2,
- ENABLE_SWORD1,
- ENABLE_SKY,
- ENABLE_IHNM,
- ENABLE_SAGA,
- ENABLE_QUEEN,
- ENABLE_PARALLACTION,
- ENABLE_MADE,
- ENABLE_LURE,
- ENABLE_KYRA,
- ENABLE_IGOR,
- ENABLE_GROOVIE,
- ENABLE_GOB,
- ENABLE_DRASCULA,
- ENABLE_CINE,
- ENABLE_AGOS,
- ENABLE_AGI,
- ENABLE_SCUMM,
- ENABLE_SCUMM_7_8,
- CONFIG_H,
- SCUMM_NEED_ALIGNMENT,
- SCUMM_LITTLE_ENDIAN,
- UNIX,
- IPHONE,
- ENABLE_HE,
- );
GCC_THUMB_SUPPORT = NO;
GCC_UNROLL_LOOPS = YES;
+ HEADER_SEARCH_PATHS = (
+ ../../engines/,
+ ../../,
+ /opt/local/include,
+ );
INFOPLIST_FILE = "/Users/oystein/iphone/scummvm/dists/iphone/Info copy 2.plist";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@@ -10499,12 +10531,11 @@
"\\\"$(SRCROOT)/../../engines/m4\\\"",
"\\\"$(SRCROOT)/lib\\\"",
);
- ONLY_ACTIVE_ARCH = YES;
PREBINDING = NO;
PRODUCT_NAME = ScummVM;
PROVISIONING_PROFILE = "EF590570-5FAC-4346-9071-D609DE2B28D8";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
- SDKROOT = iphonesimulator2.0;
+ SDKROOT = iphonesimulator3.2;
};
name = Debug;
};
@@ -10522,43 +10553,13 @@
GCC_OPTIMIZATION_LEVEL = 3;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_PREFIX_HEADER = "";
- GCC_PREPROCESSOR_DEFINITIONS = (
- XCODE,
- IPHONE_OFFICIAL,
- USE_ZLIB,
- SCUMMVM,
- ENABLE_SCI,
- ENABLE_TUCKER,
- ENABLE_TOUCHE,
- ENABLE_TINSEL,
- ENABLE_SWORD2,
- ENABLE_SWORD1,
- ENABLE_SKY,
- ENABLE_IHNM,
- ENABLE_SAGA,
- ENABLE_QUEEN,
- ENABLE_PARALLACTION,
- ENABLE_MADE,
- ENABLE_LURE,
- ENABLE_KYRA,
- ENABLE_IGOR,
- ENABLE_GROOVIE,
- ENABLE_GOB,
- ENABLE_DRASCULA,
- ENABLE_CINE,
- ENABLE_AGOS,
- ENABLE_AGI,
- ENABLE_SCUMM,
- ENABLE_SCUMM_7_8,
- CONFIG_H,
- SCUMM_NEED_ALIGNMENT,
- SCUMM_LITTLE_ENDIAN,
- UNIX,
- IPHONE,
- ENABLE_HE,
- );
GCC_THUMB_SUPPORT = NO;
GCC_UNROLL_LOOPS = YES;
+ HEADER_SEARCH_PATHS = (
+ ../../engines/,
+ ../../,
+ /opt/local/include,
+ );
INFOPLIST_FILE = "/Users/oystein/iphone/scummvm/dists/iphone/Info copy 2.plist";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@@ -10567,12 +10568,11 @@
"\\\"$(SRCROOT)/../../engines/m4\\\"",
"\\\"$(SRCROOT)/lib\\\"",
);
- ONLY_ACTIVE_ARCH = YES;
PREBINDING = NO;
PRODUCT_NAME = ScummVM;
PROVISIONING_PROFILE = "EF590570-5FAC-4346-9071-D609DE2B28D8";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
- SDKROOT = iphonesimulator2.0;
+ SDKROOT = iphonesimulator3.2;
WRAPPER_EXTENSION = app;
};
name = Release;
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index b149b43ad7..f4af4a8500 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -208,6 +208,10 @@ static void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *
desc["extra"] = realDesc->extra;
desc.setGUIOptions(realDesc->guioptions | params.guioptions);
+ desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(realDesc->language));
+
+ if (realDesc->flags & ADGF_ADDENGLISH)
+ desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY));
}
GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const {
@@ -305,7 +309,12 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
// If the GUI options were updated, we catch this here and update them in the users config
// file transparently.
- Common::updateGameGUIOptions(agdDesc->guioptions | params.guioptions);
+ Common::String lang = getGameGUIOptionsDescriptionLanguage(agdDesc->language);
+ if (agdDesc->flags & ADGF_ADDENGLISH)
+ lang += " " + getGameGUIOptionsDescriptionLanguage(Common::EN_ANY);
+
+ Common::updateGameGUIOptions(agdDesc->guioptions | params.guioptions, lang);
+
debug(2, "Running %s", toGameDescriptor(*agdDesc, params.list).description().c_str());
if (!createInstance(syst, engine, agdDesc))
@@ -340,24 +349,37 @@ static void reportUnknown(const Common::FSNode &path, const SizeMD5Map &filesSiz
static ADGameDescList detectGameFilebased(const FileMap &allFiles, const ADParams &params);
-static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &params, Common::Language language, Common::Platform platform, const Common::String &extra) {
- FileMap allFiles;
- SizeMD5Map filesSizeMD5;
-
- const ADGameFileDescription *fileDesc;
- const ADGameDescription *g;
- const byte *descPtr;
+static void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, int depth, const char **directoryGlobs) {
+ if (depth <= 0)
+ return;
if (fslist.empty())
- return ADGameDescList();
- Common::FSNode parent = fslist.begin()->getParent();
- debug(3, "Starting detection in dir '%s'", parent.getPath().c_str());
+ return;
// First we compose a hashmap of all files in fslist.
// Includes nifty stuff like removing trailing dots and ignoring case.
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- if (file->isDirectory())
- continue;
+ if (file->isDirectory()) {
+ Common::FSList files;
+
+ if (!directoryGlobs)
+ continue;
+
+ bool matched = false;
+ for (const char *glob = *directoryGlobs; *glob; glob++)
+ if (file->getName().matchString(glob, true)) {
+ matched = true;
+ break;
+ }
+
+ if (!matched)
+ continue;
+
+ if (!file->getChildren(files, Common::FSNode::kListAll))
+ continue;
+
+ composeFileHashMap(files, allFiles, depth - 1, directoryGlobs);
+ }
Common::String tstr = file->getName();
@@ -367,6 +389,24 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p
allFiles[tstr] = *file; // Record the presence of this file
}
+}
+
+static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &params, Common::Language language, Common::Platform platform, const Common::String &extra) {
+ FileMap allFiles;
+ SizeMD5Map filesSizeMD5;
+
+ const ADGameFileDescription *fileDesc;
+ const ADGameDescription *g;
+ const byte *descPtr;
+
+ if (fslist.empty())
+ return ADGameDescList();
+ Common::FSNode parent = fslist.begin()->getParent();
+ debug(3, "Starting detection in dir '%s'", parent.getPath().c_str());
+
+ // First we compose a hashmap of all files in fslist.
+ // Includes nifty stuff like removing trailing dots and ignoring case.
+ composeFileHashMap(fslist, allFiles, (params.depth == 0 ? 1 : params.depth), params.directoryGlobs);
// Check which files are included in some ADGameDescription *and* present
// in fslist. Compute MD5s and file sizes for these files.
@@ -423,7 +463,8 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p
// Do not even bother to look at entries which do not have matching
// language and platform (if specified).
- if ((language != Common::UNK_LANG && g->language != Common::UNK_LANG && g->language != language) ||
+ if ((language != Common::UNK_LANG && g->language != Common::UNK_LANG && g->language != language
+ && !(language == Common::EN_ANY && (g->flags & ADGF_ADDENGLISH))) ||
(platform != Common::kPlatformUnknown && g->platform != Common::kPlatformUnknown && g->platform != platform)) {
continue;
}
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index 370d958ce6..1e59df04bf 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -38,11 +38,14 @@ struct ADGameFileDescription {
int32 fileSize; // Optional. Set to -1 to ignore.
};
-#define AD_ENTRY1(f, x) {{ f, 0, x, -1}, {NULL, 0, NULL, 0}}
-#define AD_ENTRY1s(f, x, s) {{ f, 0, x, s}, {NULL, 0, NULL, 0}}
+#define AD_LISTEND {NULL, 0, NULL, 0}
+
+#define AD_ENTRY1(f, x) {{ f, 0, x, -1}, AD_LISTEND}
+#define AD_ENTRY1s(f, x, s) {{ f, 0, x, s}, AD_LISTEND}
enum ADGameFlags {
ADGF_NO_FLAGS = 0,
+ ADGF_ADDENGLISH = (1 << 24), // always add English as language option
ADGF_MACRESFORK = (1 << 25), // the md5 for this entry will be calculated from the resource fork
ADGF_USEEXTRAASTITLE = (1 << 26), // Extra field value will be used as main game title, not gameid
ADGF_KEEPMATCH = (1 << 27), // this entry is kept even when there are matched entries with more files
@@ -190,6 +193,21 @@ struct ADParams {
* enum for the list.
*/
uint32 guioptions;
+
+ /**
+ * Maximum depth of directories to look up
+ * If set to 0, the depth is 1 level
+ */
+ uint32 depth;
+
+ /**
+ * Case-insensitive list of directory globs which could be used for
+ * going deeper int directory structure.
+ * @see String::matchString() method for format description.
+ *
+ * @note Last item must be 0
+ */
+ const char **directoryGlobs;
};
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index c2c6d10bfe..e83ef4ead9 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -272,20 +272,18 @@ void AgiEngine::processEvents() {
}
void AgiEngine::pollTimer() {
- static uint32 m = 0;
uint32 dm;
- if (_tickTimer < m)
- m = 0;
+ if (_tickTimer < _lastTickTimer)
+ _lastTickTimer = 0;
- while ((dm = _tickTimer - m) < 5) {
+ while ((dm = _tickTimer - _lastTickTimer) < 5) {
processEvents();
- if (_console->isAttached())
- _console->onFrame();
+ _console->onFrame();
_system->delayMillis(10);
_system->updateScreen();
}
- m = _tickTimer;
+ _lastTickTimer = _tickTimer;
}
void AgiEngine::agiTimerFunctionLow(void *refCon) {
@@ -345,7 +343,7 @@ int AgiEngine::agiInit() {
// clear view table
for (i = 0; i < MAX_VIEWTABLE; i++)
- memset(&_game.viewTable[i], 0, sizeof(VtEntry));
+ memset(&_game.viewTable[i], 0, sizeof(struct VtEntry));
initWords();
@@ -506,13 +504,6 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
- const GameSettings *g;
-
- const char *gameid = ConfMan.get("gameid").c_str();
- for (g = agiSettings; g->gameid; ++g)
- if (!scumm_stricmp(g->gameid, gameid))
- _gameId = g->id;
-
parseFeatures();
_rnd = new Common::RandomSource();
@@ -543,6 +534,7 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
_allowSynthetic = false;
_tickTimer = 0;
+ _lastTickTimer = 0;
_intobj = NULL;
@@ -556,7 +548,7 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
_restartGame = false;
- _oldMode = -1;
+ _oldMode = INPUT_NONE;
_predictiveDialogRunning = false;
_predictiveDictText = NULL;
@@ -569,6 +561,10 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
_game.lastController = 0;
for (int i = 0; i < MAX_DIRS; i++)
_game.controllerOccured[i] = false;
+
+ setupOpcodes();
+ _curLogic = NULL;
+ _timerHack = 0;
}
void AgiEngine::initialize() {
@@ -583,13 +579,19 @@ void AgiEngine::initialize() {
} else if (getPlatform() == Common::kPlatformCoCo3) {
_soundemu = SOUND_EMU_COCO3;
} else {
- switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) {
- case MD_PCSPK:
+ switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK|MDT_ADLIB|MDT_PCJR|MDT_MIDI))) {
+ case MT_PCSPK:
_soundemu = SOUND_EMU_PC;
break;
- default:
+ case MT_PCJR:
+ _soundemu = SOUND_EMU_PCJR;
+ break;
+ case MT_ADLIB:
_soundemu = SOUND_EMU_NONE;
break;
+ default:
+ _soundemu = SOUND_EMU_MIDI;
+ break;
}
}
@@ -607,6 +609,8 @@ void AgiEngine::initialize() {
_renderMode = Common::kRenderEGA;
break;
}
+ } else {
+ _renderMode = Common::kRenderDefault;
}
_buttonStyle = AgiButtonStyle(_renderMode);
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index fb9e204101..507e7f7a11 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -37,6 +37,14 @@
#include "gui/debugger.h"
+// AGI resources
+#include "agi/console.h"
+#include "agi/view.h"
+#include "agi/picture.h"
+#include "agi/logic.h"
+#include "agi/sound.h"
+
+
namespace Common { class RandomSource; }
/**
@@ -110,23 +118,13 @@ enum AgiGameID {
GID_SQ2,
GID_XMASCARD,
GID_FANMADE,
- GID_GETOUTTASQ,
+ GID_GETOUTTASQ, // Fanmade
+ GID_SQ0, // Fanmade
GID_MICKEY, // PreAGI
GID_WINNIE, // PreAGI
- GID_TROLL // PreAGI
+ GID_TROLL // PreAGI
};
-} // End of namespace Agi
-
-// AGI resources
-#include "agi/console.h"
-#include "agi/view.h"
-#include "agi/picture.h"
-#include "agi/logic.h"
-#include "agi/sound.h"
-
-namespace Agi {
-
enum AgiGameType {
GType_PreAGI = 0,
GType_V2 = 1,
@@ -151,7 +149,8 @@ enum AgiGameFeatures {
GF_MENUS = (1 << 7),
GF_ESCPAUSE = (1 << 8),
GF_OLDAMIGAV20 = (1 << 9),
- GF_CLIPCOORDS = (1 << 10)
+ GF_CLIPCOORDS = (1 << 10),
+ GF_2GSOLDSOUND = (1 << 11)
};
struct AGIGameDescription;
@@ -316,6 +315,12 @@ enum AgiComputerType {
kAgiComputerAmigaOld = 20 // Older Amiga AGI interpreters' value (Seldom used)
};
+enum AgiSoundType {
+ kAgiSoundPC = 1,
+ kAgiSoundTandy = 3, // Tandy (This value is also used by the Amiga AGI and Apple IIGS AGI)
+ kAgiSound2GSOld = 8 // Apple IIGS's Gold Rush! (Version 1.0M 1989-02-28 (CE), AGI 3.003) uses value 8
+};
+
/**
* AGI flags
*/
@@ -497,10 +502,32 @@ struct ScriptPos {
int curIP;
};
-#define EGO_VIEW_TABLE 0
-#define HORIZON 36
-#define _WIDTH 160
-#define _HEIGHT 168
+enum {
+ EGO_VIEW_TABLE = 0,
+ HORIZON = 36,
+ _WIDTH = 160,
+ _HEIGHT = 168
+};
+
+enum InputMode {
+ INPUT_NORMAL = 0x01,
+ INPUT_GETSTRING = 0x02,
+ INPUT_MENU = 0x03,
+ INPUT_NONE = 0x04
+};
+
+enum State {
+ STATE_INIT = 0x00,
+ STATE_LOADED = 0x01,
+ STATE_RUNNING = 0x02
+};
+
+enum {
+ SBUF16_OFFSET = 0,
+ SBUF256_OFFSET = ((_WIDTH) * (_HEIGHT)),
+ FROM_SBUF16_TO_SBUF256_OFFSET = ((SBUF256_OFFSET) - (SBUF16_OFFSET)),
+ FROM_SBUF256_TO_SBUF16_OFFSET = ((SBUF16_OFFSET) - (SBUF256_OFFSET))
+};
/**
* AGI game structure.
@@ -508,10 +535,7 @@ struct ScriptPos {
* by the interpreter.
*/
struct AgiGame {
-#define STATE_INIT 0x00
-#define STATE_LOADED 0x01
-#define STATE_RUNNING 0x02
- int state; /**< state of the interpreter */
+ State state; /**< state of the interpreter */
// TODO: Check whether adjMouseX and adjMouseY must be saved and loaded when using savegames.
// If they must be then loading and saving is partially broken at the moment.
@@ -535,12 +559,9 @@ struct AgiGame {
uint8 inputBuffer[40]; /**< buffer for user input */
uint8 echoBuffer[40]; /**< buffer for echo.line */
int keypress;
-#define INPUT_NORMAL 0x01
-#define INPUT_GETSTRING 0x02
-#define INPUT_MENU 0x03
-#define INPUT_NONE 0x04
- int inputMode; /**< keyboard input mode */
- int inputEnabled; /**< keyboard input enabled */
+
+ InputMode inputMode; /**< keyboard input mode */
+ bool inputEnabled; /**< keyboard input enabled */
int lognum; /**< current logic number */
Common::Array<ScriptPos> execStack;
@@ -568,10 +589,7 @@ struct AgiGame {
char cursorChar;
unsigned int colorFg;
unsigned int colorBg;
-#define SBUF16_OFFSET 0
-#define SBUF256_OFFSET ((_WIDTH) * (_HEIGHT))
-#define FROM_SBUF16_TO_SBUF256_OFFSET ((SBUF256_OFFSET) - (SBUF16_OFFSET))
-#define FROM_SBUF256_TO_SBUF16_OFFSET ((SBUF16_OFFSET) - (SBUF256_OFFSET))
+
uint8 *sbufOrig; /**< Pointer to the 160x336 AGI screen buffer that contains vertically two 160x168 screens (16 color and 256 color). */
uint8 *sbuf16c; /**< 160x168 16 color (+control line & priority information) AGI screen buffer. Points at sbufOrig + SBUF16_OFFSET. */
uint8 *sbuf256c; /**< 160x168 256 color AGI screen buffer (For AGI256 and AGI256-2 support). Points at sbufOrig + SBUF256_OFFSET. */
@@ -774,8 +792,6 @@ public:
};
class AgiEngine : public AgiBase {
- int _gameId;
-
protected:
// Engine APIs
virtual Common::Error go();
@@ -788,9 +804,6 @@ protected:
public:
AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc);
virtual ~AgiEngine();
- int getGameId() {
- return _gameId;
- }
Common::Error loadGameState(int slot);
Common::Error saveGameState(int slot, const char *desc);
@@ -798,6 +811,7 @@ public:
private:
uint32 _tickTimer;
+ uint32 _lastTickTimer;
int _keyQueue[KEY_QUEUE_SIZE];
int _keyQueueStart;
@@ -829,7 +843,7 @@ public:
int loadGameSimple();
uint8 *_intobj;
- int _oldMode;
+ InputMode _oldMode;
bool _restartGame;
Menu* _menu;
@@ -871,7 +885,7 @@ public:
static void agiTimerFunctionLow(void *refCon);
void initPriTable();
- void newInputMode(int);
+ void newInputMode(InputMode mode);
void oldInputMode();
int getvar(int);
@@ -920,6 +934,17 @@ public:
int testIfCode(int);
void executeAgiCommand(uint8, uint8 *);
+private:
+ // Some submethods of testIfCode
+ uint8 testObjRight(uint8, uint8, uint8, uint8, uint8);
+ uint8 testObjCentre(uint8, uint8, uint8, uint8, uint8);
+ uint8 testObjInBox(uint8, uint8, uint8, uint8, uint8);
+ uint8 testPosn(uint8, uint8, uint8, uint8, uint8);
+ uint8 testSaid(uint8, uint8 *);
+ uint8 testController(uint8);
+ uint8 testKeypressed();
+ uint8 testCompareStrings(uint8, uint8);
+
// View
private:
@@ -1024,6 +1049,198 @@ private:
bool _predictiveDialogRunning;
public:
char _predictiveResult[40];
+
+private:
+ typedef void (AgiEngine::*AgiCommand)(uint8 *);
+
+ AgiCommand _agiCommands[183];
+ AgiLogic *_curLogic;
+ int _timerHack; // Workaround for timer loop in MH1 logic 153
+
+ void setupOpcodes();
+
+ void cmd_increment(uint8 *p);
+ void cmd_decrement(uint8 *p);
+ void cmd_assignn(uint8 *p);
+ void cmd_assignv(uint8 *p);
+ void cmd_addn(uint8 *p);
+ void cmd_addv(uint8 *p);
+ void cmd_subn(uint8 *p);
+ void cmd_subv(uint8 *p); // 0x08
+ void cmd_lindirectv(uint8 *p);
+ void cmd_rindirect(uint8 *p);
+ void cmd_lindirectn(uint8 *p);
+ void cmd_set(uint8 *p);
+ void cmd_reset(uint8 *p);
+ void cmd_toggle(uint8 *p);
+ void cmd_set_v(uint8 *p);
+ void cmd_reset_v(uint8 *p); // 0x10
+ void cmd_toggle_v(uint8 *p);
+ void cmd_new_room(uint8 *p);
+ void cmd_new_room_f(uint8 *p);
+ void cmd_load_logic(uint8 *p);
+ void cmd_load_logic_f(uint8 *p);
+ void cmd_call(uint8 *p);
+ void cmd_call_f(uint8 *p);
+ void cmd_load_pic(uint8 *p); // 0x18
+ void cmd_draw_pic(uint8 *p);
+ void cmd_show_pic(uint8 *p);
+ void cmd_discard_pic(uint8 *p);
+ void cmd_overlay_pic(uint8 *p);
+ void cmd_show_pri_screen(uint8 *p);
+ void cmd_load_view(uint8 *p);
+ void cmd_load_view_f(uint8 *p);
+ void cmd_discard_view(uint8 *p); // 0x20
+ void cmd_animate_obj(uint8 *p);
+ void cmd_unanimate_all(uint8 *p);
+ void cmd_draw(uint8 *p);
+ void cmd_erase(uint8 *p);
+ void cmd_position(uint8 *p);
+ void cmd_position_f(uint8 *p);
+ void cmd_get_posn(uint8 *p);
+ void cmd_reposition(uint8 *p); // 0x28
+ void cmd_set_view(uint8 *p);
+ void cmd_set_view_f(uint8 *p);
+ void cmd_set_loop(uint8 *p);
+ void cmd_set_loop_f(uint8 *p);
+ void cmd_fix_loop(uint8 *p);
+ void cmd_release_loop(uint8 *p);
+ void cmd_set_cel(uint8 *p);
+ void cmd_set_cel_f(uint8 *p); // 0x30
+ void cmd_last_cel(uint8 *p);
+ void cmd_current_cel(uint8 *p);
+ void cmd_current_loop(uint8 *p);
+ void cmd_current_view(uint8 *p);
+ void cmd_number_of_loops(uint8 *p);
+ void cmd_set_priority(uint8 *p);
+ void cmd_set_priority_f(uint8 *p);
+ void cmd_release_priority(uint8 *p); // 0x38
+ void cmd_get_priority(uint8 *p);
+ void cmd_stop_update(uint8 *p);
+ void cmd_start_update(uint8 *p);
+ void cmd_force_update(uint8 *p);
+ void cmd_ignore_horizon(uint8 *p);
+ void cmd_observe_horizon(uint8 *p);
+ void cmd_set_horizon(uint8 *p);
+ void cmd_object_on_water(uint8 *p); // 0x40
+ void cmd_object_on_land(uint8 *p);
+ void cmd_object_on_anything(uint8 *p);
+ void cmd_ignore_objs(uint8 *p);
+ void cmd_observe_objs(uint8 *p);
+ void cmd_distance(uint8 *p);
+ void cmd_stop_cycling(uint8 *p);
+ void cmd_start_cycling(uint8 *p);
+ void cmd_normal_cycle(uint8 *p); // 0x48
+ void cmd_end_of_loop(uint8 *p);
+ void cmd_reverse_cycle(uint8 *p);
+ void cmd_reverse_loop(uint8 *p);
+ void cmd_cycle_time(uint8 *p);
+ void cmd_stop_motion(uint8 *p);
+ void cmd_start_motion(uint8 *p);
+ void cmd_step_size(uint8 *p);
+ void cmd_step_time(uint8 *p); // 0x50
+ void cmd_move_obj(uint8 *p);
+ void cmd_move_obj_f(uint8 *p);
+ void cmd_follow_ego(uint8 *p);
+ void cmd_wander(uint8 *p);
+ void cmd_normal_motion(uint8 *p);
+ void cmd_set_dir(uint8 *p);
+ void cmd_get_dir(uint8 *p);
+ void cmd_ignore_blocks(uint8 *p); // 0x58
+ void cmd_observe_blocks(uint8 *p);
+ void cmd_block(uint8 *p);
+ void cmd_unblock(uint8 *p);
+ void cmd_get(uint8 *p);
+ void cmd_get_f(uint8 *p);
+ void cmd_drop(uint8 *p);
+ void cmd_put(uint8 *p);
+ void cmd_put_f(uint8 *p); // 0x60
+ void cmd_get_room_f(uint8 *p);
+ void cmd_load_sound(uint8 *p);
+ void cmd_sound(uint8 *p);
+ void cmd_stop_sound(uint8 *p);
+ void cmd_print(uint8 *p);
+ void cmd_print_f(uint8 *p);
+ void cmd_display(uint8 *p);
+ void cmd_display_f(uint8 *p); // 0x68
+ void cmd_clear_lines(uint8 *p);
+ void cmd_text_screen(uint8 *p);
+ void cmd_graphics(uint8 *p);
+ void cmd_set_cursor_char(uint8 *p);
+ void cmd_set_text_attribute(uint8 *p);
+ void cmd_shake_screen(uint8 *p);
+ void cmd_configure_screen(uint8 *p);
+ void cmd_status_line_on(uint8 *p); // 0x70
+ void cmd_status_line_off(uint8 *p);
+ void cmd_set_string(uint8 *p);
+ void cmd_get_string(uint8 *p);
+ void cmd_word_to_string(uint8 *p);
+ void cmd_parse(uint8 *p);
+ void cmd_get_num(uint8 *p);
+ void cmd_prevent_input(uint8 *p);
+ void cmd_accept_input(uint8 *p); // 0x78
+ void cmd_set_key(uint8 *p);
+ void cmd_add_to_pic(uint8 *p);
+ void cmd_add_to_pic_f(uint8 *p);
+ void cmd_status(uint8 *p);
+ void cmd_save_game(uint8 *p);
+ void cmd_load_game(uint8 *p);
+ void cmd_init_disk(uint8 *p);
+ void cmd_restart_game(uint8 *p); // 0x80
+ void cmd_show_obj(uint8 *p);
+ void cmd_random(uint8 *p);
+ void cmd_program_control(uint8 *p);
+ void cmd_player_control(uint8 *p);
+ void cmd_obj_status_f(uint8 *p);
+ void cmd_quit(uint8 *p);
+ void cmd_show_mem(uint8 *p);
+ void cmd_pause(uint8 *p); // 0x88
+ void cmd_echo_line(uint8 *p);
+ void cmd_cancel_line(uint8 *p);
+ void cmd_init_joy(uint8 *p);
+ void cmd_toggle_monitor(uint8 *p);
+ void cmd_version(uint8 *p);
+ void cmd_script_size(uint8 *p);
+ void cmd_set_game_id(uint8 *p);
+ void cmd_log(uint8 *p); // 0x90
+ void cmd_set_scan_start(uint8 *p);
+ void cmd_reset_scan_start(uint8 *p);
+ void cmd_reposition_to(uint8 *p);
+ void cmd_reposition_to_f(uint8 *p);
+ void cmd_trace_on(uint8 *p);
+ void cmd_trace_info(uint8 *p);
+ void cmd_print_at(uint8 *p);
+ void cmd_print_at_v(uint8 *p); // 0x98
+ //void cmd_discard_view(uint8 *p); // Opcode repeated from 0x20 ?
+ void cmd_clear_text_rect(uint8 *p);
+ void cmd_set_upper_left(uint8 *p);
+ void cmd_set_menu(uint8 *p);
+ void cmd_set_menu_item(uint8 *p);
+ void cmd_submit_menu(uint8 *p);
+ void cmd_enable_item(uint8 *p);
+ void cmd_disable_item(uint8 *p); // 0xa0
+ void cmd_menu_input(uint8 *p);
+ void cmd_show_obj_v(uint8 *p);
+ void cmd_open_dialogue(uint8 *p);
+ void cmd_close_dialogue(uint8 *p);
+ void cmd_mul_n(uint8 *p);
+ void cmd_mul_v(uint8 *p);
+ void cmd_div_n(uint8 *p);
+ void cmd_div_v(uint8 *p); // 0xa8
+ void cmd_close_window(uint8 *p);
+ void cmd_set_simple(uint8 *p);
+ void cmd_push_script(uint8 *p);
+ void cmd_pop_script(uint8 *p);
+ void cmd_hold_key(uint8 *p);
+ void cmd_set_pri_base(uint8 *p);
+ void cmd_discard_sound(uint8 *p);
+ void cmd_hide_mouse(uint8 *p); // 0xb0
+ void cmd_allow_menu(uint8 *p);
+ void cmd_show_mouse(uint8 *p);
+ void cmd_fence_mouse(uint8 *p);
+ void cmd_mouse_posn(uint8 *p);
+ void cmd_release_key(uint8 *p);
+ void cmd_adj_ego_move_to_x_y(uint8 *p);
};
} // End of namespace Agi
diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp
index a0621f80dd..e5942455e2 100644
--- a/engines/agi/console.cpp
+++ b/engines/agi/console.cpp
@@ -53,18 +53,9 @@ Console::Console(AgiEngine *vm) : GUI::Debugger() {
DCmd_Register("bt", WRAP_METHOD(Console, Cmd_BT));
}
-Console::~Console() {
-}
-
-void Console::preEnter() {
-}
-
-void Console::postEnter() {
-}
-
bool Console::Cmd_SetVar(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Usage: setvar <varnum> <value>");
+ DebugPrintf("Usage: setvar <varnum> <value>\n");
return true;
}
int p1 = (int)atoi(argv[1]);
@@ -76,7 +67,7 @@ bool Console::Cmd_SetVar(int argc, const char **argv) {
bool Console::Cmd_SetFlag(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Usage: setvar <varnum> <value>");
+ DebugPrintf("Usage: setvar <varnum> <value>\n");
return true;
}
int p1 = (int)atoi(argv[1]);
@@ -88,7 +79,7 @@ bool Console::Cmd_SetFlag(int argc, const char **argv) {
bool Console::Cmd_SetObj(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Usage: setvar <varnum> <value>");
+ DebugPrintf("Usage: setvar <varnum> <value>\n");
return true;
}
int p1 = (int)atoi(argv[1]);
@@ -99,6 +90,11 @@ bool Console::Cmd_SetObj(int argc, const char **argv) {
}
bool Console::Cmd_RunOpcode(int argc, const char **argv) {
+ if (argc < 2) {
+ DebugPrintf("Usage: runopcode <name> <parameter0> ....\n");
+ return true;
+ }
+
for (int i = 0; logicNamesCmd[i].name; i++) {
if (!strcmp(argv[1], logicNamesCmd[i].name)) {
uint8 p[16];
@@ -120,6 +116,8 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) {
}
}
+ DebugPrintf("Unknown opcode\n");
+
return true;
}
@@ -243,6 +241,10 @@ bool Console::Cmd_Cont(int argc, const char **argv) {
}
bool Console::Cmd_Room(int argc, const char **argv) {
+ if (argc == 2) {
+ _vm->newRoom(strtoul(argv[1], NULL, 0));
+ }
+
DebugPrintf("Current room: %d\n", _vm->getvar(0));
return true;
diff --git a/engines/agi/console.h b/engines/agi/console.h
index e8eccbe50a..e79db42054 100644
--- a/engines/agi/console.h
+++ b/engines/agi/console.h
@@ -46,11 +46,6 @@ struct AgiDebug {
class Console : public GUI::Debugger {
public:
Console(AgiEngine *vm);
- virtual ~Console();
-
-protected:
- virtual void preEnter();
- virtual void postEnter();
private:
bool Cmd_SetVar(int argc, const char **argv);
@@ -80,10 +75,6 @@ public:
PreAGI_Console(PreAgiEngine *vm);
virtual ~PreAGI_Console() {}
-protected:
- virtual void preEnter() {}
- virtual void postEnter() {}
-
private:
PreAgiEngine *_vm;
};
@@ -94,10 +85,6 @@ public:
Mickey_Console(PreAgiEngine *vm, Mickey *mickey);
virtual ~Mickey_Console() {}
-protected:
- virtual void preEnter() {}
- virtual void postEnter() {}
-
private:
Mickey *_mickey;
@@ -112,10 +99,6 @@ public:
Winnie_Console(PreAgiEngine *vm, Winnie *winnie);
virtual ~Winnie_Console() {}
-protected:
- virtual void preEnter() {}
- virtual void postEnter() {}
-
private:
Winnie *_winnie;
diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp
index 10df40556f..b7eba22298 100644
--- a/engines/agi/cycle.cpp
+++ b/engines/agi/cycle.cpp
@@ -177,9 +177,12 @@ void AgiEngine::updateTimer() {
setvar(vDays, getvar(vDays) + 1);
}
-void AgiEngine::newInputMode(int i) {
+void AgiEngine::newInputMode(InputMode mode) {
+ if (mode == INPUT_MENU && !getflag(fMenusWork) && !(getFeatures() & GF_MENUS))
+ return;
+
_oldMode = _game.inputMode;
- _game.inputMode = i;
+ _game.inputMode = mode;
}
void AgiEngine::oldInputMode() {
@@ -200,7 +203,7 @@ int AgiEngine::mainCycle() {
// vars in every interpreter cycle.
//
// We run AGIMOUSE always as a side effect
- if (getFeatures() & GF_AGIMOUSE || 1) {
+ if (getFeatures() & GF_AGIMOUSE || true) {
_game.vars[28] = _mouse.x / 2;
_game.vars[29] = _mouse.y;
}
@@ -314,7 +317,8 @@ int AgiEngine::playGame() {
_game.clockEnabled = true;
_game.lineUserInput = 22;
- if (getFeatures() & GF_AGIMOUSE)
+ // We run AGIMOUSE always as a side effect
+ if (getFeatures() & GF_AGIMOUSE || true)
report("Using AGI Mouse 1.0 protocol\n");
if (getFeatures() & GF_AGIPAL)
@@ -386,28 +390,33 @@ int AgiEngine::runGame() {
_restartGame = false;
}
- // Set computer type (v20 i.e. vComputer)
+ // Set computer type (v20 i.e. vComputer) and sound type
switch (getPlatform()) {
case Common::kPlatformAtariST:
setvar(vComputer, kAgiComputerAtariST);
+ setvar(vSoundgen, kAgiSoundPC);
break;
case Common::kPlatformAmiga:
if (getFeatures() & GF_OLDAMIGAV20)
setvar(vComputer, kAgiComputerAmigaOld);
else
setvar(vComputer, kAgiComputerAmiga);
+ setvar(vSoundgen, kAgiSoundTandy);
break;
case Common::kPlatformApple2GS:
setvar(vComputer, kAgiComputerApple2GS);
+ if (getFeatures() & GF_2GSOLDSOUND)
+ setvar(vSoundgen, kAgiSound2GSOld);
+ else
+ setvar(vSoundgen, kAgiSoundTandy);
break;
case Common::kPlatformPC:
default:
setvar(vComputer, kAgiComputerPC);
+ setvar(vSoundgen, kAgiSoundPC);
break;
}
- setvar(vSoundgen, 1); // IBM PC SOUND
-
// Set monitor type (v26 i.e. vMonitor)
switch (_renderMode) {
case Common::kRenderCGA:
@@ -430,7 +439,7 @@ int AgiEngine::runGame() {
setvar(vFreePages, 180); // Set amount of free memory to realistic value
setvar(vMaxInputChars, 38);
_game.inputMode = INPUT_NONE;
- _game.inputEnabled = 0;
+ _game.inputEnabled = false;
_game.hasPrompt = 0;
_game.state = STATE_RUNNING;
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index e72647d5e2..d1bed5d716 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -125,841 +125,7 @@ static const PlainGameDescriptor agiGames[] = {
{0, 0}
};
-
-namespace Agi {
-
-using Common::GUIO_NONE;
-
-#define GAME_LVFPN(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \
- { \
- id, \
- name, \
- AD_ENTRY1s(fname,md5,size), \
- lang, \
- platform, \
- ADGF_NO_FLAGS, \
- GUIO_NONE \
- }, \
- gid, \
- interp, \
- features, \
- ver, \
- }
-
-#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \
- { \
- id, \
- name, \
- AD_ENTRY1s(fname,md5,size), \
- lang, \
- platform, \
- ADGF_USEEXTRAASTITLE, \
- GUIO_NONE \
- }, \
- gid, \
- interp, \
- features, \
- ver, \
- }
-
-#define GAME(id,name,md5,ver,gid) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2)
-#define GAME3(id,name,fname,md5,ver,gid) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V3)
-
-#define GAME_P(id,name,md5,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_V2)
-
-#define GAME_FP(id,name,md5,ver,flags,gid,platform) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V2)
-
-#define GAME_PS(id,name,md5,size,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,Common::EN_ANY,ver,0,gid,platform,GType_V2)
-
-#define GAME_LPS(id,name,md5,size,lang,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,lang,ver,0,gid,platform,GType_V2)
-
-#define GAME_LFPS(id,name,md5,size,lang,ver,flags,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,lang,ver,flags,gid,platform,GType_V2)
-
-#define GAME3_P(id,name,fname,md5,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V3)
-
-#define GAMEpre_P(id,name,fname,md5,ver,gid,platform) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI)
-
-#define GAMEpre_PS(id,name,fname,md5,size,ver,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI)
-
-#define GAME3_PS(id,name,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3)
-
-#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPNF(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2)
-
-#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPNF(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2)
-#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVP("agi-fanmade",name,md5,size,ver,platform)
-
-#define FANMADE_LVF(name,md5,lang,ver,features) FANMADE_ILVF("agi-fanmade",name,md5,lang,ver,features)
-
-#define FANMADE_LF(name,md5,lang,features) FANMADE_LVF(name,md5,lang,0x2917,features)
-#define FANMADE_IF(id,name,md5,features) FANMADE_ILVF(id,name,md5,Common::EN_ANY,0x2917,features)
-
-#define FANMADE_V(name,md5,ver) FANMADE_LVF(name,md5,Common::EN_ANY,ver,0)
-#define FANMADE_F(name,md5,features) FANMADE_LF(name,md5,Common::EN_ANY,features)
-#define FANMADE_L(name,md5,lang) FANMADE_LF(name,md5,lang,0)
-#define FANMADE_I(id,name,md5) FANMADE_IF(id,name,md5,0)
-
-#define FANMADE(name,md5) FANMADE_F(name,md5,0)
-
-static const AGIGameDescription gameDescriptions[] = {
-
- // AGI Demo 1 (PC) 05/87 [AGI 2.425]
- GAME("agidemo", "Demo 1 1987-05-20", "9c4a5b09cc3564bc48b4766e679ea332", 0x2440, GID_AGIDEMO),
-
- // AGI Demo 2 (IIgs) 1.0C (Censored)
- GAME_P("agidemo", "Demo 2 1987-11-24 1.0C", "580ffdc569ff158f56fb92761604f70e", 0x2917, GID_AGIDEMO, Common::kPlatformApple2GS),
-
- // AGI Demo 2 (PC 3.5") 11/87 [AGI 2.915]
- GAME("agidemo", "Demo 2 1987-11-24 3.5\"", "e8ebeb0bbe978172fe166f91f51598c7", 0x2917, GID_AGIDEMO),
-
- // AGI Demo 2 (PC 5.25") 11/87 [v1] [AGI 2.915]
- GAME("agidemo", "Demo 2 1987-11-24 [version 1] 5.25\"", "852ac303a374df62571642ca1e2d1f0a", 0x2917, GID_AGIDEMO),
-
- // AGI Demo 2 (PC 5.25") 01/88 [v2] [AGI 2.917]
- GAME("agidemo", "Demo 2 1987-11-25 [version 2] 5.25\"", "1503f02086ea9f388e7e041c039eaa69", 0x2917, GID_AGIDEMO),
-
- // AGI Demo 3 (PC) 09/88 [AGI 3.002.102]
- GAME3("agidemo", "Demo 3 1988-09-13", "dmdir", "289c7a2c881f1d973661e961ced77d74", 0x3149, GID_AGIDEMO),
-
- // AGI Demo for Kings Quest III and Space Quest I
- GAME("agidemo", "Demo Kings Quest III and Space Quest I", "502e6bf96827b6c4d3e67c9cdccd1033", 0x2272, GID_AGIDEMO),
-
- // Black Cauldron (Amiga) 2.00 6/14/87
- GAME_P("bc", "2.00 1987-06-14", "7b01694af21213b4727bb94476f64eb5", 0x2440, GID_BC, Common::kPlatformAmiga),
-
- // Black Cauldron (Apple IIgs) 1.0O 2/24/89 (CE)
- // Menus not tested
- GAME3_P("bc", "1.0O 1989-02-24 (CE)", "bcdir", "dc09d30b147242692f4f85b9811962db", 0x3149, 0, GID_BC, Common::kPlatformApple2GS),
-
- // Black Cauldron (PC) 2.00 6/14/87 [AGI 2.439]
- GAME("bc", "2.00 1987-06-14", "7f598d4712319b09d7bd5b3be10a2e4a", 0x2440, GID_BC),
-
- // Black Cauldron (Russian)
- GAME_LPS("bc", "", "b7de782dfdf8ea7dde8064f09804bcf5", 357, Common::RU_RUS, 0x2440, GID_BC, Common::kPlatformPC),
-
- // Black Cauldron (PC 5.25") 2.10 11/10/88 [AGI 3.002.098]
- GAME3("bc", "2.10 1988-11-10 5.25\"", "bcdir", "0c5a9acbcc7e51127c34818e75806df6", 0x3149, GID_BC),
-
- // Black Cauldron (PC) 2.10 [AGI 3.002.097]
- GAME3("bc", "2.10", "bcdir", "0de3953c9225009dc91e5b0d1692967b", 0x3149, GID_BC),
-
- // Black Cauldron (CoCo3 360k) [AGI 2.023]
- GAME_PS("bc", "", "51212c54808ade96176f201ae0ac7a6f", 357, 0x2440, GID_BC, Common::kPlatformCoCo3),
-
- // Black Cauldron (CoCo3 360k) [AGI 2.072]
- GAME_PS("bc", "updated", "c4e1937f74e8100cd0152b904434d8b4", 357, 0x2440, GID_BC, Common::kPlatformCoCo3),
-
-// TODO
-// These aren't supposed to work now as they require unsupported agi engine 2.01
-#if 0
- // Donald Duck's Playground (Amiga) 1.0C
- // Menus not tested
- GAME_P("ddp", "1.0C 1987-04-27", "550971d196f65190a5c760d2479406ef", 0x2272, GID_DDP, Common::kPlatformAmiga),
-
- // Donald Duck's Playground (ST) 1.0A 8/8/86
- // Menus not tested
- GAME("ddp", "1.0A 1986-08-08", "64388812e25dbd75f7af1103bc348596", 0x2272, GID_DDP),
-
- // reported by Filippos (thebluegr) in bugreport #1654500
- // Menus not tested
- GAME_PS("ddp", "1.0C 1986-06-09", "550971d196f65190a5c760d2479406ef", 132, 0x2272, GID_DDP, Common::kPlatformPC),
-#endif
-
- // Gold Rush! (Amiga) 1.01 1/13/89 aka 2.05 3/9/89 # 2.316
- GAME3_PS("goldrush", "1.01 1989-01-13 aka 2.05 1989-03-09", "dirs", "a1d4de3e75c2688c1e2ca2634ffc3bd8", 2399, 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAmiga),
-
- // Gold Rush! (Apple IIgs) 1.0M 2/28/89 (CE) aka 2.01 12/22/88
- // Menus not tested
- GAME3_P("goldrush", "1.0M 1989-02-28 (CE) aka 2.01 1988-12-22", "grdir", "3f7b9ce62631434389f85371b11921d6", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformApple2GS),
-
- // Gold Rush! (ST) 1.01 1/13/89 aka 2.01 12/22/88
- GAME3_P("goldrush", "1.01 1989-01-13 aka 2.01 1988-12-22", "grdir", "4dd4d50480a3d6c206fa227ce8142735", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAtariST),
-
- // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149]
- GAME3("goldrush", "2.01 1988-12-22 5.25\"", "grdir", "db733d199238d4009a9e95f11ece34e9", 0x3149, GID_GOLDRUSH),
-
- // Gold Rush! (PC 3.5") 2.01 12/22/88 [AGI 3.002.149]
- GAME3("goldrush", "2.01 1988-12-22 3.5\"", "grdir", "6a285235745f69b4b421403659497216", 0x3149, GID_GOLDRUSH),
-
- // Gold Rush! (PC 3.5", bought from The Software Farm) 3.0 1998-12-22 [AGI 3.002.149]
- GAME3("goldrush", "3.0 1998-12-22 3.5\"", "grdir", "6882b6090473209da4cd78bb59f78dbe", 0x3149, GID_GOLDRUSH),
-
- {
- // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149]
- {
- "goldrush",
- "2.01 1988-12-22",
- {
- { "grdir", 0, "db733d199238d4009a9e95f11ece34e9", 2399},
- { "vol.0", 0, "4b6423d143674d3757ab1b875d25951d", 25070},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_GOLDRUSH,
- GType_V3,
- GF_MACGOLDRUSH,
- 0x3149,
- },
-
-
- // Gold Rush! (CoCo3 720k) [AGI 2.023]
- GAME_PS("goldrush", "", "0a41b65efc0cd6c4271e957e6ffbbd8e", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3),
-
- // Gold Rush! (CoCo3 360k/720k) [AGI 2.072]
- GAME_PS("goldrush", "updated", "c49bf56bf91e31a4601a604e51ef8bfb", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3),
-
- // King's Quest 1 (Amiga) 1.0U # 2.082
- // The original game did not have menus, they are enabled under ScummVM
- GAME_FP("kq1", "1.0U 1986", "246c695324f1c514aee2b904fa352fad", 0x2440, GF_MENUS, GID_KQ1, Common::kPlatformAmiga),
-
- // King's Quest 1 (ST) 1.0V
- // The original game did not have menus, they are enabled under ScummVM
- GAME_FP("kq1", "1.0V 1986", "c3a017e556c4b0eece366a4cd9abb657", 0x2272, GF_MENUS, GID_KQ1, Common::kPlatformAtariST),
-
- // King's Quest 1 (IIgs) 1.0S-88223
- // Menus not tested
- GAME_P("kq1", "1.0S 1988-02-23", "f4277aa34b43d37382bc424c81627617", 0x2272, GID_KQ1, Common::kPlatformApple2GS),
-
- // King's Quest 1 (Mac) 2.0C
- GAME_P("kq1", "2.0C 1987-03-26", "d4c4739d4ac63f7dbd29255425077d48", 0x2440, GID_KQ1, Common::kPlatformMacintosh),
-
- // King's Quest 1 (PC 5.25"/3.5") 2.0F [AGI 2.917]
- GAME("kq1", "2.0F 1987-05-05 5.25\"/3.5\"", "10ad66e2ecbd66951534a50aedcd0128", 0x2917, GID_KQ1),
-
- // King's Quest 1 (CoCo3 360k) [AGI 2.023]
- GAME_PS("kq1", "", "10ad66e2ecbd66951534a50aedcd0128", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3),
-
- // King's Quest 1 (CoCo3 360k) [AGI 2.023]
- GAME_PS("kq1", "fixed", "4c8ef8b5d2f1b6c1a93e456d1f1ffc74", 768, 0x2440, GID_KQ1, Common::kPlatformCoCo3),
-
- // King's Quest 1 (CoCo3 360k) [AGI 2.072]
- GAME_PS("kq1", "updated", "94087178c78933a4af3cd24d1c8dd7b2", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3),
-
- // King's Quest 2 (IIgs) 2.0A 6/16/88 (CE)
- GAME_P("kq2", "2.0A 1988-06-16 (CE)", "5203c8b95250a2ecfee93ddb99414753", 0x2917, GID_KQ2, Common::kPlatformApple2GS),
-
- // King's Quest 2 (Amiga) 2.0J (Broken)
- GAME_P("kq2", "2.0J 1987-01-29 [OBJECT decrypted]", "b866f0fab2fad91433a637a828cfa410", 0x2440, GID_KQ2, Common::kPlatformAmiga),
-
- // King's Quest 2 (Mac) 2.0R
- GAME_P("kq2", "2.0R 1988-03-23", "cbdb0083317c8e7cfb7ac35da4bc7fdc", 0x2440, GID_KQ2, Common::kPlatformMacintosh),
-
- // King's Quest 2 (PC) 2.1 [AGI 2.411]; entry from DAGII, but missing from Sarien?
- // XXX: any major differences from 2.411 to 2.440?
- GAME("kq2", "2.1 1987-04-10", "759e39f891a0e1d86dd29d7de485c6ac", 0x2440, GID_KQ2),
-
- // King's Quest 2 (PC 5.25"/3.5") 2.2 [AGI 2.426]
- GAME("kq2", "2.2 1987-05-07 5.25\"/3.5\"", "b944c4ff18fb8867362dc21cc688a283", 0x2917, GID_KQ2),
-
- // King's Quest 2 (Russian)
- GAME_LPS("kq2", "", "35211c574ececebdc723b23e35f99275", 543, Common::RU_RUS, 0x2917, GID_KQ2, Common::kPlatformPC),
-
- // King's Quest 2 (CoCo3 360k) [AGI 2.023]
- GAME_PS("kq2", "", "b944c4ff18fb8867362dc21cc688a283", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3),
-
- // King's Quest 2 (CoCo3 360k) [AGI 2.072]
- GAME_PS("kq2", "updated", "f64a606de740a5348f3d125c03e989fe", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3),
-
- // King's Quest 2 (CoCo3 360k) [AGI 2.023]
- GAME_PS("kq2", "fixed", "fb33ac2768a94a89117a270771db465c", 768, 0x2440, GID_KQ2, Common::kPlatformCoCo3),
-
- // King's Quest 3 (Amiga) 1.01 11/8/86
- // The original game did not have menus, they are enabled under ScummVM
- GAME_FP("kq3", "1.01 1986-11-08", "8ab343306df0e2d98f136be4e8cfd0ef", 0x2440, GF_MENUS, GID_KQ3, Common::kPlatformAmiga),
-
- // King's Quest 3 (ST) 1.02 11/18/86
- // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game
- GAME_FP("kq3", "1.02 1986-11-18", "8846df2654302b623217ba8bd6d657a9", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformAtariST),
-
- // King's Quest 3 (Mac) 2.14 3/15/88
- GAME_P("kq3", "2.14 1988-03-15", "7639c0da5ce94848227d409351fabda2", 0x2440, GID_KQ3, Common::kPlatformMacintosh),
-
- // King's Quest 3 (IIgs) 2.0A 8/28/88 (CE)
- GAME_P("kq3", "2.0A 1988-08-28 (CE)", "ac30b7ca5a089b5e642fbcdcbe872c12", 0x2917, GID_KQ3, Common::kPlatformApple2GS),
-
- // King's Quest 3 (Amiga) 2.15 11/15/89 # 2.333
- // Original pauses with ESC, has menus accessible with mouse.
- // ver = 0x3086 -> menus accessible with ESC or mouse, bug #2835581 (KQ3: Game Crash When Leaving Tavern as Fly).
- // ver = 0x3149 -> menus accessible with mouse, ESC pauses game, bug #2835581 disappears.
- GAME3_PS("kq3", "2.15 1989-11-15", "dirs", "8e35bded2bc5cf20f5eec2b15523b155", 1805, 0x3149, 0, GID_KQ3, Common::kPlatformAmiga),
-
- // King's Quest 3 (PC) 1.01 11/08/86 [AGI 2.272]
- // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game
- GAME_FP("kq3", "1.01 1986-11-08", "9c2b34e7ffaa89c8e2ecfeb3695d444b", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC),
-
- // King's Quest 3 (Russian)
- GAME_LFPS("kq3", "", "5856dec6ccb9c4b70aee21044a19270a", 390, Common::RU_RUS, 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC),
-
- // King's Quest 3 (PC 5.25") 2.00 5/25/87 [AGI 2.435]
- GAME("kq3", "2.00 1987-05-25 5.25\"", "18aad8f7acaaff760720c5c6885b6bab", 0x2440, GID_KQ3),
-
- // King's Quest 3 (Mac) 2.14 3/15/88
- // Menus not tested
- GAME_P("kq3", "2.14 1988-03-15 5.25\"", "7650e659c7bc0f1e9f8a410b7a2e9de6", 0x2440, GID_KQ3, Common::kPlatformMacintosh),
-
- // King's Quest 3 (PC 3.5") 2.14 3/15/88 [AGI 2.936]
- GAME("kq3", "2.14 1988-03-15 3.5\"", "d3d17b77b3b3cd13246749231d9473cd", 0x2936, GID_KQ3),
-
- // King's Quest 3 (CoCo3 158k/360k) [AGI 2.023]
- GAME_PS("kq3", "", "5a6be7d16b1c742c369ef5cc64fefdd2", 429, 0x2440, GID_KQ3, Common::kPlatformCoCo3),
-
- // King's Quest 4 (PC 5.25") 2.0 7/27/88 [AGI 3.002.086]
- GAME3("kq4", "2.0 1988-07-27", "kq4dir", "f50f7f997208ca0e35b2650baec43a2d", 0x3086, GID_KQ4),
-
- // King's Quest 4 (PC 3.5") 2.0 7/27/88 [AGI 3.002.086]
- GAME3("kq4", "2.0 1988-07-27 3.5\"", "kq4dir", "fe44655c42f16c6f81046fdf169b6337", 0x3086, GID_KQ4),
-
- // King's Quest 4 (PC 3.5") 2.2 9/27/88 [AGI 3.002.086]
- // Menus not tested
- GAME3("kq4", "2.2 1988-09-27 3.5\"", "kq4dir", "7470b3aeb49d867541fc66cc8454fb7d", 0x3086, GID_KQ4),
-
- // King's Quest 4 (PC 5.25") 2.3 9/27/88 [AGI 3.002.086]
- GAME3("kq4", "2.3 1988-09-27", "kq4dir", "6d7714b8b61466a5f5981242b993498f", 0x3086, GID_KQ4),
-
- // King's Quest 4 (PC 3.5") 2.3 9/27/88 [AGI 3.002.086]
- GAME3("kq4", "2.3 1988-09-27 3.5\"", "kq4dir", "82a0d39af891042e99ac1bd6e0b29046", 0x3086, GID_KQ4),
-
- // King's Quest 4 (IIgs) 1.0K 11/22/88 (CE)
- // Menus not tested
- GAME3_P("kq4", "1.0K 1988-11-22", "kq4dir", "8536859331159f15012e35dc82cb154e", 0x3086, 0, GID_KQ4, Common::kPlatformApple2GS),
-
- // King's Quest 4 demo (PC) [AGI 3.002.102]
- // Menus not tested
- GAME3("kq4", "Demo 1988-12-20", "dmdir", "a3332d70170a878469d870b14863d0bf", 0x3149, GID_KQ4),
-
- // King's Quest 4 (CoCo3 720k) [AGI 2.023]
- GAME_PS("kq4", "", "9e7729a28e749ca241d2bf71b9b2dbde", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3),
-
- // King's Quest 4 (CoCo3 360k/720k) [AGI 2.072]
- GAME_PS("kq4", "updated", "1959ca10739edb34069bb504dbd74805", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3),
-
- // Leisure Suit Larry 1 (PC 5.25"/3.5") 1.00 6/1/87 [AGI 2.440]
- GAME("lsl1", "1.00 1987-06-01 5.25\"/3.5\"", "1fe764e66857e7f305a5f03ca3f4971d", 0x2440, GID_LSL1),
-
- // Leisure Suit Larry 1 Polish
- GAME_LPS("lsl1", "2.00 2001-12-11", "7ba1fccc46d27c141e704706c1d0a85f", 303, Common::PL_POL, 0x2440, GID_LSL1, Common::kPlatformPC),
-
- // Leisure Suit Larry 1 Polish - Demo
- GAME_LPS("lsl1", "Demo", "3b2f564306c401dff6334441df967ddd", 666, Common::PL_POL, 0x2917, GID_LSL1, Common::kPlatformPC),
-
- // Leisure Suit Larry 1 (ST) 1.04 6/18/87
- GAME_P("lsl1", "1.04 1987-06-18", "8b579f8673fe9448c2538f5ed9887cf0", 0x2440, GID_LSL1, Common::kPlatformAtariST),
-
- // Leisure Suit Larry 1 (Amiga) 1.05 6/26/87 # x.yyy
- GAME_P("lsl1", "1.05 1987-06-26", "3f5d26d8834ca49c147fb60936869d56", 0x2440, GID_LSL1, Common::kPlatformAmiga),
-
- // Leisure Suit Larry 1 (IIgs) 1.0E
- GAME_P("lsl1", "1.0E 1987", "5f9e1dd68d626c6d303131c119582ad4", 0x2440, GID_LSL1, Common::kPlatformApple2GS),
-
- // Leisure Suit Larry 1 (Mac) 1.05 6/26/87
- GAME_P("lsl1", "1.05 1987-06-26", "8a0076429890531832f0dc113285e31e", 0x2440, GID_LSL1, Common::kPlatformMacintosh),
-
- // Leisure Suit Larry 1 (CoCo3 158k/360k) [AGI 2.072]
- GAME_PS("lsl1", "", "a2de1fe76565c3e8b40c9d036b5e5612", 198, 0x2440, GID_LSL1, Common::kPlatformCoCo3),
-
- // Manhunter NY (ST) 1.03 10/20/88
- GAME3_P("mh1", "1.03 1988-10-20", "mhdir", "f2d58056ad802452d60776ee920a52a6", 0x3149, 0, GID_MH1, Common::kPlatformAtariST),
-
- // Manhunter NY (IIgs) 2.0E 10/05/88 (CE)
- GAME3_P("mh1", "2.0E 1988-10-05 (CE)", "mhdir", "2f1509f76f24e6e7d213f2dadebbf156", 0x3149, 0, GID_MH1, Common::kPlatformApple2GS),
-
- // Manhunter NY (Amiga) 1.06 3/18/89
- GAME3_P("mh1", "1.06 1989-03-18", "dirs", "92c6183042d1c2bb76236236a7d7a847", 0x3149, GF_OLDAMIGAV20, GID_MH1, Common::kPlatformAmiga),
-
- // reported by Filippos (thebluegr) in bugreport #1654500
- // Manhunter NY (PC 5.25") 1.22 8/31/88 [AGI 3.002.107]
- GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "0c7b86f05fe02c2e26cff1b07450b82a", 2123, 0x3149, 0, GID_MH1, Common::kPlatformPC),
-
- // Manhunter NY (PC 3.5") 1.22 8/31/88 [AGI 3.002.102]
- GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "5b625329021ad49fd0c1d6f2d6f54bba", 2141, 0x3149, 0, GID_MH1, Common::kPlatformPC),
-
- // Manhunter NY (CoCo3 720k) [AGI 2.023]
- GAME_PS("mh1", "", "b968285caf2f591c78dd9c9e26ab8974", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3),
-
- // Manhunter NY (CoCo3 360k/720k) [AGI 2.072]
- GAME_PS("mh1", "updated", "d47da950c62289f8d4ccf36af73365f2", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3),
-
- // Manhunter SF (ST) 1.0 7/29/89
- GAME3_P("mh2", "1.0 1989-07-29", "mh2dir", "5e3581495708b952fea24438a6c7e040", 0x3149, 0, GID_MH1, Common::kPlatformAtariST),
-
- // Manhunter SF (Amiga) 3.06 8/17/89 # 2.333
- GAME3_PS("mh2", "3.06 1989-08-17", "dirs", "b412e8a126368b76696696f7632d4c16", 2573, 0x3086, GF_OLDAMIGAV20, GID_MH2, Common::kPlatformAmiga),
-
- // Manhunter SF (PC 5.25") 3.03 8/17/89 [AGI 3.002.149]
- GAME3("mh2", "3.03 1989-08-17 5.25\"", "mh2dir", "b90e4795413c43de469a715fb3c1fa93", 0x3149, GID_MH2),
-
- // Manhunter SF (PC 3.5") 3.02 7/26/89 [AGI 3.002.149]
- GAME3("mh2", "3.02 1989-07-26 3.5\"", "mh2dir", "6fb6f0ee2437704c409cf17e081ba152", 0x3149, GID_MH2),
-
- // Manhunter SF (CoCo3 720k) [AGI 2.023]
- GAME_PS("mh2", "", "acaaa577e10d1753c5a74f6ae1d858d4", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3),
-
- // Manhunter SF (CoCo3 720k) [AGI 2.072]
- GAME_PS("mh2", "updated", "c64875766700196e72a92359f70f45a9", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3),
-
- // Mickey's Space Adventure
- // Preagi game
- GAMEpre_P("mickey", "", "1.pic", "b6ec04c91a05df374792872c4d4ce66d", 0x0000, GID_MICKEY, Common::kPlatformPC),
-
-#if 0
- // Mixed-Up Mother Goose (Amiga) 1.1
- // Problematic: crashes
- // Menus not tested
- GAME3_PS("mixedup", "1.1 1986-12-10", "dirs", "5c1295fe6daaf95831195ba12894dbd9", 2021, 0x3086, 0, GID_MIXEDUP, Common::kPlatformAmiga),
-#endif
-
- // Mixed Up Mother Goose (IIgs)
- GAME_P("mixedup", "1987", "3541954a7303467c6df87665312ffb6a", 0x2917, GID_MIXEDUP, Common::kPlatformApple2GS),
-
- // Mixed-Up Mother Goose (PC) [AGI 2.915]
- GAME("mixedup", "1987-11-10", "e524655abf9b96a3b179ffcd1d0f79af", 0x2917, GID_MIXEDUP),
-
- // Mixed-Up Mother Goose (CoCo3 360k) [AGI 2.072]
- GAME_PS("mixedup", "", "44e63e9b4d4822a31edea0e8a7e7eac4", 606, 0x2440, GID_MIXEDUP, Common::kPlatformCoCo3),
-
- // Police Quest 1 (PC) 2.0E 11/17/87 [AGI 2.915]
- GAME("pq1", "2.0E 1987-11-17", "2fd992a92df6ab0461d5a2cd83c72139", 0x2917, GID_PQ1),
-
- // Police Quest 1 (Mac) 2.0G 12/3/87
- GAME_P("pq1", "2.0G 1987-12-03", "805750b66c1c5b88a214e67bfdca17a1", 0x2440, GID_PQ1, Common::kPlatformMacintosh),
-
- // Police Quest 1 (IIgs) 2.0B-88421
- GAME_P("pq1", "2.0B 1988-04-21", "e7c175918372336461e3811d594f482f", 0x2917, GID_PQ1, Common::kPlatformApple2GS),
-
- // Police Quest 1 (Amiga) 2.0B 2/22/89 # 2.310
- GAME3_PS("pq1", "2.0B 1989-02-22", "dirs", "cfa93e5f2aa7378bddd10ad6746a2ffb", 1613, 0x3149, 0, GID_PQ1, Common::kPlatformAmiga),
-
- // Police Quest 1 (IIgs) 2.0A-88318
- GAME_P("pq1", "2.0A 1988-03-18", "8994e39d0901de3d07cecfb954075bb5", 0x2917, GID_PQ1, Common::kPlatformApple2GS),
-
- // Police Quest 1 (PC) 2.0A 10/23/87 [AGI 2.903/2.911]
- GAME("pq1", "2.0A 1987-10-23", "b9dbb305092851da5e34d6a9f00240b1", 0x2917, GID_PQ1),
-
- // Police Quest 1 (Russian)
- GAME_LPS("pq1", "", "604cc8041d24c4c7e5fa8baf386ef76e", 360, Common::RU_RUS, 0x2917, GID_PQ1, Common::kPlatformPC),
-
- // Police Quest 1 2.0G 12/3/87
- GAME("pq1", "2.0G 1987-12-03 5.25\"/ST", "231f3e28170d6e982fc0ced4c98c5c1c", 0x2440, GID_PQ1),
-
- // Police Quest 1 (PC) 2.0G 12/3/87; entry from DAGII, but missing from Sarien?
- // not sure about disk format -- dsymonds
- GAME("pq1", "2.0G 1987-12-03", "d194e5d88363095f55d5096b8e32fbbb", 0x2917, GID_PQ1),
-
- // Police Quest 1 (CoCo3 360k) [AGI 2.023]
- GAME_PS("pq1", "", "28a077041f75aab78f66804800940085", 375, 0x2440, GID_PQ1, Common::kPlatformCoCo3),
-
- // Police Quest 1 (CoCo3 360k) [AGI 2.072]
- GAME_PS("pq1", "updated", "63b9a9c6eec154751dd446cd3693e0e2", 768, 0x2440, GID_PQ1, Common::kPlatformCoCo3),
-
- // Space Quest 1 (ST) 1.1A
- // The original game did not have menus, they are enabled under ScummVM
- GAME_FP("sq1", "1.1A 1986-02-06", "6421fb64b0e6604c9dd065975d9279e9", 0x2440, GF_MENUS, GID_SQ1, Common::kPlatformAtariST),
-
- // Space Quest 1 (PC 360k) 1.1A [AGI 2.272]
- // The original game did not have menus, they are enabled under ScummVM
- GAME_FP("sq1", "1.1A 1986-11-13", "8d8c20ab9f4b6e4817698637174a1cb6", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC),
-
- // Space Quest 1 (PC 720k) 1.1A [AGI 2.272]
- // The original game did not have menus, they are enabled under ScummVM
- GAME_FP("sq1", "1.1A 720kb", "0a92b1be7daf3bb98caad3f849868aeb", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC),
-
- // Space Quest 1 (Amiga) 1.2 # 2.082
- // The original game did not have menus, they are enabled under ScummVM
- GAME_FP("sq1", "1.2 1986", "0b216d931e95750f1f4837d6a4b821e5", 0x2440, GF_MENUS | GF_OLDAMIGAV20, GID_SQ1, Common::kPlatformAmiga),
-
- // Space Quest 1 (Mac) 1.5D
- GAME_P("sq1", "1.5D 1987-04-02", "ce88419aadd073d1c6682d859b3d8aa2", 0x2440, GID_SQ1, Common::kPlatformMacintosh),
-
- // Space Quest 1 (IIgs) 2.2
- GAME_P("sq1", "2.2 1987", "64b9b3d04c1066d36e6a6e56187a83f7", 0x2917, GID_SQ1, Common::kPlatformApple2GS),
-
- // Space Quest 1 (PC) 1.0X [AGI 2.089]
- // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game
- GAME_FP("sq1", "1.0X 1986-09-24", "af93941b6c51460790a9efa0e8cb7122", 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC),
-
- // Space Quest 1 (Russian)
- GAME_LFPS("sq1", "", "a279eb8ddbdefdb1ea6adc827a1d632a", 372, Common::RU_RUS, 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC),
-
- // Space Quest 1 (PC 5.25"/3.5") 2.2 [AGI 2.426/2.917]
- GAME("sq1", "2.2 1987-05-07 5.25\"/3.5\"", "5d67630aba008ec5f7f9a6d0a00582f4", 0x2440, GID_SQ1),
-
- // Space Quest 1 (CoCo3 360k) [AGI 2.072]
- GAME_PS("sq1", "", "5d67630aba008ec5f7f9a6d0a00582f4", 372, 0x2440, GID_SQ1, Common::kPlatformCoCo3),
-
- // Space Quest 1 (CoCo3 360k) [AGI 2.023]
- GAME_PS("sq1", "fixed", "ca822b768b6462e410423ea7f498daee", 768, 0x2440, GID_SQ1, Common::kPlatformCoCo3),
-
- // Space Quest 1 (CoCo3 360k) [AGI 2.072]
- GAME_PS("sq1", "updated", "7fa54e6bb7ffeb4cf20eca39d86f5fb2", 387, 0x2440, GID_SQ1, Common::kPlatformCoCo3),
-
- // Space Quest 2 (PC 3.5") 2.0D [AGI 2.936]
- GAME("sq2", "2.0D 1988-03-14 3.5\"", "85390bde8958c39830e1adbe9fff87f3", 0x2936, GID_SQ2),
-
- // Space Quest 2 (IIgs) 2.0A 7/25/88 (CE)
- GAME_P("sq2", "2.0A 1988-07-25 (CE)", "5dfdac98dd3c01fcfb166529f917e911", 0x2936, GID_SQ2, Common::kPlatformApple2GS),
-
- {
- // Space Quest 2 (Amiga) 2.0F
- {
- "sq2",
- "2.0F 1986-12-09 [VOL.2->PICTURE.16 broken]",
- {
- { "logdir", 0, "28add5125484302d213911df60d2aded", 426},
- { "object", 0, "5dc52be721257719f4b311a84ce22b16", 372},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_SQ2,
- GType_V2,
- 0,
- 0x2936,
- },
-
-
- // Space Quest 2 (Mac) 2.0D
- GAME_P("sq2", "2.0D 1988-04-04", "bfbebe0b59d83f931f2e1c62ce9484a7", 0x2936, GID_SQ2, Common::kPlatformMacintosh),
-
- // reported by Filippos (thebluegr) in bugreport #1654500
- // Space Quest 2 (PC 5.25") 2.0A [AGI 2.912]
- GAME_PS("sq2", "2.0A 1987-11-06 5.25\"", "ad7ce8f800581ecc536f3e8021d7a74d", 423, 0x2917, GID_SQ2, Common::kPlatformPC),
-
- // Space Quest 2 (Russian)
- GAME_LPS("sq2", "", "ba21c8934caf28e3ba45ce7d1cd6b041", 423, Common::RU_RUS, 0x2917, GID_SQ2, Common::kPlatformPC),
-
- // Space Quest 2 (PC 3.5") 2.0A [AGI 2.912]
- GAME_PS("sq2", "2.0A 1987-11-06 3.5\"", "6c25e33d23b8bed42a5c7fa63d588e5c", 423, 0x2917, GID_SQ2, Common::kPlatformPC),
-
- // Space Quest 2 (PC 5.25"/ST) 2.0C/A [AGI 2.915]
- // Menus not tested
- GAME("sq2", "2.0C/A 5.25\"/ST", "bd71fe54869e86945041700f1804a651", 0x2917, GID_SQ2),
-
- // Space Quest 2 (PC 3.5") 2.0F [AGI 2.936]
- GAME("sq2", "2.0F 1989-01-05 3.5\"", "28add5125484302d213911df60d2aded", 0x2936, GID_SQ2),
-
- // Space Quest 2 (CoCo3 360k) [AGI 2.023]
- GAME_PS("sq2", "", "12973d39b892dc9d280257fd271e9597", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3),
-
- // Space Quest 2 (CoCo3 360k) [AGI 2.072]
- GAME_PS("sq2", "updated", "d24f19b047e65e1763eff4b46f3d50df", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3),
-
- // Troll's Tale
- GAMEpre_PS("troll", "", "troll.img", "62903f264b3d849be4214b3a5c42a2fa", 184320, 0x0000, GID_TROLL, Common::kPlatformPC),
-
- // Winnie the Pooh in the Hundred Acre Wood
- GAMEpre_P("winnie", "", "title.pic", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformPC),
-
- // Winnie the Pooh in the Hundred Acre Wood (Amiga)
- GAMEpre_P("winnie", "", "title", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformAmiga),
-
- // Winnie the Pooh in the Hundred Acre Wood (C64)
- GAMEpre_P("winnie", "", "title.pic", "d4eb97cffc866110f71e1ec9f84fe643", 0x0000, GID_WINNIE, Common::kPlatformC64),
-
- // Winnie the Pooh in the Hundred Acre Wood (Apple //gs)
- GAMEpre_P("winnie", "", "title.pic", "45e06010a3c61d78f4661103c901ae11", 0x0000, GID_WINNIE, Common::kPlatformApple2GS),
-
- // Xmas Card 1986 (PC) [AGI 2.272]
- GAME("xmascard", "1986-11-13 [version 1]", "3067b8d5957e2861e069c3c0011bd43d", 0x2272, GID_XMASCARD),
-
- // Xmas Card 1986 (CoCo3 360k) [AGI 2.072]
- GAME_PS("xmascard", "", "25ad35e9628fc77e5e0dd35852a272b6", 768, 0x2440, GID_XMASCARD, Common::kPlatformCoCo3),
-
- FANMADE_F("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE),
- FANMADE("AGI Contest 1 Template", "d879aed25da6fc655564b29567358ae2"),
- FANMADE("AGI Contest 2 Template", "5a2fb2894207eff36c72f5c1b08bcc07"),
- FANMADE("AGI Mouse Demo 0.60 demo 1", "c07e2519de674c67386cb2cc6f2e3904"),
- FANMADE("AGI Mouse Demo 0.60 demo 2", "cc49d8b88ed6faf4f53ce92c84e0fe1b"),
- FANMADE("AGI Mouse Demo 0.70", "3497c291e4afb6f758e61740678a2aec"),
- FANMADE_F("AGI Mouse Demo 1.00", "20397f0bf0ef936f416bb321fb768fc7", GF_AGIMOUSE),
- FANMADE_F("AGI Mouse Demo 1.10", "f4ad396b496d6167635ad0b410312ab8", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE("AGI Piano (v1.0)", "8778b3d89eb93c1d50a70ef06ef10310"),
- FANMADE("AGI Quest (v1.46-TJ0)", "1cf1a5307c1a0a405f5039354f679814"),
- FANMADE_I("tetris", "", "7a874e2db2162e7a4ce31c9130248d8a"),
- FANMADE_V("AGI Trek (Demo)", "c02882b8a8245b629c91caf7eb78eafe", 0x2440),
- FANMADE_F("AGI256 Demo", "79261ac143b2e2773b2753674733b0d5", GF_AGI256),
- FANMADE_F("AGI256-2 Demo", "3cad9b3aff1467cebf0c5c5b110985c5", GF_AGI256_2),
- FANMADE_LF("Abrah: L'orphelin de l'espace (v1.2)", "b7b6d1539e14d5a26fa3088288e1badc", Common::FR_FRA, GF_AGIPAL),
- FANMADE("Acidopolis", "7017db1a4b726d0d59e65e9020f7d9f7"),
- FANMADE("Agent 0055 (v1.0)", "c2b34a0c77acb05482781dda32895f24"),
- FANMADE("Agent 06 vs. The Super Nazi", "136f89ca9f117c617e88a85119777529"),
- FANMADE("Agent Quest", "59e49e8f72058a33c00d60ee1097e631"),
- FANMADE("Al Pond - On Holiday (v1.0)", "a84975496b42d485920e886e92eed68b"),
- FANMADE("Al Pond - On Holiday (v1.1)", "7c95ac4689d0c3bfec61e935f3093634"),
- FANMADE("Al Pond - On Holiday (v1.3)", "8f30c260de9e1dd3d8b8f89cc19d2633"),
- FANMADE("Al Pond 1 - Al Lives Forever (v1.0)", "e8921c3043b749b056ff51f56d1b451b"),
- FANMADE("Al Pond 1 - Al Lives Forever (v1.3)", "fb4699474054962e0dbfb4cf12ca52f6"),
- FANMADE("Apocalyptic Quest (v0.03 Teaser)", "42ced528b67965d3bc3b52c635f94a57"),
- FANMADE_F("Apocalyptic Quest (v4.00 Alpha 1)", "e15581628d84949b8d352d224ec3184b", GF_AGIMOUSE),
- FANMADE_F("Apocalyptic Quest (v4.00 Alpha 2)", "0eee850005860e46345b38fea093d194", GF_AGIMOUSE),
- FANMADE_F("Band Quest (Demo)", "7326abefd793571cc17ed0db647bdf34", GF_AGIMOUSE),
- FANMADE_F("Band Quest (Early Demo)", "de4758dd34676b248c8301b32d93bc6f", GF_AGIMOUSE),
- FANMADE("Beyond the Titanic 2", "9b8de38dc64ffb3f52b7877ea3ebcef9"),
- FANMADE("Biri Quest 1", "1b08f34f2c43e626c775c9d6649e2f17"),
- FANMADE("Bob The Farmboy", "e4b7df9d0830addee5af946d380e66d7"),
- FANMADE_F("Boring Man 1: The Toad to Robinland", "d74481cbd227f67ace37ce6a5493039f", GF_AGIMOUSE),
- FANMADE_F("Boring Man 2: Ho Man! This Game Sucks!", "250032ba105bdf7c1bc4fed767c2d37e", GF_AGIMOUSE),
- FANMADE("Botz", "a8fabe4e807adfe5ec02bfec6d983695"),
- FANMADE("Brian's Quest (v1.0)", "0964aa79b9cdcff7f33a12b1d7e04b9c"),
- FANMADE("CPU-21 (v1.0)", "35b7cdb4d17e890e4c52018d96e9cbf4"),
- FANMADE_I("caitlyn", "Demo", "5b8a3cdb2fc05469f8119d49f50fbe98"),
- FANMADE_I("caitlyn", "", "818469c484cae6dad6f0e9a353f68bf8"),
- FANMADE("Car Driver (v1.1)", "2311611d2d36d20ccc9da806e6cba157"),
- FANMADE("Cloak of Darkness (v1.0)", "5ba6e18bf0b53be10db8f2f3831ee3e5"),
- FANMADE("Coco Coq (English) - Coco Coq In Grostesteing's Base (v.1.0.3)", "97631f8e710544a58bd6da9e780f9320"),
- FANMADE_L("Coco Coq (French) - Coco Coq Dans la Base de Grostesteing (v1.0.2)", "ef579ebccfe5e356f9a557eb3b2d8649", Common::FR_FRA),
- FANMADE("Corby's Murder Mystery (v1.0)", "4ebe62ac24c5a8c7b7898c8eb070efe5"),
- FANMADE_F("DG: The AGIMouse Adventure (English v1.1)", "efe453b92bc1487ea69fbebede4d5f26", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_LF("DG: The AGIMouse Adventure (French v1.1)", "eb3d17ca466d672cbb95947e8d6e846a", Common::FR_FRA, GF_AGIMOUSE|GF_AGIPAL),
- FANMADE("DG: The Adventure Game (English v1.1)", "0d6376d493fa7a21ec4da1a063e12b25"),
- FANMADE_L("DG: The Adventure Game (French v1.1)", "258bdb3bb8e61c92b71f2f456cc69e23", Common::FR_FRA),
- FANMADE("Dashiki (16 Colors)", "9b2c7b9b0283ab9f12bedc0cb6770a07"),
- FANMADE_F("Dashiki (256 Colors)", "c68052bb209e23b39b55ff3d759958e6", GF_AGIMOUSE|GF_AGI256),
- FANMADE("Date Quest 1 (v1.0)", "ba3dcb2600645be53a13170aa1a12e69"),
- FANMADE("Date Quest 2 (v1.0 Demo)", "1602d6a2874856e928d9a8c8d2d166e9"),
- FANMADE("Date Quest 2 (v1.0)", "f13f6fc85aa3e6e02b0c20408fb63b47"),
- FANMADE("Dave's Quest (v0.07)", "f29c3660de37bacc1d23547a167f27c9"),
- FANMADE("Dave's Quest (v0.17)", "da3772624cc4a86f7137db812f6d7c39"),
- FANMADE("Disco Nights (Demo)", "dc5a2b21182ba38bdcd992a3a978e690"),
- FANMADE("Dogs Quest - The Quest for the Golden Bone (v1.0)", "f197357edaaea0ff70880602d2f09b3e"),
- FANMADE("Dr. Jummybummy's Space Adventure", "988bd81785f8a452440a2a8ac67f96aa"),
- FANMADE("Ed Ward", "98be839b9f30cbedea4c9cee5442d827"),
- FANMADE("Elfintard", "c3b847e9e9e978af9708df76a0751dc2"),
- FANMADE("Enclosure (v1.01)", "f08e66fee9ecdde77db7ee9a10c96ba2"),
- FANMADE("Enclosure (v1.03)", "e4a0613ed02401502e506ba3565a8c40"),
- FANMADE_SVP("Enclosure", "fe98e6126db74c6cc6fd8fe395cc6e8c", 345, 0x2440, Common::kPlatformCoCo3),
- FANMADE("Epic Fighting (v0.1)", "aff24a1b3bdd676187685c4d95ba4294"),
- FANMADE("Escape Quest (v0.0.3)", "2346b65619b1da0298b715b06d1a45a1"),
- FANMADE("Escape from the Desert (beta 1)", "dfdc634d340854bd6ece28024010758d"),
- FANMADE("Escape from the Salesman", "e723ca4fe0f6f56affe039fbb4dbeb6c"),
- FANMADE("Fu$k Quest 1 (final)", "1cd0587422313f6ca77d6a95988e88ed"),
- FANMADE("Fu$k Quest 1", "1cd0587422313f6ca77d6a95988e88ed"),
- FANMADE("Fu$k Quest 2 - Romancing the Bone (Teaser)", "d288355d71d9bb1639260ccaa3b2fbfe"),
- FANMADE("Fu$k Quest 2 - Romancing the Bone", "294beeb7765c7ea6b05ed7b9bf7bff4f"),
- FANMADE("Gennadi Tahab Autot - Mission Pack 1 - Kuressaare", "bfa5fe71978e6ccf3d4eedd430124015"),
- FANMADE("Go West, Young Hippie", "ff31484ea465441cb5f3a0f8e956b716"),
- FANMADE("Good Man (demo v3.41)", "3facd8a8f856b7b6e0f6c3200274d88c"),
-
- {
- // Groza
- {
- "agi-fanmade",
- "Groza (russian) [AGDS sample]",
- AD_ENTRY1("logdir", "421da3a18004122a966d64ab6bd86d2e"),
- Common::RU_RUS,
- Common::kPlatformPC,
- ADGF_USEEXTRAASTITLE,
- GUIO_NONE
- },
- GID_FANMADE,
- GType_V2,
- GF_AGDS,
- 0x2440,
- },
-
- {
- // Get Outta SQ
- {
- "agi-fanmade",
- "Get Outta Space Quest",
- AD_ENTRY1("logdir", "aaea5b4a348acb669d13b0e6f22d4dc9"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_USEEXTRAASTITLE,
- GUIO_NONE
- },
- GID_GETOUTTASQ,
- GType_V2,
- 0,
- 0x2440,
- },
-
- FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE),
- FANMADE("Hank's Quest (v1.0 English) - Victim of Society", "64c15b3d0483d17888129100dc5af213"),
- FANMADE("Hank's Quest (v1.1 English) - Victim of Society", "86d1f1dd9b0c4858d096e2a60cca8a14"),
- FANMADE_L("Hank's Quest (v1.81 Dutch) - Slachtoffer Van Het Gebeuren", "41e53972d55ff3dff9e90d15fe1b659f", Common::NL_NLD),
- FANMADE("Hank's Quest (v1.81 English) - Victim of Society", "7a776383282f62a57c3a960dafca62d1"),
- FANMADE("Herbao (v0.2)", "6a5186fc8383a9060517403e85214fc2"),
- FANMADE_F("Hitler's Legacy (v.0004q)", "a412881269ba34584bd0a3268e5a9863", GF_AGIMOUSE),
- FANMADE("Hobbits", "4a1c1ef3a7901baf0ab45fde0cfadd89"),
- FANMADE_F("Isabella Coq - A Present For My Dad", "55c6819f2330c4d5d6459874c9f123d9", GF_AGIMOUSE),
- FANMADE("Jack & Julia - VAMPYR", "8aa0b9a26f8d5a4421067ab8cc3706f6"),
- FANMADE("Jeff's Quest (v.5 alpha Jun 1)", "10f1720eed40c12b02a0f32df3e72ded"),
- FANMADE("Jeff's Quest (v.5 alpha May 31)", "51ff71c0ed90db4e987a488ed3bf0551"),
- FANMADE("Jen's Quest (Demo 1)", "361afb5bdb6160213a1857245e711939"),
- FANMADE("Jen's Quest (Demo 2)", "3c321eee33013b289ab8775449df7df2"),
- FANMADE("Jiggy Jiggy Uh! Uh!", "bc331588a71e7a1c8840f6cc9b9487e4"),
- FANMADE("Jimmy In: The Alien Attack (v0.1)", "a4e9db0564a494728de7873684a4307c"),
- FANMADE("Joe McMuffin In \"What's Cooking, Doc\" (v1.0)", "8a3de7e61a99cb605fa6d233dd91c8e1"),
- FANMADE_LVF("Jolimie, le Village Maudit (v0.5)", "21818501636b3cb8ad5de5c1a66de5c2", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_LVF("Jolimie, le Village Maudit (v1.1)", "68d7aef1161bb5972fe03efdf29ccb7f", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL),
- FANMADE("Journey Of Chef", "aa0a0b5a6364801ae65fdb96d6741df5"),
- FANMADE("Jukebox (v1.0)", "c4b9c5528cc67f6ba777033830de7751"),
- FANMADE("Justin Quest (v1.0 in development)", "103050989da7e0ffdc1c5e1793a4e1ec"),
- FANMADE("J\xf5ulumaa (v0.05) (Estonian)", "53982ecbfb907e41392b3961ad1c3475"),
- FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Mar 26)", "a25d7379d281b1b296d4785df90a8e78"),
- FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Aug 16)", "6b4f796d0421d2e12e501b511962e03a"),
- FANMADE("Lasse Holm: The Quest for Revenge (v1.0)", "f9fbcc8a4ef510bfbb92423296ff4abb"),
- FANMADE("Lawman for Hire", "c78b28bfd3767dd455b992cd8b7854fa"),
- FANMADE("Lefty Goes on Vacation (Not in The Right Place)", "ccdc49a33870310b01f2c48b8a1f3c34"),
- FANMADE("Les Ins\xe3parables (v1.0)", "4b780887cab0ecabc5eca319acb3acf2"),
- FANMADE("Little Pirate (Demo 2 v0.6)", "437068efe4ec32d436da09d6f2ea56e1"),
- FANMADE("Lost Eternity (v1.0)", "95f15c5632feb8a39e9ca3d9af35fcc9"),
- FANMADE("MD Quest - The Search for Michiel (v0.10)", "2a6fcb21d2b5e4144c38ed817fabe8ee"),
- FANMADE("Maale Adummin Quest", "ddfbeb33feb7cf78504fe4dba14ec63b"),
- FANMADE("Monkey Man", "2322d03f997e8cc235d4578efff69cfa"),
- FANMADE_F("Napalm Quest (v0.5)", "b659afb491d967bb34810d1c6ce22093", GF_AGIMOUSE),
- FANMADE("Naturette 1 (English v1.2)", "0a75884e7f010974a230bdf269651117"),
- FANMADE("Naturette 1 (English v1.3)", "f15bbf999ac55ebd404aa1eb84f7c1d9"),
- FANMADE_L("Naturette 1 (French v1.2)", "d3665622cc41aeb9c7ecf4fa43f20e53", Common::FR_FRA),
- FANMADE_F("Naturette 2: Daughter of the Moon (v1.0)", "bdf76a45621c7f56d1c9d40292c6137a", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_F("Naturette 3: Adventure in Treeworld (v1.0a)", "6dbb0e7fc75fec442e6d9e5a06f1530e", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_F("Naturette 4: From a Planet to Another Planet (Not Finished)", "13be8cd9cf35aeff0a39b8757057fbc8", GF_AGIMOUSE),
- // FIXME: Actually Naturette 4 has both English and French language support built into it. How to add that information?
- FANMADE_F("Naturette 4: From a Planet to Another Planet (2007-10-05)", "8253706b6ef5423a79413b216760297c", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE("New AGI Hangman Test", "d69c0e9050ccc29fd662b74d9fc73a15"),
- FANMADE("Nick's Quest - In Pursuit of QuakeMovie (v2.1 Gold)", "e29cbf9222551aee40397fabc83eeca0"),
- FANMADE_F("Open Mic Night (v0.1)", "70000a2f67aac27d1133d019df70246d", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE("Operation: Recon", "0679ce8405411866ccffc8a6743370d0"),
- FANMADE("Patrick's Quest (Demo v1.0)", "f254f5b894b98fec5f92acc07fb62841"),
- FANMADE("Phantasmagoria", "87d20c1c11aee99a4baad3797b63146b"),
- FANMADE("Pharaoh Quest (v0.0)", "51c630899d076cf799e573dadaa2276d"),
- FANMADE("Phil's Quest - the Search for Tolbaga", "5e7ca45c360e03164b8358e49900c588"),
- FANMADE("Pinkun Maze Quest (v0.1)", "148ff0843af389928b3939f463bfd20d"),
- FANMADE("Pirate Quest", "bb612a919ed2b9ea23bbf03ce69fed42"),
- FANMADE("Pothead (v0.1)", "d181101385d3a45082f418cd4b3c5b01"),
- FANMADE("President's Quest", "4937d0e8ecadb7888faeb347799b0388"),
- FANMADE("Prince Quest", "266248d75c3130c8ccc9c9bf2ad30a0d"),
- FANMADE("Professor (English) - The Professor is Missing (Mar 17)", "6232de31cc204affdf2e92dfe3dc0e4d"),
- FANMADE("Professor (English) - The Professor is Missing (Mar 22)", "b5fcf0ca2f0d1c073be82f01e2170961"),
- FANMADE_L("Professor (French) - Le Professeur a Disparu", "7d9f8a4d4610bb9b0b97caa17590c2d3", Common::FR_FRA),
- FANMADE("Quest for Glory VI - Hero's Adventure", "d26765c3075064c80d284c5e06e33a7e"),
- FANMADE("Quest for Home", "d2895dc1cd3930f2489af0f843b144b3"),
- FANMADE("Quest for Ladies (demo v1.1 Apr 1)", "3f6e02f16e1154a0daf296c8895edd97"),
- FANMADE("Quest for Ladies (demo v1.1 Apr 6)", "f75e7b6a0769a3fa926eea0854711591"),
- FANMADE("Quest for Piracy 1 - Enter the Silver Pirate (v0.15)", "d23f5c2a26f6dc60c686f8a2436ea4a6"),
- FANMADE("Quest for a Record Deal", "f4fbd7abf056d2d3204f790da5ac89ab"),
- FANMADE("Ralph's Quest (v0.1)", "5cf56378aa01a26ec30f25295f0750ca"),
- FANMADE("Residence 44 Quest (Dutch v0.99)", "7c5cc64200660c70240053b33d379d7d"),
- FANMADE("Residence 44 Quest (English v0.99)", "fe507851fddc863d540f2bec67cc67fd"),
- FANMADE("Residence 44 Quest (English v1.0a)", "f99e3f69dc8c77a45399da9472ef5801"),
- FANMADE("SQ2Eye (v0.3)", "2be2519401d38ad9ce8f43b948d093a3"),
- // FANMADE("SQ2Eye (v0.4)", "2be2519401d38ad9ce8f43b948d093a3"),
- FANMADE("SQ2Eye (v0.41)", "f0e82c55f10eb3542d7cd96c107ae113"),
- FANMADE("SQ2Eye (v0.42)", "d7beae55f6328ef8b2da47b1aafea40c"),
- FANMADE("SQ2Eye (v0.43)", "2a895f06e45de153bb4b77c982009e06"),
- FANMADE("SQ2Eye (v0.44)", "5174fc4b6d8a477ba0ff0575cd64e0aa"),
- FANMADE("SQ2Eye (v0.45)", "6e06f8bb7b90ce6f6aabf1a0e620159c"),
- FANMADE("SQ2Eye (v0.46)", "bf0ad7a035ff9113951d09d1efe380c4"),
- FANMADE("SQ2Eye (v0.47)", "85dc3be1d33ff932c292b74f9037abaa"),
- FANMADE("SQ2Eye (v0.48)", "587574252972a5b5c070a647973a9b4a"),
- FANMADE("SQ2Eye (v0.481)", "fc9234beb49804ae869696ce5af8ef30"),
- FANMADE("SQ2Eye (v0.482)", "3ed84b7b87fa6840f25c15f250a11ffb"),
- FANMADE("SQ2Eye (v0.483)", "647c31298d3f9cda641231b893e347c0"),
- FANMADE("SQ2Eye (v0.484)", "f2c86fae7b9046d408c62c8c49a4b882"),
- FANMADE("SQ2Eye (v0.485)", "af59e36bc28f44545458b68a93e91e67"),
- FANMADE("SQ2Eye (v0.486)", "3fd86436e93456770dbdd4593eded70a"),
- FANMADE("Save Santa (v1.0)", "4644f6beb5802081772f14be56ae196c"),
- FANMADE("Save Santa (v1.3)", "f8afdb6efc5af5e7c0228b44633066af"),
- FANMADE("Schiller (preview 1)", "ade39dea968c959cfebe1cf935d653e9"),
- FANMADE("Schiller (preview 2)", "62cd1f8fc758bf6b4aa334e553624cef"),
- FANMADE_IF("serguei1", "v1.0", "b86725f067e456e10cdbdf5f58e01dec", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_IF("serguei1", "v1.1 2002 Sep 5", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_IF("serguei1", "v1.1 2003 Apr 10", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_IF("serguei2", "v0.1.1 Demo", "906ccbc2ddedb29b63141acc6d10cd28", GF_AGIMOUSE),
- FANMADE_IF("serguei2", "v1.3.1 Demo (March 22nd 2008)", "ad1308fcb8f48723cd388e012ebf5e20", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE("Shifty (v1.0)", "2a07984d27b938364bf6bd243ac75080"),
- FANMADE_F("Sliding Tile Game (v1.00)", "949bfff5d8a81c3139152eed4d84ca75", GF_AGIMOUSE),
- FANMADE("Snowboarding Demo (v1.0)", "24bb8f29f1eddb5c0a099705267c86e4"),
- FANMADE("Solar System Tour", "b5a3d0f392dfd76a6aa63f3d5f578403"),
- FANMADE("Sorceror's Appraisal", "fe62615557b3cb7b08dd60c9d35efef1"),
- FANMADE_I("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590"),
- FANMADE_I("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6"),
- FANMADE_ISVP("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, Common::kPlatformCoCo3),
- FANMADE_I("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1"),
- FANMADE_I("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910"),
- FANMADE_ISVP("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, Common::kPlatformCoCo3),
- FANMADE_F("Space Quest 3.5", "c077bc28d7b36213dd99dc9ecb0147fc", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_F("Space Trek (v1.0)", "807a1aeadb2ace6968831d36ab5ea37a", GF_CLIPCOORDS),
- FANMADE("Special Delivery", "88764dfe61126b8e73612c851b510a33"),
- FANMADE("Speeder Bike Challenge (v1.0)", "2deb25bab379285ca955df398d96c1e7"),
- FANMADE("Star Commander 1 - The Escape (v1.0)", "a7806f01e6fa14ebc029faa58f263750"),
- FANMADE("Star Pilot: Bigger Fish", "8cb26f8e1c045b75c6576c839d4a0172"),
- FANMADE_F("Street Quest (Demo)", "cf2aa94a7eb78dce6892c37f03e310d6", GF_AGIPAL),
- FANMADE("Tales of the Tiki", "8103c9c87e3964690a14a3d0d83f7ddc"),
- FANMADE("Tex McPhilip 1 - Quest For The Papacy", "3c74b9a24b51aa8020ac82bee3132266"),
- FANMADE("Tex McPhilip 2 - Road To Divinity (v1.5)", "7387e8df854440bc26620ca0ea43af9a"),
- FANMADE("Tex McPhilip 3 - A Destiny of Sin (Demo v0.25)", "992d12031a486ad84e592ff5d7c9d782"),
- FANMADE("The 13th Disciple (v1.00)", "887719ad59afce9a41ec057dbb73ad73"),
- FANMADE("The Adventures of a Crazed Hermit", "6e3086cbb794d3299a9c5a9792295511"),
- FANMADE("The Grateful Dead", "c2146631afacf8cb455ce24f3d2d46e7"),
- FANMADE("The Legend of Shay-Larah 1 - The Lost Prince", "04e720c8e30c9cf12db22ea14a24a3dd"),
- FANMADE("The Legend of Zelda: The Fungus of Time (Demo v1.00)", "dcaf8166ceb62a3d9b9aea7f3b197c09"),
- FANMADE("The Legendary Harry Soupsmith (Demo 1998 Apr 2)", "64c46b0d6fc135c9835afa80980d2831"),
- FANMADE("The Legendary Harry Soupsmith (Demo 1998 Aug 19)", "8d06d82970f2c591d880a95476efbcf0"),
- FANMADE("The Long Haired Dude: Encounter of the 18-th Kind", "86ea17b9fc2f3e537a7e40863d352c29"),
- FANMADE("The Lost Planet (v0.9)", "590dffcbd932a9fbe554be13b769cac0"),
- FANMADE("The Lost Planet (v1.0)", "58564df8b6394612dd4b6f5c0fd68d44"),
- FANMADE("The New Adventure of Roger Wilco (v1.00)", "e5f0a7cb8d49f66b89114951888ca688"),
- FANMADE("The Ruby Cast (v0.02)", "ed138e461bb1516e097007e017ab62df"),
- FANMADE("The Shadow Plan", "c02cd10267e721f4e836b1431f504a0a"),
- FANMADE("Time Quest (Demo v0.1)", "12e1a6f03ea4b8c5531acd0400b4ed8d"),
- FANMADE("Time Quest (Demo v0.2)", "7b710608abc99e0861ac59b967bf3f6d"),
- FANMADE_SVP("Time Quest", "90314f473d8317be5cd1f0306f139aea", 300, 0x2440, Common::kPlatformCoCo3),
- FANMADE("Tonight The Shrieking Corpses Bleed (Demo v0.11)", "bcc57a7c8d563fa0c333107ae1c0a6e6"),
- FANMADE("Tonight The Shrieking Corpses Bleed (v1.01)", "36b38f621b38e8d104aa0807302dc8c9"),
- FANMADE("Turks' Quest - Heir to the Planet", "3d19254b737c8b218e5bc4580542b79a"),
- FANMADE("URI Quest (v0.173 Feb 27)", "3986eefcf546dafc45f920ae91a697c3"),
- FANMADE("URI Quest (v0.173 Jan 29)", "494150940d34130605a4f2e67ee40b12"),
- {
- // V - The Graphical Adventure
- {
- "agi-fanmade",
- "V - The Graphical Adventure (Demo 2)",
- AD_ENTRY1s("vdir", "c71f5c1e008d352ae9040b77fcf79327", 3080),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_USEEXTRAASTITLE,
- GUIO_NONE
- },
- GID_FANMADE,
- GType_V3,
- GF_FANMADE,
- 0x3149,
- },
- FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3),
-
- FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Jan 1)", "ae95f0c77d9a97b61420fd192348b937"),
- FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Mar 29)", "11d0417b7b886f963d0b36789dac4c8f"),
- FANMADE("Wizaro (v0.1)", "abeec1eda6eaf8dbc52443ea97ff140c"),
-
- { AD_TABLE_END_MARKER, 0, 0, 0, 0 }
-};
-
-/**
- * The fallback game descriptor used by the AGI engine's fallbackDetector.
- * Contents of this struct are to be overwritten by the fallbackDetector.
- */
-static AGIGameDescription g_fallbackDesc = {
- {
- "",
- "",
- AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
- Common::UNK_LANG,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_FANMADE,
- GType_V2,
- GF_FANMADE,
- 0x2917,
-};
+#include "agi/detection_tables.h"
static const ADParams detectionParams = {
// Pointer to ADGameDescription or its superset structure
@@ -979,11 +145,13 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI
+ Common::GUIO_NOSPEECH,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
-} // End of namespace Agi
-
using namespace Agi;
class AgiMetaEngine : public AdvancedMetaEngine {
@@ -1322,6 +490,9 @@ bool AgiBase::canLoadGameStateCurrently() {
}
bool AgiBase::canSaveGameStateCurrently() {
+ if (getGameID() == GID_BC) // Technically in Black Cauldron we may save anytime
+ return true;
+
return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork) && !_noSaveLoadAllowed && _game.inputEnabled);
}
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
new file mode 100644
index 0000000000..711701f55a
--- /dev/null
+++ b/engines/agi/detection_tables.h
@@ -0,0 +1,863 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Agi {
+
+using Common::GUIO_NONE;
+
+#define GAME_LVFPN(id,extra,fname,md5,size,lang,ver,features,gid,platform,interp) { \
+ { \
+ id, \
+ extra, \
+ AD_ENTRY1s(fname,md5,size), \
+ lang, \
+ platform, \
+ ADGF_NO_FLAGS, \
+ GUIO_NONE \
+ }, \
+ gid, \
+ interp, \
+ features, \
+ ver, \
+ }
+
+#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \
+ { \
+ id, \
+ name, \
+ AD_ENTRY1s(fname,md5,size), \
+ lang, \
+ platform, \
+ ADGF_USEEXTRAASTITLE, \
+ GUIO_NONE \
+ }, \
+ gid, \
+ interp, \
+ features, \
+ ver, \
+ }
+
+#define GAME(id,extra,md5,ver,gid) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2)
+#define GAME3(id,extra,fname,md5,ver,gid) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V3)
+
+#define GAME_P(id,extra,md5,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_V2)
+
+#define GAME_FP(id,extra,md5,ver,flags,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V2)
+#define GAME_F(id,extra,md5,ver,flags,gid) GAME_FP(id,extra,md5,ver,flags,gid,Common::kPlatformPC)
+
+#define GAME_PS(id,extra,md5,size,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,Common::EN_ANY,ver,0,gid,platform,GType_V2)
+
+#define GAME_LPS(id,extra,md5,size,lang,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,lang,ver,0,gid,platform,GType_V2)
+
+#define GAME_LFPS(id,extra,md5,size,lang,ver,flags,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,lang,ver,flags,gid,platform,GType_V2)
+
+#define GAME3_P(id,extra,fname,md5,ver,flags,gid,platform) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V3)
+
+#define GAMEpre_P(id,extra,fname,md5,ver,gid,platform) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI)
+
+#define GAMEpre_PS(id,extra,fname,md5,size,ver,gid,platform) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI)
+
+#define GAME3_PS(id,extra,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3)
+
+#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPNF(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2)
+
+#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPNF(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2)
+#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVP("agi-fanmade",name,md5,size,ver,platform)
+
+#define FANMADE_LVF(name,md5,lang,ver,features) FANMADE_ILVF("agi-fanmade",name,md5,lang,ver,features)
+
+#define FANMADE_LF(name,md5,lang,features) FANMADE_LVF(name,md5,lang,0x2917,features)
+#define FANMADE_IF(id,name,md5,features) FANMADE_ILVF(id,name,md5,Common::EN_ANY,0x2917,features)
+
+#define FANMADE_V(name,md5,ver) FANMADE_LVF(name,md5,Common::EN_ANY,ver,0)
+#define FANMADE_F(name,md5,features) FANMADE_LF(name,md5,Common::EN_ANY,features)
+#define FANMADE_L(name,md5,lang) FANMADE_LF(name,md5,lang,0)
+#define FANMADE_I(id,name,md5) FANMADE_IF(id,name,md5,0)
+
+#define FANMADE(name,md5) FANMADE_F(name,md5,0)
+
+static const AGIGameDescription gameDescriptions[] = {
+
+ // AGI Demo 1 (PC) 05/87 [AGI 2.425]
+ GAME("agidemo", "Demo 1 1987-05-20", "9c4a5b09cc3564bc48b4766e679ea332", 0x2440, GID_AGIDEMO),
+
+ // AGI Demo 2 (IIgs) 1.0C (Censored)
+ GAME_P("agidemo", "Demo 2 1987-11-24 1.0C", "580ffdc569ff158f56fb92761604f70e", 0x2917, GID_AGIDEMO, Common::kPlatformApple2GS),
+
+ // AGI Demo 2 (PC 3.5") 11/87 [AGI 2.915]
+ GAME("agidemo", "Demo 2 1987-11-24 3.5\"", "e8ebeb0bbe978172fe166f91f51598c7", 0x2917, GID_AGIDEMO),
+
+ // AGI Demo 2 (PC 5.25") 11/87 [v1] [AGI 2.915]
+ GAME("agidemo", "Demo 2 1987-11-24 [version 1] 5.25\"", "852ac303a374df62571642ca1e2d1f0a", 0x2917, GID_AGIDEMO),
+
+ // AGI Demo 2 (PC 5.25") 01/88 [v2] [AGI 2.917]
+ GAME("agidemo", "Demo 2 1987-11-25 [version 2] 5.25\"", "1503f02086ea9f388e7e041c039eaa69", 0x2917, GID_AGIDEMO),
+
+ // AGI Demo 3 (PC) 09/88 [AGI 3.002.102]
+ GAME3("agidemo", "Demo 3 1988-09-13", "dmdir", "289c7a2c881f1d973661e961ced77d74", 0x3149, GID_AGIDEMO),
+
+ // AGI Demo for Kings Quest III and Space Quest I
+ GAME("agidemo", "Demo Kings Quest III and Space Quest I", "502e6bf96827b6c4d3e67c9cdccd1033", 0x2272, GID_AGIDEMO),
+
+ // Black Cauldron (Amiga) 2.00 6/14/87
+ GAME_P("bc", "2.00 1987-06-14", "7b01694af21213b4727bb94476f64eb5", 0x2440, GID_BC, Common::kPlatformAmiga),
+
+ // Black Cauldron (Apple IIgs) 1.0O 2/24/89 (CE)
+ // Menus not tested
+ GAME3_P("bc", "1.0O 1989-02-24 (CE)", "bcdir", "dc09d30b147242692f4f85b9811962db", 0x3149, 0, GID_BC, Common::kPlatformApple2GS),
+
+ // Black Cauldron (PC) 2.00 6/14/87 [AGI 2.439]
+ GAME("bc", "2.00 1987-06-14", "7f598d4712319b09d7bd5b3be10a2e4a", 0x2440, GID_BC),
+
+ // Black Cauldron (Russian)
+ GAME_LPS("bc", "", "b7de782dfdf8ea7dde8064f09804bcf5", 357, Common::RU_RUS, 0x2440, GID_BC, Common::kPlatformPC),
+
+ // Black Cauldron (PC 5.25") 2.10 11/10/88 [AGI 3.002.098]
+ GAME3("bc", "2.10 1988-11-10 5.25\"", "bcdir", "0c5a9acbcc7e51127c34818e75806df6", 0x3149, GID_BC),
+
+ // Black Cauldron (PC) 2.10 [AGI 3.002.097]
+ GAME3("bc", "2.10", "bcdir", "0de3953c9225009dc91e5b0d1692967b", 0x3149, GID_BC),
+
+ // Black Cauldron (CoCo3 360k) [AGI 2.023]
+ GAME_PS("bc", "", "51212c54808ade96176f201ae0ac7a6f", 357, 0x2440, GID_BC, Common::kPlatformCoCo3),
+
+ // Black Cauldron (CoCo3 360k) [AGI 2.072]
+ GAME_PS("bc", "updated", "c4e1937f74e8100cd0152b904434d8b4", 357, 0x2440, GID_BC, Common::kPlatformCoCo3),
+
+// TODO
+// These aren't supposed to work now as they require unsupported agi engine 2.01
+#if 0
+ // Donald Duck's Playground (Amiga) 1.0C
+ // Menus not tested
+ GAME_P("ddp", "1.0C 1987-04-27", "550971d196f65190a5c760d2479406ef", 0x2272, GID_DDP, Common::kPlatformAmiga),
+
+ // Donald Duck's Playground (ST) 1.0A 8/8/86
+ // Menus not tested
+ GAME("ddp", "1.0A 1986-08-08", "64388812e25dbd75f7af1103bc348596", 0x2272, GID_DDP),
+
+ // reported by Filippos (thebluegr) in bugreport #1654500
+ // Menus not tested
+ GAME_PS("ddp", "1.0C 1986-06-09", "550971d196f65190a5c760d2479406ef", 132, 0x2272, GID_DDP, Common::kPlatformPC),
+#endif
+
+ // Gold Rush! (Amiga) 1.01 1/13/89 aka 2.05 3/9/89 # 2.316
+ GAME3_PS("goldrush", "1.01 1989-01-13 aka 2.05 1989-03-09", "dirs", "a1d4de3e75c2688c1e2ca2634ffc3bd8", 2399, 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAmiga),
+
+ // Gold Rush! (Apple IIgs) 1.0M 2/28/89 (CE) aka 2.01 12/22/88
+ // Menus not tested
+ GAME3_P("goldrush", "1.0M 1989-02-28 (CE) aka 2.01 1988-12-22", "grdir", "3f7b9ce62631434389f85371b11921d6", 0x3149, GF_2GSOLDSOUND, GID_GOLDRUSH, Common::kPlatformApple2GS),
+
+ // Gold Rush! (ST) 1.01 1/13/89 aka 2.01 12/22/88
+ GAME3_P("goldrush", "1.01 1989-01-13 aka 2.01 1988-12-22", "grdir", "4dd4d50480a3d6c206fa227ce8142735", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAtariST),
+
+ // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149]
+ GAME3("goldrush", "2.01 1988-12-22 5.25\"", "grdir", "db733d199238d4009a9e95f11ece34e9", 0x3149, GID_GOLDRUSH),
+
+ // Gold Rush! (PC 3.5") 2.01 12/22/88 [AGI 3.002.149]
+ GAME3("goldrush", "2.01 1988-12-22 3.5\"", "grdir", "6a285235745f69b4b421403659497216", 0x3149, GID_GOLDRUSH),
+
+ // Gold Rush! (PC 3.5", bought from The Software Farm) 3.0 1998-12-22 [AGI 3.002.149]
+ GAME3("goldrush", "3.0 1998-12-22 3.5\"", "grdir", "6882b6090473209da4cd78bb59f78dbe", 0x3149, GID_GOLDRUSH),
+
+ {
+ // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149]
+ {
+ "goldrush",
+ "2.01 1988-12-22",
+ {
+ { "grdir", 0, "db733d199238d4009a9e95f11ece34e9", 2399},
+ { "vol.0", 0, "4b6423d143674d3757ab1b875d25951d", 25070},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_GOLDRUSH,
+ GType_V3,
+ GF_MACGOLDRUSH,
+ 0x3149,
+ },
+
+
+ // Gold Rush! (CoCo3 720k) [AGI 2.023]
+ GAME_PS("goldrush", "", "0a41b65efc0cd6c4271e957e6ffbbd8e", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3),
+
+ // Gold Rush! (CoCo3 360k/720k) [AGI 2.072]
+ GAME_PS("goldrush", "updated", "c49bf56bf91e31a4601a604e51ef8bfb", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3),
+
+ // King's Quest 1 (Amiga) 1.0U # 2.082
+ // The original game did not have menus, they are enabled under ScummVM
+ GAME_FP("kq1", "1.0U 1986", "246c695324f1c514aee2b904fa352fad", 0x2440, GF_MENUS, GID_KQ1, Common::kPlatformAmiga),
+
+ // King's Quest 1 (ST) 1.0V
+ // The original game did not have menus, they are enabled under ScummVM
+ GAME_FP("kq1", "1.0V 1986", "c3a017e556c4b0eece366a4cd9abb657", 0x2272, GF_MENUS, GID_KQ1, Common::kPlatformAtariST),
+
+ // King's Quest 1 (IIgs) 1.0S-88223
+ // Menus not tested
+ GAME_P("kq1", "1.0S 1988-02-23", "f4277aa34b43d37382bc424c81627617", 0x2272, GID_KQ1, Common::kPlatformApple2GS),
+
+ // King's Quest 1 (Mac) 2.0C
+ GAME_P("kq1", "2.0C 1987-03-26", "d4c4739d4ac63f7dbd29255425077d48", 0x2440, GID_KQ1, Common::kPlatformMacintosh),
+
+ // King's Quest 1 (PC 5.25"/3.5") 2.0F [AGI 2.917]
+ GAME("kq1", "2.0F 1987-05-05 5.25\"/3.5\"", "10ad66e2ecbd66951534a50aedcd0128", 0x2917, GID_KQ1),
+
+ // King's Quest 1 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("kq1", "", "10ad66e2ecbd66951534a50aedcd0128", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3),
+
+ // King's Quest 1 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("kq1", "fixed", "4c8ef8b5d2f1b6c1a93e456d1f1ffc74", 768, 0x2440, GID_KQ1, Common::kPlatformCoCo3),
+
+ // King's Quest 1 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("kq1", "updated", "94087178c78933a4af3cd24d1c8dd7b2", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3),
+
+ // King's Quest 2 (IIgs) 2.0A 6/16/88 (CE)
+ GAME_P("kq2", "2.0A 1988-06-16 (CE)", "5203c8b95250a2ecfee93ddb99414753", 0x2917, GID_KQ2, Common::kPlatformApple2GS),
+
+ // King's Quest 2 (Amiga) 2.0J (Broken)
+ GAME_P("kq2", "2.0J 1987-01-29 [OBJECT decrypted]", "b866f0fab2fad91433a637a828cfa410", 0x2440, GID_KQ2, Common::kPlatformAmiga),
+
+ // King's Quest 2 (Mac) 2.0R
+ GAME_P("kq2", "2.0R 1988-03-23", "cbdb0083317c8e7cfb7ac35da4bc7fdc", 0x2440, GID_KQ2, Common::kPlatformMacintosh),
+
+ // King's Quest 2 (PC) 2.1 [AGI 2.411]; entry from DAGII, but missing from Sarien?
+ // XXX: any major differences from 2.411 to 2.440?
+ GAME("kq2", "2.1 1987-04-10", "759e39f891a0e1d86dd29d7de485c6ac", 0x2440, GID_KQ2),
+
+ // King's Quest 2 (PC 5.25"/3.5") 2.2 [AGI 2.426]
+ GAME("kq2", "2.2 1987-05-07 5.25\"/3.5\"", "b944c4ff18fb8867362dc21cc688a283", 0x2917, GID_KQ2),
+
+ // King's Quest 2 (Russian)
+ GAME_LPS("kq2", "", "35211c574ececebdc723b23e35f99275", 543, Common::RU_RUS, 0x2917, GID_KQ2, Common::kPlatformPC),
+
+ // King's Quest 2 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("kq2", "", "b944c4ff18fb8867362dc21cc688a283", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3),
+
+ // King's Quest 2 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("kq2", "updated", "f64a606de740a5348f3d125c03e989fe", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3),
+
+ // King's Quest 2 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("kq2", "fixed", "fb33ac2768a94a89117a270771db465c", 768, 0x2440, GID_KQ2, Common::kPlatformCoCo3),
+
+ // King's Quest 3 (Amiga) 1.01 11/8/86
+ // The original game did not have menus, they are enabled under ScummVM
+ GAME_FP("kq3", "1.01 1986-11-08", "8ab343306df0e2d98f136be4e8cfd0ef", 0x2440, GF_MENUS, GID_KQ3, Common::kPlatformAmiga),
+
+ // King's Quest 3 (ST) 1.02 11/18/86
+ // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game
+ GAME_FP("kq3", "1.02 1986-11-18", "8846df2654302b623217ba8bd6d657a9", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformAtariST),
+
+ // King's Quest 3 (Mac) 2.14 3/15/88
+ GAME_P("kq3", "2.14 1988-03-15", "7639c0da5ce94848227d409351fabda2", 0x2440, GID_KQ3, Common::kPlatformMacintosh),
+
+ // King's Quest 3 (IIgs) 2.0A 8/28/88 (CE)
+ GAME_P("kq3", "2.0A 1988-08-28 (CE)", "ac30b7ca5a089b5e642fbcdcbe872c12", 0x2917, GID_KQ3, Common::kPlatformApple2GS),
+
+ // King's Quest 3 (Amiga) 2.15 11/15/89 # 2.333
+ // Original pauses with ESC, has menus accessible with mouse.
+ // ver = 0x3086 -> menus accessible with ESC or mouse, bug #2835581 (KQ3: Game Crash When Leaving Tavern as Fly).
+ // ver = 0x3149 -> menus accessible with mouse, ESC pauses game, bug #2835581 disappears.
+ GAME3_PS("kq3", "2.15 1989-11-15", "dirs", "8e35bded2bc5cf20f5eec2b15523b155", 1805, 0x3149, 0, GID_KQ3, Common::kPlatformAmiga),
+
+ // King's Quest 3 (PC) 1.01 11/08/86 [AGI 2.272]
+ // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game
+ GAME_FP("kq3", "1.01 1986-11-08", "9c2b34e7ffaa89c8e2ecfeb3695d444b", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC),
+
+ // King's Quest 3 (Russian)
+ GAME_LFPS("kq3", "", "5856dec6ccb9c4b70aee21044a19270a", 390, Common::RU_RUS, 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC),
+
+ // King's Quest 3 (PC 5.25") 2.00 5/25/87 [AGI 2.435]
+ GAME("kq3", "2.00 1987-05-25 5.25\"", "18aad8f7acaaff760720c5c6885b6bab", 0x2440, GID_KQ3),
+
+ // King's Quest 3 (Mac) 2.14 3/15/88
+ // Menus not tested
+ GAME_P("kq3", "2.14 1988-03-15 5.25\"", "7650e659c7bc0f1e9f8a410b7a2e9de6", 0x2440, GID_KQ3, Common::kPlatformMacintosh),
+
+ // King's Quest 3 (PC 3.5") 2.14 3/15/88 [AGI 2.936]
+ GAME("kq3", "2.14 1988-03-15 3.5\"", "d3d17b77b3b3cd13246749231d9473cd", 0x2936, GID_KQ3),
+
+ // King's Quest 3 (CoCo3 158k/360k) [AGI 2.023]
+ GAME_PS("kq3", "", "5a6be7d16b1c742c369ef5cc64fefdd2", 429, 0x2440, GID_KQ3, Common::kPlatformCoCo3),
+
+ // King's Quest 4 (PC 5.25") 2.0 7/27/88 [AGI 3.002.086]
+ GAME3("kq4", "2.0 1988-07-27", "kq4dir", "f50f7f997208ca0e35b2650baec43a2d", 0x3086, GID_KQ4),
+
+ // King's Quest 4 (PC 3.5") 2.0 7/27/88 [AGI 3.002.086]
+ GAME3("kq4", "2.0 1988-07-27 3.5\"", "kq4dir", "fe44655c42f16c6f81046fdf169b6337", 0x3086, GID_KQ4),
+
+ // King's Quest 4 (PC 3.5") 2.2 9/27/88 [AGI 3.002.086]
+ // Menus not tested
+ GAME3("kq4", "2.2 1988-09-27 3.5\"", "kq4dir", "7470b3aeb49d867541fc66cc8454fb7d", 0x3086, GID_KQ4),
+
+ // King's Quest 4 (PC 5.25") 2.3 9/27/88 [AGI 3.002.086]
+ GAME3("kq4", "2.3 1988-09-27", "kq4dir", "6d7714b8b61466a5f5981242b993498f", 0x3086, GID_KQ4),
+
+ // King's Quest 4 (PC 3.5") 2.3 9/27/88 [AGI 3.002.086]
+ GAME3("kq4", "2.3 1988-09-27 3.5\"", "kq4dir", "82a0d39af891042e99ac1bd6e0b29046", 0x3086, GID_KQ4),
+
+ // King's Quest 4 (IIgs) 1.0K 11/22/88 (CE)
+ // Menus not tested
+ GAME3_P("kq4", "1.0K 1988-11-22", "kq4dir", "8536859331159f15012e35dc82cb154e", 0x3086, 0, GID_KQ4, Common::kPlatformApple2GS),
+
+ // King's Quest 4 demo (PC) [AGI 3.002.102]
+ // Menus not tested
+ GAME3("kq4", "Demo 1988-12-20", "dmdir", "a3332d70170a878469d870b14863d0bf", 0x3149, GID_KQ4),
+
+ // King's Quest 4 (CoCo3 720k) [AGI 2.023]
+ GAME_PS("kq4", "", "9e7729a28e749ca241d2bf71b9b2dbde", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3),
+
+ // King's Quest 4 (CoCo3 360k/720k) [AGI 2.072]
+ GAME_PS("kq4", "updated", "1959ca10739edb34069bb504dbd74805", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3),
+
+ // Leisure Suit Larry 1 (PC 5.25"/3.5") 1.00 6/1/87 [AGI 2.440]
+ GAME("lsl1", "1.00 1987-06-01 5.25\"/3.5\"", "1fe764e66857e7f305a5f03ca3f4971d", 0x2440, GID_LSL1),
+
+ // Leisure Suit Larry 1 Polish
+ GAME_LPS("lsl1", "2.00 2001-12-11", "7ba1fccc46d27c141e704706c1d0a85f", 303, Common::PL_POL, 0x2440, GID_LSL1, Common::kPlatformPC),
+
+ // Leisure Suit Larry 1 Polish - Demo
+ GAME_LPS("lsl1", "Demo", "3b2f564306c401dff6334441df967ddd", 666, Common::PL_POL, 0x2917, GID_LSL1, Common::kPlatformPC),
+
+ // Leisure Suit Larry 1 (ST) 1.04 6/18/87
+ GAME_P("lsl1", "1.04 1987-06-18", "8b579f8673fe9448c2538f5ed9887cf0", 0x2440, GID_LSL1, Common::kPlatformAtariST),
+
+ // Leisure Suit Larry 1 (Amiga) 1.05 6/26/87 # x.yyy
+ GAME_P("lsl1", "1.05 1987-06-26", "3f5d26d8834ca49c147fb60936869d56", 0x2440, GID_LSL1, Common::kPlatformAmiga),
+
+ // Leisure Suit Larry 1 (IIgs) 1.0E
+ GAME_P("lsl1", "1.0E 1987", "5f9e1dd68d626c6d303131c119582ad4", 0x2440, GID_LSL1, Common::kPlatformApple2GS),
+
+ // Leisure Suit Larry 1 (Mac) 1.05 6/26/87
+ GAME_P("lsl1", "1.05 1987-06-26", "8a0076429890531832f0dc113285e31e", 0x2440, GID_LSL1, Common::kPlatformMacintosh),
+
+ // Leisure Suit Larry 1 (CoCo3 158k/360k) [AGI 2.072]
+ GAME_PS("lsl1", "", "a2de1fe76565c3e8b40c9d036b5e5612", 198, 0x2440, GID_LSL1, Common::kPlatformCoCo3),
+
+ // Manhunter NY (ST) 1.03 10/20/88
+ GAME3_P("mh1", "1.03 1988-10-20", "mhdir", "f2d58056ad802452d60776ee920a52a6", 0x3149, 0, GID_MH1, Common::kPlatformAtariST),
+
+ // Manhunter NY (IIgs) 2.0E 10/05/88 (CE)
+ GAME3_P("mh1", "2.0E 1988-10-05 (CE)", "mhdir", "2f1509f76f24e6e7d213f2dadebbf156", 0x3149, 0, GID_MH1, Common::kPlatformApple2GS),
+
+ // Manhunter NY (Amiga) 1.06 3/18/89
+ GAME3_P("mh1", "1.06 1989-03-18", "dirs", "92c6183042d1c2bb76236236a7d7a847", 0x3149, GF_OLDAMIGAV20, GID_MH1, Common::kPlatformAmiga),
+
+ // reported by Filippos (thebluegr) in bugreport #1654500
+ // Manhunter NY (PC 5.25") 1.22 8/31/88 [AGI 3.002.107]
+ GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "0c7b86f05fe02c2e26cff1b07450b82a", 2123, 0x3149, 0, GID_MH1, Common::kPlatformPC),
+
+ // Manhunter NY (PC 3.5") 1.22 8/31/88 [AGI 3.002.102]
+ GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "5b625329021ad49fd0c1d6f2d6f54bba", 2141, 0x3149, 0, GID_MH1, Common::kPlatformPC),
+
+ // Manhunter NY (CoCo3 720k) [AGI 2.023]
+ GAME_PS("mh1", "", "b968285caf2f591c78dd9c9e26ab8974", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3),
+
+ // Manhunter NY (CoCo3 360k/720k) [AGI 2.072]
+ GAME_PS("mh1", "updated", "d47da950c62289f8d4ccf36af73365f2", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3),
+
+ // Manhunter SF (ST) 1.0 7/29/89
+ GAME3_P("mh2", "1.0 1989-07-29", "mh2dir", "5e3581495708b952fea24438a6c7e040", 0x3149, 0, GID_MH1, Common::kPlatformAtariST),
+
+ // Manhunter SF (Amiga) 3.06 8/17/89 # 2.333
+ GAME3_PS("mh2", "3.06 1989-08-17", "dirs", "b412e8a126368b76696696f7632d4c16", 2573, 0x3086, GF_OLDAMIGAV20, GID_MH2, Common::kPlatformAmiga),
+
+ // Manhunter SF (PC 5.25") 3.03 8/17/89 [AGI 3.002.149]
+ GAME3("mh2", "3.03 1989-08-17 5.25\"", "mh2dir", "b90e4795413c43de469a715fb3c1fa93", 0x3149, GID_MH2),
+
+ // Manhunter SF (PC 3.5") 3.02 7/26/89 [AGI 3.002.149]
+ GAME3("mh2", "3.02 1989-07-26 3.5\"", "mh2dir", "6fb6f0ee2437704c409cf17e081ba152", 0x3149, GID_MH2),
+
+ // Manhunter SF (CoCo3 720k) [AGI 2.023]
+ GAME_PS("mh2", "", "acaaa577e10d1753c5a74f6ae1d858d4", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3),
+
+ // Manhunter SF (CoCo3 720k) [AGI 2.072]
+ GAME_PS("mh2", "updated", "c64875766700196e72a92359f70f45a9", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3),
+
+ // Mickey's Space Adventure
+ // Preagi game
+ GAMEpre_P("mickey", "", "1.pic", "b6ec04c91a05df374792872c4d4ce66d", 0x0000, GID_MICKEY, Common::kPlatformPC),
+
+#if 0
+ // Mixed-Up Mother Goose (Amiga) 1.1
+ // Problematic: crashes
+ // Menus not tested
+ GAME3_PS("mixedup", "1.1 1986-12-10", "dirs", "5c1295fe6daaf95831195ba12894dbd9", 2021, 0x3086, 0, GID_MIXEDUP, Common::kPlatformAmiga),
+#endif
+
+ // Mixed Up Mother Goose (IIgs)
+ GAME_P("mixedup", "1987", "3541954a7303467c6df87665312ffb6a", 0x2917, GID_MIXEDUP, Common::kPlatformApple2GS),
+
+ // Mixed-Up Mother Goose (PC) [AGI 2.915]
+ GAME("mixedup", "1987-11-10", "e524655abf9b96a3b179ffcd1d0f79af", 0x2917, GID_MIXEDUP),
+
+ // Mixed-Up Mother Goose (CoCo3 360k) [AGI 2.072]
+ GAME_PS("mixedup", "", "44e63e9b4d4822a31edea0e8a7e7eac4", 606, 0x2440, GID_MIXEDUP, Common::kPlatformCoCo3),
+
+ // Police Quest 1 (PC) 2.0E 11/17/87 [AGI 2.915]
+ GAME("pq1", "2.0E 1987-11-17", "2fd992a92df6ab0461d5a2cd83c72139", 0x2917, GID_PQ1),
+
+ // Police Quest 1 (Mac) 2.0G 12/3/87
+ GAME_P("pq1", "2.0G 1987-12-03", "805750b66c1c5b88a214e67bfdca17a1", 0x2440, GID_PQ1, Common::kPlatformMacintosh),
+
+ // Police Quest 1 (IIgs) 2.0B-88421
+ GAME_P("pq1", "2.0B 1988-04-21", "e7c175918372336461e3811d594f482f", 0x2917, GID_PQ1, Common::kPlatformApple2GS),
+
+ // Police Quest 1 (Amiga) 2.0B 2/22/89 # 2.310
+ GAME3_PS("pq1", "2.0B 1989-02-22", "dirs", "cfa93e5f2aa7378bddd10ad6746a2ffb", 1613, 0x3149, 0, GID_PQ1, Common::kPlatformAmiga),
+
+ // Police Quest 1 (IIgs) 2.0A-88318
+ GAME_P("pq1", "2.0A 1988-03-18", "8994e39d0901de3d07cecfb954075bb5", 0x2917, GID_PQ1, Common::kPlatformApple2GS),
+
+ // Police Quest 1 (PC) 2.0A 10/23/87 [AGI 2.903/2.911]
+ GAME("pq1", "2.0A 1987-10-23", "b9dbb305092851da5e34d6a9f00240b1", 0x2917, GID_PQ1),
+
+ // Police Quest 1 (Russian)
+ GAME_LPS("pq1", "", "604cc8041d24c4c7e5fa8baf386ef76e", 360, Common::RU_RUS, 0x2917, GID_PQ1, Common::kPlatformPC),
+
+ // Police Quest 1 2.0G 12/3/87
+ GAME("pq1", "2.0G 1987-12-03 5.25\"/ST", "231f3e28170d6e982fc0ced4c98c5c1c", 0x2440, GID_PQ1),
+
+ // Police Quest 1 (PC) 2.0G 12/3/87; entry from DAGII, but missing from Sarien?
+ // not sure about disk format -- dsymonds
+ GAME("pq1", "2.0G 1987-12-03", "d194e5d88363095f55d5096b8e32fbbb", 0x2917, GID_PQ1),
+
+ // Police Quest 1 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("pq1", "", "28a077041f75aab78f66804800940085", 375, 0x2440, GID_PQ1, Common::kPlatformCoCo3),
+
+ // Police Quest 1 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("pq1", "updated", "63b9a9c6eec154751dd446cd3693e0e2", 768, 0x2440, GID_PQ1, Common::kPlatformCoCo3),
+
+ // Space Quest 1 (ST) 1.1A
+ // The original game did not have menus, they are enabled under ScummVM
+ GAME_FP("sq1", "1.1A 1986-02-06", "6421fb64b0e6604c9dd065975d9279e9", 0x2440, GF_MENUS, GID_SQ1, Common::kPlatformAtariST),
+
+ // Space Quest 1 (PC 360k) 1.1A [AGI 2.272]
+ // The original game did not have menus, they are enabled under ScummVM
+ GAME_FP("sq1", "1.1A 1986-11-13", "8d8c20ab9f4b6e4817698637174a1cb6", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC),
+
+ // Space Quest 1 (PC 720k) 1.1A [AGI 2.272]
+ // The original game did not have menus, they are enabled under ScummVM
+ GAME_FP("sq1", "1.1A 720kb", "0a92b1be7daf3bb98caad3f849868aeb", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC),
+
+ // Space Quest 1 (Amiga) 1.2 # 2.082
+ // The original game did not have menus, they are enabled under ScummVM
+ GAME_FP("sq1", "1.2 1986", "0b216d931e95750f1f4837d6a4b821e5", 0x2440, GF_MENUS | GF_OLDAMIGAV20, GID_SQ1, Common::kPlatformAmiga),
+
+ // Space Quest 1 (Mac) 1.5D
+ GAME_P("sq1", "1.5D 1987-04-02", "ce88419aadd073d1c6682d859b3d8aa2", 0x2440, GID_SQ1, Common::kPlatformMacintosh),
+
+ // Space Quest 1 (IIgs) 2.2
+ GAME_P("sq1", "2.2 1987", "64b9b3d04c1066d36e6a6e56187a83f7", 0x2917, GID_SQ1, Common::kPlatformApple2GS),
+
+ // Space Quest 1 (PC) 1.0X [AGI 2.089]
+ // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game
+ GAME_FP("sq1", "1.0X 1986-09-24", "af93941b6c51460790a9efa0e8cb7122", 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC),
+
+ // Space Quest 1 (Russian)
+ GAME_LFPS("sq1", "", "a279eb8ddbdefdb1ea6adc827a1d632a", 372, Common::RU_RUS, 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC),
+
+ // Space Quest 1 (PC 5.25"/3.5") 2.2 [AGI 2.426/2.917]
+ GAME("sq1", "2.2 1987-05-07 5.25\"/3.5\"", "5d67630aba008ec5f7f9a6d0a00582f4", 0x2440, GID_SQ1),
+
+ // Space Quest 1 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("sq1", "", "5d67630aba008ec5f7f9a6d0a00582f4", 372, 0x2440, GID_SQ1, Common::kPlatformCoCo3),
+
+ // Space Quest 1 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("sq1", "fixed", "ca822b768b6462e410423ea7f498daee", 768, 0x2440, GID_SQ1, Common::kPlatformCoCo3),
+
+ // Space Quest 1 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("sq1", "updated", "7fa54e6bb7ffeb4cf20eca39d86f5fb2", 387, 0x2440, GID_SQ1, Common::kPlatformCoCo3),
+
+ // Space Quest 2 (PC 3.5") 2.0D [AGI 2.936]
+ GAME("sq2", "2.0D 1988-03-14 3.5\"", "85390bde8958c39830e1adbe9fff87f3", 0x2936, GID_SQ2),
+
+ // Space Quest 2 (IIgs) 2.0A 7/25/88 (CE)
+ GAME_P("sq2", "2.0A 1988-07-25 (CE)", "5dfdac98dd3c01fcfb166529f917e911", 0x2936, GID_SQ2, Common::kPlatformApple2GS),
+
+ {
+ // Space Quest 2 (Amiga) 2.0F
+ {
+ "sq2",
+ "2.0F 1986-12-09 [VOL.2->PICTURE.16 broken]",
+ {
+ { "logdir", 0, "28add5125484302d213911df60d2aded", 426},
+ { "object", 0, "5dc52be721257719f4b311a84ce22b16", 372},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_SQ2,
+ GType_V2,
+ 0,
+ 0x2936,
+ },
+
+
+ // Space Quest 2 (Mac) 2.0D
+ GAME_P("sq2", "2.0D 1988-04-04", "bfbebe0b59d83f931f2e1c62ce9484a7", 0x2936, GID_SQ2, Common::kPlatformMacintosh),
+
+ // reported by Filippos (thebluegr) in bugreport #1654500
+ // Space Quest 2 (PC 5.25") 2.0A [AGI 2.912]
+ GAME_PS("sq2", "2.0A 1987-11-06 5.25\"", "ad7ce8f800581ecc536f3e8021d7a74d", 423, 0x2917, GID_SQ2, Common::kPlatformPC),
+
+ // Space Quest 2 (Russian)
+ GAME_LPS("sq2", "", "ba21c8934caf28e3ba45ce7d1cd6b041", 423, Common::RU_RUS, 0x2917, GID_SQ2, Common::kPlatformPC),
+
+ // Space Quest 2 (PC 3.5") 2.0A [AGI 2.912]
+ GAME_PS("sq2", "2.0A 1987-11-06 3.5\"", "6c25e33d23b8bed42a5c7fa63d588e5c", 423, 0x2917, GID_SQ2, Common::kPlatformPC),
+
+ // Space Quest 2 (PC 5.25"/ST) 2.0C/A [AGI 2.915]
+ // Menus not tested
+ GAME("sq2", "2.0C/A 5.25\"/ST", "bd71fe54869e86945041700f1804a651", 0x2917, GID_SQ2),
+
+ // Space Quest 2 (PC 3.5") 2.0F [AGI 2.936]
+ GAME("sq2", "2.0F 1989-01-05 3.5\"", "28add5125484302d213911df60d2aded", 0x2936, GID_SQ2),
+
+ // Space Quest 2 (CoCo3 360k) [AGI 2.023]
+ GAME_PS("sq2", "", "12973d39b892dc9d280257fd271e9597", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3),
+
+ // Space Quest 2 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("sq2", "updated", "d24f19b047e65e1763eff4b46f3d50df", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3),
+
+ // Troll's Tale
+ GAMEpre_PS("troll", "", "troll.img", "62903f264b3d849be4214b3a5c42a2fa", 184320, 0x0000, GID_TROLL, Common::kPlatformPC),
+
+ // Winnie the Pooh in the Hundred Acre Wood
+ GAMEpre_P("winnie", "", "title.pic", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformPC),
+
+ // Winnie the Pooh in the Hundred Acre Wood (Amiga)
+ GAMEpre_P("winnie", "", "title", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformAmiga),
+
+ // Winnie the Pooh in the Hundred Acre Wood (C64)
+ GAMEpre_P("winnie", "", "title.pic", "d4eb97cffc866110f71e1ec9f84fe643", 0x0000, GID_WINNIE, Common::kPlatformC64),
+
+ // Winnie the Pooh in the Hundred Acre Wood (Apple //gs)
+ GAMEpre_P("winnie", "", "title.pic", "45e06010a3c61d78f4661103c901ae11", 0x0000, GID_WINNIE, Common::kPlatformApple2GS),
+
+ // Xmas Card 1986 (PC) [AGI 2.272]
+ GAME("xmascard", "1986-11-13 [version 1]", "3067b8d5957e2861e069c3c0011bd43d", 0x2272, GID_XMASCARD),
+
+ // Xmas Card 1986 (CoCo3 360k) [AGI 2.072]
+ GAME_PS("xmascard", "", "25ad35e9628fc77e5e0dd35852a272b6", 768, 0x2440, GID_XMASCARD, Common::kPlatformCoCo3),
+
+ FANMADE_F("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE),
+ FANMADE("AGI Contest 1 Template", "d879aed25da6fc655564b29567358ae2"),
+ FANMADE("AGI Contest 2 Template", "5a2fb2894207eff36c72f5c1b08bcc07"),
+ FANMADE("AGI Mouse Demo 0.60 demo 1", "c07e2519de674c67386cb2cc6f2e3904"),
+ FANMADE("AGI Mouse Demo 0.60 demo 2", "cc49d8b88ed6faf4f53ce92c84e0fe1b"),
+ FANMADE("AGI Mouse Demo 0.70", "3497c291e4afb6f758e61740678a2aec"),
+ FANMADE_F("AGI Mouse Demo 1.00", "20397f0bf0ef936f416bb321fb768fc7", GF_AGIMOUSE),
+ FANMADE_F("AGI Mouse Demo 1.10", "f4ad396b496d6167635ad0b410312ab8", GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE("AGI Piano (v1.0)", "8778b3d89eb93c1d50a70ef06ef10310"),
+ FANMADE("AGI Quest (v1.46-TJ0)", "1cf1a5307c1a0a405f5039354f679814"),
+ GAME("tetris", "", "7a874e2db2162e7a4ce31c9130248d8a", 0x2917, GID_FANMADE),
+ FANMADE_V("AGI Trek (Demo)", "c02882b8a8245b629c91caf7eb78eafe", 0x2440),
+ FANMADE_F("AGI256 Demo", "79261ac143b2e2773b2753674733b0d5", GF_AGI256),
+ FANMADE_F("AGI256-2 Demo", "3cad9b3aff1467cebf0c5c5b110985c5", GF_AGI256_2),
+ FANMADE_LF("Abrah: L'orphelin de l'espace (v1.2)", "b7b6d1539e14d5a26fa3088288e1badc", Common::FR_FRA, GF_AGIPAL),
+ FANMADE("Acidopolis", "7017db1a4b726d0d59e65e9020f7d9f7"),
+ FANMADE("Agent 0055 (v1.0)", "c2b34a0c77acb05482781dda32895f24"),
+ FANMADE("Agent 06 vs. The Super Nazi", "136f89ca9f117c617e88a85119777529"),
+ FANMADE("Agent Quest", "59e49e8f72058a33c00d60ee1097e631"),
+ FANMADE("Al Pond - On Holiday (v1.0)", "a84975496b42d485920e886e92eed68b"),
+ FANMADE("Al Pond - On Holiday (v1.1)", "7c95ac4689d0c3bfec61e935f3093634"),
+ FANMADE("Al Pond - On Holiday (v1.3)", "8f30c260de9e1dd3d8b8f89cc19d2633"),
+ FANMADE("Al Pond 1 - Al Lives Forever (v1.0)", "e8921c3043b749b056ff51f56d1b451b"),
+ FANMADE("Al Pond 1 - Al Lives Forever (v1.3)", "fb4699474054962e0dbfb4cf12ca52f6"),
+ FANMADE("Apocalyptic Quest (v0.03 Teaser)", "42ced528b67965d3bc3b52c635f94a57"),
+ FANMADE_F("Apocalyptic Quest (v4.00 Alpha 1)", "e15581628d84949b8d352d224ec3184b", GF_AGIMOUSE),
+ FANMADE_F("Apocalyptic Quest (v4.00 Alpha 2)", "0eee850005860e46345b38fea093d194", GF_AGIMOUSE),
+ FANMADE_F("Band Quest (Demo)", "7326abefd793571cc17ed0db647bdf34", GF_AGIMOUSE),
+ FANMADE_F("Band Quest (Early Demo)", "de4758dd34676b248c8301b32d93bc6f", GF_AGIMOUSE),
+ FANMADE("Beyond the Titanic 2", "9b8de38dc64ffb3f52b7877ea3ebcef9"),
+ FANMADE("Biri Quest 1", "1b08f34f2c43e626c775c9d6649e2f17"),
+ FANMADE("Bob The Farmboy", "e4b7df9d0830addee5af946d380e66d7"),
+ FANMADE_F("Boring Man 1: The Toad to Robinland", "d74481cbd227f67ace37ce6a5493039f", GF_AGIMOUSE),
+ FANMADE_F("Boring Man 2: Ho Man! This Game Sucks!", "250032ba105bdf7c1bc4fed767c2d37e", GF_AGIMOUSE),
+ FANMADE("Botz", "a8fabe4e807adfe5ec02bfec6d983695"),
+ FANMADE("Brian's Quest (v1.0)", "0964aa79b9cdcff7f33a12b1d7e04b9c"),
+ FANMADE("CPU-21 (v1.0)", "35b7cdb4d17e890e4c52018d96e9cbf4"),
+ GAME("caitlyn", "Demo", "5b8a3cdb2fc05469f8119d49f50fbe98", 0x2917, GID_FANMADE),
+ GAME("caitlyn", "", "818469c484cae6dad6f0e9a353f68bf8", 0x2917, GID_FANMADE),
+ FANMADE("Car Driver (v1.1)", "2311611d2d36d20ccc9da806e6cba157"),
+ FANMADE("Cloak of Darkness (v1.0)", "5ba6e18bf0b53be10db8f2f3831ee3e5"),
+ FANMADE("Coco Coq (English) - Coco Coq In Grostesteing's Base (v.1.0.3)", "97631f8e710544a58bd6da9e780f9320"),
+ FANMADE_L("Coco Coq (French) - Coco Coq Dans la Base de Grostesteing (v1.0.2)", "ef579ebccfe5e356f9a557eb3b2d8649", Common::FR_FRA),
+ FANMADE("Corby's Murder Mystery (v1.0)", "4ebe62ac24c5a8c7b7898c8eb070efe5"),
+ FANMADE_F("DG: The AGIMouse Adventure (English v1.1)", "efe453b92bc1487ea69fbebede4d5f26", GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE_LF("DG: The AGIMouse Adventure (French v1.1)", "eb3d17ca466d672cbb95947e8d6e846a", Common::FR_FRA, GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE("DG: The Adventure Game (English v1.1)", "0d6376d493fa7a21ec4da1a063e12b25"),
+ FANMADE_L("DG: The Adventure Game (French v1.1)", "258bdb3bb8e61c92b71f2f456cc69e23", Common::FR_FRA),
+ FANMADE("Dashiki (16 Colors)", "9b2c7b9b0283ab9f12bedc0cb6770a07"),
+ FANMADE_F("Dashiki (256 Colors)", "c68052bb209e23b39b55ff3d759958e6", GF_AGIMOUSE|GF_AGI256),
+ FANMADE("Date Quest 1 (v1.0)", "ba3dcb2600645be53a13170aa1a12e69"),
+ FANMADE("Date Quest 2 (v1.0 Demo)", "1602d6a2874856e928d9a8c8d2d166e9"),
+ FANMADE("Date Quest 2 (v1.0)", "f13f6fc85aa3e6e02b0c20408fb63b47"),
+ FANMADE("Dave's Quest (v0.07)", "f29c3660de37bacc1d23547a167f27c9"),
+ FANMADE("Dave's Quest (v0.17)", "da3772624cc4a86f7137db812f6d7c39"),
+ FANMADE("Disco Nights (Demo)", "dc5a2b21182ba38bdcd992a3a978e690"),
+ FANMADE("Dogs Quest - The Quest for the Golden Bone (v1.0)", "f197357edaaea0ff70880602d2f09b3e"),
+ FANMADE("Dr. Jummybummy's Space Adventure", "988bd81785f8a452440a2a8ac67f96aa"),
+ FANMADE("Ed Ward", "98be839b9f30cbedea4c9cee5442d827"),
+ FANMADE("Elfintard", "c3b847e9e9e978af9708df76a0751dc2"),
+ FANMADE("Enclosure (v1.01)", "f08e66fee9ecdde77db7ee9a10c96ba2"),
+ FANMADE("Enclosure (v1.03)", "e4a0613ed02401502e506ba3565a8c40"),
+ FANMADE_SVP("Enclosure", "fe98e6126db74c6cc6fd8fe395cc6e8c", 345, 0x2440, Common::kPlatformCoCo3),
+ FANMADE("Epic Fighting (v0.1)", "aff24a1b3bdd676187685c4d95ba4294"),
+ FANMADE("Escape Quest (v0.0.3)", "2346b65619b1da0298b715b06d1a45a1"),
+ FANMADE("Escape from the Desert (beta 1)", "dfdc634d340854bd6ece28024010758d"),
+ FANMADE("Escape from the Salesman", "e723ca4fe0f6f56affe039fbb4dbeb6c"),
+ FANMADE("Fu$k Quest 1 (final)", "1cd0587422313f6ca77d6a95988e88ed"),
+ FANMADE("Fu$k Quest 1", "1cd0587422313f6ca77d6a95988e88ed"),
+ FANMADE("Fu$k Quest 2 - Romancing the Bone (Teaser)", "d288355d71d9bb1639260ccaa3b2fbfe"),
+ FANMADE("Fu$k Quest 2 - Romancing the Bone", "294beeb7765c7ea6b05ed7b9bf7bff4f"),
+ FANMADE("Gennadi Tahab Autot - Mission Pack 1 - Kuressaare", "bfa5fe71978e6ccf3d4eedd430124015"),
+ FANMADE("Go West, Young Hippie", "ff31484ea465441cb5f3a0f8e956b716"),
+ FANMADE("Good Man (demo v3.41)", "3facd8a8f856b7b6e0f6c3200274d88c"),
+
+ {
+ // Groza
+ {
+ "agi-fanmade",
+ "Groza (russian) [AGDS sample]",
+ AD_ENTRY1("logdir", "421da3a18004122a966d64ab6bd86d2e"),
+ Common::RU_RUS,
+ Common::kPlatformPC,
+ ADGF_USEEXTRAASTITLE,
+ GUIO_NONE
+ },
+ GID_FANMADE,
+ GType_V2,
+ GF_AGDS,
+ 0x2440,
+ },
+
+ {
+ // Get Outta SQ
+ {
+ "agi-fanmade",
+ "Get Outta Space Quest",
+ AD_ENTRY1("logdir", "aaea5b4a348acb669d13b0e6f22d4dc9"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_USEEXTRAASTITLE,
+ GUIO_NONE
+ },
+ GID_GETOUTTASQ,
+ GType_V2,
+ 0,
+ 0x2440,
+ },
+
+ FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE),
+ FANMADE("Hank's Quest (v1.0 English) - Victim of Society", "64c15b3d0483d17888129100dc5af213"),
+ FANMADE("Hank's Quest (v1.1 English) - Victim of Society", "86d1f1dd9b0c4858d096e2a60cca8a14"),
+ FANMADE_L("Hank's Quest (v1.81 Dutch) - Slachtoffer Van Het Gebeuren", "41e53972d55ff3dff9e90d15fe1b659f", Common::NL_NLD),
+ FANMADE("Hank's Quest (v1.81 English) - Victim of Society", "7a776383282f62a57c3a960dafca62d1"),
+ FANMADE("Herbao (v0.2)", "6a5186fc8383a9060517403e85214fc2"),
+ FANMADE_F("Hitler's Legacy (v.0004q)", "a412881269ba34584bd0a3268e5a9863", GF_AGIMOUSE),
+ FANMADE("Hobbits", "4a1c1ef3a7901baf0ab45fde0cfadd89"),
+ FANMADE_F("Isabella Coq - A Present For My Dad", "55c6819f2330c4d5d6459874c9f123d9", GF_AGIMOUSE),
+ FANMADE("Jack & Julia - VAMPYR", "8aa0b9a26f8d5a4421067ab8cc3706f6"),
+ FANMADE("Jeff's Quest (v.5 alpha Jun 1)", "10f1720eed40c12b02a0f32df3e72ded"),
+ FANMADE("Jeff's Quest (v.5 alpha May 31)", "51ff71c0ed90db4e987a488ed3bf0551"),
+ FANMADE("Jen's Quest (Demo 1)", "361afb5bdb6160213a1857245e711939"),
+ FANMADE("Jen's Quest (Demo 2)", "3c321eee33013b289ab8775449df7df2"),
+ FANMADE("Jiggy Jiggy Uh! Uh!", "bc331588a71e7a1c8840f6cc9b9487e4"),
+ FANMADE("Jimmy In: The Alien Attack (v0.1)", "a4e9db0564a494728de7873684a4307c"),
+ FANMADE("Joe McMuffin In \"What's Cooking, Doc\" (v1.0)", "8a3de7e61a99cb605fa6d233dd91c8e1"),
+ FANMADE_LVF("Jolimie, le Village Maudit (v0.5)", "21818501636b3cb8ad5de5c1a66de5c2", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE_LVF("Jolimie, le Village Maudit (v1.1)", "68d7aef1161bb5972fe03efdf29ccb7f", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE("Journey Of Chef", "aa0a0b5a6364801ae65fdb96d6741df5"),
+ FANMADE("Jukebox (v1.0)", "c4b9c5528cc67f6ba777033830de7751"),
+ FANMADE("Justin Quest (v1.0 in development)", "103050989da7e0ffdc1c5e1793a4e1ec"),
+ FANMADE("J\xf5ulumaa (v0.05) (Estonian)", "53982ecbfb907e41392b3961ad1c3475"),
+ FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Mar 26)", "a25d7379d281b1b296d4785df90a8e78"),
+ FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Aug 16)", "6b4f796d0421d2e12e501b511962e03a"),
+ FANMADE("Lasse Holm: The Quest for Revenge (v1.0)", "f9fbcc8a4ef510bfbb92423296ff4abb"),
+ FANMADE("Lawman for Hire", "c78b28bfd3767dd455b992cd8b7854fa"),
+ FANMADE("Lefty Goes on Vacation (Not in The Right Place)", "ccdc49a33870310b01f2c48b8a1f3c34"),
+ FANMADE("Les Ins\xe3parables (v1.0)", "4b780887cab0ecabc5eca319acb3acf2"),
+ FANMADE("Little Pirate (Demo 2 v0.6)", "437068efe4ec32d436da09d6f2ea56e1"),
+ FANMADE("Lost Eternity (v1.0)", "95f15c5632feb8a39e9ca3d9af35fcc9"),
+ FANMADE("MD Quest - The Search for Michiel (v0.10)", "2a6fcb21d2b5e4144c38ed817fabe8ee"),
+ FANMADE("Maale Adummin Quest", "ddfbeb33feb7cf78504fe4dba14ec63b"),
+ FANMADE("Monkey Man", "2322d03f997e8cc235d4578efff69cfa"),
+ FANMADE_F("Napalm Quest (v0.5)", "b659afb491d967bb34810d1c6ce22093", GF_AGIMOUSE),
+ FANMADE("Naturette 1 (English v1.2)", "0a75884e7f010974a230bdf269651117"),
+ FANMADE("Naturette 1 (English v1.3)", "f15bbf999ac55ebd404aa1eb84f7c1d9"),
+ FANMADE_L("Naturette 1 (French v1.2)", "d3665622cc41aeb9c7ecf4fa43f20e53", Common::FR_FRA),
+ FANMADE_F("Naturette 2: Daughter of the Moon (v1.0)", "bdf76a45621c7f56d1c9d40292c6137a", GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE_F("Naturette 3: Adventure in Treeworld (v1.0a)", "6dbb0e7fc75fec442e6d9e5a06f1530e", GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE_F("Naturette 4: From a Planet to Another Planet (Not Finished)", "13be8cd9cf35aeff0a39b8757057fbc8", GF_AGIMOUSE),
+ // FIXME: Actually Naturette 4 has both English and French language support built into it. How to add that information?
+ FANMADE_F("Naturette 4: From a Planet to Another Planet (2007-10-05)", "8253706b6ef5423a79413b216760297c", GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE("New AGI Hangman Test", "d69c0e9050ccc29fd662b74d9fc73a15"),
+ FANMADE("Nick's Quest - In Pursuit of QuakeMovie (v2.1 Gold)", "e29cbf9222551aee40397fabc83eeca0"),
+ FANMADE_F("Open Mic Night (v0.1)", "70000a2f67aac27d1133d019df70246d", GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE("Operation: Recon", "0679ce8405411866ccffc8a6743370d0"),
+ FANMADE("Patrick's Quest (Demo v1.0)", "f254f5b894b98fec5f92acc07fb62841"),
+ FANMADE("Phantasmagoria", "87d20c1c11aee99a4baad3797b63146b"),
+ FANMADE("Pharaoh Quest (v0.0)", "51c630899d076cf799e573dadaa2276d"),
+ FANMADE("Phil's Quest - the Search for Tolbaga", "5e7ca45c360e03164b8358e49900c588"),
+ FANMADE("Pinkun Maze Quest (v0.1)", "148ff0843af389928b3939f463bfd20d"),
+ FANMADE("Pirate Quest", "bb612a919ed2b9ea23bbf03ce69fed42"),
+ FANMADE("Pothead (v0.1)", "d181101385d3a45082f418cd4b3c5b01"),
+ FANMADE("President's Quest", "4937d0e8ecadb7888faeb347799b0388"),
+ FANMADE("Prince Quest", "266248d75c3130c8ccc9c9bf2ad30a0d"),
+ FANMADE("Professor (English) - The Professor is Missing (Mar 17)", "6232de31cc204affdf2e92dfe3dc0e4d"),
+ FANMADE("Professor (English) - The Professor is Missing (Mar 22)", "b5fcf0ca2f0d1c073be82f01e2170961"),
+ FANMADE_L("Professor (French) - Le Professeur a Disparu", "7d9f8a4d4610bb9b0b97caa17590c2d3", Common::FR_FRA),
+ FANMADE("Quest for Glory VI - Hero's Adventure", "d26765c3075064c80d284c5e06e33a7e"),
+ FANMADE("Quest for Home", "d2895dc1cd3930f2489af0f843b144b3"),
+ FANMADE("Quest for Ladies (demo v1.1 Apr 1)", "3f6e02f16e1154a0daf296c8895edd97"),
+ FANMADE("Quest for Ladies (demo v1.1 Apr 6)", "f75e7b6a0769a3fa926eea0854711591"),
+ FANMADE("Quest for Piracy 1 - Enter the Silver Pirate (v0.15)", "d23f5c2a26f6dc60c686f8a2436ea4a6"),
+ FANMADE("Quest for a Record Deal", "f4fbd7abf056d2d3204f790da5ac89ab"),
+ FANMADE("Ralph's Quest (v0.1)", "5cf56378aa01a26ec30f25295f0750ca"),
+ FANMADE("Residence 44 Quest (Dutch v0.99)", "7c5cc64200660c70240053b33d379d7d"),
+ FANMADE("Residence 44 Quest (English v0.99)", "fe507851fddc863d540f2bec67cc67fd"),
+ FANMADE("Residence 44 Quest (English v1.0a)", "f99e3f69dc8c77a45399da9472ef5801"),
+ FANMADE("SQ2Eye (v0.3)", "2be2519401d38ad9ce8f43b948d093a3"),
+ // FANMADE("SQ2Eye (v0.4)", "2be2519401d38ad9ce8f43b948d093a3"),
+ FANMADE("SQ2Eye (v0.41)", "f0e82c55f10eb3542d7cd96c107ae113"),
+ FANMADE("SQ2Eye (v0.42)", "d7beae55f6328ef8b2da47b1aafea40c"),
+ FANMADE("SQ2Eye (v0.43)", "2a895f06e45de153bb4b77c982009e06"),
+ FANMADE("SQ2Eye (v0.44)", "5174fc4b6d8a477ba0ff0575cd64e0aa"),
+ FANMADE("SQ2Eye (v0.45)", "6e06f8bb7b90ce6f6aabf1a0e620159c"),
+ FANMADE("SQ2Eye (v0.46)", "bf0ad7a035ff9113951d09d1efe380c4"),
+ FANMADE("SQ2Eye (v0.47)", "85dc3be1d33ff932c292b74f9037abaa"),
+ FANMADE("SQ2Eye (v0.48)", "587574252972a5b5c070a647973a9b4a"),
+ FANMADE("SQ2Eye (v0.481)", "fc9234beb49804ae869696ce5af8ef30"),
+ FANMADE("SQ2Eye (v0.482)", "3ed84b7b87fa6840f25c15f250a11ffb"),
+ FANMADE("SQ2Eye (v0.483)", "647c31298d3f9cda641231b893e347c0"),
+ FANMADE("SQ2Eye (v0.484)", "f2c86fae7b9046d408c62c8c49a4b882"),
+ FANMADE("SQ2Eye (v0.485)", "af59e36bc28f44545458b68a93e91e67"),
+ FANMADE("SQ2Eye (v0.486)", "3fd86436e93456770dbdd4593eded70a"),
+ FANMADE("Save Santa (v1.0)", "4644f6beb5802081772f14be56ae196c"),
+ FANMADE("Save Santa (v1.3)", "f8afdb6efc5af5e7c0228b44633066af"),
+ FANMADE("Schiller (preview 1)", "ade39dea968c959cfebe1cf935d653e9"),
+ FANMADE("Schiller (preview 2)", "62cd1f8fc758bf6b4aa334e553624cef"),
+ GAME_F("serguei1", "v1.0", "b86725f067e456e10cdbdf5f58e01dec", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE),
+ // FIXME: The following two entries have identical MD5 checksums?
+ GAME_F("serguei1", "v1.1 2002 Sep 5", "91975c1fb4b13b0f9a8e9ff74731030d", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE),
+ GAME_F("serguei1", "v1.1 2003 Apr 10", "91975c1fb4b13b0f9a8e9ff74731030d", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE),
+ GAME_F("serguei2", "v0.1.1 Demo", "906ccbc2ddedb29b63141acc6d10cd28", 0x2917, GF_FANMADE|GF_AGIMOUSE, GID_FANMADE),
+ GAME_F("serguei2", "v1.3.1 Demo (March 22nd 2008)", "ad1308fcb8f48723cd388e012ebf5e20", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE),
+ FANMADE("Shifty (v1.0)", "2a07984d27b938364bf6bd243ac75080"),
+ FANMADE_F("Sliding Tile Game (v1.00)", "949bfff5d8a81c3139152eed4d84ca75", GF_AGIMOUSE),
+ FANMADE("Snowboarding Demo (v1.0)", "24bb8f29f1eddb5c0a099705267c86e4"),
+ FANMADE("Solar System Tour", "b5a3d0f392dfd76a6aa63f3d5f578403"),
+ FANMADE("Sorceror's Appraisal", "fe62615557b3cb7b08dd60c9d35efef1"),
+ GAME("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590", 0x2917, GID_FANMADE),
+ GAME("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6", 0x2917, GID_FANMADE),
+ GAME_PS("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, GID_FANMADE, Common::kPlatformCoCo3),
+ GAME("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1", 0x2917, GID_FANMADE),
+ GAME("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910", 0x2917, GID_FANMADE),
+ GAME_PS("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, GID_FANMADE, Common::kPlatformCoCo3),
+ FANMADE_F("Space Quest 3.5", "c077bc28d7b36213dd99dc9ecb0147fc", GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE_F("Space Trek (v1.0)", "807a1aeadb2ace6968831d36ab5ea37a", GF_CLIPCOORDS),
+ FANMADE("Special Delivery", "88764dfe61126b8e73612c851b510a33"),
+ FANMADE("Speeder Bike Challenge (v1.0)", "2deb25bab379285ca955df398d96c1e7"),
+ FANMADE("Star Commander 1 - The Escape (v1.0)", "a7806f01e6fa14ebc029faa58f263750"),
+ FANMADE("Star Pilot: Bigger Fish", "8cb26f8e1c045b75c6576c839d4a0172"),
+ FANMADE_F("Street Quest (Demo)", "cf2aa94a7eb78dce6892c37f03e310d6", GF_AGIPAL),
+ FANMADE("Tales of the Tiki", "8103c9c87e3964690a14a3d0d83f7ddc"),
+ FANMADE("Tex McPhilip 1 - Quest For The Papacy", "3c74b9a24b51aa8020ac82bee3132266"),
+ FANMADE("Tex McPhilip 2 - Road To Divinity (v1.5)", "7387e8df854440bc26620ca0ea43af9a"),
+ FANMADE("Tex McPhilip 3 - A Destiny of Sin (Demo v0.25)", "992d12031a486ad84e592ff5d7c9d782"),
+ FANMADE("The 13th Disciple (v1.00)", "887719ad59afce9a41ec057dbb73ad73"),
+ FANMADE("The Adventures of a Crazed Hermit", "6e3086cbb794d3299a9c5a9792295511"),
+ FANMADE("The Grateful Dead", "c2146631afacf8cb455ce24f3d2d46e7"),
+ FANMADE("The Legend of Shay-Larah 1 - The Lost Prince", "04e720c8e30c9cf12db22ea14a24a3dd"),
+ FANMADE("The Legend of Zelda: The Fungus of Time (Demo v1.00)", "dcaf8166ceb62a3d9b9aea7f3b197c09"),
+ FANMADE("The Legendary Harry Soupsmith (Demo 1998 Apr 2)", "64c46b0d6fc135c9835afa80980d2831"),
+ FANMADE("The Legendary Harry Soupsmith (Demo 1998 Aug 19)", "8d06d82970f2c591d880a95476efbcf0"),
+ FANMADE("The Long Haired Dude: Encounter of the 18-th Kind", "86ea17b9fc2f3e537a7e40863d352c29"),
+ FANMADE("The Lost Planet (v0.9)", "590dffcbd932a9fbe554be13b769cac0"),
+ FANMADE("The Lost Planet (v1.0)", "58564df8b6394612dd4b6f5c0fd68d44"),
+ FANMADE("The New Adventure of Roger Wilco (v1.00)", "e5f0a7cb8d49f66b89114951888ca688"),
+ FANMADE("The Ruby Cast (v0.02)", "ed138e461bb1516e097007e017ab62df"),
+ FANMADE("The Shadow Plan", "c02cd10267e721f4e836b1431f504a0a"),
+ FANMADE("Time Quest (Demo v0.1)", "12e1a6f03ea4b8c5531acd0400b4ed8d"),
+ FANMADE("Time Quest (Demo v0.2)", "7b710608abc99e0861ac59b967bf3f6d"),
+ FANMADE_SVP("Time Quest", "90314f473d8317be5cd1f0306f139aea", 300, 0x2440, Common::kPlatformCoCo3),
+ FANMADE("Tonight The Shrieking Corpses Bleed (Demo v0.11)", "bcc57a7c8d563fa0c333107ae1c0a6e6"),
+ FANMADE("Tonight The Shrieking Corpses Bleed (v1.01)", "36b38f621b38e8d104aa0807302dc8c9"),
+ FANMADE("Turks' Quest - Heir to the Planet", "3d19254b737c8b218e5bc4580542b79a"),
+ FANMADE("URI Quest (v0.173 Feb 27)", "3986eefcf546dafc45f920ae91a697c3"),
+ FANMADE("URI Quest (v0.173 Jan 29)", "494150940d34130605a4f2e67ee40b12"),
+ {
+ // V - The Graphical Adventure
+ {
+ "agi-fanmade",
+ "V - The Graphical Adventure (Demo 2)",
+ AD_ENTRY1s("vdir", "c71f5c1e008d352ae9040b77fcf79327", 3080),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_USEEXTRAASTITLE,
+ GUIO_NONE
+ },
+ GID_FANMADE,
+ GType_V3,
+ GF_FANMADE,
+ 0x3149,
+ },
+ FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3),
+
+ FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Jan 1)", "ae95f0c77d9a97b61420fd192348b937"),
+ FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Mar 29)", "11d0417b7b886f963d0b36789dac4c8f"),
+ FANMADE("Wizaro (v0.1)", "abeec1eda6eaf8dbc52443ea97ff140c"),
+
+ { AD_TABLE_END_MARKER, 0, 0, 0, 0 }
+};
+
+/**
+ * The fallback game descriptor used by the AGI engine's fallbackDetector.
+ * Contents of this struct are to be overwritten by the fallbackDetector.
+ */
+static AGIGameDescription g_fallbackDesc = {
+ {
+ "",
+ "",
+ AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
+ Common::UNK_LANG,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_FANMADE,
+ GType_V2,
+ GF_FANMADE,
+ 0x2917,
+};
+
+} // End of namespace Agi
diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp
index 2bea49a807..62bcd5d8d8 100644
--- a/engines/agi/keyboard.cpp
+++ b/engines/agi/keyboard.cpp
@@ -104,10 +104,10 @@ int AgiEngine::handleController(int key) {
VtEntry *v = &_game.viewTable[0];
int i;
- // AGI 3.149 games and The Black Cauldron need KEY_ESCAPE to use menus
+ // AGI 3.149 games, The Black Cauldron and King's Quest 4 need KEY_ESCAPE to use menus
// Games with the GF_ESCPAUSE flag need KEY_ESCAPE to pause the game
if (key == 0 ||
- (key == KEY_ESCAPE && getVersion() != 0x3149 && getGameID() != GID_BC && !(getFeatures() & GF_ESCPAUSE)) )
+ (key == KEY_ESCAPE && getVersion() != 0x3149 && getGameID() != GID_BC && getGameID() != GID_KQ4 && !(getFeatures() & GF_ESCPAUSE)) )
return false;
if ((getGameID() == GID_MH1 || getGameID() == GID_MH2) && (key == KEY_ENTER) &&
@@ -121,7 +121,7 @@ int AgiEngine::handleController(int key) {
if (_game.controllers[i].keycode == key) {
debugC(3, kDebugLevelInput, "event %d: key press", _game.controllers[i].controller);
_game.controllerOccured[_game.controllers[i].controller] = true;
- report("event AC:%i occured\n", _game.controllers[i].controller);
+ report("event AC:%i occurred\n", _game.controllers[i].controller);
return true;
}
}
@@ -191,9 +191,8 @@ int AgiEngine::handleController(int key) {
}
}
- v->flags &= ~ADJ_EGO_XY;
-
if (d || key == KEY_STATIONARY) {
+ v->flags &= ~ADJ_EGO_XY;
v->direction = v->direction == d ? 0 : d;
return true;
}
@@ -320,7 +319,7 @@ void AgiEngine::handleKeys(int key) {
// Clear to start a new line
_game.hasPrompt = 0;
_game.inputBuffer[_game.cursorPos = 0] = 0;
- debugC(3, kDebugLevelInput, "clear lines");
+ debugC(3, kDebugLevelInput | kDebugLevelText, "clear lines");
clearLines(l, l + 1, bg);
flushLines(l, l + 1);
#ifdef __DS__
diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp
index 3d1c4fa2cf..de6f8d0653 100644
--- a/engines/agi/loader_v2.cpp
+++ b/engines/agi/loader_v2.cpp
@@ -232,7 +232,7 @@ int AgiLoader_v2::loadResource(int t, int n) {
if (data != NULL) {
// Freeing of the raw resource from memory is delegated to the createFromRawResource-function
- _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound);
+ _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound, _vm->_soundemu);
_vm->_game.dirSound[n].flags |= RES_LOADED;
} else {
ec = errBadResource;
diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp
index cd97c44521..f145140768 100644
--- a/engines/agi/loader_v3.cpp
+++ b/engines/agi/loader_v3.cpp
@@ -227,19 +227,12 @@ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) {
compBuffer = (uint8 *)calloc(1, agid->clen + 32);
fp.read(compBuffer, agid->clen);
- if (x[2] & 0x80 || agid->len == agid->clen) {
+ if (x[2] & 0x80) { // compressed pic
+ data = _vm->_picture->convertV3Pic(compBuffer, agid->clen);
+ // compBuffer has been freed inside convertV3Pic()
+ } else if (agid->len == agid->clen) {
// do not decompress
data = compBuffer;
-
-#if 0
- // CM: added to avoid problems in
- // convert_v2_v3_pic() when clen > len
- // e.g. Sierra demo 4, first picture
- // (Tue Mar 16 13:13:43 EST 1999)
- agid->len = agid->clen;
-
- // Now removed to fix Gold Rush! in demo4
-#endif
} else {
// it is compressed
data = (uint8 *)calloc(1, agid->len + 32);
@@ -309,7 +302,6 @@ int AgiLoader_v3::loadResource(int t, int n) {
unloadResource(rPICTURE, n);
data = loadVolRes(&_vm->_game.dirPic[n]);
if (data != NULL) {
- data = _vm->_picture->convertV3Pic(data, _vm->_game.dirPic[n].len);
_vm->_game.pictures[n].rdata = data;
_vm->_game.dirPic[n].flags |= RES_LOADED;
} else {
@@ -324,7 +316,7 @@ int AgiLoader_v3::loadResource(int t, int n) {
data = loadVolRes(&_vm->_game.dirSound[n]);
if (data != NULL) {
// Freeing of the raw resource from memory is delegated to the createFromRawResource-function
- _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound);
+ _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound, _vm->_soundemu);
_vm->_game.dirSound[n].flags |= RES_LOADED;
} else {
ec = errBadResource;
diff --git a/engines/agi/module.mk b/engines/agi/module.mk
index f031834c9d..2339d1019f 100644
--- a/engines/agi/module.mk
+++ b/engines/agi/module.mk
@@ -30,6 +30,11 @@ MODULE_OBJS := \
predictive.o \
saveload.o \
sound.o \
+ sound_2gs.o \
+ sound_coco3.o \
+ sound_midi.o \
+ sound_pcjr.o \
+ sound_sarien.o \
sprite.o \
text.o \
view.o \
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index d7e3ba416c..a60080186c 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -43,221 +43,201 @@ namespace Agi {
#define p5 (p[5])
#define p6 (p[6])
-#define game g_agi->_game
-#define g_sprites g_agi->_sprites
-#define g_sound g_agi->_sound
-#define g_gfx g_agi->_gfx
-#define g_picture g_agi->_picture
+#define ip _curLogic->cIP
+#define vt _game.viewTable[p0]
+#define vt_v _game.viewTable[_game.vars[p0]]
-#define ip curLogic->cIP
-#define vt game.viewTable[p0]
-#define vt_v game.viewTable[game.vars[p0]]
+#define _v _game.vars
-static struct AgiLogic *curLogic;
-
-int timerHack; // Workaround for timer loop in MH1
-
-#define _v game.vars
-#define cmd(x) static void cmd_##x (AgiEngine *g_agi, uint8 *p)
-
-cmd(increment) {
+void AgiEngine::cmd_increment(uint8 *p) {
if (_v[p0] != 0xff)
++_v[p0];
}
-cmd(decrement) {
+void AgiEngine::cmd_decrement(uint8 *p) {
if (_v[p0] != 0)
--_v[p0];
}
-cmd(assignn) {
+void AgiEngine::cmd_assignn(uint8 *p) {
_v[p0] = p1;
- // WORKAROUND for a bug in fan game "Get outta SQ"
+ // WORKAROUND for a bug in fan _game "Get outta SQ"
// Total number of points is stored in variable 7, which
- // is then incorrectly assigned to 0. Thus, when the game
+ // is then incorrectly assigned to 0. Thus, when the _game
// is restarted, "Points 0 of 0" is shown. We set the
// variable to the correct value here
// Fixes bug #1942476 - "AGI: Fan(Get Outta SQ) - Score
// is lost on restart"
- if (g_agi->getGameID() == GID_GETOUTTASQ && p0 == 7)
+ if (getGameID() == GID_GETOUTTASQ && p0 == 7)
_v[p0] = 8;
}
-cmd(addn) {
+void AgiEngine::cmd_addn(uint8 *p) {
_v[p0] += p1;
}
-cmd(subn) {
+void AgiEngine::cmd_subn(uint8 *p) {
_v[p0] -= p1;
}
-cmd(assignv) {
+void AgiEngine::cmd_assignv(uint8 *p) {
_v[p0] = _v[p1];
}
-cmd(addv) {
+void AgiEngine::cmd_addv(uint8 *p) {
_v[p0] += _v[p1];
}
-cmd(subv) {
+void AgiEngine::cmd_subv(uint8 *p) {
_v[p0] -= _v[p1];
}
-cmd(mul_n) {
+void AgiEngine::cmd_mul_n(uint8 *p) {
_v[p0] *= p1;
}
-cmd(mul_v) {
+void AgiEngine::cmd_mul_v(uint8 *p) {
_v[p0] *= _v[p1];
}
-cmd(div_n) {
+void AgiEngine::cmd_div_n(uint8 *p) {
_v[p0] /= p1;
}
-cmd(div_v) {
+void AgiEngine::cmd_div_v(uint8 *p) {
_v[p0] /= _v[p1];
}
-cmd(random) {
- _v[p2] = g_agi->_rnd->getRandomNumber(p1 - p0) + p0;
+void AgiEngine::cmd_random(uint8 *p) {
+ _v[p2] = _rnd->getRandomNumber(p1 - p0) + p0;
}
-cmd(lindirectn) {
+void AgiEngine::cmd_lindirectn(uint8 *p) {
_v[_v[p0]] = p1;
}
-cmd(lindirectv) {
+void AgiEngine::cmd_lindirectv(uint8 *p) {
_v[_v[p0]] = _v[p1];
}
-cmd(rindirect) {
+void AgiEngine::cmd_rindirect(uint8 *p) {
_v[p0] = _v[_v[p1]];
}
-cmd(set) {
- g_agi->setflag(*p, true);
+void AgiEngine::cmd_set(uint8 *p) {
+ setflag(*p, true);
}
-cmd(reset) {
- g_agi->setflag(*p, false);
+void AgiEngine::cmd_reset(uint8 *p) {
+ setflag(*p, false);
}
-cmd(toggle) {
- g_agi->setflag(*p, !g_agi->getflag(*p));
+void AgiEngine::cmd_toggle(uint8 *p) {
+ setflag(*p, !getflag(*p));
}
-cmd(set_v) {
- g_agi->setflag(_v[p0], true);
+void AgiEngine::cmd_set_v(uint8 *p) {
+ setflag(_v[p0], true);
}
-cmd(reset_v) {
- g_agi->setflag(_v[p0], false);
+void AgiEngine::cmd_reset_v(uint8 *p) {
+ setflag(_v[p0], false);
}
-cmd(toggle_v) {
- g_agi->setflag(_v[p0], !g_agi->getflag(_v[p0]));
+void AgiEngine::cmd_toggle_v(uint8 *p) {
+ setflag(_v[p0], !getflag(_v[p0]));
}
-cmd(new_room) {
- g_agi->newRoom(p0);
+void AgiEngine::cmd_new_room(uint8 *p) {
+ newRoom(p0);
// WORKAROUND: Works around intro skipping bug (#1737343) in Gold Rush.
// Intro was skipped because the enter-keypress finalizing the entering
// of the copy protection string (Copy protection is in logic.128) was
// left over to the intro scene (Starts with room 73 i.e. logic.073).
// The intro scene checks for any keys pressed and if it finds any it
- // jumps to the game's start (Room 1 i.e. logic.001). We clear the
+ // jumps to the _game's start (Room 1 i.e. logic.001). We clear the
// keyboard buffer when the intro sequence's first room (Room 73) is
// loaded so that no keys from the copy protection scene can be left
- // over to cause the intro to skip to the game's start.
- if (g_agi->getGameID() == GID_GOLDRUSH && p0 == 73)
- game.keypress = 0;
+ // over to cause the intro to skip to the _game's start.
+ if (getGameID() == GID_GOLDRUSH && p0 == 73)
+ _game.keypress = 0;
}
-cmd(new_room_f) {
- g_agi->newRoom(_v[p0]);
+void AgiEngine::cmd_new_room_f(uint8 *p) {
+ newRoom(_v[p0]);
}
-cmd(load_view) {
- g_agi->agiLoadResource(rVIEW, p0);
+void AgiEngine::cmd_load_view(uint8 *p) {
+ agiLoadResource(rVIEW, p0);
}
-cmd(load_logic) {
- g_agi->agiLoadResource(rLOGIC, p0);
+void AgiEngine::cmd_load_logic(uint8 *p) {
+ agiLoadResource(rLOGIC, p0);
}
-cmd(load_sound) {
- g_agi->agiLoadResource(rSOUND, p0);
+void AgiEngine::cmd_load_sound(uint8 *p) {
+ agiLoadResource(rSOUND, p0);
}
-cmd(load_view_f) {
- g_agi->agiLoadResource(rVIEW, _v[p0]);
+void AgiEngine::cmd_load_view_f(uint8 *p) {
+ agiLoadResource(rVIEW, _v[p0]);
}
-cmd(load_logic_f) {
- g_agi->agiLoadResource(rLOGIC, _v[p0]);
+void AgiEngine::cmd_load_logic_f(uint8 *p) {
+ agiLoadResource(rLOGIC, _v[p0]);
}
-cmd(discard_view) {
- g_agi->agiUnloadResource(rVIEW, p0);
+void AgiEngine::cmd_discard_view(uint8 *p) {
+ agiUnloadResource(rVIEW, p0);
}
-cmd(object_on_anything) {
+void AgiEngine::cmd_object_on_anything(uint8 *p) {
vt.flags &= ~(ON_WATER | ON_LAND);
}
-cmd(object_on_land) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
+void AgiEngine::cmd_object_on_land(uint8 *p) {
vt.flags |= ON_LAND;
}
-cmd(object_on_water) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
+void AgiEngine::cmd_object_on_water(uint8 *p) {
vt.flags |= ON_WATER;
}
-cmd(observe_horizon) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
+void AgiEngine::cmd_observe_horizon(uint8 *p) {
vt.flags &= ~IGNORE_HORIZON;
}
-cmd(ignore_horizon) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
+void AgiEngine::cmd_ignore_horizon(uint8 *p) {
vt.flags |= IGNORE_HORIZON;
}
-cmd(observe_objs) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
+void AgiEngine::cmd_observe_objs(uint8 *p) {
vt.flags &= ~IGNORE_OBJECTS;
}
-cmd(ignore_objs) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
+void AgiEngine::cmd_ignore_objs(uint8 *p) {
vt.flags |= IGNORE_OBJECTS;
}
-cmd(observe_blocks) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
+void AgiEngine::cmd_observe_blocks(uint8 *p) {
vt.flags &= ~IGNORE_BLOCKS;
}
-cmd(ignore_blocks) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
+void AgiEngine::cmd_ignore_blocks(uint8 *p) {
vt.flags |= IGNORE_BLOCKS;
}
-cmd(set_horizon) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
- game.horizon = p0;
+void AgiEngine::cmd_set_horizon(uint8 *p) {
+ _game.horizon = p0;
}
-cmd(get_priority) {
+void AgiEngine::cmd_get_priority(uint8 *p) {
_v[p1] = vt.priority;
}
-cmd(set_priority) {
+void AgiEngine::cmd_set_priority(uint8 *p) {
vt.flags |= FIXED_PRIORITY;
vt.priority = p1;
@@ -268,259 +248,256 @@ cmd(set_priority) {
// It seems that in this scene, ego's priority is set to 8, but the priority of
// the last dwarf with the soup bowls (view 152) is also set to 8, which causes
// the dwarf to be drawn behind ego
- // With this workaround, when the game scripts set the priority of view 152
+ // With this workaround, when the _game scripts set the priority of view 152
// (seventh dwarf with soup bowls), ego's priority is set to 7
- // The game script itself sets priotity 8 for ego before she starts walking,
+ // The _game script itself sets priotity 8 for ego before she starts walking,
// and then releases the fixed priority set on ego after ego is seated
// Therefore, this workaround only affects that specific part of this scene
// Ego is set to object 19 by script 54
- if (g_agi->getGameID() == GID_KQ4 && vt.currentView == 152) {
- game.viewTable[19].flags |= FIXED_PRIORITY;
- game.viewTable[19].priority = 7;
+ if (getGameID() == GID_KQ4 && vt.currentView == 152) {
+ _game.viewTable[19].flags |= FIXED_PRIORITY;
+ _game.viewTable[19].priority = 7;
}
}
-cmd(set_priority_f) {
+void AgiEngine::cmd_set_priority_f(uint8 *p) {
vt.flags |= FIXED_PRIORITY;
vt.priority = _v[p1];
}
-cmd(release_priority) {
+void AgiEngine::cmd_release_priority(uint8 *p) {
vt.flags &= ~FIXED_PRIORITY;
}
-cmd(set_upper_left) { // do nothing (AGI 2.917)
+void AgiEngine::cmd_set_upper_left(uint8 *p) { // do nothing (AGI 2.917)
}
-cmd(start_update) {
- g_agi->startUpdate(&vt);
+void AgiEngine::cmd_start_update(uint8 *p) {
+ startUpdate(&vt);
}
-cmd(stop_update) {
- g_agi->stopUpdate(&vt);
+void AgiEngine::cmd_stop_update(uint8 *p) {
+ stopUpdate(&vt);
}
-cmd(current_view) {
+void AgiEngine::cmd_current_view(uint8 *p) {
_v[p1] = vt.currentView;
}
-cmd(current_cel) {
+void AgiEngine::cmd_current_cel(uint8 *p) {
_v[p1] = vt.currentCel;
debugC(4, kDebugLevelScripts, "v%d=%d", p1, _v[p1]);
}
-cmd(current_loop) {
+void AgiEngine::cmd_current_loop(uint8 *p) {
_v[p1] = vt.currentLoop;
}
-cmd(last_cel) {
+void AgiEngine::cmd_last_cel(uint8 *p) {
_v[p1] = vt.loopData->numCels - 1;
}
-cmd(set_cel) {
- g_agi->setCel(&vt, p1);
+void AgiEngine::cmd_set_cel(uint8 *p) {
+ setCel(&vt, p1);
vt.flags &= ~DONTUPDATE;
}
-cmd(set_cel_f) {
- g_agi->setCel(&vt, _v[p1]);
+void AgiEngine::cmd_set_cel_f(uint8 *p) {
+ setCel(&vt, _v[p1]);
vt.flags &= ~DONTUPDATE;
}
-cmd(set_view) {
- debugC(4, kDebugLevelScripts, "o%d, %d", p0, p1);
- g_agi->setView(&vt, p1);
+void AgiEngine::cmd_set_view(uint8 *p) {
+ setView(&vt, p1);
}
-cmd(set_view_f) {
- g_agi->setView(&vt, _v[p1]);
+void AgiEngine::cmd_set_view_f(uint8 *p) {
+ setView(&vt, _v[p1]);
}
-cmd(set_loop) {
- g_agi->setLoop(&vt, p1);
+void AgiEngine::cmd_set_loop(uint8 *p) {
+ setLoop(&vt, p1);
}
-cmd(set_loop_f) {
- g_agi->setLoop(&vt, _v[p1]);
+void AgiEngine::cmd_set_loop_f(uint8 *p) {
+ setLoop(&vt, _v[p1]);
}
-cmd(number_of_loops) {
+void AgiEngine::cmd_number_of_loops(uint8 *p) {
_v[p1] = vt.numLoops;
}
-cmd(fix_loop) {
+void AgiEngine::cmd_fix_loop(uint8 *p) {
vt.flags |= FIX_LOOP;
}
-cmd(release_loop) {
+void AgiEngine::cmd_release_loop(uint8 *p) {
vt.flags &= ~FIX_LOOP;
}
-cmd(step_size) {
+void AgiEngine::cmd_step_size(uint8 *p) {
vt.stepSize = _v[p1];
}
-cmd(step_time) {
+void AgiEngine::cmd_step_time(uint8 *p) {
vt.stepTime = vt.stepTimeCount = _v[p1];
}
-cmd(cycle_time) {
+void AgiEngine::cmd_cycle_time(uint8 *p) {
vt.cycleTime = vt.cycleTimeCount = _v[p1];
}
-cmd(stop_cycling) {
+void AgiEngine::cmd_stop_cycling(uint8 *p) {
vt.flags &= ~CYCLING;
}
-cmd(start_cycling) {
+void AgiEngine::cmd_start_cycling(uint8 *p) {
vt.flags |= CYCLING;
}
-cmd(normal_cycle) {
+void AgiEngine::cmd_normal_cycle(uint8 *p) {
vt.cycle = CYCLE_NORMAL;
vt.flags |= CYCLING;
}
-cmd(reverse_cycle) {
+void AgiEngine::cmd_reverse_cycle(uint8 *p) {
vt.cycle = CYCLE_REVERSE;
vt.flags |= CYCLING;
}
-cmd(set_dir) {
+void AgiEngine::cmd_set_dir(uint8 *p) {
vt.direction = _v[p1];
}
-cmd(get_dir) {
+void AgiEngine::cmd_get_dir(uint8 *p) {
_v[p1] = vt.direction;
}
-cmd(get_room_f) {
- _v[p1] = g_agi->objectGetLocation(_v[p0]);
+void AgiEngine::cmd_get_room_f(uint8 *p) {
+ _v[p1] = objectGetLocation(_v[p0]);
}
-cmd(put) {
- g_agi->objectSetLocation(p0, _v[p1]);
+void AgiEngine::cmd_put(uint8 *p) {
+ objectSetLocation(p0, _v[p1]);
}
-cmd(put_f) {
- g_agi->objectSetLocation(_v[p0], _v[p1]);
+void AgiEngine::cmd_put_f(uint8 *p) {
+ objectSetLocation(_v[p0], _v[p1]);
}
-cmd(drop) {
- g_agi->objectSetLocation(p0, 0);
+void AgiEngine::cmd_drop(uint8 *p) {
+ objectSetLocation(p0, 0);
}
-cmd(get) {
- g_agi->objectSetLocation(p0, EGO_OWNED);
+void AgiEngine::cmd_get(uint8 *p) {
+ objectSetLocation(p0, EGO_OWNED);
}
-cmd(get_f) {
- g_agi->objectSetLocation(_v[p0], EGO_OWNED);
+void AgiEngine::cmd_get_f(uint8 *p) {
+ objectSetLocation(_v[p0], EGO_OWNED);
}
-cmd(word_to_string) {
- strcpy(game.strings[p0], game.egoWords[p1].word);
+void AgiEngine::cmd_word_to_string(uint8 *p) {
+ strcpy(_game.strings[p0], _game.egoWords[p1].word);
}
-cmd(open_dialogue) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
- game.hasWindow = true;
+void AgiEngine::cmd_open_dialogue(uint8 *p) {
+ _game.hasWindow = true;
}
-cmd(close_dialogue) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
- game.hasWindow = false;
+void AgiEngine::cmd_close_dialogue(uint8 *p) {
+ _game.hasWindow = false;
}
-cmd(close_window) {
- g_agi->closeWindow();
+void AgiEngine::cmd_close_window(uint8 *p) {
+ closeWindow();
}
-cmd(status_line_on) {
- game.statusLine = true;
- g_agi->writeStatus();
+void AgiEngine::cmd_status_line_on(uint8 *p) {
+ _game.statusLine = true;
+ writeStatus();
}
-cmd(status_line_off) {
- game.statusLine = false;
- g_agi->writeStatus();
+void AgiEngine::cmd_status_line_off(uint8 *p) {
+ _game.statusLine = false;
+ writeStatus();
}
-cmd(show_obj) {
- g_sprites->showObj(p0);
+void AgiEngine::cmd_show_obj(uint8 *p) {
+ _sprites->showObj(p0);
}
-cmd(show_obj_v) {
- g_sprites->showObj(_v[p0]);
+void AgiEngine::cmd_show_obj_v(uint8 *p) {
+ _sprites->showObj(_v[p0]);
}
-cmd(sound) {
- g_sound->startSound(p0, p1);
+void AgiEngine::cmd_sound(uint8 *p) {
+ _sound->startSound(p0, p1);
}
-cmd(stop_sound) {
- g_sound->stopSound();
+void AgiEngine::cmd_stop_sound(uint8 *p) {
+ _sound->stopSound();
}
-cmd(menu_input) {
- g_agi->newInputMode(INPUT_MENU);
+void AgiEngine::cmd_menu_input(uint8 *p) {
+ newInputMode(INPUT_MENU);
}
-cmd(enable_item) {
- g_agi->_menu->setItem(p0, true);
+void AgiEngine::cmd_enable_item(uint8 *p) {
+ _menu->setItem(p0, true);
}
-cmd(disable_item) {
- g_agi->_menu->setItem(p0, false);
+void AgiEngine::cmd_disable_item(uint8 *p) {
+ _menu->setItem(p0, false);
}
-cmd(submit_menu) {
- g_agi->_menu->submit();
+void AgiEngine::cmd_submit_menu(uint8 *p) {
+ _menu->submit();
}
-cmd(set_scan_start) {
- curLogic->sIP = curLogic->cIP;
+void AgiEngine::cmd_set_scan_start(uint8 *p) {
+ _curLogic->sIP = _curLogic->cIP;
}
-cmd(reset_scan_start) {
- curLogic->sIP = 2;
+void AgiEngine::cmd_reset_scan_start(uint8 *p) {
+ _curLogic->sIP = 2;
}
-cmd(save_game) {
- game.simpleSave ? g_agi->saveGameSimple() : g_agi->saveGameDialog();
+void AgiEngine::cmd_save_game(uint8 *p) {
+ _game.simpleSave ? saveGameSimple() : saveGameDialog();
}
-cmd(load_game) {
+void AgiEngine::cmd_load_game(uint8 *p) {
assert(1);
- game.simpleSave ? g_agi->loadGameSimple() : g_agi->loadGameDialog();
+ _game.simpleSave ? loadGameSimple() : loadGameDialog();
}
-cmd(init_disk) { // do nothing
+void AgiEngine::cmd_init_disk(uint8 *p) { // do nothing
}
-cmd(log) { // do nothing
+void AgiEngine::cmd_log(uint8 *p) { // do nothing
}
-cmd(trace_on) { // do nothing
+void AgiEngine::cmd_trace_on(uint8 *p) { // do nothing
}
-cmd(trace_info) { // do nothing
+void AgiEngine::cmd_trace_info(uint8 *p) { // do nothing
}
-cmd(show_mem) {
- g_agi->messageBox("Enough memory");
+void AgiEngine::cmd_show_mem(uint8 *p) {
+ messageBox("Enough memory");
}
-cmd(init_joy) { // do nothing
+void AgiEngine::cmd_init_joy(uint8 *p) { // do nothing
}
-cmd(script_size) {
+void AgiEngine::cmd_script_size(uint8 *p) {
report("script.size(%d)\n", p0);
}
-cmd(cancel_line) {
- g_agi->_game.inputBuffer[0] = 0;
- g_agi->writePrompt();
+void AgiEngine::cmd_cancel_line(uint8 *p) {
+ _game.inputBuffer[0] = 0;
+ writePrompt();
}
// This implementation is based on observations of Amiga's Gold Rush.
@@ -533,7 +510,7 @@ cmd(cancel_line) {
// 4051 (When ego is stationary),
// 471 (When walking on the first screen's bridge),
// 71 (When walking around, using the mouse or the keyboard).
-cmd(obj_status_f) {
+void AgiEngine::cmd_obj_status_f(uint8 *p) {
const char *cycleDesc; // Object's cycle description line
const char *motionDesc; // Object's motion description line
char msg[256]; // The whole object status message
@@ -594,7 +571,7 @@ cmd(obj_status_f) {
vt_v.stepSize,
cycleDesc,
motionDesc);
- g_agi->messageBox(msg);
+ messageBox(msg);
}
// unknown commands:
@@ -605,49 +582,49 @@ cmd(obj_status_f) {
// unk_174: Change priority table (used in KQ4) -- j5
// unk_177: Disable menus completely -- j5
// unk_181: Deactivate keypressed control (default control of ego)
-cmd(set_simple) {
- if (!(g_agi->getFeatures() & (GF_AGI256 | GF_AGI256_2))) {
- game.simpleSave = true;
+void AgiEngine::cmd_set_simple(uint8 *p) {
+ if (!(getFeatures() & (GF_AGI256 | GF_AGI256_2))) {
+ _game.simpleSave = true;
} else { // AGI256 and AGI256-2 use this unknown170 command to load 256 color pictures.
- // Load the picture. Similar to cmd(load_pic).
- g_sprites->eraseBoth();
- g_agi->agiLoadResource(rPICTURE, _v[p0]);
+ // Load the picture. Similar to void AgiEngine::cmd_load_pic(uint8 *p).
+ _sprites->eraseBoth();
+ agiLoadResource(rPICTURE, _v[p0]);
- // Draw the picture. Similar to cmd(draw_pic).
- g_picture->decodePicture(_v[p0], false, true);
- g_sprites->blitBoth();
- game.pictureShown = 0;
+ // Draw the picture. Similar to void AgiEngine::cmd_draw_pic(uint8 *p).
+ _picture->decodePicture(_v[p0], false, true);
+ _sprites->blitBoth();
+ _game.pictureShown = 0;
- // Show the picture. Similar to cmd(show_pic).
- g_agi->setflag(fOutputMode, false);
- cmd_close_window(g_agi, NULL);
- g_picture->showPic();
- game.pictureShown = 1;
+ // Show the picture. Similar to void AgiEngine::cmd_show_pic(uint8 *p).
+ setflag(fOutputMode, false);
+ closeWindow();
+ _picture->showPic();
+ _game.pictureShown = 1;
// Simulate slowww computer. Many effects rely on this
- g_agi->pause(kPausePicture);
+ pause(kPausePicture);
}
}
-cmd(pop_script) {
- if (g_agi->getVersion() >= 0x2915) {
+void AgiEngine::cmd_pop_script(uint8 *p) {
+ if (getVersion() >= 0x2915) {
report("pop.script\n");
}
}
-cmd(hold_key) {
- if (g_agi->getVersion() >= 0x3098) {
- g_agi->_egoHoldKey = true;
+void AgiEngine::cmd_hold_key(uint8 *p) {
+ if (getVersion() >= 0x3098) {
+ _egoHoldKey = true;
}
}
-cmd(discard_sound) {
- if (g_agi->getVersion() >= 0x2936) {
+void AgiEngine::cmd_discard_sound(uint8 *p) {
+ if (getVersion() >= 0x2936) {
report("discard.sound\n");
}
}
-cmd(hide_mouse) {
+void AgiEngine::cmd_hide_mouse(uint8 *p) {
// WORKAROUND: Turns off current movement that's being caused with the mouse.
// This fixes problems with too many popup boxes appearing in the Amiga
// Gold Rush's copy protection failure scene (i.e. the hanging scene, logic.192).
@@ -655,34 +632,34 @@ cmd(hide_mouse) {
// to walk somewhere else than to the right using the mouse.
// FIXME: Write a proper implementation using disassembly and
// apply it to other games as well if applicable.
- game.viewTable[0].flags &= ~ADJ_EGO_XY;
+ _game.viewTable[0].flags &= ~ADJ_EGO_XY;
g_system->showMouse(false);
}
-cmd(allow_menu) {
- if (g_agi->getVersion() >= 0x3098) {
- g_agi->setflag(fMenusWork, ((p0 != 0) ? true : false));
+void AgiEngine::cmd_allow_menu(uint8 *p) {
+ if (getVersion() >= 0x3098) {
+ setflag(fMenusWork, ((p0 != 0) ? true : false));
}
}
-cmd(show_mouse) {
+void AgiEngine::cmd_show_mouse(uint8 *p) {
g_system->showMouse(true);
}
-cmd(fence_mouse) {
- g_agi->_game.mouseFence.moveTo(p0, p1);
- g_agi->_game.mouseFence.setWidth(p2 - p0);
- g_agi->_game.mouseFence.setHeight(p3 - p1);
+void AgiEngine::cmd_fence_mouse(uint8 *p) {
+ _game.mouseFence.moveTo(p0, p1);
+ _game.mouseFence.setWidth(p2 - p0);
+ _game.mouseFence.setHeight(p3 - p1);
}
-cmd(release_key) {
- if (g_agi->getVersion() >= 0x3098) {
- g_agi->_egoHoldKey = false;
+void AgiEngine::cmd_release_key(uint8 *p) {
+ if (getVersion() >= 0x3098) {
+ _egoHoldKey = false;
}
}
-cmd(adj_ego_move_to_x_y) {
+void AgiEngine::cmd_adj_ego_move_to_x_y(uint8 *p) {
int8 x, y;
switch (logicNamesCmd[182].numArgs) {
@@ -704,56 +681,57 @@ cmd(adj_ego_move_to_x_y) {
// onto the ladder so this is more like it (Although that may be caused
// by something else because this command doesn't do any flag manipulations
// in the Amiga version - checked it with disassembly).
- if (x != game.adjMouseX || y != game.adjMouseY)
- game.viewTable[EGO_VIEW_TABLE].flags &= ~ADJ_EGO_XY;
+ if (x != _game.adjMouseX || y != _game.adjMouseY)
+ _game.viewTable[EGO_VIEW_TABLE].flags &= ~ADJ_EGO_XY;
- game.adjMouseX = x;
- game.adjMouseY = y;
+ _game.adjMouseX = x;
+ _game.adjMouseY = y;
debugC(4, kDebugLevelScripts, "adj.ego.move.to.x.y(%d, %d)", x, y);
break;
// TODO: Check where (if anywhere) the 0 arguments version is used
case 0:
default:
- game.viewTable[0].flags |= ADJ_EGO_XY;
+ _game.viewTable[0].flags |= ADJ_EGO_XY;
break;
}
}
-cmd(parse) {
+void AgiEngine::cmd_parse(uint8 *p) {
_v[vWordNotFound] = 0;
- g_agi->setflag(fEnteredCli, false);
- g_agi->setflag(fSaidAcceptedInput, false);
+ setflag(fEnteredCli, false);
+ setflag(fSaidAcceptedInput, false);
- g_agi->dictionaryWords(g_agi->agiSprintf(game.strings[p0]));
+ dictionaryWords(agiSprintf(_game.strings[p0]));
}
-cmd(call) {
+void AgiEngine::cmd_call(uint8 *p) {
int oldCIP;
int oldLognum;
// CM: we don't save sIP because set.scan.start can be
// used in a called script (fixes xmas demo)
- oldCIP = curLogic->cIP;
- oldLognum = game.lognum;
+ oldCIP = _curLogic->cIP;
+ oldLognum = _game.lognum;
- g_agi->runLogic(p0);
+ runLogic(p0);
- game.lognum = oldLognum;
- curLogic = &game.logics[game.lognum];
- curLogic->cIP = oldCIP;
+ _game.lognum = oldLognum;
+ _curLogic = &_game.logics[_game.lognum];
+ _curLogic->cIP = oldCIP;
}
-cmd(call_f) {
- cmd_call(g_agi, &_v[p0]);
+void AgiEngine::cmd_call_f(uint8 *p) {
+ cmd_call(&_v[p0]);
}
-cmd(draw_pic) {
+void AgiEngine::cmd_draw_pic(uint8 *p) {
debugC(6, kDebugLevelScripts, "=== draw pic %d ===", _v[p0]);
- g_sprites->eraseBoth();
- g_picture->decodePicture(_v[p0], true);
- g_sprites->blitBoth();
- game.pictureShown = 0;
+ _sprites->eraseBoth();
+ _picture->decodePicture(_v[p0], true);
+ _sprites->blitBoth();
+ _sprites->commitBoth();
+ _game.pictureShown = 0;
debugC(6, kDebugLevelScripts, "--- end of draw pic %d ---", _v[p0]);
// WORKAROUND for a script bug which exists in SQ1, logic scripts
@@ -768,63 +746,64 @@ cmd(draw_pic) {
// above the ground), flag 103 is reset, thereby fixing this issue. Note
// that this is a script bug and occurs in the original interpreter as well.
// Fixes bug #1658514: AGI: SQ1 (2.2 DOS ENG) bizzare exploding roger
- if (g_agi->getGameID() == GID_SQ1 && _v[p0] == 20)
- g_agi->setflag(103, false);
+ if (getGameID() == GID_SQ1 && _v[p0] == 20)
+ setflag(103, false);
// Simulate slowww computer. Many effects rely on this
- g_agi->pause(kPausePicture);
+ pause(kPausePicture);
}
-cmd(show_pic) {
+void AgiEngine::cmd_show_pic(uint8 *p) {
debugC(6, kDebugLevelScripts, "=== show pic ===");
- g_agi->setflag(fOutputMode, false);
- cmd_close_window(g_agi, NULL);
- g_picture->showPic();
- game.pictureShown = 1;
+ setflag(fOutputMode, false);
+ closeWindow();
+ _picture->showPic();
+ _game.pictureShown = 1;
debugC(6, kDebugLevelScripts, "--- end of show pic ---");
}
-cmd(load_pic) {
- g_sprites->eraseBoth();
- g_agi->agiLoadResource(rPICTURE, _v[p0]);
- g_sprites->blitBoth();
+void AgiEngine::cmd_load_pic(uint8 *p) {
+ _sprites->eraseBoth();
+ agiLoadResource(rPICTURE, _v[p0]);
+ _sprites->blitBoth();
+ _sprites->commitBoth();
}
-cmd(discard_pic) {
+void AgiEngine::cmd_discard_pic(uint8 *p) {
debugC(6, kDebugLevelScripts, "--- discard pic ---");
// do nothing
}
-cmd(overlay_pic) {
+void AgiEngine::cmd_overlay_pic(uint8 *p) {
debugC(6, kDebugLevelScripts, "--- overlay pic ---");
- g_sprites->eraseBoth();
- g_picture->decodePicture(_v[p0], false);
- g_sprites->blitBoth();
- game.pictureShown = 0;
- g_sprites->commitBoth();
+ _sprites->eraseBoth();
+ _picture->decodePicture(_v[p0], false);
+ _sprites->blitBoth();
+ _game.pictureShown = 0;
+ _sprites->commitBoth();
// Simulate slowww computer. Many effects rely on this
- g_agi->pause(kPausePicture);
+ pause(kPausePicture);
}
-cmd(show_pri_screen) {
- g_agi->_debug.priority = 1;
- g_sprites->eraseBoth();
- g_picture->showPic();
- g_sprites->blitBoth();
+void AgiEngine::cmd_show_pri_screen(uint8 *p) {
+ _debug.priority = 1;
+ _sprites->eraseBoth();
+ _picture->showPic();
+ _sprites->blitBoth();
- g_agi->waitKey();
+ waitKey();
- g_agi->_debug.priority = 0;
- g_sprites->eraseBoth();
- g_picture->showPic();
- g_sprites->blitBoth();
+ _debug.priority = 0;
+ _sprites->eraseBoth();
+ _picture->showPic();
+ _sprites->blitBoth();
}
-cmd(animate_obj) {
+void AgiEngine::cmd_animate_obj(uint8 *p) {
if (vt.flags & ANIMATED)
return;
@@ -835,14 +814,14 @@ cmd(animate_obj) {
vt.direction = 0;
}
-cmd(unanimate_all) {
+void AgiEngine::cmd_unanimate_all(uint8 *p) {
int i;
for (i = 0; i < MAX_VIEWTABLE; i++)
- game.viewTable[i].flags &= ~(ANIMATED | DRAWN);
+ _game.viewTable[i].flags &= ~(ANIMATED | DRAWN);
}
-cmd(draw) {
+void AgiEngine::cmd_draw(uint8 *p) {
if (vt.flags & DRAWN)
return;
@@ -852,19 +831,19 @@ cmd(draw) {
debugC(4, kDebugLevelScripts, "draw entry %d", vt.entry);
vt.flags |= UPDATE;
- if (g_agi->getVersion() >= 0x3000) {
- g_agi->setLoop(&vt, vt.currentLoop);
- g_agi->setCel(&vt, vt.currentCel);
+ if (getVersion() >= 0x3000) {
+ setLoop(&vt, vt.currentLoop);
+ setCel(&vt, vt.currentCel);
}
- g_agi->fixPosition(p0);
+ fixPosition(p0);
vt.xPos2 = vt.xPos;
vt.yPos2 = vt.yPos;
vt.celData2 = vt.celData;
- g_sprites->eraseUpdSprites();
+ _sprites->eraseUpdSprites();
vt.flags |= DRAWN;
- // WORKAROUND: This fixes a bug with AGI Fanmade game Space Trek.
+ // WORKAROUND: This fixes a bug with AGI Fanmade _game Space Trek.
// The original workaround checked if AGI version was <= 2.440, which could
// cause regressions with some AGI games. The original workaround no longer
// works for Space Trek in ScummVM, as all fanmade games are set to use
@@ -875,36 +854,43 @@ cmd(draw) {
// TODO: Investigate this further and check if any other fanmade AGI
// games are affected. If yes, then it'd be best to set this for Space
// Trek only
- if (g_agi->getFeatures() & GF_FANMADE) // See Sarien bug #546562
+ if (getFeatures() & GF_FANMADE) // See Sarien bug #546562
vt.flags |= ANIMATED;
- g_sprites->blitUpdSprites();
+ _sprites->blitUpdSprites();
vt.flags &= ~DONTUPDATE;
- g_sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos);
+ _sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos, true);
debugC(4, kDebugLevelScripts, "vt entry #%d flags = %02x", p0, vt.flags);
}
-cmd(erase) {
+void AgiEngine::cmd_erase(uint8 *p) {
if (~vt.flags & DRAWN)
return;
- g_sprites->eraseUpdSprites();
+ _sprites->eraseUpdSprites();
if (vt.flags & UPDATE) {
vt.flags &= ~DRAWN;
} else {
- g_sprites->eraseNonupdSprites();
+ _sprites->eraseNonupdSprites();
vt.flags &= ~DRAWN;
- g_sprites->blitNonupdSprites();
+ _sprites->blitNonupdSprites();
}
- g_sprites->blitUpdSprites();
+ _sprites->blitUpdSprites();
+
+ int x1, y1, x2, y2;
+
+ x1 = MIN((int)MIN(vt.xPos, vt.xPos2), MIN(vt.xPos + vt.celData->width, vt.xPos2 + vt.celData2->width));
+ x2 = MAX((int)MAX(vt.xPos, vt.xPos2), MAX(vt.xPos + vt.celData->width, vt.xPos2 + vt.celData2->width));
+ y1 = MIN((int)MIN(vt.yPos, vt.yPos2), MIN(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height));
+ y2 = MAX((int)MAX(vt.yPos, vt.yPos2), MAX(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height));
- g_sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos);
+ _sprites->commitBlock(x1, y1, x2, y2, true);
}
-cmd(position) {
+void AgiEngine::cmd_position(uint8 *p) {
vt.xPos = vt.xPos2 = p1;
vt.yPos = vt.yPos2 = p2;
@@ -921,27 +907,27 @@ cmd(position) {
// I haven't checked but if Space Trek solely abuses the position-command we wouldn't
// strictly need the identical workaround in the position.v-command but it does make
// for a nice symmetry.
- if (g_agi->getFeatures() & GF_CLIPCOORDS)
- g_agi->clipViewCoordinates(&vt);
+ if (getFeatures() & GF_CLIPCOORDS)
+ clipViewCoordinates(&vt);
}
-cmd(position_f) {
+void AgiEngine::cmd_position_f(uint8 *p) {
vt.xPos = vt.xPos2 = _v[p1];
vt.yPos = vt.yPos2 = _v[p2];
// WORKAROUND: Part of the fix for bug #1659209 "AGI: Space Trek sprite duplication"
// with an accompanying identical workaround in position-command (i.e. command 0x25).
// See that workaround's comment for more in-depth information.
- if (g_agi->getFeatures() & GF_CLIPCOORDS)
- g_agi->clipViewCoordinates(&vt);
+ if (getFeatures() & GF_CLIPCOORDS)
+ clipViewCoordinates(&vt);
}
-cmd(get_posn) {
- game.vars[p1] = (unsigned char)vt.xPos;
- game.vars[p2] = (unsigned char)vt.yPos;
+void AgiEngine::cmd_get_posn(uint8 *p) {
+ _game.vars[p1] = (unsigned char)vt.xPos;
+ _game.vars[p2] = (unsigned char)vt.yPos;
}
-cmd(reposition) {
+void AgiEngine::cmd_reposition(uint8 *p) {
int dx = (int8) _v[p1], dy = (int8) _v[p2];
debugC(4, kDebugLevelScripts, "dx=%d, dy=%d", dx, dy);
@@ -957,106 +943,106 @@ cmd(reposition) {
else
vt.yPos += dy;
- g_agi->fixPosition(p0);
+ fixPosition(p0);
}
-cmd(reposition_to) {
+void AgiEngine::cmd_reposition_to(uint8 *p) {
vt.xPos = p1;
vt.yPos = p2;
vt.flags |= UPDATE_POS;
- g_agi->fixPosition(p0);
+ fixPosition(p0);
}
-cmd(reposition_to_f) {
+void AgiEngine::cmd_reposition_to_f(uint8 *p) {
vt.xPos = _v[p1];
vt.yPos = _v[p2];
vt.flags |= UPDATE_POS;
- g_agi->fixPosition(p0);
+ fixPosition(p0);
}
-cmd(add_to_pic) {
- g_sprites->addToPic(p0, p1, p2, p3, p4, p5, p6);
+void AgiEngine::cmd_add_to_pic(uint8 *p) {
+ _sprites->addToPic(p0, p1, p2, p3, p4, p5, p6);
}
-cmd(add_to_pic_f) {
- g_sprites->addToPic(_v[p0], _v[p1], _v[p2], _v[p3], _v[p4], _v[p5], _v[p6]);
+void AgiEngine::cmd_add_to_pic_f(uint8 *p) {
+ _sprites->addToPic(_v[p0], _v[p1], _v[p2], _v[p3], _v[p4], _v[p5], _v[p6]);
}
-cmd(force_update) {
- g_sprites->eraseBoth();
- g_sprites->blitBoth();
- g_sprites->commitBoth();
+void AgiEngine::cmd_force_update(uint8 *p) {
+ _sprites->eraseBoth();
+ _sprites->blitBoth();
+ _sprites->commitBoth();
}
-cmd(reverse_loop) {
+void AgiEngine::cmd_reverse_loop(uint8 *p) {
debugC(4, kDebugLevelScripts, "o%d, f%d", p0, p1);
vt.cycle = CYCLE_REV_LOOP;
vt.flags |= (DONTUPDATE | UPDATE | CYCLING);
vt.parm1 = p1;
- g_agi->setflag(p1, false);
+ setflag(p1, false);
}
-cmd(end_of_loop) {
+void AgiEngine::cmd_end_of_loop(uint8 *p) {
debugC(4, kDebugLevelScripts, "o%d, f%d", p0, p1);
vt.cycle = CYCLE_END_OF_LOOP;
vt.flags |= (DONTUPDATE | UPDATE | CYCLING);
vt.parm1 = p1;
- g_agi->setflag(p1, false);
+ setflag(p1, false);
}
-cmd(block) {
+void AgiEngine::cmd_block(uint8 *p) {
debugC(4, kDebugLevelScripts, "x1=%d, y1=%d, x2=%d, y2=%d", p0, p1, p2, p3);
- game.block.active = true;
- game.block.x1 = p0;
- game.block.y1 = p1;
- game.block.x2 = p2;
- game.block.y2 = p3;
+ _game.block.active = true;
+ _game.block.x1 = p0;
+ _game.block.y1 = p1;
+ _game.block.x2 = p2;
+ _game.block.y2 = p3;
}
-cmd(unblock) {
- game.block.active = false;
+void AgiEngine::cmd_unblock(uint8 *p) {
+ _game.block.active = false;
}
-cmd(normal_motion) {
+void AgiEngine::cmd_normal_motion(uint8 *p) {
vt.motion = MOTION_NORMAL;
}
-cmd(stop_motion) {
+void AgiEngine::cmd_stop_motion(uint8 *p) {
vt.direction = 0;
vt.motion = MOTION_NORMAL;
if (p0 == 0) { // ego only
_v[vEgoDir] = 0;
- game.playerControl = false;
+ _game.playerControl = false;
}
}
-cmd(start_motion) {
+void AgiEngine::cmd_start_motion(uint8 *p) {
vt.motion = MOTION_NORMAL;
if (p0 == 0) { // ego only
_v[vEgoDir] = 0;
- game.playerControl = true;
+ _game.playerControl = true;
}
}
-cmd(player_control) {
- game.playerControl = true;
- game.viewTable[0].motion = MOTION_NORMAL;
+void AgiEngine::cmd_player_control(uint8 *p) {
+ _game.playerControl = true;
+ _game.viewTable[0].motion = MOTION_NORMAL;
}
-cmd(program_control) {
- game.playerControl = false;
+void AgiEngine::cmd_program_control(uint8 *p) {
+ _game.playerControl = false;
}
-cmd(follow_ego) {
+void AgiEngine::cmd_follow_ego(uint8 *p) {
vt.motion = MOTION_FOLLOW_EGO;
vt.parm1 = p1 > vt.stepSize ? p1 : vt.stepSize;
vt.parm2 = p2;
vt.parm3 = 0xff;
- g_agi->setflag(p2, false);
+ setflag(p2, false);
vt.flags |= UPDATE;
}
-cmd(move_obj) {
+void AgiEngine::cmd_move_obj(uint8 *p) {
// _D (_D_WARN "o=%d, x=%d, y=%d, s=%d, f=%d", p0, p1, p2, p3, p4);
vt.motion = MOTION_MOVE_OBJ;
@@ -1068,18 +1054,18 @@ cmd(move_obj) {
if (p3 != 0)
vt.stepSize = p3;
- g_agi->setflag(p4, false);
+ setflag(p4, false);
vt.flags |= UPDATE;
if (p0 == 0)
- game.playerControl = false;
+ _game.playerControl = false;
// AGI 2.272 (ddp, xmas) doesn't call move_obj!
- if (g_agi->getVersion() > 0x2272)
- g_agi->moveObj(&vt);
+ if (getVersion() > 0x2272)
+ moveObj(&vt);
}
-cmd(move_obj_f) {
+void AgiEngine::cmd_move_obj_f(uint8 *p) {
vt.motion = MOTION_MOVE_OBJ;
vt.parm1 = _v[p1];
vt.parm2 = _v[p2];
@@ -1089,67 +1075,67 @@ cmd(move_obj_f) {
if (_v[p3] != 0)
vt.stepSize = _v[p3];
- g_agi->setflag(p4, false);
+ setflag(p4, false);
vt.flags |= UPDATE;
if (p0 == 0)
- game.playerControl = false;
+ _game.playerControl = false;
// AGI 2.272 (ddp, xmas) doesn't call move_obj!
- if (g_agi->getVersion() > 0x2272)
- g_agi->moveObj(&vt);
+ if (getVersion() > 0x2272)
+ moveObj(&vt);
}
-cmd(wander) {
+void AgiEngine::cmd_wander(uint8 *p) {
if (p0 == 0)
- game.playerControl = false;
+ _game.playerControl = false;
vt.motion = MOTION_WANDER;
vt.flags |= UPDATE;
}
-cmd(set_game_id) {
- if (curLogic->texts && (p0 - 1) <= curLogic->numTexts)
- strncpy(game.id, curLogic->texts[p0 - 1], 8);
+void AgiEngine::cmd_set_game_id(uint8 *p) {
+ if (_curLogic->texts && (p0 - 1) <= _curLogic->numTexts)
+ strncpy(_game.id, _curLogic->texts[p0 - 1], 8);
else
- game.id[0] = 0;
+ _game.id[0] = 0;
- report("Game ID: \"%s\"\n", game.id);
+ report("Game ID: \"%s\"\n", _game.id);
}
-cmd(pause) {
- int tmp = game.clockEnabled;
+void AgiEngine::cmd_pause(uint8 *p) {
+ int tmp = _game.clockEnabled;
const char *b[] = { "Continue", NULL };
const char *b_ru[] = { "\x8f\xe0\xae\xa4\xae\xab\xa6\xa8\xe2\xec", NULL };
- game.clockEnabled = false;
+ _game.clockEnabled = false;
- switch (g_agi->getLanguage()) {
+ switch (getLanguage()) {
case Common::RU_RUS:
- g_agi->selectionBox(" \x88\xa3\xe0\xa0 \xae\xe1\xe2\xa0\xad\xae\xa2\xab\xa5\xad\xa0. \n\n\n", b_ru);
+ selectionBox(" \x88\xa3\xe0\xa0 \xae\xe1\xe2\xa0\xad\xae\xa2\xab\xa5\xad\xa0. \n\n\n", b_ru);
break;
default:
- g_agi->selectionBox(" Game is paused. \n\n\n", b);
+ selectionBox(" Game is paused. \n\n\n", b);
break;
}
- game.clockEnabled = tmp;
+ _game.clockEnabled = tmp;
}
-cmd(set_menu) {
- debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, curLogic->numTexts);
+void AgiEngine::cmd_set_menu(uint8 *p) {
+ debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, _curLogic->numTexts);
- if (curLogic->texts != NULL && p0 <= curLogic->numTexts)
- g_agi->_menu->add(curLogic->texts[p0 - 1]);
+ if (_curLogic->texts != NULL && p0 <= _curLogic->numTexts)
+ _menu->add(_curLogic->texts[p0 - 1]);
}
-cmd(set_menu_item) {
- debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, curLogic->numTexts);
+void AgiEngine::cmd_set_menu_item(uint8 *p) {
+ debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, _curLogic->numTexts);
- if (curLogic->texts != NULL && p0 <= curLogic->numTexts)
- g_agi->_menu->addItem(curLogic->texts[p0 - 1], p1);
+ if (_curLogic->texts != NULL && p0 <= _curLogic->numTexts)
+ _menu->addItem(_curLogic->texts[p0 - 1], p1);
}
-cmd(version) {
+void AgiEngine::cmd_version(uint8 *p) {
char verMsg[64];
char ver2Msg[] =
"\n"
@@ -1168,7 +1154,7 @@ cmd(version) {
sprintf(verMsg, TITLE " v%s", gScummVMVersion);
- ver = g_agi->getVersion();
+ ver = getVersion();
maj = (ver >> 12) & 0xf;
min = ver & 0xfff;
@@ -1186,88 +1172,87 @@ cmd(version) {
strncpy(q + 1 + gap, verMsg, strlen(verMsg));
sprintf(msg, q, maj, min);
- g_agi->messageBox(msg);
+ messageBox(msg);
}
-cmd(configure_screen) {
- game.lineMinPrint = p0;
- game.lineUserInput = p1;
- game.lineStatus = p2;
+void AgiEngine::cmd_configure_screen(uint8 *p) {
+ _game.lineMinPrint = p0;
+ _game.lineUserInput = p1;
+ _game.lineStatus = p2;
}
-cmd(text_screen) {
+void AgiEngine::cmd_text_screen(uint8 *p) {
debugC(4, kDebugLevelScripts, "switching to text mode");
- game.gfxMode = false;
+ _game.gfxMode = false;
// Simulates the "bright background bit" of the PC video
// controller.
- if (game.colorBg)
- game.colorBg |= 0x08;
+ if (_game.colorBg)
+ _game.colorBg |= 0x08;
- g_gfx->clearScreen(game.colorBg);
+ _gfx->clearScreen(_game.colorBg);
}
-cmd(graphics) {
+void AgiEngine::cmd_graphics(uint8 *p) {
debugC(4, kDebugLevelScripts, "switching to graphics mode");
- if (!game.gfxMode) {
- game.gfxMode = true;
- g_gfx->clearScreen(0);
- g_picture->showPic();
- g_agi->writeStatus();
- g_agi->writePrompt();
+ if (!_game.gfxMode) {
+ _game.gfxMode = true;
+ _gfx->clearScreen(0);
+ _picture->showPic();
+ writeStatus();
+ writePrompt();
}
}
-cmd(set_text_attribute) {
- game.colorFg = p0;
- game.colorBg = p1;
+void AgiEngine::cmd_set_text_attribute(uint8 *p) {
+ _game.colorFg = p0;
+ _game.colorBg = p1;
- if (game.gfxMode) {
- if (game.colorBg != 0) {
- game.colorFg = 0;
- game.colorBg = 15;
+ if (_game.gfxMode) {
+ if (_game.colorBg != 0) {
+ _game.colorFg = 0;
+ _game.colorBg = 15;
}
}
}
-cmd(status) {
- g_agi->inventory();
+void AgiEngine::cmd_status(uint8 *p) {
+ inventory();
}
-cmd(quit) {
+void AgiEngine::cmd_quit(uint8 *p) {
const char *buttons[] = { "Quit", "Continue", NULL };
- g_sound->stopSound();
+ _sound->stopSound();
if (p0) {
- g_agi->quitGame();
+ quitGame();
} else {
- if (g_agi->selectionBox
- (" Quit the game, or continue? \n\n\n", buttons) == 0) {
- g_agi->quitGame();
+ if (selectionBox(" Quit the game, or continue? \n\n\n", buttons) == 0) {
+ quitGame();
}
}
}
-cmd(restart_game) {
+void AgiEngine::cmd_restart_game(uint8 *p) {
const char *buttons[] = { "Restart", "Continue", NULL };
int sel;
- g_sound->stopSound();
- sel = g_agi->getflag(fAutoRestart) ? 0 :
- g_agi->selectionBox(" Restart game, or continue? \n\n\n", buttons);
+ _sound->stopSound();
+ sel = getflag(fAutoRestart) ? 0 :
+ selectionBox(" Restart _game, or continue? \n\n\n", buttons);
if (sel == 0) {
- g_agi->_restartGame = true;
- g_agi->setflag(fRestartGame, true);
- g_agi->_menu->enableAll();
+ _restartGame = true;
+ setflag(fRestartGame, true);
+ _menu->enableAll();
}
}
-cmd(distance) {
+void AgiEngine::cmd_distance(uint8 *p) {
int16 x1, y1, x2, y2, d;
- VtEntry *v0 = &game.viewTable[p0];
- VtEntry *v1 = &game.viewTable[p1];
+ VtEntry *v0 = &_game.viewTable[p0];
+ VtEntry *v1 = &_game.viewTable[p1];
if (v0->flags & DRAWN && v1->flags & DRAWN) {
x1 = v0->xPos + v0->xSize / 2;
@@ -1290,7 +1275,7 @@ cmd(distance) {
// wouldn't chase Rosella around anymore. If it had worked correctly the zombie
// wouldn't have come up at all or it would have come up and gone back down
// immediately. The latter approach is the one implemented here.
- if (g_agi->getGameID() == GID_KQ4 && (_v[vCurRoom] == 16 || _v[vCurRoom] == 18) && p2 >= 221 && p2 <= 223) {
+ if (getGameID() == GID_KQ4 && (_v[vCurRoom] == 16 || _v[vCurRoom] == 18) && p2 >= 221 && p2 <= 223) {
// Rooms 16 and 18 are graveyards where three zombies come up at night. They use logics 16 and 18.
// Variables 221-223 are used to save the distance between each zombie and Rosella.
// Variables 155, 156 and 162 are used to save the state of each zombie in room 16.
@@ -1315,24 +1300,24 @@ cmd(distance) {
_v[p2] = (unsigned char)d;
}
-cmd(accept_input) {
+void AgiEngine::cmd_accept_input(uint8 *p) {
debugC(4, kDebugLevelScripts | kDebugLevelInput, "input normal");
- g_agi->newInputMode(INPUT_NORMAL);
- game.inputEnabled = true;
- g_agi->writePrompt();
+ newInputMode(INPUT_NORMAL);
+ _game.inputEnabled = true;
+ writePrompt();
}
-cmd(prevent_input) {
+void AgiEngine::cmd_prevent_input(uint8 *p) {
debugC(4, kDebugLevelScripts | kDebugLevelInput, "no input");
- g_agi->newInputMode(INPUT_NONE);
- game.inputEnabled = false;
+ newInputMode(INPUT_NONE);
+ _game.inputEnabled = false;
- g_agi->clearPrompt();
+ clearPrompt();
}
-cmd(get_string) {
+void AgiEngine::cmd_get_string(uint8 *p) {
int tex, row, col;
debugC(4, kDebugLevelScripts, "%d %d %d %d %d", p0, p1, p2, p3, p4);
@@ -1348,63 +1333,63 @@ cmd(get_string) {
if (col > 39)
col = 39;
- g_agi->newInputMode(INPUT_GETSTRING);
+ newInputMode(INPUT_GETSTRING);
- if (curLogic->texts != NULL && curLogic->numTexts >= tex) {
- int len = strlen(curLogic->texts[tex]);
+ if (_curLogic->texts != NULL && _curLogic->numTexts >= tex) {
+ int len = strlen(_curLogic->texts[tex]);
- g_agi->printText(curLogic->texts[tex], 0, col, row, len, game.colorFg, game.colorBg);
- g_agi->getString(col + len - 1, row, p4, p0);
+ printText(_curLogic->texts[tex], 0, col, row, len, _game.colorFg, _game.colorBg);
+ getString(col + len - 1, row, p4, p0);
// SGEO: display input char
- g_gfx->printCharacter((col + len), row, game.cursorChar, game.colorFg, game.colorBg);
+ _gfx->printCharacter((col + len), row, _game.cursorChar, _game.colorFg, _game.colorBg);
}
do {
- g_agi->mainCycle();
- } while (game.inputMode == INPUT_GETSTRING && !(g_agi->shouldQuit() || g_agi->_restartGame));
+ mainCycle();
+ } while (_game.inputMode == INPUT_GETSTRING && !(shouldQuit() || _restartGame));
}
-cmd(get_num) {
+void AgiEngine::cmd_get_num(uint8 *p) {
debugC(4, kDebugLevelScripts, "%d %d", p0, p1);
- g_agi->newInputMode(INPUT_GETSTRING);
+ newInputMode(INPUT_GETSTRING);
- if (curLogic->texts != NULL && curLogic->numTexts >= (p0 - 1)) {
- int len = strlen(curLogic->texts[p0 - 1]);
+ if (_curLogic->texts != NULL && _curLogic->numTexts >= (p0 - 1)) {
+ int len = strlen(_curLogic->texts[p0 - 1]);
- g_agi->printText(curLogic->texts[p0 - 1], 0, 0, 22, len, game.colorFg, game.colorBg);
- g_agi->getString(len - 1, 22, 3, MAX_STRINGS);
+ printText(_curLogic->texts[p0 - 1], 0, 0, 22, len, _game.colorFg, _game.colorBg);
+ getString(len - 1, 22, 3, MAX_STRINGS);
// CM: display input char
- g_gfx->printCharacter((p3 + len), 22, game.cursorChar, game.colorFg, game.colorBg);
+ _gfx->printCharacter((p3 + len), 22, _game.cursorChar, _game.colorFg, _game.colorBg);
}
do {
- g_agi->mainCycle();
- } while (game.inputMode == INPUT_GETSTRING && !(g_agi->shouldQuit() || g_agi->_restartGame));
+ mainCycle();
+ } while (_game.inputMode == INPUT_GETSTRING && !(shouldQuit() || _restartGame));
- _v[p1] = atoi(game.strings[MAX_STRINGS]);
+ _v[p1] = atoi(_game.strings[MAX_STRINGS]);
- debugC(4, kDebugLevelScripts, "[%s] -> %d", game.strings[MAX_STRINGS], _v[p1]);
+ debugC(4, kDebugLevelScripts, "[%s] -> %d", _game.strings[MAX_STRINGS], _v[p1]);
- g_agi->clearLines(22, 22, game.colorBg);
- g_agi->flushLines(22, 22);
+ clearLines(22, 22, _game.colorBg);
+ flushLines(22, 22);
}
-cmd(set_cursor_char) {
- if (curLogic->texts != NULL && (p0 - 1) <= curLogic->numTexts) {
- game.cursorChar = *curLogic->texts[p0 - 1];
+void AgiEngine::cmd_set_cursor_char(uint8 *p) {
+ if (_curLogic->texts != NULL && (p0 - 1) <= _curLogic->numTexts) {
+ _game.cursorChar = *_curLogic->texts[p0 - 1];
} else {
// default
- game.cursorChar = '_';
+ _game.cursorChar = '_';
}
}
-cmd(set_key) {
+void AgiEngine::cmd_set_key(uint8 *p) {
int key;
- if (game.lastController >= MAX_CONTROLLERS) {
+ if (_game.lastController >= MAX_CONTROLLERS) {
warning("Number of set.keys exceeded %d", MAX_CONTROLLERS);
return;
}
@@ -1413,36 +1398,35 @@ cmd(set_key) {
key = 256 * p1 + p0;
- game.controllers[game.lastController].keycode = key;
- game.controllers[game.lastController].controller = p2;
- game.lastController++;
+ _game.controllers[_game.lastController].keycode = key;
+ _game.controllers[_game.lastController].controller = p2;
+ _game.lastController++;
- game.controllerOccured[p2] = false;
+ _game.controllerOccured[p2] = false;
}
-cmd(set_string) {
+void AgiEngine::cmd_set_string(uint8 *p) {
// CM: to avoid crash in Groza (str = 150)
if (p0 > MAX_STRINGS)
return;
- strcpy(game.strings[p0], curLogic->texts[p1 - 1]);
+ strcpy(_game.strings[p0], _curLogic->texts[p1 - 1]);
}
-cmd(display) {
+void AgiEngine::cmd_display(uint8 *p) {
int len = 40;
- char *s = g_agi->wordWrapString(curLogic->texts[p2 - 1], &len);
+ char *s = wordWrapString(_curLogic->texts[p2 - 1], &len);
- g_agi->printText(s, p1, 0, p0, 40, game.colorFg, game.colorBg);
+ printText(s, p1, 0, p0, 40, _game.colorFg, _game.colorBg);
free(s);
}
-cmd(display_f) {
- debugC(4, kDebugLevelScripts, "p0 = %d", p0);
- g_agi->printText(curLogic->texts[_v[p2] - 1], _v[p1], 0, _v[p0], 40, game.colorFg, game.colorBg);
+void AgiEngine::cmd_display_f(uint8 *p) {
+ printText(_curLogic->texts[_v[p2] - 1], _v[p1], 0, _v[p0], 40, _game.colorFg, _game.colorBg);
}
-cmd(clear_text_rect) {
+void AgiEngine::cmd_clear_text_rect(uint8 *p) {
int c, x1, y1, x2, y2;
if ((c = p4) != 0)
@@ -1463,21 +1447,21 @@ cmd(clear_text_rect) {
if (y2 > GFX_HEIGHT)
y2 = GFX_HEIGHT - 1;
- g_gfx->drawRectangle(x1, y1, x2, y2, c);
- g_gfx->flushBlock(x1, y1, x2, y2);
+ _gfx->drawRectangle(x1, y1, x2, y2, c);
+ _gfx->flushBlock(x1, y1, x2, y2);
}
-cmd(toggle_monitor) {
+void AgiEngine::cmd_toggle_monitor(uint8 *p) {
report("toggle.monitor\n");
}
-cmd(echo_line) {
- strcpy((char *)game.inputBuffer, (const char *)game.echoBuffer);
- game.cursorPos = strlen((char *)game.inputBuffer);
- game.hasPrompt = 0;
+void AgiEngine::cmd_echo_line(uint8 *p) {
+ strcpy((char *)_game.inputBuffer, (const char *)_game.echoBuffer);
+ _game.cursorPos = strlen((char *)_game.inputBuffer);
+ _game.hasPrompt = 0;
}
-cmd(clear_lines) {
+void AgiEngine::cmd_clear_lines(uint8 *p) {
uint8 l;
// Residence 44 calls clear.lines(24,0,0), see Sarien bug #558423
@@ -1487,78 +1471,78 @@ cmd(clear_lines) {
// #1935838 and #1935842
l = (l <= 24) ? l : 24;
- g_agi->clearLines(p0, l, p2);
- g_agi->flushLines(p0, l);
+ clearLines(p0, l, p2);
+ flushLines(p0, l);
}
-cmd(print) {
+void AgiEngine::cmd_print(uint8 *p) {
int n = p0 < 1 ? 1 : p0;
- g_agi->print(curLogic->texts[n - 1], 0, 0, 0);
+ print(_curLogic->texts[n - 1], 0, 0, 0);
}
-cmd(print_f) {
+void AgiEngine::cmd_print_f(uint8 *p) {
int n = _v[p0] < 1 ? 1 : _v[p0];
- g_agi->print(curLogic->texts[n - 1], 0, 0, 0);
+ print(_curLogic->texts[n - 1], 0, 0, 0);
}
-cmd(print_at) {
+void AgiEngine::cmd_print_at(uint8 *p) {
int n = p0 < 1 ? 1 : p0;
debugC(4, kDebugLevelScripts, "%d %d %d %d", p0, p1, p2, p3);
- g_agi->print(curLogic->texts[n - 1], p1, p2, p3);
+ print(_curLogic->texts[n - 1], p1, p2, p3);
}
-cmd(print_at_v) {
+void AgiEngine::cmd_print_at_v(uint8 *p) {
int n = _v[p0] < 1 ? 1 : _v[p0];
- g_agi->print(curLogic->texts[n - 1], p1, p2, p3);
+ print(_curLogic->texts[n - 1], p1, p2, p3);
}
-cmd(push_script) {
+void AgiEngine::cmd_push_script(uint8 *p) {
// We run AGIMOUSE always as a side effect
- if (g_agi->getFeatures() & GF_AGIMOUSE || 1) {
- game.vars[27] = g_agi->_mouse.button;
- game.vars[28] = g_agi->_mouse.x / 2;
- game.vars[29] = g_agi->_mouse.y;
+ if (getFeatures() & GF_AGIMOUSE || true) {
+ _game.vars[27] = _mouse.button;
+ _game.vars[28] = _mouse.x / 2;
+ _game.vars[29] = _mouse.y;
} else {
- if (g_agi->getVersion() >= 0x2915) {
+ if (getVersion() >= 0x2915) {
report("push.script\n");
}
}
}
-cmd(set_pri_base) {
+void AgiEngine::cmd_set_pri_base(uint8 *p) {
int i, x, pri;
report("Priority base set to %d\n", p0);
- // game.alt_pri = true;
+ // _game.alt_pri = true;
x = (_HEIGHT - p0) * _HEIGHT / 10;
for (i = 0; i < _HEIGHT; i++) {
pri = (i - p0) < 0 ? 4 : (i - p0) * _HEIGHT / x + 5;
if (pri > 15)
pri = 15;
- game.priTable[i] = pri;
+ _game.priTable[i] = pri;
}
}
-cmd(mouse_posn) {
- _v[p0] = WIN_TO_PIC_X(g_agi->_mouse.x);
- _v[p1] = WIN_TO_PIC_Y(g_agi->_mouse.y);
+void AgiEngine::cmd_mouse_posn(uint8 *p) {
+ _v[p0] = WIN_TO_PIC_X(_mouse.x);
+ _v[p1] = WIN_TO_PIC_Y(_mouse.y);
}
-cmd(shake_screen) {
+void AgiEngine::cmd_shake_screen(uint8 *p) {
int i;
// AGIPAL uses shake.screen values between 100 and 109 to set the palette
// (Checked the original AGIPAL-hack's shake.screen-routine's disassembly).
if (p0 >= 100 && p0 < 110) {
- if (g_agi->getFeatures() & GF_AGIPAL) {
- g_gfx->setAGIPal(p0);
+ if (getFeatures() & GF_AGIPAL) {
+ _gfx->setAGIPal(p0);
return;
} else {
warning("It looks like GF_AGIPAL flag is missing");
@@ -1567,208 +1551,213 @@ cmd(shake_screen) {
// Disables input while shaking to prevent bug
// #1678230: AGI: Entering text while screen is shaking
- int originalValue = game.inputEnabled;
- game.inputEnabled = 0;
+ bool originalValue = _game.inputEnabled;
+ _game.inputEnabled = false;
- g_gfx->shakeStart();
+ _gfx->shakeStart();
- g_sprites->commitBoth(); // Fixes SQ1 demo
+ _sprites->commitBoth(); // Fixes SQ1 demo
for (i = 4 * p0; i; i--) {
- g_gfx->shakeScreen(i & 1);
- g_gfx->flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1);
- g_agi->mainCycle();
+ _gfx->shakeScreen(i & 1);
+ _gfx->flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1);
+ mainCycle();
}
- g_gfx->shakeEnd();
+ _gfx->shakeEnd();
// Sets input back to what it was
- game.inputEnabled = originalValue;
-}
-
-static void (*agiCommand[183])(AgiEngine *, uint8 *) = {
- NULL, // 0x00
- cmd_increment,
- cmd_decrement,
- cmd_assignn,
- cmd_assignv,
- cmd_addn,
- cmd_addv,
- cmd_subn,
- cmd_subv, // 0x08
- cmd_lindirectv,
- cmd_rindirect,
- cmd_lindirectn,
- cmd_set,
- cmd_reset,
- cmd_toggle,
- cmd_set_v,
- cmd_reset_v, // 0x10
- cmd_toggle_v,
- cmd_new_room,
- cmd_new_room_f,
- cmd_load_logic,
- cmd_load_logic_f,
- cmd_call,
- cmd_call_f,
- cmd_load_pic, // 0x18
- cmd_draw_pic,
- cmd_show_pic,
- cmd_discard_pic,
- cmd_overlay_pic,
- cmd_show_pri_screen,
- cmd_load_view,
- cmd_load_view_f,
- cmd_discard_view, // 0x20
- cmd_animate_obj,
- cmd_unanimate_all,
- cmd_draw,
- cmd_erase,
- cmd_position,
- cmd_position_f,
- cmd_get_posn,
- cmd_reposition, // 0x28
- cmd_set_view,
- cmd_set_view_f,
- cmd_set_loop,
- cmd_set_loop_f,
- cmd_fix_loop,
- cmd_release_loop,
- cmd_set_cel,
- cmd_set_cel_f, // 0x30
- cmd_last_cel,
- cmd_current_cel,
- cmd_current_loop,
- cmd_current_view,
- cmd_number_of_loops,
- cmd_set_priority,
- cmd_set_priority_f,
- cmd_release_priority, // 0x38
- cmd_get_priority,
- cmd_stop_update,
- cmd_start_update,
- cmd_force_update,
- cmd_ignore_horizon,
- cmd_observe_horizon,
- cmd_set_horizon,
- cmd_object_on_water, // 0x40
- cmd_object_on_land,
- cmd_object_on_anything,
- cmd_ignore_objs,
- cmd_observe_objs,
- cmd_distance,
- cmd_stop_cycling,
- cmd_start_cycling,
- cmd_normal_cycle, // 0x48
- cmd_end_of_loop,
- cmd_reverse_cycle,
- cmd_reverse_loop,
- cmd_cycle_time,
- cmd_stop_motion,
- cmd_start_motion,
- cmd_step_size,
- cmd_step_time, // 0x50
- cmd_move_obj,
- cmd_move_obj_f,
- cmd_follow_ego,
- cmd_wander,
- cmd_normal_motion,
- cmd_set_dir,
- cmd_get_dir,
- cmd_ignore_blocks, // 0x58
- cmd_observe_blocks,
- cmd_block,
- cmd_unblock,
- cmd_get,
- cmd_get_f,
- cmd_drop,
- cmd_put,
- cmd_put_f, // 0x60
- cmd_get_room_f,
- cmd_load_sound,
- cmd_sound,
- cmd_stop_sound,
- cmd_print,
- cmd_print_f,
- cmd_display,
- cmd_display_f, // 0x68
- cmd_clear_lines,
- cmd_text_screen,
- cmd_graphics,
- cmd_set_cursor_char,
- cmd_set_text_attribute,
- cmd_shake_screen,
- cmd_configure_screen,
- cmd_status_line_on, // 0x70
- cmd_status_line_off,
- cmd_set_string,
- cmd_get_string,
- cmd_word_to_string,
- cmd_parse,
- cmd_get_num,
- cmd_prevent_input,
- cmd_accept_input, // 0x78
- cmd_set_key,
- cmd_add_to_pic,
- cmd_add_to_pic_f,
- cmd_status,
- cmd_save_game,
- cmd_load_game,
- cmd_init_disk,
- cmd_restart_game, // 0x80
- cmd_show_obj,
- cmd_random,
- cmd_program_control,
- cmd_player_control,
- cmd_obj_status_f,
- cmd_quit,
- cmd_show_mem,
- cmd_pause, // 0x88
- cmd_echo_line,
- cmd_cancel_line,
- cmd_init_joy,
- cmd_toggle_monitor,
- cmd_version,
- cmd_script_size,
- cmd_set_game_id,
- cmd_log, // 0x90
- cmd_set_scan_start,
- cmd_reset_scan_start,
- cmd_reposition_to,
- cmd_reposition_to_f,
- cmd_trace_on,
- cmd_trace_info,
- cmd_print_at,
- cmd_print_at_v, // 0x98
- cmd_discard_view,
- cmd_clear_text_rect,
- cmd_set_upper_left,
- cmd_set_menu,
- cmd_set_menu_item,
- cmd_submit_menu,
- cmd_enable_item,
- cmd_disable_item, // 0xa0
- cmd_menu_input,
- cmd_show_obj_v,
- cmd_open_dialogue,
- cmd_close_dialogue,
- cmd_mul_n,
- cmd_mul_v,
- cmd_div_n,
- cmd_div_v, // 0xa8
- cmd_close_window,
- cmd_set_simple,
- cmd_push_script,
- cmd_pop_script,
- cmd_hold_key,
- cmd_set_pri_base,
- cmd_discard_sound,
- cmd_hide_mouse, // 0xb0
- cmd_allow_menu,
- cmd_show_mouse,
- cmd_fence_mouse,
- cmd_mouse_posn,
- cmd_release_key,
- cmd_adj_ego_move_to_x_y
-};
+ _game.inputEnabled = originalValue;
+}
+
+void AgiEngine::setupOpcodes() {
+ AgiCommand tmp[] = {
+ NULL, // 0x00
+ &AgiEngine::cmd_increment,
+ &AgiEngine::cmd_decrement,
+ &AgiEngine::cmd_assignn,
+ &AgiEngine::cmd_assignv,
+ &AgiEngine::cmd_addn,
+ &AgiEngine::cmd_addv,
+ &AgiEngine::cmd_subn,
+ &AgiEngine::cmd_subv, // 0x08
+ &AgiEngine::cmd_lindirectv,
+ &AgiEngine::cmd_rindirect,
+ &AgiEngine::cmd_lindirectn,
+ &AgiEngine::cmd_set,
+ &AgiEngine::cmd_reset,
+ &AgiEngine::cmd_toggle,
+ &AgiEngine::cmd_set_v,
+ &AgiEngine::cmd_reset_v, // 0x10
+ &AgiEngine::cmd_toggle_v,
+ &AgiEngine::cmd_new_room,
+ &AgiEngine::cmd_new_room_f,
+ &AgiEngine::cmd_load_logic,
+ &AgiEngine::cmd_load_logic_f,
+ &AgiEngine::cmd_call,
+ &AgiEngine::cmd_call_f,
+ &AgiEngine::cmd_load_pic, // 0x18
+ &AgiEngine::cmd_draw_pic,
+ &AgiEngine::cmd_show_pic,
+ &AgiEngine::cmd_discard_pic,
+ &AgiEngine::cmd_overlay_pic,
+ &AgiEngine::cmd_show_pri_screen,
+ &AgiEngine::cmd_load_view,
+ &AgiEngine::cmd_load_view_f,
+ &AgiEngine::cmd_discard_view, // 0x20
+ &AgiEngine::cmd_animate_obj,
+ &AgiEngine::cmd_unanimate_all,
+ &AgiEngine::cmd_draw,
+ &AgiEngine::cmd_erase,
+ &AgiEngine::cmd_position,
+ &AgiEngine::cmd_position_f,
+ &AgiEngine::cmd_get_posn,
+ &AgiEngine::cmd_reposition, // 0x28
+ &AgiEngine::cmd_set_view,
+ &AgiEngine::cmd_set_view_f,
+ &AgiEngine::cmd_set_loop,
+ &AgiEngine::cmd_set_loop_f,
+ &AgiEngine::cmd_fix_loop,
+ &AgiEngine::cmd_release_loop,
+ &AgiEngine::cmd_set_cel,
+ &AgiEngine::cmd_set_cel_f, // 0x30
+ &AgiEngine::cmd_last_cel,
+ &AgiEngine::cmd_current_cel,
+ &AgiEngine::cmd_current_loop,
+ &AgiEngine::cmd_current_view,
+ &AgiEngine::cmd_number_of_loops,
+ &AgiEngine::cmd_set_priority,
+ &AgiEngine::cmd_set_priority_f,
+ &AgiEngine::cmd_release_priority, // 0x38
+ &AgiEngine::cmd_get_priority,
+ &AgiEngine::cmd_stop_update,
+ &AgiEngine::cmd_start_update,
+ &AgiEngine::cmd_force_update,
+ &AgiEngine::cmd_ignore_horizon,
+ &AgiEngine::cmd_observe_horizon,
+ &AgiEngine::cmd_set_horizon,
+ &AgiEngine::cmd_object_on_water, // 0x40
+ &AgiEngine::cmd_object_on_land,
+ &AgiEngine::cmd_object_on_anything,
+ &AgiEngine::cmd_ignore_objs,
+ &AgiEngine::cmd_observe_objs,
+ &AgiEngine::cmd_distance,
+ &AgiEngine::cmd_stop_cycling,
+ &AgiEngine::cmd_start_cycling,
+ &AgiEngine::cmd_normal_cycle, // 0x48
+ &AgiEngine::cmd_end_of_loop,
+ &AgiEngine::cmd_reverse_cycle,
+ &AgiEngine::cmd_reverse_loop,
+ &AgiEngine::cmd_cycle_time,
+ &AgiEngine::cmd_stop_motion,
+ &AgiEngine::cmd_start_motion,
+ &AgiEngine::cmd_step_size,
+ &AgiEngine::cmd_step_time, // 0x50
+ &AgiEngine::cmd_move_obj,
+ &AgiEngine::cmd_move_obj_f,
+ &AgiEngine::cmd_follow_ego,
+ &AgiEngine::cmd_wander,
+ &AgiEngine::cmd_normal_motion,
+ &AgiEngine::cmd_set_dir,
+ &AgiEngine::cmd_get_dir,
+ &AgiEngine::cmd_ignore_blocks, // 0x58
+ &AgiEngine::cmd_observe_blocks,
+ &AgiEngine::cmd_block,
+ &AgiEngine::cmd_unblock,
+ &AgiEngine::cmd_get,
+ &AgiEngine::cmd_get_f,
+ &AgiEngine::cmd_drop,
+ &AgiEngine::cmd_put,
+ &AgiEngine::cmd_put_f, // 0x60
+ &AgiEngine::cmd_get_room_f,
+ &AgiEngine::cmd_load_sound,
+ &AgiEngine::cmd_sound,
+ &AgiEngine::cmd_stop_sound,
+ &AgiEngine::cmd_print,
+ &AgiEngine::cmd_print_f,
+ &AgiEngine::cmd_display,
+ &AgiEngine::cmd_display_f, // 0x68
+ &AgiEngine::cmd_clear_lines,
+ &AgiEngine::cmd_text_screen,
+ &AgiEngine::cmd_graphics,
+ &AgiEngine::cmd_set_cursor_char,
+ &AgiEngine::cmd_set_text_attribute,
+ &AgiEngine::cmd_shake_screen,
+ &AgiEngine::cmd_configure_screen,
+ &AgiEngine::cmd_status_line_on, // 0x70
+ &AgiEngine::cmd_status_line_off,
+ &AgiEngine::cmd_set_string,
+ &AgiEngine::cmd_get_string,
+ &AgiEngine::cmd_word_to_string,
+ &AgiEngine::cmd_parse,
+ &AgiEngine::cmd_get_num,
+ &AgiEngine::cmd_prevent_input,
+ &AgiEngine::cmd_accept_input, // 0x78
+ &AgiEngine::cmd_set_key,
+ &AgiEngine::cmd_add_to_pic,
+ &AgiEngine::cmd_add_to_pic_f,
+ &AgiEngine::cmd_status,
+ &AgiEngine::cmd_save_game,
+ &AgiEngine::cmd_load_game,
+ &AgiEngine::cmd_init_disk,
+ &AgiEngine::cmd_restart_game, // 0x80
+ &AgiEngine::cmd_show_obj,
+ &AgiEngine::cmd_random,
+ &AgiEngine::cmd_program_control,
+ &AgiEngine::cmd_player_control,
+ &AgiEngine::cmd_obj_status_f,
+ &AgiEngine::cmd_quit,
+ &AgiEngine::cmd_show_mem,
+ &AgiEngine::cmd_pause, // 0x88
+ &AgiEngine::cmd_echo_line,
+ &AgiEngine::cmd_cancel_line,
+ &AgiEngine::cmd_init_joy,
+ &AgiEngine::cmd_toggle_monitor,
+ &AgiEngine::cmd_version,
+ &AgiEngine::cmd_script_size,
+ &AgiEngine::cmd_set_game_id,
+ &AgiEngine::cmd_log, // 0x90
+ &AgiEngine::cmd_set_scan_start,
+ &AgiEngine::cmd_reset_scan_start,
+ &AgiEngine::cmd_reposition_to,
+ &AgiEngine::cmd_reposition_to_f,
+ &AgiEngine::cmd_trace_on,
+ &AgiEngine::cmd_trace_info,
+ &AgiEngine::cmd_print_at,
+ &AgiEngine::cmd_print_at_v, // 0x98
+ &AgiEngine::cmd_discard_view, // Opcode repeated from 0x20 ?
+ &AgiEngine::cmd_clear_text_rect,
+ &AgiEngine::cmd_set_upper_left,
+ &AgiEngine::cmd_set_menu,
+ &AgiEngine::cmd_set_menu_item,
+ &AgiEngine::cmd_submit_menu,
+ &AgiEngine::cmd_enable_item,
+ &AgiEngine::cmd_disable_item, // 0xa0
+ &AgiEngine::cmd_menu_input,
+ &AgiEngine::cmd_show_obj_v,
+ &AgiEngine::cmd_open_dialogue,
+ &AgiEngine::cmd_close_dialogue,
+ &AgiEngine::cmd_mul_n,
+ &AgiEngine::cmd_mul_v,
+ &AgiEngine::cmd_div_n,
+ &AgiEngine::cmd_div_v, // 0xa8
+ &AgiEngine::cmd_close_window,
+ &AgiEngine::cmd_set_simple,
+ &AgiEngine::cmd_push_script,
+ &AgiEngine::cmd_pop_script,
+ &AgiEngine::cmd_hold_key,
+ &AgiEngine::cmd_set_pri_base,
+ &AgiEngine::cmd_discard_sound,
+ &AgiEngine::cmd_hide_mouse, // 0xb0
+ &AgiEngine::cmd_allow_menu,
+ &AgiEngine::cmd_show_mouse,
+ &AgiEngine::cmd_fence_mouse,
+ &AgiEngine::cmd_mouse_posn,
+ &AgiEngine::cmd_release_key,
+ &AgiEngine::cmd_adj_ego_move_to_x_y
+ };
+ assert(ARRAYSIZE(_agiCommands) == ARRAYSIZE(tmp));
+ for (int i = 0; i < ARRAYSIZE(tmp); ++i)
+ _agiCommands[i] = tmp[i];
+}
/**
* Execute a logic script
@@ -1781,6 +1770,9 @@ int AgiEngine::runLogic(int n) {
int num = 0;
ScriptPos sp;
+ debugC(2, kDebugLevelScripts, "=================");
+ debugC(2, kDebugLevelScripts, "runLogic(%d)", n);
+
sp.script = n;
sp.curIP = 0;
_game.execStack.push_back(sp);
@@ -1792,12 +1784,12 @@ int AgiEngine::runLogic(int n) {
}
_game.lognum = n;
- curLogic = &_game.logics[_game.lognum];
+ _curLogic = &_game.logics[_game.lognum];
- code = curLogic->data;
- curLogic->cIP = curLogic->sIP;
+ code = _curLogic->data;
+ _curLogic->cIP = _curLogic->sIP;
- timerHack = 0;
+ _timerHack = 0;
while (ip < _game.logics[n].size && !(shouldQuit() || _restartGame)) {
if (_debug.enabled) {
if (_debug.steps > 0) {
@@ -1807,6 +1799,7 @@ int AgiEngine::runLogic(int n) {
}
} else {
_sprites->blitBoth();
+ _sprites->commitBoth();
do {
mainCycle();
} while (!_debug.steps && _debug.enabled);
@@ -1816,6 +1809,11 @@ int AgiEngine::runLogic(int n) {
_game.execStack.back().curIP = ip;
+ char st[101];
+ int sz = MIN(_game.execStack.size(), 100u);
+ memset(st, '.', sz);
+ st[sz] = 0;
+
switch (op = *(code + ip++)) {
case 0xff: // if (open/close)
testIfCode(n);
@@ -1826,13 +1824,16 @@ int AgiEngine::runLogic(int n) {
// timer must keep running even in goto loops,
// but AGI engine can't do that :(
- if (timerHack > 20) {
+ if (_timerHack > 20) {
pollTimer();
updateTimer();
- timerHack = 0;
+ _timerHack = 0;
}
break;
case 0x00: // return
+ debugC(2, kDebugLevelScripts, "%sreturn() // Logic %d", st, n);
+ debugC(2, kDebugLevelScripts, "=================");
+
_game.execStack.pop_back();
return 1;
default:
@@ -1840,8 +1841,9 @@ int AgiEngine::runLogic(int n) {
memmove(p, code + ip, num);
memset(p + num, 0, CMD_BSIZE - num);
- debugC(2, kDebugLevelScripts, "%s(%d %d %d)", logicNamesCmd[op].name, p[0], p[1], p[2]);
- agiCommand[op](this, p);
+ debugC(2, kDebugLevelScripts, "%s%s(%d %d %d)", st, logicNamesCmd[op].name, p[0], p[1], p[2]);
+
+ (this->*_agiCommands[op])(p);
ip += num;
}
@@ -1857,7 +1859,7 @@ int AgiEngine::runLogic(int n) {
void AgiEngine::executeAgiCommand(uint8 op, uint8 *p) {
debugC(2, kDebugLevelScripts, "%s(%d %d %d)", logicNamesCmd[op].name, p[0], p[1], p[2]);
- agiCommand[op] (this, p);
+ (this->*_agiCommands[op])(p);
}
} // End of namespace Agi
diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp
index 71d307556b..ab4f6cadc5 100644
--- a/engines/agi/op_test.cpp
+++ b/engines/agi/op_test.cpp
@@ -29,37 +29,23 @@
namespace Agi {
-static uint8 testObjRight(uint8, uint8, uint8, uint8, uint8);
-static uint8 testObjCentre(uint8, uint8, uint8, uint8, uint8);
-static uint8 testObjInBox(uint8, uint8, uint8, uint8, uint8);
-static uint8 testPosn(uint8, uint8, uint8, uint8, uint8);
-static uint8 testSaid(uint8, uint8 *);
-static uint8 testController(uint8);
-static uint8 testKeypressed();
-static uint8 testCompareStrings(uint8, uint8);
-
-static AgiEngine *g_agi;
-#define game g_agi->_game
-
-#define ip (game.logics[lognum].cIP)
-#define code (game.logics[lognum].data)
-
-#define testEqual(v1, v2) (g_agi->getvar(v1) == (v2))
-#define testLess(v1, v2) (g_agi->getvar(v1) < (v2))
-#define testGreater(v1, v2) (g_agi->getvar(v1) > (v2))
-#define testIsSet(flag) (g_agi->getflag(flag))
-#define testHas(obj) (g_agi->objectGetLocation(obj) == EGO_OWNED)
-#define testObjInRoom(obj, v) (g_agi->objectGetLocation(obj) == g_agi->getvar(v))
-
-extern int timerHack; // For the timer loop in MH1 logic 153
-
-static uint8 testCompareStrings(uint8 s1, uint8 s2) {
+#define ip (_game.logics[lognum].cIP)
+#define code (_game.logics[lognum].data)
+
+#define testEqual(v1, v2) (getvar(v1) == (v2))
+#define testLess(v1, v2) (getvar(v1) < (v2))
+#define testGreater(v1, v2) (getvar(v1) > (v2))
+#define testIsSet(flag) (getflag(flag))
+#define testHas(obj) (objectGetLocation(obj) == EGO_OWNED)
+#define testObjInRoom(obj, v) (objectGetLocation(obj) == getvar(v))
+
+uint8 AgiEngine::testCompareStrings(uint8 s1, uint8 s2) {
char ms1[MAX_STRINGLEN];
char ms2[MAX_STRINGLEN];
int j, k, l;
- strcpy(ms1, game.strings[s1]);
- strcpy(ms2, game.strings[s2]);
+ strcpy(ms1, _game.strings[s1]);
+ strcpy(ms2, _game.strings[s2]);
l = strlen(ms1);
for (k = 0, j = 0; k < l; k++) {
@@ -106,16 +92,16 @@ static uint8 testCompareStrings(uint8 s1, uint8 s2) {
return !strcmp(ms1, ms2);
}
-static uint8 testKeypressed() {
- int x = game.keypress;
+uint8 AgiEngine::testKeypressed() {
+ int x = _game.keypress;
- game.keypress = 0;
+ _game.keypress = 0;
if (!x) {
- int mode = game.inputMode;
+ InputMode mode = _game.inputMode;
- game.inputMode = INPUT_NONE;
- g_agi->mainCycle();
- game.inputMode = mode;
+ _game.inputMode = INPUT_NONE;
+ mainCycle();
+ _game.inputMode = mode;
}
if (x)
@@ -124,12 +110,12 @@ static uint8 testKeypressed() {
return x;
}
-static uint8 testController(uint8 cont) {
- return (game.controllerOccured[cont] ? 1 : 0);
+uint8 AgiEngine::testController(uint8 cont) {
+ return (_game.controllerOccured[cont] ? 1 : 0);
}
-static uint8 testPosn(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
- VtEntry *v = &game.viewTable[n];
+uint8 AgiEngine::testPosn(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
+ VtEntry *v = &_game.viewTable[n];
uint8 r;
r = v->xPos >= x1 && v->yPos >= y1 && v->xPos <= x2 && v->yPos <= y2;
@@ -139,35 +125,35 @@ static uint8 testPosn(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
return r;
}
-static uint8 testObjInBox(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
- VtEntry *v = &game.viewTable[n];
+uint8 AgiEngine::testObjInBox(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
+ VtEntry *v = &_game.viewTable[n];
return v->xPos >= x1 &&
v->yPos >= y1 && v->xPos + v->xSize - 1 <= x2 && v->yPos <= y2;
}
// if n is in centre of box
-static uint8 testObjCentre(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
- VtEntry *v = &game.viewTable[n];
+uint8 AgiEngine::testObjCentre(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
+ VtEntry *v = &_game.viewTable[n];
return v->xPos + v->xSize / 2 >= x1 &&
v->xPos + v->xSize / 2 <= x2 && v->yPos >= y1 && v->yPos <= y2;
}
// if nect N is in right corner
-static uint8 testObjRight(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
- VtEntry *v = &game.viewTable[n];
+uint8 AgiEngine::testObjRight(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
+ VtEntry *v = &_game.viewTable[n];
return v->xPos + v->xSize - 1 >= x1 &&
v->xPos + v->xSize - 1 <= x2 && v->yPos >= y1 && v->yPos <= y2;
}
// When player has entered something, it is parsed elsewhere
-static uint8 testSaid(uint8 nwords, uint8 *cc) {
- int c, n = game.numEgoWords;
+uint8 AgiEngine::testSaid(uint8 nwords, uint8 *cc) {
+ int c, n = _game.numEgoWords;
int z = 0;
- if (g_agi->getflag(fSaidAcceptedInput) || !g_agi->getflag(fEnteredCli))
+ if (getflag(fSaidAcceptedInput) || !getflag(fEnteredCli))
return false;
// FR:
@@ -198,7 +184,7 @@ static uint8 testSaid(uint8 nwords, uint8 *cc) {
case 1: // any word
break;
default:
- if (game.egoWords[c].id != z)
+ if (_game.egoWords[c].id != z)
return false;
break;
}
@@ -213,13 +199,12 @@ static uint8 testSaid(uint8 nwords, uint8 *cc) {
if (nwords != 0 && READ_LE_UINT16(cc) != 9999)
return false;
- g_agi->setflag(fSaidAcceptedInput, true);
+ setflag(fSaidAcceptedInput, true);
return true;
}
int AgiEngine::testIfCode(int lognum) {
- g_agi = this;
int ec = true;
int retval = true;
uint8 op = 0;
@@ -263,32 +248,32 @@ int AgiEngine::testIfCode(int lognum) {
case 0x01:
ec = testEqual(p[0], p[1]);
if (p[0] == 11)
- timerHack++;
+ _timerHack++;
break;
case 0x02:
ec = testEqual(p[0], getvar(p[1]));
if (p[0] == 11 || p[1] == 11)
- timerHack++;
+ _timerHack++;
break;
case 0x03:
ec = testLess(p[0], p[1]);
if (p[0] == 11)
- timerHack++;
+ _timerHack++;
break;
case 0x04:
ec = testLess(p[0], getvar(p[1]));
if (p[0] == 11 || p[1] == 11)
- timerHack++;
+ _timerHack++;
break;
case 0x05:
ec = testGreater(p[0], p[1]);
if (p[0] == 11)
- timerHack++;
+ _timerHack++;
break;
case 0x06:
ec = testGreater(p[0], getvar(p[1]));
if (p[0] == 11 || p[1] == 11)
- timerHack++;
+ _timerHack++;
break;
case 0x07:
ec = testIsSet(p[0]);
@@ -319,7 +304,7 @@ int AgiEngine::testIfCode(int lognum) {
ip++; // skip num_words opcode
break;
case 0x0F:
- debugC(7, kDebugLevelScripts, "comparing [%s], [%s]", game.strings[p[0]], game.strings[p[1]]);
+ debugC(7, kDebugLevelScripts, "comparing [%s], [%s]", _game.strings[p[0]], _game.strings[p[1]]);
ec = testCompareStrings(p[0], p[1]);
break;
case 0x10:
@@ -338,7 +323,7 @@ int AgiEngine::testIfCode(int lognum) {
// This command is used at least in the Amiga version of Gold Rush! v2.05 1989-03-09
// (AGI 2.316) in logics 1, 3, 5, 6, 137 and 192 (Logic.192 revealed this command's nature).
// TODO: Check this command's implementation using disassembly just to be sure.
- ec = game.viewTable[0].flags & ADJ_EGO_XY;
+ ec = _game.viewTable[0].flags & ADJ_EGO_XY;
debugC(7, kDebugLevelScripts, "op_test: in.motion.using.mouse = %s (Amiga-specific testcase 19)", ec ? "true" : "false");
break;
default:
diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp
index 60877de430..dc77433cb2 100644
--- a/engines/agi/picture.cpp
+++ b/engines/agi/picture.cpp
@@ -476,7 +476,7 @@ void PictureMgr::plotPattern(int x, int y) {
// new purpose for temp16
- temp16 =( pen_size<<1) +1; // pen size
+ temp16 = (pen_size << 1) + 1; // pen size
pen_final_y += temp16; // the last row of this shape
temp16 = temp16 << 1;
pen_width = temp16; // width of shape?
@@ -495,7 +495,7 @@ void PictureMgr::plotPattern(int x, int y) {
} else {
circleCond = ((_patCode & 0x10) != 0);
counterStep = 4;
- ditherCond = 0x02;
+ ditherCond = 0x01;
}
for (; pen_y < pen_final_y; pen_y++) {
@@ -503,10 +503,12 @@ void PictureMgr::plotPattern(int x, int y) {
for (counter = 0; counter <= pen_width; counter += counterStep) {
if (circleCond || ((binary_list[counter>>1] & circle_word) != 0)) {
- temp8 = t % 2;
- t = t >> 1;
- if (temp8 != 0)
- t = t ^ 0xB8;
+ if ((_patCode & 0x20) != 0) {
+ temp8 = t % 2;
+ t = t >> 1;
+ if (temp8 != 0)
+ t = t ^ 0xB8;
+ }
// == box plot, != circle plot
if ((_patCode & 0x20) == 0 || (t & 0x03) == ditherCond)
diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp
index 35285798d4..1a5698dffc 100644
--- a/engines/agi/preagi.cpp
+++ b/engines/agi/preagi.cpp
@@ -68,8 +68,8 @@ void PreAgiEngine::initialize() {
// drivers, and I'm not sure what they are. For now, they might
// as well be called "PC Speaker" and "Not PC Speaker".
- switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) {
- case MD_PCSPK:
+ switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK))) {
+ case MT_PCSPK:
_soundemu = SOUND_EMU_PC;
break;
default:
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index b7e830dc53..88b14dcfe2 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -132,7 +132,7 @@ int AgiEngine::saveGame(const char *fileName, const char *description) {
out->writeSint16BE((int16)_game.hasPrompt);
out->writeSint16BE((int16)_game.gameFlags);
- out->writeSint16BE((int16)_game.inputEnabled);
+ out->writeSint16BE(_game.inputEnabled);
for (i = 0; i < _HEIGHT; i++)
out->writeByte(_game.priTable[i]);
@@ -302,7 +302,7 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) {
// TODO: played time
}
- _game.state = in->readByte();
+ _game.state = (State)in->readByte();
in->read(loadId, 8);
if (strcmp(loadId, _game.id) && checkId) {
@@ -361,7 +361,7 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) {
_game.echoBuffer[0] = 0;
_game.keypress = 0;
- _game.inputMode = in->readSint16BE();
+ _game.inputMode = (InputMode)in->readSint16BE();
_game.lognum = in->readSint16BE();
_game.playerControl = in->readSint16BE();
@@ -864,6 +864,10 @@ int AgiEngine::saveGameDialog() {
sprintf(fileName, "%s", getSavegameFilename(_firstSlot + slot));
debugC(8, kDebugLevelMain | kDebugLevelResources, "file is [%s]", fileName);
+ // Make sure all graphics was blitted to screen. This fixes bug
+ // #2960567: "AGI: Ego partly erased in Load/Save thumbnails"
+ _gfx->doUpdate();
+
int result = saveGame(fileName, desc);
if (result == errOK)
diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp
index ca5d42d981..cb4e307ea6 100644
--- a/engines/agi/sound.cpp
+++ b/engines/agi/sound.cpp
@@ -23,23 +23,21 @@
*
*/
-#include "common/md5.h"
-#include "common/config-manager.h"
-#include "common/fs.h"
-#include "common/random.h"
-#include "common/str-array.h"
-
#include "agi/agi.h"
-namespace Agi {
+#include "agi/sound_2gs.h"
+#include "agi/sound_coco3.h"
+#include "agi/sound_midi.h"
+#include "agi/sound_sarien.h"
+#include "agi/sound_pcjr.h"
-#define USE_INTERPOLATION
+namespace Agi {
//
// TODO: add support for variable sampling rate in the output device
//
-AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager) {
+AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager, int soundemu) {
if (data == NULL || len < 2) // Check for too small resource or no resource at all
return NULL;
uint16 type = READ_LE_UINT16(data);
@@ -48,27 +46,19 @@ AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, S
case AGI_SOUND_SAMPLE:
return new IIgsSample(data, len, resnum, manager);
case AGI_SOUND_MIDI:
- return new IIgsMidi (data, len, resnum, manager);
+ return new IIgsMidi(data, len, resnum, manager);
case AGI_SOUND_4CHN:
- return new PCjrSound (data, len, resnum, manager);
+ if (soundemu == SOUND_EMU_MIDI) {
+ return new MIDISound(data, len, resnum, manager);
+ } else {
+ return new PCjrSound(data, len, resnum, manager);
+ }
}
warning("Sound resource (%d) has unknown type (0x%04x). Not using the sound", resnum, type);
return NULL;
}
-IIgsMidi::IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) {
- _data = data; // Save the resource pointer
- _ptr = _data + 2; // Set current position to just after the header
- _len = len; // Save the resource's length
- _type = READ_LE_UINT16(data); // Read sound resource's type
- _midiTicks = _soundBufTicks = 0;
- _isValid = (_type == AGI_SOUND_MIDI) && (_data != NULL) && (_len >= 2);
-
- if (!_isValid) // Check for errors
- warning("Error creating Apple IIGS midi sound from resource %d (Type %d, length %d)", resnum, _type, len);
-}
-
PCjrSound::PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) {
_data = data; // Save the resource pointer
_len = len; // Save the resource's length
@@ -86,247 +76,12 @@ const uint8 *PCjrSound::getVoicePointer(uint voiceNum) {
return _data + voiceStartOffset;
}
-IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) {
- Common::MemoryReadStream stream(data, len, DisposeAfterUse::YES);
-
- // Check that the header was read ok and that it's of the correct type
- if (_header.read(stream) && _header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource
- uint32 sampleStartPos = stream.pos();
- uint32 tailLen = stream.size() - sampleStartPos;
-
- if (tailLen < _header.sampleSize) { // Check if there's no room for the sample data in the stream
- // Apple IIGS Manhunter I: Sound resource 16 has only 16074 bytes
- // of sample data although header says it should have 16384 bytes.
- warning("Apple IIGS sample (%d) too short (%d bytes. Should be %d bytes). Using the part that's left",
- resnum, tailLen, _header.sampleSize);
-
- _header.sampleSize = (uint16) tailLen; // Use the part that's left
- }
-
- if (_header.pitch > 0x7F) { // Check if the pitch is invalid
- warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resnum, _header.pitch);
-
- _header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too
- }
-
- // Finalize the header info using the 8-bit unsigned sample data
- _header.finalize(stream);
-
- // Convert sample data from 8-bit unsigned to 8-bit signed format
- stream.seek(sampleStartPos);
- _sample = new int8[_header.sampleSize];
-
- if (_sample != NULL)
- _isValid = SoundMgr::convertWave(stream, _sample, _header.sampleSize);
- }
-
- if (!_isValid) // Check for errors
- warning("Error creating Apple IIGS sample from resource %d (Type %d, length %d)", resnum, _header.type, len);
-}
-
-/** Reads an Apple IIGS envelope from then given stream. */
-bool IIgsEnvelope::read(Common::SeekableReadStream &stream) {
- for (int segNum = 0; segNum < ENVELOPE_SEGMENT_COUNT; segNum++) {
- seg[segNum].bp = stream.readByte();
- seg[segNum].inc = stream.readUint16LE();
- }
-
- return !(stream.eos() || stream.err());
-}
-
-/** Reads an Apple IIGS wave information structure from the given stream. */
-bool IIgsWaveInfo::read(Common::SeekableReadStream &stream, bool ignoreAddr) {
- top = stream.readByte();
- addr = stream.readByte() * 256;
- size = (1 << (stream.readByte() & 7)) * 256;
-
- // Read packed mode byte and parse it into parts
- byte packedModeByte = stream.readByte();
- channel = (packedModeByte >> 4) & 1; // Bit 4
- mode = (packedModeByte >> 1) & 3; // Bits 1-2
- halt = (packedModeByte & 1) != 0; // Bit 0 (Converted to boolean)
-
- relPitch = stream.readSint16LE();
-
- // Zero the wave address if we want to ignore the wave address info
- if (ignoreAddr)
- addr = 0;
-
- return !(stream.eos() || stream.err());
-}
-
-bool IIgsWaveInfo::finalize(Common::SeekableReadStream &uint8Wave) {
- uint32 startPos = uint8Wave.pos(); // Save stream's starting position
- uint8Wave.seek(addr, SEEK_CUR); // Seek to wave's address
-
- // Calculate the true sample size (A zero ends the sample prematurely)
- uint trueSize = size; // Set a default value for the result
- for (uint i = 0; i < size; i++) {
- if (uint8Wave.readByte() == 0) {
- trueSize = i;
- // A zero in the sample stream turns off looping
- // (At least that's what MESS 0.117 and KEGS32 0.91 seem to do)
- if (mode == OSC_MODE_LOOP)
- mode = OSC_MODE_ONESHOT;
- break;
- }
- }
- size = trueSize; // Set the true sample size
-
- uint8Wave.seek(startPos); // Seek back to the stream's starting position
-
- return true;
-}
-
-bool IIgsOscillator::finalize(Common::SeekableReadStream &uint8Wave) {
- for (uint i = 0; i < WAVES_PER_OSCILLATOR; i++)
- if (!waves[i].finalize(uint8Wave))
- return false;
-
- return true;
-}
-
-bool IIgsOscillatorList::read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr) {
- // First read the A waves and then the B waves for the oscillators
- for (uint waveNum = 0; waveNum < WAVES_PER_OSCILLATOR; waveNum++)
- for (uint oscNum = 0; oscNum < oscillatorCount; oscNum++)
- if (!osc[oscNum].waves[waveNum].read(stream, ignoreAddr))
- return false;
-
- count = oscillatorCount; // Set the oscillator count
-
- return true;
-}
-
-bool IIgsOscillatorList::finalize(Common::SeekableReadStream &uint8Wave) {
- for (uint i = 0; i < count; i++)
- if (!osc[i].finalize(uint8Wave))
- return false;
-
- return true;
-}
-
-bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreAddr) {
- env.read(stream);
- relseg = stream.readByte();
- /*byte priority =*/ stream.readByte(); // Not needed? 32 in all tested data.
- bendrange = stream.readByte();
- vibdepth = stream.readByte();
- vibspeed = stream.readByte();
- /*byte spare =*/ stream.readByte(); // Not needed? 0 in all tested data.
- byte wac = stream.readByte(); // Read A wave count
- byte wbc = stream.readByte(); // Read B wave count
- oscList.read(stream, wac, ignoreAddr); // Read the oscillators
- return (wac == wbc) && !(stream.eos() || stream.err()); // A and B wave counts must match
-}
-
-bool IIgsInstrumentHeader::finalize(Common::SeekableReadStream &uint8Wave) {
- return oscList.finalize(uint8Wave);
-}
-
-bool IIgsSampleHeader::read(Common::SeekableReadStream &stream) {
- type = stream.readUint16LE();
- pitch = stream.readByte();
- unknownByte_Ofs3 = stream.readByte();
- volume = stream.readByte();
- unknownByte_Ofs5 = stream.readByte();
- instrumentSize = stream.readUint16LE();
- sampleSize = stream.readUint16LE();
- // Read the instrument header *ignoring* its wave address info
-
- return instrument.read(stream, true);
-}
-
-bool IIgsSampleHeader::finalize(Common::SeekableReadStream &uint8Wave) {
- return instrument.finalize(uint8Wave);
-}
-
-/** Older Apple IIGS AGI MIDI program change to instrument number mapping. */
-static const MidiProgramChangeMapping progToInstMappingV1 = {
- {19, 20, 22, 23, 21, 24, 5, 5, 5, 5,
- 6, 7, 10, 9, 11, 9, 15, 8, 5, 5,
- 17, 16, 18, 12, 14, 5, 5, 5, 5, 5,
- 0, 1, 2, 9, 3, 4, 15, 2, 2, 2,
- 25, 13, 13, 25},
- 5
-};
-
-/** Newer Apple IIGS AGI MIDI program change to instrument number mapping. */
-static const MidiProgramChangeMapping progToInstMappingV2 = {
- {21, 22, 24, 25, 23, 26, 6, 6, 6, 6,
- 7, 9, 12, 8, 13, 11, 17, 10, 6, 6,
- 19, 18, 20, 14, 16, 6, 6, 6, 6, 6,
- 0, 1, 2, 4, 3, 5, 17, 2, 2, 2,
- 27, 15, 15, 27},
- 6
-};
-
-/** Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002). */
-static const InstrumentSetInfo instSetV1 = {
- 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", progToInstMappingV1
-};
-
-/** Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I. */
-static const InstrumentSetInfo instSetV2 = {
- 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", progToInstMappingV2
-};
-
-/** Information about different Apple IIGS AGI executables. */
-static const IIgsExeInfo IIgsExeInfos[] = {
- {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, instSetV1},
- {GID_LSL1, "LL", 0x1003, 141003, 0x844E, instSetV2},
- {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, instSetV2},
- {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, instSetV2},
- {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, instSetV2},
- {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, instSetV2},
- {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, instSetV2},
- {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, instSetV2},
- {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, instSetV2},
- {GID_MH1, "MH", 0x2004, 147678, 0x8979, instSetV2},
- {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, instSetV2},
- {GID_BC, "BC", 0x3001, 148192, 0x8979, instSetV2},
- {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2}
-};
-
-static const int16 waveformRamp[WAVEFORM_SIZE] = {
- 0, 8, 16, 24, 32, 40, 48, 56,
- 64, 72, 80, 88, 96, 104, 112, 120,
- 128, 136, 144, 152, 160, 168, 176, 184,
- 192, 200, 208, 216, 224, 232, 240, 255,
- 0, -248, -240, -232, -224, -216, -208, -200,
- -192, -184, -176, -168, -160, -152, -144, -136,
- -128, -120, -112, -104, -96, -88, -80, -72,
- -64, -56, -48, -40, -32, -24, -16, -8 // Ramp up
-};
-
-static const int16 waveformSquare[WAVEFORM_SIZE] = {
- 255, 230, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 110,
- -255, -230, -220, -220, -220, -220, -220, -220,
- -220, -220, -220, -220, -220, -220, -220, -220,
- -220, -220, -220, -220, -220, -220, -220, -220,
- -220, -220, -220, -110, 0, 0, 0, 0 // Square
-};
-
-static const int16 waveformMac[WAVEFORM_SIZE] = {
- 45, 110, 135, 161, 167, 173, 175, 176,
- 156, 137, 123, 110, 91, 72, 35, -2,
- -60, -118, -142, -165, -170, -176, -177, -179,
- -177, -176, -164, -152, -117, -82, -17, 47,
- 92, 137, 151, 166, 170, 173, 171, 169,
- 151, 133, 116, 100, 72, 43, -7, -57,
- -99, -141, -156, -170, -174, -177, -178, -179,
- -175, -172, -165, -159, -137, -114, -67, -19
-};
-
+#if 0
static const uint16 period[] = {
1024, 1085, 1149, 1218, 1290, 1367,
1448, 1534, 1625, 1722, 1825, 1933
};
-#if 0
static int noteToPeriod(int note) {
return 10 * (period[note % 12] >> (note / 12 - 3));
}
@@ -346,8 +101,7 @@ void SoundMgr::unloadSound(int resnum) {
}
void SoundMgr::startSound(int resnum, int flag) {
- int i;
- AgiSoundType type;
+ AgiSoundEmuType type;
if (_vm->_game.sounds[resnum] != NULL && _vm->_game.sounds[resnum]->isPlaying())
return;
@@ -357,7 +111,7 @@ void SoundMgr::startSound(int resnum, int flag) {
if (_vm->_game.sounds[resnum] == NULL) // Is this needed at all?
return;
- type = (AgiSoundType)_vm->_game.sounds[resnum]->type();
+ type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type();
if (type != AGI_SOUND_SAMPLE && type != AGI_SOUND_MIDI && type != AGI_SOUND_4CHN)
return;
@@ -367,39 +121,8 @@ void SoundMgr::startSound(int resnum, int flag) {
debugC(3, kDebugLevelSound, "startSound(resnum = %d, flag = %d) type = %d", resnum, flag, type);
- switch (type) {
- case AGI_SOUND_SAMPLE: {
- IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[_playingSound];
- _gsSound.playSampleSound(sampleRes->getHeader(), sampleRes->getSample());
- break;
- }
- case AGI_SOUND_MIDI:
- ((IIgsMidi *) _vm->_game.sounds[_playingSound])->rewind();
- break;
- case AGI_SOUND_4CHN:
- PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum];
-
- // Initialize channel info
- for (i = 0; i < NUM_CHANNELS; i++) {
- _chn[i].type = type;
- _chn[i].flags = AGI_SOUND_LOOP;
-
- if (_env) {
- _chn[i].flags |= AGI_SOUND_ENVELOPE;
- _chn[i].adsr = AGI_SOUND_ENV_ATTACK;
- }
-
- _chn[i].ins = _waveform;
- _chn[i].size = WAVEFORM_SIZE;
- _chn[i].ptr = pcjrSound->getVoicePointer(i % 4);
- _chn[i].timer = 0;
- _chn[i].vol = 0;
- _chn[i].end = 0;
- }
- break;
- }
+ _soundGen->play(resnum);
- memset(_sndBuffer, 0, BUFFER_SIZE << 1);
_endflag = flag;
// Nat Budin reports that the flag should be reset when sound starts
@@ -407,907 +130,68 @@ void SoundMgr::startSound(int resnum, int flag) {
}
void SoundMgr::stopSound() {
- int i;
-
debugC(3, kDebugLevelSound, "stopSound() --> %d", _playingSound);
_endflag = -1;
- if (_vm->_soundemu != SOUND_EMU_APPLE2GS) {
- for (i = 0; i < NUM_CHANNELS; i++)
- stopNote(i);
- }
if (_playingSound != -1) {
if (_vm->_game.sounds[_playingSound]) // sanity checking
_vm->_game.sounds[_playingSound]->stop();
- if (_vm->_soundemu == SOUND_EMU_APPLE2GS) {
- _gsSound.stopSounds();
- }
+ _soundGen->stop();
_playingSound = -1;
}
-}
-void IIgsSoundMgr::stopSounds() {
- // Stops all sounds on all MIDI channels
- for (iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter)
- iter->stopSounds();
+ if (_endflag != -1)
+ _vm->setflag(_endflag, true);
}
-bool IIgsSoundMgr::playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample) {
- stopSounds();
- IIgsMidiChannel &channel = _midiChannels[kSfxMidiChannel];
+int SoundMgr::initSound() {
+ return -1;
+}
- channel.setInstrument(&sampleHeader.instrument, sample);
- channel.setVolume(sampleHeader.volume);
- channel.noteOn(sampleHeader.pitch, 64); // Use default velocity (i.e. 64)
+void SoundMgr::deinitSound() {
+ stopSound();
- return true;
+ delete _soundGen;
}
-void IIgsMidiChannel::stopSounds() {
- // Stops all sounds on this single MIDI channel
- for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter)
- iter->stop();
+void SoundMgr::soundIsFinished() {
+ if (_endflag != -1)
+ _vm->setflag(_endflag, true);
- _gsChannels.clear();
+ if (_playingSound != -1)
+ _vm->_game.sounds[_playingSound]->stop();
+ _playingSound = -1;
+ _endflag = -1;
}
-int SoundMgr::initSound() {
- int r = -1;
-
- memset(_sndBuffer, 0, BUFFER_SIZE << 1);
- _env = false;
+SoundMgr::SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer) {
+ _vm = agi;
+ _endflag = -1;
+ _playingSound = -1;
switch (_vm->_soundemu) {
case SOUND_EMU_NONE:
- _waveform = waveformRamp;
- _env = true;
- break;
case SOUND_EMU_AMIGA:
- case SOUND_EMU_PC:
- _waveform = waveformSquare;
- break;
case SOUND_EMU_MAC:
- _waveform = waveformMac;
+ _soundGen = new SoundGenSarien(_vm, pMixer);
+ break;
+ case SOUND_EMU_PC:
+ case SOUND_EMU_PCJR:
+ _soundGen = new SoundGenPCJr(_vm, pMixer);
break;
case SOUND_EMU_APPLE2GS:
- _disabledMidi = !loadInstruments();
+ _soundGen = new SoundGen2GS(_vm, pMixer);
break;
case SOUND_EMU_COCO3:
+ _soundGen = new SoundGenCoCo3(_vm, pMixer);
break;
- }
-
- report("Initializing sound:\n");
-
- report("sound: envelopes ");
- if (_env) {
- report("enabled (decay=%d, sustain=%d)\n", ENV_DECAY, ENV_SUSTAIN);
- } else {
- report("disabled\n");
- }
-
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
- return r;
-}
-
-void SoundMgr::deinitSound() {
- debugC(3, kDebugLevelSound, "()");
-
- _mixer->stopHandle(_soundHandle);
-}
-
-void SoundMgr::stopNote(int i) {
- _chn[i].adsr = AGI_SOUND_ENV_RELEASE;
-
- if (_useChorus) {
- // Stop chorus ;)
- if (_chn[i].type == AGI_SOUND_4CHN &&
- _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
- stopNote(i + 4);
- }
- }
-}
-
-void SoundMgr::playNote(int i, int freq, int vol) {
- if (!_vm->getflag(fSoundOn))
- vol = 0;
- else if (vol && _vm->_soundemu == SOUND_EMU_PC)
- vol = 160;
-
- _chn[i].phase = 0;
- _chn[i].freq = freq;
- _chn[i].vol = vol;
- _chn[i].env = 0x10000;
- _chn[i].adsr = AGI_SOUND_ENV_ATTACK;
-
- if (_useChorus) {
- // Add chorus ;)
- if (_chn[i].type == AGI_SOUND_4CHN &&
- _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
-
- int newfreq = freq * 1007 / 1000;
-
- if (freq == newfreq)
- newfreq++;
-
- playNote(i + 4, newfreq, vol * 2 / 3);
- }
- }
-}
-
-void SoundMgr::playMidiSound() {
- if (_disabledMidi)
- return;
-
- const uint8 *p;
- uint8 parm1, parm2;
- static uint8 cmd, ch;
-
- if (_playingSound == -1 || _vm->_game.sounds[_playingSound] == NULL) {
- warning("Error playing Apple IIGS MIDI sound resource");
- _playing = false;
-
- return;
- }
-
- IIgsMidi *midiObj = (IIgsMidi *) _vm->_game.sounds[_playingSound];
-
- _playing = true;
- p = midiObj->getPtr();
-
- midiObj->_soundBufTicks++;
-
- while (true) {
- uint8 readByte = *p;
-
- // Check for end of MIDI sequence marker (Can also be here before delta-time)
- if (readByte == MIDI_BYTE_STOP_SEQUENCE) {
- debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)");
- _playing = false;
-
- midiObj->rewind();
-
- return;
- } else if (readByte == MIDI_BYTE_TIMER_SYNC) {
- debugC(3, kDebugLevelSound, "Timer sync");
- p++; // Jump over the timer sync byte as it's not needed
-
- continue;
- }
-
- uint8 deltaTime = readByte;
- if (midiObj->_midiTicks + deltaTime > midiObj->_soundBufTicks) {
- break;
- }
- midiObj->_midiTicks += deltaTime;
- p++; // Jump over the delta-time byte as it was already taken care of
-
- // Check for end of MIDI sequence marker (This time it after reading delta-time)
- if (*p == MIDI_BYTE_STOP_SEQUENCE) {
- debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)");
- _playing = false;
-
- midiObj->rewind();
-
- return;
- }
-
- // Separate byte into command and channel if it's a command byte.
- // Otherwise use running status (i.e. previously set command and channel).
- if (*p & 0x80) {
- cmd = *p++;
- ch = cmd & 0x0f;
- cmd >>= 4;
- }
-
- switch (cmd) {
- case MIDI_CMD_NOTE_OFF:
- parm1 = *p++;
- parm2 = *p++;
- _gsSound.midiNoteOff(ch, parm1, parm2);
- break;
- case MIDI_CMD_NOTE_ON:
- parm1 = *p++;
- parm2 = *p++;
- _gsSound.midiNoteOn(ch, parm1, parm2);
- break;
- case MIDI_CMD_CONTROLLER:
- parm1 = *p++;
- parm2 = *p++;
- _gsSound.midiController(ch, parm1, parm2);
- break;
- case MIDI_CMD_PROGRAM_CHANGE:
- parm1 = *p++;
- _gsSound.midiProgramChange(ch, parm1);
- break;
- case MIDI_CMD_PITCH_WHEEL:
- parm1 = *p++;
- parm2 = *p++;
-
- uint16 wheelPos = ((parm2 & 0x7F) << 7) | (parm1 & 0x7F); // 14-bit value
- _gsSound.midiPitchWheel(wheelPos);
- break;
- }
- }
-
- midiObj->setPtr(p);
-}
-
-void IIgsSoundMgr::midiNoteOff(uint8 channel, uint8 note, uint8 velocity) {
- _midiChannels[channel].noteOff(note, velocity);
- debugC(3, kDebugLevelSound, "note off, channel %02x, note %02x, velocity %02x", channel, note, velocity);
-}
-
-void IIgsSoundMgr::midiNoteOn(uint8 channel, uint8 note, uint8 velocity) {
- _midiChannels[channel].noteOn(note, velocity);
- debugC(3, kDebugLevelSound, "note on, channel %02x, note %02x, velocity %02x", channel, note, velocity);
-}
-
-// TODO: Check if controllers behave differently on different MIDI channels
-// TODO: Doublecheck what other controllers than the volume controller do
-void IIgsSoundMgr::midiController(uint8 channel, uint8 controller, uint8 value) {
- IIgsMidiChannel &midiChannel = _midiChannels[channel];
-
- // The tested Apple IIGS AGI MIDI resources only used
- // controllers 0 (Bank select?), 7 (Volume) and 64 (Sustain On/Off).
- // Controller 0's parameter was in range 94-127,
- // controller 7's parameter was in range 0-127 and
- // controller 64's parameter was always 0 (i.e. sustain off).
- bool unimplemented = false;
- switch (controller) {
- case 7: // Volume
- midiChannel.setVolume(value);
- break;
- default:
- unimplemented = true;
+ case SOUND_EMU_MIDI:
+ _soundGen = new SoundGenMIDI(_vm, pMixer);
break;
}
- debugC(3, kDebugLevelSound, "controller %02x, ch %02x, val %02x%s", controller, channel, value, unimplemented ? " (Unimplemented)" : "");
-}
-
-void IIgsSoundMgr::midiProgramChange(uint8 channel, uint8 program) {
- _midiChannels[channel].setInstrument(getInstrument(program), _wave.begin());
- debugC(3, kDebugLevelSound, "program change %02x, channel %02x", program, channel);
-}
-
-void IIgsSoundMgr::midiPitchWheel(uint8 wheelPos) {
- // In all the tested Apple IIGS AGI MIDI resources
- // pitch wheel commands always used 0x2000 (Center position).
- // Therefore it should be quite safe to ignore this command.
- debugC(3, kDebugLevelSound, "pitch wheel position %04x (Unimplemented)", wheelPos);
-}
-
-IIgsSoundMgr::IIgsSoundMgr() {
- _midiChannels.resize(16); // Set the amount of available MIDI channels
-}
-
-const IIgsInstrumentHeader* IIgsSoundMgr::getInstrument(uint8 program) const {
- return &_instruments[_midiProgToInst->map(program)];
-}
-
-void IIgsSoundMgr::setProgramChangeMapping(const MidiProgramChangeMapping *mapping) {
- _midiProgToInst = mapping;
-}
-
-void IIgsSoundMgr::removeStoppedSounds() {
- for (Common::Array<IIgsMidiChannel>::iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter)
- iter->removeStoppedSounds();
-}
-
-void IIgsMidiChannel::removeStoppedSounds() {
- for (int i = _gsChannels.size() - 1; i >= 0; i--)
- if (!_gsChannels[i].playing())
- _gsChannels.remove_at(i);
-}
-
-uint IIgsSoundMgr::activeSounds() const {
- uint result = 0;
-
- for (Common::Array<IIgsMidiChannel>::const_iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter)
- result += iter->activeSounds();
-
- return result;
-}
-
-uint IIgsMidiChannel::activeSounds() const {
- uint result = 0;
-
- for (const_iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter)
- if (!iter->end)
- result++;
-
- return result;
-}
-
-void IIgsMidiChannel::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) {
- _instrument = instrument;
- _sample = sample;
-
- // Set program on each Apple IIGS channel playing on this MIDI channel
- for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter)
- iter->setInstrument(instrument, sample);
-}
-
-void IIgsMidiChannel::setVolume(uint8 volume) {
- _volume = volume;
-
- // Set volume on each Apple IIGS channel playing on this MIDI channel
- for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter)
- iter->setChannelVolume(volume);
-}
-
-void IIgsMidiChannel::noteOff(uint8 note, uint8 velocity) {
- // Go through all the notes playing on this MIDI channel
- // and turn off the ones that are playing the given note
- for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter)
- if (iter->origNote == note)
- iter->noteOff(velocity);
-}
-
-void IIgsMidiChannel::noteOn(uint8 note, uint8 velocity) {
- IIgsChannelInfo channel;
-
- // Use the default channel volume and instrument
- channel.setChannelVolume(_volume);
- channel.setInstrument(_instrument, _sample);
-
- // Set the note on and save the channel
- channel.noteOn(note, velocity);
- _gsChannels.push_back(channel);
-}
-
-void IIgsChannelInfo::rewind() {
- this->envVol = this->startEnvVol;
- this->envSeg = 0;
- this->pos = intToFrac(0);
-}
-
-void IIgsChannelInfo::setChannelVolume(uint8 volume) {
- this->chanVol = intToFrac(volume);
-}
-
-void IIgsChannelInfo::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) {
- assert(instrument != NULL && sample != NULL);
- this->ins = instrument;
- this->unrelocatedSample = sample;
-}
-
-// TODO/FIXME: Implement correctly and fully (Take velocity into account etc)
-void IIgsChannelInfo::noteOn(uint8 noteParam, uint8 velocity) {
- this->origNote = noteParam;
- this->startEnvVol = intToFrac(0);
- rewind();
-
- const IIgsWaveInfo *waveInfo = NULL;
-
- for (uint i = 0; i < ins->oscList.count; i++)
- if (ins->oscList(i).waves[0].top >= noteParam)
- waveInfo = &ins->oscList(i).waves[0];
-
- assert(waveInfo != NULL);
-
- this->relocatedSample = this->unrelocatedSample + waveInfo->addr;
- this->posAdd = intToFrac(0);
- this->note = intToFrac(noteParam) + doubleToFrac(waveInfo->relPitch/256.0);
- this->vol = doubleToFrac(fracToDouble(this->envVol) * fracToDouble(this->chanVol) / 127.0);
- this->loop = (waveInfo->mode == OSC_MODE_LOOP);
- this->size = waveInfo->size - waveInfo->addr;
- this->end = waveInfo->halt;
-}
-
-// TODO/FIXME: Implement correctly and fully (Take release time and velocity into account etc)
-void IIgsChannelInfo::noteOff(uint8 velocity) {
- this->loop = false;
- this->envSeg = ins->relseg;
-}
-
-void IIgsChannelInfo::stop() {
- this->end = true;
-}
-
-bool IIgsChannelInfo::playing() {
- return !this->end;
-}
-
-void SoundMgr::playSampleSound() {
- if (_vm->_soundemu != SOUND_EMU_APPLE2GS) {
- warning("Trying to play a sample but not using Apple IIGS sound emulation mode");
- return;
- }
-
- if (_playingSound != -1)
- _playing = _gsSound.activeSounds() > 0;
-}
-
-static int cocoFrequencies[] = {
- 130, 138, 146, 155, 164, 174, 184, 195, 207, 220, 233, 246,
- 261, 277, 293, 311, 329, 349, 369, 391, 415, 440, 466, 493,
- 523, 554, 587, 622, 659, 698, 739, 783, 830, 880, 932, 987,
- 1046, 1108, 1174, 1244, 1318, 1396, 1479, 1567, 1661, 1760, 1864, 1975,
- 2093, 2217, 2349, 2489, 2637, 2793, 2959, 3135, 3322, 3520, 3729, 3951
-};
-
-void SoundMgr::playCoCoSound() {
- int i = 0;
- CoCoNote note;
-
- do {
- note.read(_chn[i].ptr);
-
- if (note.freq != 0xff) {
- playNote(0, cocoFrequencies[note.freq], note.volume);
-
- uint32 start_time = _vm->_system->getMillis();
-
- while (_vm->_system->getMillis() < start_time + note.duration) {
- _vm->_system->updateScreen();
-
- _vm->_system->delayMillis(10);
- }
- }
- } while (note.freq != 0xff);
-}
-
-void SoundMgr::playAgiSound() {
- int i;
- AgiNote note;
-
- _playing = false;
- for (i = 0; i < (_vm->_soundemu == SOUND_EMU_PC ? 1 : 4); i++) {
- _playing |= !_chn[i].end;
- note.read(_chn[i].ptr); // Read a single note (Doesn't advance the pointer)
-
- if (_chn[i].end)
- continue;
-
- if ((--_chn[i].timer) <= 0) {
- stopNote(i);
-
- if (note.freqDiv != 0) {
- int volume = (note.attenuation == 0x0F) ? 0 : (0xFF - note.attenuation * 2);
- playNote(i, note.freqDiv * 10, volume);
- }
-
- _chn[i].timer = note.duration;
-
- if (_chn[i].timer == 0xffff) {
- _chn[i].end = 1;
- _chn[i].vol = 0;
- _chn[i].env = 0;
-
- if (_useChorus) {
- // chorus
- if (_chn[i].type == AGI_SOUND_4CHN && _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
- _chn[i + 4].vol = 0;
- _chn[i + 4].env = 0;
- }
- }
- }
- _chn[i].ptr += 5; // Advance the pointer to the next note data (5 bytes per note)
- }
- }
-}
-
-void SoundMgr::playSound() {
- int i;
-
- if (_endflag == -1)
- return;
-
- if (_vm->_soundemu == SOUND_EMU_APPLE2GS) {
- if (_playingSound != -1) {
- if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_MIDI) {
- playMidiSound();
- //warning("playSound: Trying to play an Apple IIGS MIDI sound. Not yet implemented");
- } else if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_SAMPLE) {
- //debugC(3, kDebugLevelSound, "playSound: Trying to play an Apple IIGS sample");
- playSampleSound();
- }
- }
- } else if (_vm->_soundemu == SOUND_EMU_COCO3) {
- playCoCoSound();
- } else {
- //debugC(3, kDebugLevelSound, "playSound: Trying to play a PCjr 4-channel sound");
- playAgiSound();
- }
-
- if (!_playing) {
- if (_vm->_soundemu != SOUND_EMU_APPLE2GS) {
- for (i = 0; i < NUM_CHANNELS; _chn[i++].vol = 0)
- ;
- }
-
- if (_endflag != -1)
- _vm->setflag(_endflag, true);
-
- if (_playingSound != -1)
- _vm->_game.sounds[_playingSound]->stop();
- _playingSound = -1;
- _endflag = -1;
- }
-}
-
-uint32 SoundMgr::mixSound() {
- register int i, p;
- const int16 *src;
- int c, b, m;
-
- memset(_sndBuffer, 0, BUFFER_SIZE << 1);
-
- if (!_playing || _playingSound == -1)
- return BUFFER_SIZE;
-
- // Handle Apple IIGS sound mixing here
- // TODO: Implement playing both waves in an oscillator
- // TODO: Implement swap-mode in an oscillator
- if (_vm->_soundemu == SOUND_EMU_APPLE2GS) {
- for (uint midiChan = 0; midiChan < _gsSound._midiChannels.size(); midiChan++) {
- for (uint gsChan = 0; gsChan < _gsSound._midiChannels[midiChan]._gsChannels.size(); gsChan++) {
- IIgsChannelInfo &channel = _gsSound._midiChannels[midiChan]._gsChannels[gsChan];
- if (channel.playing()) { // Only mix in actively playing channels
- // Frequency multiplier was 1076.0 based on tests made with MESS 0.117.
- // Tests made with KEGS32 averaged the multiplier to around 1045.
- // So this is a guess but maybe it's 1046.5... i.e. C6's frequency?
- double hertz = C6_FREQ * pow(SEMITONE, fracToDouble(channel.note));
- channel.posAdd = doubleToFrac(hertz / getRate());
- channel.vol = doubleToFrac(fracToDouble(channel.envVol) * fracToDouble(channel.chanVol) / 127.0);
- double tempVol = fracToDouble(channel.vol)/127.0;
- for (i = 0; i < IIGS_BUFFER_SIZE; i++) {
- b = channel.relocatedSample[fracToInt(channel.pos)];
- // TODO: Find out what volume/amplification setting is loud enough
- // but still doesn't clip when playing many channels on it.
- _sndBuffer[i] += (int16) (b * tempVol * 256/4);
- channel.pos += channel.posAdd;
-
- if (channel.pos >= intToFrac(channel.size)) {
- if (channel.loop) {
- // Don't divide by zero on zero length samples
- channel.pos %= intToFrac(channel.size + (channel.size == 0));
- // Probably we should loop the envelope too
- channel.envSeg = 0;
- channel.envVol = channel.startEnvVol;
- } else {
- channel.pos = channel.chanVol = 0;
- channel.end = true;
- break;
- }
- }
- }
-
- if (channel.envSeg < ENVELOPE_SEGMENT_COUNT) {
- const IIgsEnvelopeSegment &seg = channel.ins->env.seg[channel.envSeg];
- // I currently assume enveloping works with the same speed as the MIDI
- // (i.e. with 1/60ths of a second ticks).
- // TODO: Check if enveloping really works with the same speed as MIDI
- frac_t envVolDelta = doubleToFrac(seg.inc/256.0);
- if (intToFrac(seg.bp) >= channel.envVol) {
- channel.envVol += envVolDelta;
- if (channel.envVol >= intToFrac(seg.bp)) {
- channel.envVol = intToFrac(seg.bp);
- channel.envSeg += 1;
- }
- } else {
- channel.envVol -= envVolDelta;
- if (channel.envVol <= intToFrac(seg.bp)) {
- channel.envVol = intToFrac(seg.bp);
- channel.envSeg += 1;
- }
- }
- }
- }
- }
- }
- _gsSound.removeStoppedSounds();
- return IIGS_BUFFER_SIZE;
- } // else ...
-
- // Handle PCjr 4-channel sound mixing here
- for (c = 0; c < NUM_CHANNELS; c++) {
- if (!_chn[c].vol)
- continue;
-
- m = _chn[c].flags & AGI_SOUND_ENVELOPE ?
- _chn[c].vol * _chn[c].env >> 16 : _chn[c].vol;
-
- if (_chn[c].type != AGI_SOUND_4CHN || c != 3) {
- src = _chn[c].ins;
-
- p = _chn[c].phase;
- for (i = 0; i < BUFFER_SIZE; i++) {
- b = src[p >> 8];
-#ifdef USE_INTERPOLATION
- b += ((src[((p >> 8) + 1) % _chn[c].size] - src[p >> 8]) * (p & 0xff)) >> 8;
-#endif
- _sndBuffer[i] += (b * m) >> 4;
-
- p += (uint32) 118600 *4 / _chn[c].freq;
-
- // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what
- // needs fixing, or remove it!
- // FIXME
- if (_chn[c].flags & AGI_SOUND_LOOP) {
- p %= _chn[c].size << 8;
- } else {
- if (p >= _chn[c].size << 8) {
- p = _chn[c].vol = 0;
- _chn[c].end = 1;
- break;
- }
- }
-
- }
- _chn[c].phase = p;
- } else {
- // Add white noise
- for (i = 0; i < BUFFER_SIZE; i++) {
- b = _vm->_rnd->getRandomNumber(255) - 128;
- _sndBuffer[i] += (b * m) >> 4;
- }
- }
-
- switch (_chn[c].adsr) {
- case AGI_SOUND_ENV_ATTACK:
- // not implemented
- _chn[c].adsr = AGI_SOUND_ENV_DECAY;
- break;
- case AGI_SOUND_ENV_DECAY:
- if (_chn[c].env > _chn[c].vol * ENV_SUSTAIN + ENV_DECAY) {
- _chn[c].env -= ENV_DECAY;
- } else {
- _chn[c].env = _chn[c].vol * ENV_SUSTAIN;
- _chn[c].adsr = AGI_SOUND_ENV_SUSTAIN;
- }
- break;
- case AGI_SOUND_ENV_SUSTAIN:
- break;
- case AGI_SOUND_ENV_RELEASE:
- if (_chn[c].env >= ENV_RELEASE) {
- _chn[c].env -= ENV_RELEASE;
- } else {
- _chn[c].env = 0;
- }
- }
- }
-
- return BUFFER_SIZE;
-}
-
-/**
- * Finds information about an Apple IIGS AGI executable based on the game ID.
- * @return A non-null IIgsExeInfo pointer if successful, otherwise NULL.
- */
-const IIgsExeInfo *SoundMgr::getIIgsExeInfo(enum AgiGameID gameid) const {
- for (int i = 0; i < ARRAYSIZE(IIgsExeInfos); i++)
- if (IIgsExeInfos[i].gameid == gameid)
- return &IIgsExeInfos[i];
- return NULL;
-}
-
-bool IIgsSoundMgr::loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo) {
- bool loadedOk = false; // Was loading successful?
- Common::File file;
-
- // Open the executable file and check that it has correct size
- file.open(exePath);
- if (file.size() != (int32)exeInfo.exeSize) {
- debugC(3, kDebugLevelSound, "Apple IIGS executable (%s) has wrong size (Is %d, should be %d)",
- exePath.getPath().c_str(), file.size(), exeInfo.exeSize);
- }
-
- // Read the whole executable file into memory
- Common::SharedPtr<Common::MemoryReadStream> data(file.readStream(file.size()));
- file.close();
-
- // Check that we got enough data to be able to parse the instruments
- if (data && data->size() >= (int32)(exeInfo.instSetStart + exeInfo.instSet.byteCount)) {
- // Check instrument set's length (The info's saved in the executable)
- data->seek(exeInfo.instSetStart - 4);
- uint16 instSetByteCount = data->readUint16LE();
- if (instSetByteCount != exeInfo.instSet.byteCount) {
- debugC(3, kDebugLevelSound, "Wrong instrument set size (Is %d, should be %d) in Apple IIGS executable (%s)",
- instSetByteCount, exeInfo.instSet.byteCount, exePath.getPath().c_str());
- }
-
- // Check instrument set's md5sum
- data->seek(exeInfo.instSetStart);
-
- char md5str[32+1];
- Common::md5_file_string(*data, md5str, exeInfo.instSet.byteCount);
- if (scumm_stricmp(md5str, exeInfo.instSet.md5)) {
- warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless",
- md5str, exePath.getPath().c_str());
- }
-
- // Read in the instrument set one instrument at a time
- data->seek(exeInfo.instSetStart);
-
- // Load the instruments
- _instruments.clear();
- _instruments.reserve(exeInfo.instSet.instCount);
-
- IIgsInstrumentHeader instrument;
- for (uint i = 0; i < exeInfo.instSet.instCount; i++) {
- if (!instrument.read(*data)) {
- warning("Error loading Apple IIGS instrument (%d. of %d) from %s, not loading more instruments",
- i + 1, exeInfo.instSet.instCount, exePath.getPath().c_str());
- break;
- }
- _instruments.push_back(instrument); // Add the successfully loaded instrument to the instruments array
- }
-
- // Loading was successful only if all instruments were loaded successfully
- loadedOk = (_instruments.size() == exeInfo.instSet.instCount);
- } else // Couldn't read enough data from the executable file
- warning("Error loading instruments from Apple IIGS executable (%s)", exePath.getPath().c_str());
-
- return loadedOk;
-}
-
-/**
- * Convert sample from 8-bit unsigned to 8-bit signed format.
- * @param source Source stream containing the 8-bit unsigned sample data.
- * @param dest Destination buffer for the 8-bit signed sample data.
- * @param length Length of the sample data to be converted.
- */
-bool SoundMgr::convertWave(Common::SeekableReadStream &source, int8 *dest, uint length) {
- // Convert the wave from 8-bit unsigned to 8-bit signed format
- for (uint i = 0; i < length; i++)
- dest[i] = (int8) ((int) source.readByte() - 128);
- return !(source.eos() || source.err());
-}
-
-bool IIgsSoundMgr::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo) {
- Common::File file;
-
- // Open the wave file and read it into memory
- file.open(wavePath);
- Common::SharedPtr<Common::MemoryReadStream> uint8Wave(file.readStream(file.size()));
- file.close();
-
- // Check that we got the whole wave file
- if (uint8Wave && uint8Wave->size() == SIERRASTANDARD_SIZE) {
- // Check wave file's md5sum
- char md5str[32+1];
- Common::md5_file_string(*uint8Wave, md5str, SIERRASTANDARD_SIZE);
- if (scumm_stricmp(md5str, exeInfo.instSet.waveFileMd5)) {
- warning("Unknown Apple IIGS wave file (md5: %s, game: %s).\n" \
- "Please report the information on the previous line to the ScummVM team.\n" \
- "Using the wave file as it is - music may sound weird", md5str, exeInfo.exePrefix);
- }
-
- uint8Wave->seek(0); // Seek wave to its start
- // Convert the wave file from 8-bit unsigned to 8-bit signed and save the result
- _wave.resize(uint8Wave->size());
- return SoundMgr::convertWave(*uint8Wave, _wave.begin(), uint8Wave->size());
- } else { // Couldn't read the wave file or it had incorrect size
- warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.getPath().c_str());
- return false;
- }
-}
-
-/**
- * A function object (i.e. a functor) for testing if a Common::FSNode
- * 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 Common::FSNode&, bool> {
-// FIXME: This should be replaced; use SearchMan instead
- fsnodeNameEqualsIgnoreCase(const Common::StringArray &str) : _str(str) {}
- fsnodeNameEqualsIgnoreCase(const Common::String str) { _str.push_back(str); }
- bool operator()(const Common::FSNode &param) const {
- for (Common::StringArray::const_iterator iter = _str.begin(); iter != _str.end(); ++iter)
- if (param.getName().equalsIgnoreCase(*iter))
- return true;
- return false;
- }
-private:
- Common::StringArray _str;
-};
-
-bool SoundMgr::loadInstruments() {
- // Check that the platform is Apple IIGS, as only it uses custom instruments
- if (_vm->getPlatform() != Common::kPlatformApple2GS) {
- debugC(3, kDebugLevelSound, "Platform isn't Apple IIGS so not loading any instruments");
- return true;
- }
-
- // Get info on the particular Apple IIGS AGI game's executable
- const IIgsExeInfo *exeInfo = getIIgsExeInfo((enum AgiGameID) _vm->getGameID());
- if (exeInfo == NULL) {
- warning("Unsupported Apple IIGS game, not loading instruments");
- return false;
- }
-
- // List files in the game path
- Common::FSList fslist;
- Common::FSNode dir(ConfMan.get("path"));
- if (!dir.getChildren(fslist, Common::FSNode::kListFilesOnly)) {
- warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.getPath().c_str());
- return false;
- }
-
- // Populate executable filenames list (Long filename and short filename) for searching
- Common::StringArray exeNames;
- exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS16");
- exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS");
-
- // Populate wave filenames list (Long filename and short filename) for searching
- Common::StringArray waveNames;
- waveNames.push_back("SIERRASTANDARD");
- waveNames.push_back("SIERRAST");
-
- // Search for the executable file and the wave file (i.e. check if any of the filenames match)
- 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));
-
- // Make sure that we found the executable file
- if (exeFsnode == fslist.end()) {
- warning("Couldn't find Apple IIGS game executable (%s), not loading instruments", exeNames.begin()->c_str());
- return false;
- }
-
- // Make sure that we found the wave file
- if (waveFsnode == fslist.end()) {
- warning("Couldn't find Apple IIGS wave file (%s), not loading instruments", waveNames.begin()->c_str());
- return false;
- }
-
- // Set the MIDI program change to instrument number mapping and
- // load the instrument headers and their sample data.
- // None of the tested SIERRASTANDARD-files have zeroes in them so
- // there's no need to check for prematurely ending samples here.
- _gsSound.setProgramChangeMapping(&exeInfo->instSet.progToInst);
- return _gsSound.loadWaveFile(*waveFsnode, *exeInfo) && _gsSound.loadInstrumentHeaders(*exeFsnode, *exeInfo);
-}
-
-void SoundMgr::fillAudio(void *udata, int16 *stream, uint len) {
- SoundMgr *soundMgr = (SoundMgr *)udata;
- uint32 p = 0;
-
- // current number of audio bytes in _sndBuffer
- static uint32 data_available = 0;
- // offset of start of audio bytes in _sndBuffer
- static uint32 data_offset = 0;
-
- len <<= 2;
-
- debugC(5, kDebugLevelSound, "(%p, %p, %d)", (void *)udata, (void *)stream, len);
-
- while (len > data_available) {
- memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, data_available);
- p += data_available;
- len -= data_available;
-
- soundMgr->playSound();
- data_available = soundMgr->mixSound() << 1;
- data_offset = 0;
- }
-
- memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, len);
- data_offset += len;
- data_available -= len;
-}
-
-SoundMgr::SoundMgr(AgiBase *agi, Audio::Mixer *pMixer) : _chn() {
- _vm = agi;
- _mixer = pMixer;
- _sampleRate = pMixer->getOutputRate();
- _endflag = -1;
- _playingSound = -1;
- _env = false;
- _playing = false;
- _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE);
- _waveform = 0;
- _disabledMidi = false;
- _useChorus = true; // FIXME: Currently always true?
-}
-
-void SoundMgr::premixerCall(int16 *data, uint len) {
- fillAudio(this, data, len);
}
void SoundMgr::setVolume(uint8 volume) {
@@ -1315,7 +199,6 @@ void SoundMgr::setVolume(uint8 volume) {
}
SoundMgr::~SoundMgr() {
- free(_sndBuffer);
}
} // End of namespace Agi
diff --git a/engines/agi/sound.h b/engines/agi/sound.h
index 881e3efd56..63b36e017c 100644
--- a/engines/agi/sound.h
+++ b/engines/agi/sound.h
@@ -26,160 +26,18 @@
#ifndef AGI_SOUND_H
#define AGI_SOUND_H
-#include "sound/audiostream.h"
#include "sound/mixer.h"
-#include "common/frac.h"
namespace Agi {
-#define BUFFER_SIZE 410
-
-// Apple IIGS MIDI uses 60 ticks per second (Based on tests with Apple IIGS
-// KQ1 and SQ1 under MESS 0.124a). So we make the audio buffer size to be a
-// 1/60th of a second in length. That should be getSampleRate() / 60 samples
-// in length but as getSampleRate() is always 22050 at the moment we just use
-// the hardcoded value of 368 (22050/60 = 367.5 which rounds up to 368).
-// FIXME: Use getSampleRate() / 60 rather than a hardcoded value
-#define IIGS_BUFFER_SIZE 368
-
#define SOUND_EMU_NONE 0
#define SOUND_EMU_PC 1
-#define SOUND_EMU_TANDY 2
+#define SOUND_EMU_PCJR 2
#define SOUND_EMU_MAC 3
#define SOUND_EMU_AMIGA 4
#define SOUND_EMU_APPLE2GS 5
#define SOUND_EMU_COCO3 6
-
-#define WAVEFORM_SIZE 64
-#define ENV_ATTACK 10000 /**< envelope attack rate */
-#define ENV_DECAY 1000 /**< envelope decay rate */
-#define ENV_SUSTAIN 100 /**< envelope sustain level */
-#define ENV_RELEASE 7500 /**< envelope release rate */
-#define NUM_CHANNELS 7 /**< number of sound channels */
-
-// MIDI command values (Shifted right by 4 so they're in the lower nibble)
-#define MIDI_CMD_NOTE_OFF 0x08
-#define MIDI_CMD_NOTE_ON 0x09
-#define MIDI_CMD_CONTROLLER 0x0B
-#define MIDI_CMD_PROGRAM_CHANGE 0x0C
-#define MIDI_CMD_PITCH_WHEEL 0x0E
-// Whole MIDI byte values (Command and channel info together)
-#define MIDI_BYTE_STOP_SEQUENCE 0xFC
-#define MIDI_BYTE_TIMER_SYNC 0xF8
-
-struct IIgsEnvelopeSegment {
- uint8 bp;
- uint16 inc; ///< 8b.8b fixed point, very probably little endian
-};
-
-#define ENVELOPE_SEGMENT_COUNT 8
-struct IIgsEnvelope {
- IIgsEnvelopeSegment seg[ENVELOPE_SEGMENT_COUNT];
-
- /** Reads an Apple IIGS envelope from then given stream. */
- bool read(Common::SeekableReadStream &stream);
-};
-
-// 2**(1/12) i.e. the 12th root of 2
-#define SEMITONE 1.059463094359295
-
-// C6's frequency is A4's (440 Hz) frequency but one full octave and three semitones higher
-// i.e. C6_FREQ = 440 * pow(2.0, 15/12.0)
-#define C6_FREQ 1046.502261202395
-
-// Size of the SIERRASTANDARD file (i.e. the wave file i.e. the sample data used by the instruments).
-#define SIERRASTANDARD_SIZE 65536
-
-// Maximum number of instruments in an Apple IIGS instrument set.
-// Chosen empirically based on Apple IIGS AGI game data, increase if needed.
-#define MAX_INSTRUMENTS 28
-
-struct IIgsWaveInfo {
- uint8 top;
- uint addr;
- uint size;
-// Oscillator channel
-#define OSC_CHANNEL_RIGHT 0
-#define OSC_CHANNEL_LEFT 1
- uint channel;
-// Oscillator mode
-#define OSC_MODE_LOOP 0
-#define OSC_MODE_ONESHOT 1
-#define OSC_MODE_SYNC_AM 2
-#define OSC_MODE_SWAP 3
- uint mode;
- bool halt;
- int16 relPitch; ///< Relative pitch in semitones (Signed 8b.8b fixed point)
-
- /** Reads an Apple IIGS wave information structure from the given stream. */
- bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false);
- bool finalize(Common::SeekableReadStream &uint8Wave);
-};
-
-// Number of waves per Apple IIGS sound oscillator
-#define WAVES_PER_OSCILLATOR 2
-
-/** An Apple IIGS sound oscillator. Consists always of two waves. */
-struct IIgsOscillator {
- IIgsWaveInfo waves[WAVES_PER_OSCILLATOR];
-
- bool finalize(Common::SeekableReadStream &uint8Wave);
-};
-
-// Maximum number of oscillators in an Apple IIGS instrument.
-// Chosen empirically based on Apple IIGS AGI game data, increase if needed.
-#define MAX_OSCILLATORS 4
-
-/** An Apple IIGS sound oscillator list. */
-struct IIgsOscillatorList {
- uint count; ///< Oscillator count
- IIgsOscillator osc[MAX_OSCILLATORS]; ///< The oscillators
-
- /** Indexing operators for easier access to the oscillators. */
- const IIgsOscillator &operator()(uint index) const { return osc[index]; }
- IIgsOscillator &operator()(uint index) { return osc[index]; }
-
- /** Reads an Apple IIGS oscillator list from the given stream. */
- bool read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr = false);
- bool finalize(Common::SeekableReadStream &uint8Wave);
-};
-
-struct IIgsInstrumentHeader {
- IIgsEnvelope env;
- uint8 relseg;
- uint8 bendrange;
- uint8 vibdepth;
- uint8 vibspeed;
- IIgsOscillatorList oscList;
-
- /**
- * Read an Apple IIGS instrument header from the given stream.
- * @param stream The source stream from which to read the data.
- * @param ignoreAddr Should we ignore wave infos' wave address variable's value?
- * @return True if successful, false otherwise.
- */
- bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false);
- bool finalize(Common::SeekableReadStream &uint8Wave);
-};
-
-struct IIgsSampleHeader {
- uint16 type;
- uint8 pitch; ///< Logarithmic, base is 2**(1/12), unknown multiplier (Possibly in range 1040-1080)
- uint8 unknownByte_Ofs3; // 0x7F in Gold Rush's sound resource 60, 0 in all others.
- uint8 volume; ///< Current guess: Logarithmic in 6 dB steps
- uint8 unknownByte_Ofs5; ///< 0 in all tested samples.
- uint16 instrumentSize; ///< Little endian. 44 in all tested samples. A guess.
- uint16 sampleSize; ///< Little endian. Accurate in all tested samples excluding Manhunter I's sound resource 16.
- IIgsInstrumentHeader instrument;
-
- /**
- * Read an Apple IIGS AGI sample header from the given stream.
- * @param stream The source stream from which to read the data.
- * @return True if successful, false otherwise.
- */
- bool read(Common::SeekableReadStream &stream);
- bool finalize(Common::SeekableReadStream &uint8Wave);
-};
+#define SOUND_EMU_MIDI 7
/**
* AGI sound note structure.
@@ -200,87 +58,38 @@ struct AgiNote {
}
};
-struct IIgsChannelInfo {
- const IIgsInstrumentHeader *ins; ///< Instrument info
- const int8 *relocatedSample; ///< Source sample data (8-bit signed format) using relocation
- const int8 *unrelocatedSample; ///< Source sample data (8-bit signed format) without relocation
- frac_t pos; ///< Current sample position
- frac_t posAdd; ///< Current sample position adder (Calculated using note, vibrato etc)
- uint8 origNote; ///< The original note without the added relative pitch
- frac_t note; ///< Note (With the added relative pitch)
- frac_t vol; ///< Current volume (Takes both channel volume and enveloping into account)
- frac_t chanVol; ///< Channel volume
- frac_t startEnvVol; ///< Starting envelope volume
- frac_t envVol; ///< Current envelope volume
- uint envSeg; ///< Current envelope segment
- uint size; ///< Sample size
- bool loop; ///< Should we loop the sample?
- bool end; ///< Has the playing ended?
-
- void rewind(); ///< Rewinds the sound playing on this channel to its start
- void setChannelVolume(uint8 volume); ///< Sets the channel volume
- void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample); ///< Sets the instrument to be used on this channel
- void noteOn(uint8 noteParam, uint8 velocity); ///< Starts playing a note on this channel
- void noteOff(uint8 velocity); ///< Releases the note on this channel
- void stop(); ///< Stops the note playing on this channel instantly
- bool playing(); ///< Is there a note playing on this channel?
-};
-
-struct CoCoNote {
- uint8 freq;
- uint8 volume;
- uint16 duration; ///< Note duration
-
- /** Reads a CoCoNote through the given pointer. */
- void read(const uint8 *ptr) {
- freq = *ptr;
- volume = *(ptr + 1);
- duration = READ_LE_UINT16(ptr + 2);
- }
-};
-
/**
* AGI sound resource types.
* It's probably coincidence that all the values here are powers of two
* as they're simply the different used values in AGI sound resources'
* starts (The first 16-bit little endian word, to be precise).
*/
-enum AgiSoundType {
+enum AgiSoundEmuType {
AGI_SOUND_SAMPLE = 0x0001,
AGI_SOUND_MIDI = 0x0002,
AGI_SOUND_4CHN = 0x0008
};
-enum AgiSoundFlags {
- AGI_SOUND_LOOP = 0x0001,
- AGI_SOUND_ENVELOPE = 0x0002
-};
-enum AgiSoundEnv {
- AGI_SOUND_ENV_ATTACK = 3,
- AGI_SOUND_ENV_DECAY = 2,
- AGI_SOUND_ENV_SUSTAIN = 1,
- AGI_SOUND_ENV_RELEASE = 0
-};
+class SoundMgr;
-/**
- * AGI engine sound channel structure.
- */
-struct ChannelInfo {
- AgiSoundType type;
- const uint8 *ptr; // Pointer to the AgiNote data
- const int16 *ins;
- int32 size;
- uint32 phase;
- uint32 flags; // ORs values from AgiSoundFlags
- AgiSoundEnv adsr;
- int32 timer;
- uint32 end;
- uint32 freq;
- uint32 vol;
- uint32 env;
-};
+class SoundGen {
+public:
+ SoundGen(AgiEngine *vm, Audio::Mixer *pMixer) : _vm(vm), _mixer(pMixer) {
+ _sampleRate = pMixer->getOutputRate();
+ }
-class SoundMgr;
+ virtual ~SoundGen() {}
+
+ virtual void play(int resnum) = 0;
+ virtual void stop(void) = 0;
+
+ AgiEngine *_vm;
+
+ Audio::Mixer *_mixer;
+ Audio::SoundHandle _soundHandle;
+
+ uint32 _sampleRate;
+};
/**
* AGI sound resource structure.
@@ -302,7 +111,7 @@ public:
* from memory using free() or delegate the responsibility onwards to some other
* function!
*/
- static AgiSound *createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
+ static AgiSound *createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager, int soundemu);
protected:
SoundMgr &_manager; ///< AGI sound manager object
@@ -313,7 +122,7 @@ protected:
class PCjrSound : public AgiSound {
public:
PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
- ~PCjrSound() { if (_data != NULL) free(_data); }
+ ~PCjrSound() { free(_data); }
virtual uint16 type() { return _type; }
const uint8 *getVoicePointer(uint voiceNum);
protected:
@@ -322,192 +131,30 @@ protected:
uint16 _type; ///< Sound resource type
};
-class IIgsMidi : public AgiSound {
-public:
- IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
- ~IIgsMidi() { if (_data != NULL) free(_data); }
- virtual uint16 type() { return _type; }
- virtual const uint8 *getPtr() { return _ptr; }
- virtual void setPtr(const uint8 *ptr) { _ptr = ptr; }
- virtual void rewind() { _ptr = _data + 2; _midiTicks = _soundBufTicks = 0; }
-protected:
- uint8 *_data; ///< Raw sound resource data
- const uint8 *_ptr; ///< Pointer to the current position in the MIDI data
- uint32 _len; ///< Length of the raw sound resource
- uint16 _type; ///< Sound resource type
-public:
- uint _midiTicks; ///< MIDI song position in ticks (1/60ths of a second)
- uint _soundBufTicks; ///< Sound buffer position in ticks (1/60ths of a second)
-};
-
-class IIgsSample : public AgiSound {
-public:
- IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
- ~IIgsSample() { delete[] _sample; }
- virtual uint16 type() { return _header.type; }
- const IIgsSampleHeader &getHeader() const { return _header; }
- const int8 *getSample() const { return _sample; }
-protected:
- IIgsSampleHeader _header; ///< Apple IIGS AGI sample header
- int8 *_sample; ///< Sample data (8-bit signed format)
-};
-
-/** Apple IIGS MIDI program change to instrument number mapping. */
-struct MidiProgramChangeMapping {
- byte midiProgToInst[44]; ///< Lookup table for the MIDI program number to instrument number mapping
- byte undefinedInst; ///< The undefined instrument number
-
- // Maps the MIDI program number to an instrument number
- byte map(uint midiProg) const {
- return midiProg < ARRAYSIZE(midiProgToInst) ? midiProgToInst[midiProg] : undefinedInst;
- }
-};
-
-/** Apple IIGS AGI instrument set information. */
-struct InstrumentSetInfo {
- uint byteCount; ///< Length of the whole instrument set in bytes
- uint instCount; ///< Amount of instrument in the set
- const char *md5; ///< MD5 hex digest of the whole instrument set
- const char *waveFileMd5; ///< MD5 hex digest of the wave file (i.e. the sample data used by the instruments)
- const MidiProgramChangeMapping &progToInst; ///< Program change to instrument number mapping
-};
-
-/** Apple IIGS AGI executable file information. */
-struct IIgsExeInfo {
- enum AgiGameID gameid; ///< Game ID
- const char *exePrefix; ///< Prefix of the Apple IIGS AGI executable (e.g. "SQ", "PQ", "KQ4" etc)
- uint agiVer; ///< Apple IIGS AGI version number, not strictly needed
- uint exeSize; ///< Size of the Apple IIGS AGI executable file in bytes
- uint instSetStart; ///< Starting offset of the instrument set inside the executable file
- const InstrumentSetInfo &instSet; ///< Information about the used instrument set
-};
-
-class IIgsMidiChannel {
-public:
- IIgsMidiChannel() : _instrument(0), _sample(0), _volume(0) {}
- uint activeSounds() const; ///< How many active sounds are playing?
- void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample);
- void setVolume(uint8 volume);
- void noteOff(uint8 note, uint8 velocity);
- void noteOn(uint8 note, uint8 velocity);
- void stopSounds(); ///< Clears the channel of any sounds
- void removeStoppedSounds(); ///< Removes all stopped sounds from this MIDI channel
-public:
- typedef Common::Array<IIgsChannelInfo>::const_iterator const_iterator;
- typedef Common::Array<IIgsChannelInfo>::iterator iterator;
- Common::Array<IIgsChannelInfo> _gsChannels; ///< Apple IIGS channels playing on this MIDI channel
-protected:
- const IIgsInstrumentHeader *_instrument; ///< Instrument used on this MIDI channel
- const int8 *_sample; ///< Sample data used on this MIDI channel
- uint8 _volume; ///< MIDI controller number 7 (Volume)
-};
-
-/**
- * Class for managing Apple IIGS sound channels.
- * TODO: Check what instruments are used by default on the MIDI channels
- * FIXME: Some instrument choices sound wrong
- */
-class IIgsSoundMgr {
-public:
- typedef Common::Array<IIgsMidiChannel>::const_iterator const_iterator;
- typedef Common::Array<IIgsMidiChannel>::iterator iterator;
- static const uint kSfxMidiChannel = 0; ///< The MIDI channel used for playing sound effects
-public:
- // For initializing
- IIgsSoundMgr();
- void setProgramChangeMapping(const MidiProgramChangeMapping *mapping);
- bool loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo);
- bool loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo);
- // Miscellaneous methods
- uint activeSounds() const; ///< How many active sounds are playing?
- void stopSounds(); ///< Stops all sounds
- void removeStoppedSounds(); ///< Removes all stopped sounds from the MIDI channels
- // For playing Apple IIGS AGI samples (Sound effects etc)
- bool playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample);
- // MIDI commands
- void midiNoteOff(uint8 channel, uint8 note, uint8 velocity);
- void midiNoteOn(uint8 channel, uint8 note, uint8 velocity);
- void midiController(uint8 channel, uint8 controller, uint8 value);
- void midiProgramChange(uint8 channel, uint8 program);
- void midiPitchWheel(uint8 wheelPos);
-protected:
- const IIgsInstrumentHeader* getInstrument(uint8 program) const;
-public:
- Common::Array<IIgsMidiChannel> _midiChannels; ///< Information about each MIDI channel
-protected:
- Common::Array<int8> _wave; ///< Sample data used by the Apple IIGS MIDI instruments
- const MidiProgramChangeMapping *_midiProgToInst; ///< MIDI program change to instrument number mapping
- Common::Array<IIgsInstrumentHeader> _instruments; ///< Instruments used by the Apple IIGS AGI
-};
-
-class AgiEngine;
-class AgiBase;
-
-class SoundMgr : public Audio::AudioStream {
- AgiBase *_vm;
+class SoundMgr {
public:
- SoundMgr(AgiBase *agi, Audio::Mixer *pMixer);
+ SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer);
~SoundMgr();
- virtual void setVolume(uint8 volume);
-
- // AudioStream API
- int readBuffer(int16 *buffer, const int numSamples) {
- premixerCall(buffer, numSamples / 2);
- return numSamples;
- }
-
- bool isStereo() const {
- return false;
- }
- bool endOfData() const {
- return false;
- }
-
- int getRate() const {
- // FIXME: Ideally, we should use _sampleRate.
- return 22050;
- }
-
-private:
- Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
- uint32 _sampleRate;
-
- bool _playing;
- ChannelInfo _chn[NUM_CHANNELS];
- IIgsSoundMgr _gsSound;
- int _endflag;
- int _playingSound;
- uint8 _env;
- bool _disabledMidi;
-
- int16 *_sndBuffer;
- const int16 *_waveform;
-
- bool _useChorus;
-
- void premixerCall(int16 *buf, uint len);
- void fillAudio(void *udata, int16 *stream, uint len);
+ void setVolume(uint8 volume);
-public:
void unloadSound(int);
void playSound();
int initSound();
void deinitSound();
void startSound(int, int);
void stopSound();
- void stopNote(int i);
- void playNote(int i, int freq, int vol);
- void playAgiSound();
- void playCoCoSound();
- uint32 mixSound();
- bool loadInstruments();
- void playMidiSound();
- void playSampleSound();
- const IIgsExeInfo *getIIgsExeInfo(enum AgiGameID gameid) const;
- static bool convertWave(Common::SeekableReadStream &source, int8 *dest, uint length);
+
+ void soundIsFinished();
+
+private:
+ int _endflag;
+ AgiEngine *_vm;
+
+ SoundGen *_soundGen;
+
+ int _playingSound;
};
} // End of namespace Agi
diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp
new file mode 100644
index 0000000000..cc1cd0f6d5
--- /dev/null
+++ b/engines/agi/sound_2gs.cpp
@@ -0,0 +1,919 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/config-manager.h"
+#include "common/fs.h"
+#include "common/md5.h"
+#include "common/str-array.h"
+
+#include "agi/agi.h"
+#include "agi/sound_2gs.h"
+
+namespace Agi {
+
+SoundGen2GS::SoundGen2GS(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) {
+ _disabledMidi = !loadInstruments();
+
+ _playingSound = -1;
+ _playing = false;
+
+ _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE);
+
+ _midiChannels.resize(16); // Set the amount of available MIDI channels
+
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+}
+
+SoundGen2GS::~SoundGen2GS() {
+ _mixer->stopHandle(_soundHandle);
+
+ free(_sndBuffer);
+}
+
+int SoundGen2GS::readBuffer(int16 *buffer, const int numSamples) {
+ fillAudio(buffer, numSamples / 2);
+
+ return numSamples;
+}
+
+void SoundGen2GS::play(int resnum) {
+ AgiSoundEmuType type;
+
+ _playingSound = resnum;
+
+ type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type();
+
+ assert (type == AGI_SOUND_SAMPLE || type == AGI_SOUND_MIDI);
+
+ switch (type) {
+ case AGI_SOUND_SAMPLE: {
+ IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[_playingSound];
+ playSampleSound(sampleRes->getHeader(), sampleRes->getSample());
+ break;
+ }
+ case AGI_SOUND_MIDI:
+ ((IIgsMidi *) _vm->_game.sounds[_playingSound])->rewind();
+ break;
+ default:
+ break;
+ }
+}
+
+void SoundGen2GS::stop() {
+ _playingSound = -1;
+
+ // Stops all sounds on all MIDI channels
+ for (iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter)
+ iter->stopSounds();
+}
+
+void SoundGen2GS::playSound() {
+ if (_playingSound == -1)
+ return;
+
+ if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_MIDI) {
+ playMidiSound();
+ //warning("playSound: Trying to play an Apple IIGS MIDI sound. Not yet implemented");
+ } else if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_SAMPLE) {
+ //debugC(3, kDebugLevelSound, "playSound: Trying to play an Apple IIGS sample");
+ playSampleSound();
+ }
+
+ if (!_playing) {
+ _vm->_sound->soundIsFinished();
+
+ _playingSound = -1;
+ }
+}
+
+uint32 SoundGen2GS::mixSound() {
+ int i, b;
+
+ memset(_sndBuffer, 0, BUFFER_SIZE << 1);
+
+ if (!_playing || _playingSound == -1)
+ return BUFFER_SIZE;
+
+ // Handle Apple IIGS sound mixing here
+ // TODO: Implement playing both waves in an oscillator
+ // TODO: Implement swap-mode in an oscillator
+ for (uint midiChan = 0; midiChan < _midiChannels.size(); midiChan++) {
+ for (uint gsChan = 0; gsChan < _midiChannels[midiChan]._gsChannels.size(); gsChan++) {
+ IIgsChannelInfo &channel = _midiChannels[midiChan]._gsChannels[gsChan];
+ if (channel.playing()) { // Only mix in actively playing channels
+ // Frequency multiplier was 1076.0 based on tests made with MESS 0.117.
+ // Tests made with KEGS32 averaged the multiplier to around 1045.
+ // So this is a guess but maybe it's 1046.5... i.e. C6's frequency?
+ double hertz = C6_FREQ * pow(SEMITONE, fracToDouble(channel.note));
+ channel.posAdd = doubleToFrac(hertz / getRate());
+ channel.vol = doubleToFrac(fracToDouble(channel.envVol) * fracToDouble(channel.chanVol) / 127.0);
+ double tempVol = fracToDouble(channel.vol)/127.0;
+ for (i = 0; i < IIGS_BUFFER_SIZE; i++) {
+ b = channel.relocatedSample[fracToInt(channel.pos)];
+ // TODO: Find out what volume/amplification setting is loud enough
+ // but still doesn't clip when playing many channels on it.
+ _sndBuffer[i] += (int16) (b * tempVol * 256/4);
+ channel.pos += channel.posAdd;
+
+ if (channel.pos >= intToFrac(channel.size)) {
+ if (channel.loop) {
+ // Don't divide by zero on zero length samples
+ channel.pos %= intToFrac(channel.size + (channel.size == 0));
+ // Probably we should loop the envelope too
+ channel.envSeg = 0;
+ channel.envVol = channel.startEnvVol;
+ } else {
+ channel.pos = channel.chanVol = 0;
+ channel.end = true;
+ break;
+ }
+ }
+ }
+
+ if (channel.envSeg < ENVELOPE_SEGMENT_COUNT) {
+ const IIgsEnvelopeSegment &seg = channel.ins->env.seg[channel.envSeg];
+ // I currently assume enveloping works with the same speed as the MIDI
+ // (i.e. with 1/60ths of a second ticks).
+ // TODO: Check if enveloping really works with the same speed as MIDI
+ frac_t envVolDelta = doubleToFrac(seg.inc/256.0);
+ if (intToFrac(seg.bp) >= channel.envVol) {
+ channel.envVol += envVolDelta;
+ if (channel.envVol >= intToFrac(seg.bp)) {
+ channel.envVol = intToFrac(seg.bp);
+ channel.envSeg += 1;
+ }
+ } else {
+ channel.envVol -= envVolDelta;
+ if (channel.envVol <= intToFrac(seg.bp)) {
+ channel.envVol = intToFrac(seg.bp);
+ channel.envSeg += 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ removeStoppedSounds();
+
+ return IIGS_BUFFER_SIZE;
+}
+
+void SoundGen2GS::fillAudio(int16 *stream, uint len) {
+ uint32 p = 0;
+
+ // current number of audio bytes in _sndBuffer
+ static uint32 data_available = 0;
+ // offset of start of audio bytes in _sndBuffer
+ static uint32 data_offset = 0;
+
+ len <<= 2;
+
+ debugC(5, kDebugLevelSound, "(%p, %d)", (void *)stream, len);
+
+ while (len > data_available) {
+ memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, data_available);
+ p += data_available;
+ len -= data_available;
+
+ playSound();
+ data_available = mixSound() << 1;
+ data_offset = 0;
+ }
+
+ memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, len);
+ data_offset += len;
+ data_available -= len;
+}
+
+void SoundGen2GS::playSampleSound() {
+ if (_vm->_soundemu != SOUND_EMU_APPLE2GS) {
+ warning("Trying to play a sample but not using Apple IIGS sound emulation mode");
+ return;
+ }
+
+ if (_playingSound != -1)
+ _playing = activeSounds() > 0;
+}
+
+void SoundGen2GS::stopSounds() {
+ // Stops all sounds on all MIDI channels
+ for (iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter)
+ iter->stopSounds();
+}
+
+bool SoundGen2GS::playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample) {
+ stopSounds();
+ IIgsMidiChannel &channel = _midiChannels[kSfxMidiChannel];
+
+ channel.setInstrument(&sampleHeader.instrument, sample);
+ channel.setVolume(sampleHeader.volume);
+ channel.noteOn(sampleHeader.pitch, 64); // Use default velocity (i.e. 64)
+
+ return true;
+}
+
+void SoundGen2GS::playMidiSound() {
+ if (_disabledMidi)
+ return;
+
+ const uint8 *p;
+ uint8 parm1, parm2;
+ static uint8 cmd, ch;
+
+ if (_playingSound == -1 || _vm->_game.sounds[_playingSound] == NULL) {
+ warning("Error playing Apple IIGS MIDI sound resource");
+ _playing = false;
+
+ return;
+ }
+
+ IIgsMidi *midiObj = (IIgsMidi *) _vm->_game.sounds[_playingSound];
+
+ _playing = true;
+ p = midiObj->getPtr();
+
+ midiObj->_soundBufTicks++;
+
+ while (true) {
+ uint8 readByte = *p;
+
+ // Check for end of MIDI sequence marker (Can also be here before delta-time)
+ if (readByte == MIDI_BYTE_STOP_SEQUENCE) {
+ debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)");
+ _playing = false;
+
+ midiObj->rewind();
+
+ return;
+ } else if (readByte == MIDI_BYTE_TIMER_SYNC) {
+ debugC(3, kDebugLevelSound, "Timer sync");
+ p++; // Jump over the timer sync byte as it's not needed
+
+ continue;
+ }
+
+ uint8 deltaTime = readByte;
+ if (midiObj->_midiTicks + deltaTime > midiObj->_soundBufTicks) {
+ break;
+ }
+ midiObj->_midiTicks += deltaTime;
+ p++; // Jump over the delta-time byte as it was already taken care of
+
+ // Check for end of MIDI sequence marker (This time it after reading delta-time)
+ if (*p == MIDI_BYTE_STOP_SEQUENCE) {
+ debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)");
+ _playing = false;
+
+ midiObj->rewind();
+
+ return;
+ }
+
+ // Separate byte into command and channel if it's a command byte.
+ // Otherwise use running status (i.e. previously set command and channel).
+ if (*p & 0x80) {
+ cmd = *p++;
+ ch = cmd & 0x0f;
+ cmd >>= 4;
+ }
+
+ switch (cmd) {
+ case MIDI_CMD_NOTE_OFF:
+ parm1 = *p++;
+ parm2 = *p++;
+ midiNoteOff(ch, parm1, parm2);
+ break;
+ case MIDI_CMD_NOTE_ON:
+ parm1 = *p++;
+ parm2 = *p++;
+ midiNoteOn(ch, parm1, parm2);
+ break;
+ case MIDI_CMD_CONTROLLER:
+ parm1 = *p++;
+ parm2 = *p++;
+ midiController(ch, parm1, parm2);
+ break;
+ case MIDI_CMD_PROGRAM_CHANGE:
+ parm1 = *p++;
+ midiProgramChange(ch, parm1);
+ break;
+ case MIDI_CMD_PITCH_WHEEL:
+ parm1 = *p++;
+ parm2 = *p++;
+
+ uint16 wheelPos = ((parm2 & 0x7F) << 7) | (parm1 & 0x7F); // 14-bit value
+ midiPitchWheel(wheelPos);
+ break;
+ }
+ }
+
+ midiObj->setPtr(p);
+}
+
+void SoundGen2GS::midiNoteOff(uint8 channel, uint8 note, uint8 velocity) {
+ _midiChannels[channel].noteOff(note, velocity);
+ debugC(3, kDebugLevelSound, "note off, channel %02x, note %02x, velocity %02x", channel, note, velocity);
+}
+
+void SoundGen2GS::midiNoteOn(uint8 channel, uint8 note, uint8 velocity) {
+ _midiChannels[channel].noteOn(note, velocity);
+ debugC(3, kDebugLevelSound, "note on, channel %02x, note %02x, velocity %02x", channel, note, velocity);
+}
+
+// TODO: Check if controllers behave differently on different MIDI channels
+// TODO: Doublecheck what other controllers than the volume controller do
+void SoundGen2GS::midiController(uint8 channel, uint8 controller, uint8 value) {
+ IIgsMidiChannel &midiChannel = _midiChannels[channel];
+
+ // The tested Apple IIGS AGI MIDI resources only used
+ // controllers 0 (Bank select?), 7 (Volume) and 64 (Sustain On/Off).
+ // Controller 0's parameter was in range 94-127,
+ // controller 7's parameter was in range 0-127 and
+ // controller 64's parameter was always 0 (i.e. sustain off).
+ bool unimplemented = false;
+ switch (controller) {
+ case 7: // Volume
+ midiChannel.setVolume(value);
+ break;
+ default:
+ unimplemented = true;
+ break;
+ }
+ debugC(3, kDebugLevelSound, "controller %02x, ch %02x, val %02x%s", controller, channel, value, unimplemented ? " (Unimplemented)" : "");
+}
+
+void SoundGen2GS::midiProgramChange(uint8 channel, uint8 program) {
+ _midiChannels[channel].setInstrument(getInstrument(program), _wave.begin());
+ debugC(3, kDebugLevelSound, "program change %02x, channel %02x", program, channel);
+}
+
+void SoundGen2GS::midiPitchWheel(uint8 wheelPos) {
+ // In all the tested Apple IIGS AGI MIDI resources
+ // pitch wheel commands always used 0x2000 (Center position).
+ // Therefore it should be quite safe to ignore this command.
+ debugC(3, kDebugLevelSound, "pitch wheel position %04x (Unimplemented)", wheelPos);
+}
+
+const IIgsInstrumentHeader* SoundGen2GS::getInstrument(uint8 program) const {
+ return &_instruments[_midiProgToInst->map(program)];
+}
+
+void SoundGen2GS::setProgramChangeMapping(const MidiProgramChangeMapping *mapping) {
+ _midiProgToInst = mapping;
+}
+
+void SoundGen2GS::removeStoppedSounds() {
+ for (Common::Array<IIgsMidiChannel>::iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter)
+ iter->removeStoppedSounds();
+}
+
+uint SoundGen2GS::activeSounds() const {
+ uint result = 0;
+
+ for (Common::Array<IIgsMidiChannel>::const_iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter)
+ result += iter->activeSounds();
+
+ return result;
+}
+
+IIgsMidi::IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) {
+ _data = data; // Save the resource pointer
+ _ptr = _data + 2; // Set current position to just after the header
+ _len = len; // Save the resource's length
+ _type = READ_LE_UINT16(data); // Read sound resource's type
+ _midiTicks = _soundBufTicks = 0;
+ _isValid = (_type == AGI_SOUND_MIDI) && (_data != NULL) && (_len >= 2);
+
+ if (!_isValid) // Check for errors
+ warning("Error creating Apple IIGS midi sound from resource %d (Type %d, length %d)", resnum, _type, len);
+}
+
+/**
+ * Convert sample from 8-bit unsigned to 8-bit signed format.
+ * @param source Source stream containing the 8-bit unsigned sample data.
+ * @param dest Destination buffer for the 8-bit signed sample data.
+ * @param length Length of the sample data to be converted.
+ */
+static bool convertWave(Common::SeekableReadStream &source, int8 *dest, uint length) {
+ // Convert the wave from 8-bit unsigned to 8-bit signed format
+ for (uint i = 0; i < length; i++)
+ dest[i] = (int8) ((int) source.readByte() - 128);
+ return !(source.eos() || source.err());
+}
+
+IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) {
+ Common::MemoryReadStream stream(data, len, DisposeAfterUse::YES);
+
+ // Check that the header was read ok and that it's of the correct type
+ if (_header.read(stream) && _header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource
+ uint32 sampleStartPos = stream.pos();
+ uint32 tailLen = stream.size() - sampleStartPos;
+
+ if (tailLen < _header.sampleSize) { // Check if there's no room for the sample data in the stream
+ // Apple IIGS Manhunter I: Sound resource 16 has only 16074 bytes
+ // of sample data although header says it should have 16384 bytes.
+ warning("Apple IIGS sample (%d) too short (%d bytes. Should be %d bytes). Using the part that's left",
+ resnum, tailLen, _header.sampleSize);
+
+ _header.sampleSize = (uint16) tailLen; // Use the part that's left
+ }
+
+ if (_header.pitch > 0x7F) { // Check if the pitch is invalid
+ warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resnum, _header.pitch);
+
+ _header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too
+ }
+
+ // Finalize the header info using the 8-bit unsigned sample data
+ _header.finalize(stream);
+
+ // Convert sample data from 8-bit unsigned to 8-bit signed format
+ stream.seek(sampleStartPos);
+ _sample = new int8[_header.sampleSize];
+
+ if (_sample != NULL)
+ _isValid = convertWave(stream, _sample, _header.sampleSize);
+ }
+
+ if (!_isValid) // Check for errors
+ warning("Error creating Apple IIGS sample from resource %d (Type %d, length %d)", resnum, _header.type, len);
+}
+
+/** Reads an Apple IIGS envelope from then given stream. */
+bool IIgsEnvelope::read(Common::SeekableReadStream &stream) {
+ for (int segNum = 0; segNum < ENVELOPE_SEGMENT_COUNT; segNum++) {
+ seg[segNum].bp = stream.readByte();
+ seg[segNum].inc = stream.readUint16LE();
+ }
+
+ return !(stream.eos() || stream.err());
+}
+
+/** Reads an Apple IIGS wave information structure from the given stream. */
+bool IIgsWaveInfo::read(Common::SeekableReadStream &stream, bool ignoreAddr) {
+ top = stream.readByte();
+ addr = stream.readByte() * 256;
+ size = (1 << (stream.readByte() & 7)) * 256;
+
+ // Read packed mode byte and parse it into parts
+ byte packedModeByte = stream.readByte();
+ channel = (packedModeByte >> 4) & 1; // Bit 4
+ mode = (packedModeByte >> 1) & 3; // Bits 1-2
+ halt = (packedModeByte & 1) != 0; // Bit 0 (Converted to boolean)
+
+ relPitch = stream.readSint16LE();
+
+ // Zero the wave address if we want to ignore the wave address info
+ if (ignoreAddr)
+ addr = 0;
+
+ return !(stream.eos() || stream.err());
+}
+
+bool IIgsWaveInfo::finalize(Common::SeekableReadStream &uint8Wave) {
+ uint32 startPos = uint8Wave.pos(); // Save stream's starting position
+ uint8Wave.seek(addr, SEEK_CUR); // Seek to wave's address
+
+ // Calculate the true sample size (A zero ends the sample prematurely)
+ uint trueSize = size; // Set a default value for the result
+ for (uint i = 0; i < size; i++) {
+ if (uint8Wave.readByte() == 0) {
+ trueSize = i;
+ // A zero in the sample stream turns off looping
+ // (At least that's what MESS 0.117 and KEGS32 0.91 seem to do)
+ if (mode == OSC_MODE_LOOP)
+ mode = OSC_MODE_ONESHOT;
+ break;
+ }
+ }
+ size = trueSize; // Set the true sample size
+
+ uint8Wave.seek(startPos); // Seek back to the stream's starting position
+
+ return true;
+}
+
+bool IIgsOscillator::finalize(Common::SeekableReadStream &uint8Wave) {
+ for (uint i = 0; i < WAVES_PER_OSCILLATOR; i++)
+ if (!waves[i].finalize(uint8Wave))
+ return false;
+
+ return true;
+}
+
+bool IIgsOscillatorList::read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr) {
+ // First read the A waves and then the B waves for the oscillators
+ for (uint waveNum = 0; waveNum < WAVES_PER_OSCILLATOR; waveNum++)
+ for (uint oscNum = 0; oscNum < oscillatorCount; oscNum++)
+ if (!osc[oscNum].waves[waveNum].read(stream, ignoreAddr))
+ return false;
+
+ count = oscillatorCount; // Set the oscillator count
+
+ return true;
+}
+
+bool IIgsOscillatorList::finalize(Common::SeekableReadStream &uint8Wave) {
+ for (uint i = 0; i < count; i++)
+ if (!osc[i].finalize(uint8Wave))
+ return false;
+
+ return true;
+}
+
+bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreAddr) {
+ env.read(stream);
+ relseg = stream.readByte();
+ /*byte priority =*/ stream.readByte(); // Not needed? 32 in all tested data.
+ bendrange = stream.readByte();
+ vibdepth = stream.readByte();
+ vibspeed = stream.readByte();
+ /*byte spare =*/ stream.readByte(); // Not needed? 0 in all tested data.
+ byte wac = stream.readByte(); // Read A wave count
+ byte wbc = stream.readByte(); // Read B wave count
+ oscList.read(stream, wac, ignoreAddr); // Read the oscillators
+ return (wac == wbc) && !(stream.eos() || stream.err()); // A and B wave counts must match
+}
+
+bool IIgsInstrumentHeader::finalize(Common::SeekableReadStream &uint8Wave) {
+ return oscList.finalize(uint8Wave);
+}
+
+bool IIgsSampleHeader::read(Common::SeekableReadStream &stream) {
+ type = stream.readUint16LE();
+ pitch = stream.readByte();
+ unknownByte_Ofs3 = stream.readByte();
+ volume = stream.readByte();
+ unknownByte_Ofs5 = stream.readByte();
+ instrumentSize = stream.readUint16LE();
+ sampleSize = stream.readUint16LE();
+ // Read the instrument header *ignoring* its wave address info
+
+ return instrument.read(stream, true);
+}
+
+bool IIgsSampleHeader::finalize(Common::SeekableReadStream &uint8Wave) {
+ return instrument.finalize(uint8Wave);
+}
+
+void IIgsMidiChannel::stopSounds() {
+ // Stops all sounds on this single MIDI channel
+ for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter)
+ iter->stop();
+
+ _gsChannels.clear();
+}
+
+void IIgsMidiChannel::removeStoppedSounds() {
+ for (int i = _gsChannels.size() - 1; i >= 0; i--)
+ if (!_gsChannels[i].playing())
+ _gsChannels.remove_at(i);
+}
+
+uint IIgsMidiChannel::activeSounds() const {
+ uint result = 0;
+
+ for (const_iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter)
+ if (!iter->end)
+ result++;
+
+ return result;
+}
+
+void IIgsMidiChannel::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) {
+ _instrument = instrument;
+ _sample = sample;
+
+ // Set program on each Apple IIGS channel playing on this MIDI channel
+ for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter)
+ iter->setInstrument(instrument, sample);
+}
+
+void IIgsMidiChannel::setVolume(uint8 volume) {
+ _volume = volume;
+
+ // Set volume on each Apple IIGS channel playing on this MIDI channel
+ for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter)
+ iter->setChannelVolume(volume);
+}
+
+void IIgsMidiChannel::noteOff(uint8 note, uint8 velocity) {
+ // Go through all the notes playing on this MIDI channel
+ // and turn off the ones that are playing the given note
+ for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter)
+ if (iter->origNote == note)
+ iter->noteOff(velocity);
+}
+
+void IIgsMidiChannel::noteOn(uint8 note, uint8 velocity) {
+ IIgsChannelInfo channel;
+
+ // Use the default channel volume and instrument
+ channel.setChannelVolume(_volume);
+ channel.setInstrument(_instrument, _sample);
+
+ // Set the note on and save the channel
+ channel.noteOn(note, velocity);
+ _gsChannels.push_back(channel);
+}
+
+void IIgsChannelInfo::rewind() {
+ this->envVol = this->startEnvVol;
+ this->envSeg = 0;
+ this->pos = intToFrac(0);
+}
+
+void IIgsChannelInfo::setChannelVolume(uint8 volume) {
+ this->chanVol = intToFrac(volume);
+}
+
+void IIgsChannelInfo::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) {
+ assert(instrument != NULL && sample != NULL);
+ this->ins = instrument;
+ this->unrelocatedSample = sample;
+}
+
+// TODO/FIXME: Implement correctly and fully (Take velocity into account etc)
+void IIgsChannelInfo::noteOn(uint8 noteParam, uint8 velocity) {
+ this->origNote = noteParam;
+ this->startEnvVol = intToFrac(0);
+ rewind();
+
+ const IIgsWaveInfo *waveInfo = NULL;
+
+ for (uint i = 0; i < ins->oscList.count; i++)
+ if (ins->oscList(i).waves[0].top >= noteParam)
+ waveInfo = &ins->oscList(i).waves[0];
+
+ assert(waveInfo != NULL);
+
+ this->relocatedSample = this->unrelocatedSample + waveInfo->addr;
+ this->posAdd = intToFrac(0);
+ this->note = intToFrac(noteParam) + doubleToFrac(waveInfo->relPitch/256.0);
+ this->vol = doubleToFrac(fracToDouble(this->envVol) * fracToDouble(this->chanVol) / 127.0);
+ this->loop = (waveInfo->mode == OSC_MODE_LOOP);
+ this->size = waveInfo->size - waveInfo->addr;
+ this->end = waveInfo->halt;
+}
+
+// TODO/FIXME: Implement correctly and fully (Take release time and velocity into account etc)
+void IIgsChannelInfo::noteOff(uint8 velocity) {
+ this->loop = false;
+ this->envSeg = ins->relseg;
+}
+
+void IIgsChannelInfo::stop() {
+ this->end = true;
+}
+
+bool IIgsChannelInfo::playing() {
+ return !this->end;
+}
+
+/**
+ * A function object (i.e. a functor) for testing if a Common::FSNode
+ * 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 Common::FSNode&, bool> {
+// FIXME: This should be replaced; use SearchMan instead
+ fsnodeNameEqualsIgnoreCase(const Common::StringArray &str) : _str(str) {}
+ fsnodeNameEqualsIgnoreCase(const Common::String str) { _str.push_back(str); }
+ bool operator()(const Common::FSNode &param) const {
+ for (Common::StringArray::const_iterator iter = _str.begin(); iter != _str.end(); ++iter)
+ if (param.getName().equalsIgnoreCase(*iter))
+ return true;
+ return false;
+ }
+private:
+ Common::StringArray _str;
+};
+
+bool SoundGen2GS::loadInstruments() {
+ // Check that the platform is Apple IIGS, as only it uses custom instruments
+ if (_vm->getPlatform() != Common::kPlatformApple2GS) {
+ debugC(3, kDebugLevelSound, "Platform isn't Apple IIGS so not loading any instruments");
+ return true;
+ }
+
+ // Get info on the particular Apple IIGS AGI game's executable
+ const IIgsExeInfo *exeInfo = getIIgsExeInfo((enum AgiGameID) _vm->getGameID());
+ if (exeInfo == NULL) {
+ warning("Unsupported Apple IIGS game, not loading instruments");
+ return false;
+ }
+
+ // List files in the game path
+ Common::FSList fslist;
+ Common::FSNode dir(ConfMan.get("path"));
+ if (!dir.getChildren(fslist, Common::FSNode::kListFilesOnly)) {
+ warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.getPath().c_str());
+ return false;
+ }
+
+ // Populate executable filenames list (Long filename and short filename) for searching
+ Common::StringArray exeNames;
+ exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS16");
+ exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS");
+
+ // Populate wave filenames list (Long filename and short filename) for searching
+ Common::StringArray waveNames;
+ waveNames.push_back("SIERRASTANDARD");
+ waveNames.push_back("SIERRAST");
+
+ // Search for the executable file and the wave file (i.e. check if any of the filenames match)
+ 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));
+
+ // Make sure that we found the executable file
+ if (exeFsnode == fslist.end()) {
+ warning("Couldn't find Apple IIGS game executable (%s), not loading instruments", exeNames.begin()->c_str());
+ return false;
+ }
+
+ // Make sure that we found the wave file
+ if (waveFsnode == fslist.end()) {
+ warning("Couldn't find Apple IIGS wave file (%s), not loading instruments", waveNames.begin()->c_str());
+ return false;
+ }
+
+ // Set the MIDI program change to instrument number mapping and
+ // load the instrument headers and their sample data.
+ // None of the tested SIERRASTANDARD-files have zeroes in them so
+ // there's no need to check for prematurely ending samples here.
+ setProgramChangeMapping(&exeInfo->instSet.progToInst);
+ return loadWaveFile(*waveFsnode, *exeInfo) && loadInstrumentHeaders(*exeFsnode, *exeInfo);
+}
+
+/** Older Apple IIGS AGI MIDI program change to instrument number mapping. */
+static const MidiProgramChangeMapping progToInstMappingV1 = {
+ {19, 20, 22, 23, 21, 24, 5, 5, 5, 5,
+ 6, 7, 10, 9, 11, 9, 15, 8, 5, 5,
+ 17, 16, 18, 12, 14, 5, 5, 5, 5, 5,
+ 0, 1, 2, 9, 3, 4, 15, 2, 2, 2,
+ 25, 13, 13, 25},
+ 5
+};
+
+/** Newer Apple IIGS AGI MIDI program change to instrument number mapping. */
+static const MidiProgramChangeMapping progToInstMappingV2 = {
+ {21, 22, 24, 25, 23, 26, 6, 6, 6, 6,
+ 7, 9, 12, 8, 13, 11, 17, 10, 6, 6,
+ 19, 18, 20, 14, 16, 6, 6, 6, 6, 6,
+ 0, 1, 2, 4, 3, 5, 17, 2, 2, 2,
+ 27, 15, 15, 27},
+ 6
+};
+
+/** Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002). */
+static const InstrumentSetInfo instSetV1 = {
+ 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", progToInstMappingV1
+};
+
+/** Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I. */
+static const InstrumentSetInfo instSetV2 = {
+ 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", progToInstMappingV2
+};
+
+/** Information about different Apple IIGS AGI executables. */
+static const IIgsExeInfo IIgsExeInfos[] = {
+ {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, instSetV1},
+ {GID_LSL1, "LL", 0x1003, 141003, 0x844E, instSetV2},
+ {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, instSetV2},
+ {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, instSetV2},
+ {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, instSetV2},
+ {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, instSetV2},
+ {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, instSetV2},
+ {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, instSetV2},
+ {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, instSetV2},
+ {GID_MH1, "MH", 0x2004, 147678, 0x8979, instSetV2},
+ {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, instSetV2},
+ {GID_BC, "BC", 0x3001, 148192, 0x8979, instSetV2},
+ {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2}
+};
+
+/**
+ * Finds information about an Apple IIGS AGI executable based on the game ID.
+ * @return A non-null IIgsExeInfo pointer if successful, otherwise NULL.
+ */
+const IIgsExeInfo *SoundGen2GS::getIIgsExeInfo(enum AgiGameID gameid) const {
+ for (int i = 0; i < ARRAYSIZE(IIgsExeInfos); i++)
+ if (IIgsExeInfos[i].gameid == gameid)
+ return &IIgsExeInfos[i];
+ return NULL;
+}
+
+bool SoundGen2GS::loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo) {
+ bool loadedOk = false; // Was loading successful?
+ Common::File file;
+
+ // Open the executable file and check that it has correct size
+ file.open(exePath);
+ if (file.size() != (int32)exeInfo.exeSize) {
+ debugC(3, kDebugLevelSound, "Apple IIGS executable (%s) has wrong size (Is %d, should be %d)",
+ exePath.getPath().c_str(), file.size(), exeInfo.exeSize);
+ }
+
+ // Read the whole executable file into memory
+ Common::SharedPtr<Common::MemoryReadStream> data(file.readStream(file.size()));
+ file.close();
+
+ // Check that we got enough data to be able to parse the instruments
+ if (data && data->size() >= (int32)(exeInfo.instSetStart + exeInfo.instSet.byteCount)) {
+ // Check instrument set's length (The info's saved in the executable)
+ data->seek(exeInfo.instSetStart - 4);
+ uint16 instSetByteCount = data->readUint16LE();
+ if (instSetByteCount != exeInfo.instSet.byteCount) {
+ debugC(3, kDebugLevelSound, "Wrong instrument set size (Is %d, should be %d) in Apple IIGS executable (%s)",
+ instSetByteCount, exeInfo.instSet.byteCount, exePath.getPath().c_str());
+ }
+
+ // Check instrument set's md5sum
+ data->seek(exeInfo.instSetStart);
+
+ char md5str[32+1];
+ Common::md5_file_string(*data, md5str, exeInfo.instSet.byteCount);
+ if (scumm_stricmp(md5str, exeInfo.instSet.md5)) {
+ warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless",
+ md5str, exePath.getPath().c_str());
+ }
+
+ // Read in the instrument set one instrument at a time
+ data->seek(exeInfo.instSetStart);
+
+ // Load the instruments
+ _instruments.clear();
+ _instruments.reserve(exeInfo.instSet.instCount);
+
+ IIgsInstrumentHeader instrument;
+ for (uint i = 0; i < exeInfo.instSet.instCount; i++) {
+ if (!instrument.read(*data)) {
+ warning("Error loading Apple IIGS instrument (%d. of %d) from %s, not loading more instruments",
+ i + 1, exeInfo.instSet.instCount, exePath.getPath().c_str());
+ break;
+ }
+ _instruments.push_back(instrument); // Add the successfully loaded instrument to the instruments array
+ }
+
+ // Loading was successful only if all instruments were loaded successfully
+ loadedOk = (_instruments.size() == exeInfo.instSet.instCount);
+ } else // Couldn't read enough data from the executable file
+ warning("Error loading instruments from Apple IIGS executable (%s)", exePath.getPath().c_str());
+
+ return loadedOk;
+}
+
+bool SoundGen2GS::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo) {
+ Common::File file;
+
+ // Open the wave file and read it into memory
+ file.open(wavePath);
+ Common::SharedPtr<Common::MemoryReadStream> uint8Wave(file.readStream(file.size()));
+ file.close();
+
+ // Check that we got the whole wave file
+ if (uint8Wave && uint8Wave->size() == SIERRASTANDARD_SIZE) {
+ // Check wave file's md5sum
+ char md5str[32+1];
+ Common::md5_file_string(*uint8Wave, md5str, SIERRASTANDARD_SIZE);
+ if (scumm_stricmp(md5str, exeInfo.instSet.waveFileMd5)) {
+ warning("Unknown Apple IIGS wave file (md5: %s, game: %s).\n" \
+ "Please report the information on the previous line to the ScummVM team.\n" \
+ "Using the wave file as it is - music may sound weird", md5str, exeInfo.exePrefix);
+ }
+
+ uint8Wave->seek(0); // Seek wave to its start
+ // Convert the wave file from 8-bit unsigned to 8-bit signed and save the result
+ _wave.resize(uint8Wave->size());
+ return convertWave(*uint8Wave, _wave.begin(), uint8Wave->size());
+ } else { // Couldn't read the wave file or it had incorrect size
+ warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.getPath().c_str());
+ return false;
+ }
+}
+
+} // End of namespace Agi
diff --git a/engines/agi/sound_2gs.h b/engines/agi/sound_2gs.h
new file mode 100644
index 0000000000..12dede0b69
--- /dev/null
+++ b/engines/agi/sound_2gs.h
@@ -0,0 +1,353 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 AGI_SOUND_2GS_H
+#define AGI_SOUND_2GS_H
+
+#include "common/frac.h"
+#include "sound/audiostream.h"
+
+namespace Agi {
+
+#define BUFFER_SIZE 410
+
+// Apple IIGS MIDI uses 60 ticks per second (Based on tests with Apple IIGS
+// KQ1 and SQ1 under MESS 0.124a). So we make the audio buffer size to be a
+// 1/60th of a second in length. That should be getSampleRate() / 60 samples
+// in length but as getSampleRate() is always 22050 at the moment we just use
+// the hardcoded value of 368 (22050/60 = 367.5 which rounds up to 368).
+// FIXME: Use getSampleRate() / 60 rather than a hardcoded value
+#define IIGS_BUFFER_SIZE 368
+
+// MIDI command values (Shifted right by 4 so they're in the lower nibble)
+#define MIDI_CMD_NOTE_OFF 0x08
+#define MIDI_CMD_NOTE_ON 0x09
+#define MIDI_CMD_CONTROLLER 0x0B
+#define MIDI_CMD_PROGRAM_CHANGE 0x0C
+#define MIDI_CMD_PITCH_WHEEL 0x0E
+// Whole MIDI byte values (Command and channel info together)
+#define MIDI_BYTE_STOP_SEQUENCE 0xFC
+#define MIDI_BYTE_TIMER_SYNC 0xF8
+
+struct IIgsEnvelopeSegment {
+ uint8 bp;
+ uint16 inc; ///< 8b.8b fixed point, very probably little endian
+};
+
+#define ENVELOPE_SEGMENT_COUNT 8
+struct IIgsEnvelope {
+ IIgsEnvelopeSegment seg[ENVELOPE_SEGMENT_COUNT];
+
+ /** Reads an Apple IIGS envelope from then given stream. */
+ bool read(Common::SeekableReadStream &stream);
+};
+
+// 2**(1/12) i.e. the 12th root of 2
+#define SEMITONE 1.059463094359295
+
+// C6's frequency is A4's (440 Hz) frequency but one full octave and three semitones higher
+// i.e. C6_FREQ = 440 * pow(2.0, 15/12.0)
+#define C6_FREQ 1046.502261202395
+
+// Size of the SIERRASTANDARD file (i.e. the wave file i.e. the sample data used by the instruments).
+#define SIERRASTANDARD_SIZE 65536
+
+// Maximum number of instruments in an Apple IIGS instrument set.
+// Chosen empirically based on Apple IIGS AGI game data, increase if needed.
+#define MAX_INSTRUMENTS 28
+
+struct IIgsWaveInfo {
+ uint8 top;
+ uint addr;
+ uint size;
+// Oscillator channel
+#define OSC_CHANNEL_RIGHT 0
+#define OSC_CHANNEL_LEFT 1
+ uint channel;
+// Oscillator mode
+#define OSC_MODE_LOOP 0
+#define OSC_MODE_ONESHOT 1
+#define OSC_MODE_SYNC_AM 2
+#define OSC_MODE_SWAP 3
+ uint mode;
+ bool halt;
+ int16 relPitch; ///< Relative pitch in semitones (Signed 8b.8b fixed point)
+
+ /** Reads an Apple IIGS wave information structure from the given stream. */
+ bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false);
+ bool finalize(Common::SeekableReadStream &uint8Wave);
+};
+
+// Number of waves per Apple IIGS sound oscillator
+#define WAVES_PER_OSCILLATOR 2
+
+/** An Apple IIGS sound oscillator. Consists always of two waves. */
+struct IIgsOscillator {
+ IIgsWaveInfo waves[WAVES_PER_OSCILLATOR];
+
+ bool finalize(Common::SeekableReadStream &uint8Wave);
+};
+
+// Maximum number of oscillators in an Apple IIGS instrument.
+// Chosen empirically based on Apple IIGS AGI game data, increase if needed.
+#define MAX_OSCILLATORS 4
+
+/** An Apple IIGS sound oscillator list. */
+struct IIgsOscillatorList {
+ uint count; ///< Oscillator count
+ IIgsOscillator osc[MAX_OSCILLATORS]; ///< The oscillators
+
+ /** Indexing operators for easier access to the oscillators. */
+ const IIgsOscillator &operator()(uint index) const { return osc[index]; }
+ IIgsOscillator &operator()(uint index) { return osc[index]; }
+
+ /** Reads an Apple IIGS oscillator list from the given stream. */
+ bool read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr = false);
+ bool finalize(Common::SeekableReadStream &uint8Wave);
+};
+
+struct IIgsInstrumentHeader {
+ IIgsEnvelope env;
+ uint8 relseg;
+ uint8 bendrange;
+ uint8 vibdepth;
+ uint8 vibspeed;
+ IIgsOscillatorList oscList;
+
+ /**
+ * Read an Apple IIGS instrument header from the given stream.
+ * @param stream The source stream from which to read the data.
+ * @param ignoreAddr Should we ignore wave infos' wave address variable's value?
+ * @return True if successful, false otherwise.
+ */
+ bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false);
+ bool finalize(Common::SeekableReadStream &uint8Wave);
+};
+
+struct IIgsSampleHeader {
+ uint16 type;
+ uint8 pitch; ///< Logarithmic, base is 2**(1/12), unknown multiplier (Possibly in range 1040-1080)
+ uint8 unknownByte_Ofs3; // 0x7F in Gold Rush's sound resource 60, 0 in all others.
+ uint8 volume; ///< Current guess: Logarithmic in 6 dB steps
+ uint8 unknownByte_Ofs5; ///< 0 in all tested samples.
+ uint16 instrumentSize; ///< Little endian. 44 in all tested samples. A guess.
+ uint16 sampleSize; ///< Little endian. Accurate in all tested samples excluding Manhunter I's sound resource 16.
+ IIgsInstrumentHeader instrument;
+
+ /**
+ * Read an Apple IIGS AGI sample header from the given stream.
+ * @param stream The source stream from which to read the data.
+ * @return True if successful, false otherwise.
+ */
+ bool read(Common::SeekableReadStream &stream);
+ bool finalize(Common::SeekableReadStream &uint8Wave);
+};
+
+struct IIgsChannelInfo {
+ const IIgsInstrumentHeader *ins; ///< Instrument info
+ const int8 *relocatedSample; ///< Source sample data (8-bit signed format) using relocation
+ const int8 *unrelocatedSample; ///< Source sample data (8-bit signed format) without relocation
+ frac_t pos; ///< Current sample position
+ frac_t posAdd; ///< Current sample position adder (Calculated using note, vibrato etc)
+ uint8 origNote; ///< The original note without the added relative pitch
+ frac_t note; ///< Note (With the added relative pitch)
+ frac_t vol; ///< Current volume (Takes both channel volume and enveloping into account)
+ frac_t chanVol; ///< Channel volume
+ frac_t startEnvVol; ///< Starting envelope volume
+ frac_t envVol; ///< Current envelope volume
+ uint envSeg; ///< Current envelope segment
+ uint size; ///< Sample size
+ bool loop; ///< Should we loop the sample?
+ bool end; ///< Has the playing ended?
+
+ void rewind(); ///< Rewinds the sound playing on this channel to its start
+ void setChannelVolume(uint8 volume); ///< Sets the channel volume
+ void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample); ///< Sets the instrument to be used on this channel
+ void noteOn(uint8 noteParam, uint8 velocity); ///< Starts playing a note on this channel
+ void noteOff(uint8 velocity); ///< Releases the note on this channel
+ void stop(); ///< Stops the note playing on this channel instantly
+ bool playing(); ///< Is there a note playing on this channel?
+};
+
+class IIgsMidi : public AgiSound {
+public:
+ IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
+ ~IIgsMidi() { if (_data != NULL) free(_data); }
+ virtual uint16 type() { return _type; }
+ virtual const uint8 *getPtr() { return _ptr; }
+ virtual void setPtr(const uint8 *ptr) { _ptr = ptr; }
+ virtual void rewind() { _ptr = _data + 2; _midiTicks = _soundBufTicks = 0; }
+protected:
+ uint8 *_data; ///< Raw sound resource data
+ const uint8 *_ptr; ///< Pointer to the current position in the MIDI data
+ uint32 _len; ///< Length of the raw sound resource
+ uint16 _type; ///< Sound resource type
+public:
+ uint _midiTicks; ///< MIDI song position in ticks (1/60ths of a second)
+ uint _soundBufTicks; ///< Sound buffer position in ticks (1/60ths of a second)
+};
+
+class IIgsSample : public AgiSound {
+public:
+ IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
+ ~IIgsSample() { delete[] _sample; }
+ virtual uint16 type() { return _header.type; }
+ const IIgsSampleHeader &getHeader() const { return _header; }
+ const int8 *getSample() const { return _sample; }
+protected:
+ IIgsSampleHeader _header; ///< Apple IIGS AGI sample header
+ int8 *_sample; ///< Sample data (8-bit signed format)
+};
+
+/** Apple IIGS MIDI program change to instrument number mapping. */
+struct MidiProgramChangeMapping {
+ byte midiProgToInst[44]; ///< Lookup table for the MIDI program number to instrument number mapping
+ byte undefinedInst; ///< The undefined instrument number
+
+ // Maps the MIDI program number to an instrument number
+ byte map(uint midiProg) const {
+ return midiProg < ARRAYSIZE(midiProgToInst) ? midiProgToInst[midiProg] : undefinedInst;
+ }
+};
+
+/** Apple IIGS AGI instrument set information. */
+struct InstrumentSetInfo {
+ uint byteCount; ///< Length of the whole instrument set in bytes
+ uint instCount; ///< Amount of instrument in the set
+ const char *md5; ///< MD5 hex digest of the whole instrument set
+ const char *waveFileMd5; ///< MD5 hex digest of the wave file (i.e. the sample data used by the instruments)
+ const MidiProgramChangeMapping &progToInst; ///< Program change to instrument number mapping
+};
+
+/** Apple IIGS AGI executable file information. */
+struct IIgsExeInfo {
+ enum AgiGameID gameid; ///< Game ID
+ const char *exePrefix; ///< Prefix of the Apple IIGS AGI executable (e.g. "SQ", "PQ", "KQ4" etc)
+ uint agiVer; ///< Apple IIGS AGI version number, not strictly needed
+ uint exeSize; ///< Size of the Apple IIGS AGI executable file in bytes
+ uint instSetStart; ///< Starting offset of the instrument set inside the executable file
+ const InstrumentSetInfo &instSet; ///< Information about the used instrument set
+};
+
+class IIgsMidiChannel {
+public:
+ IIgsMidiChannel() : _instrument(0), _sample(0), _volume(0) {}
+ uint activeSounds() const; ///< How many active sounds are playing?
+ void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample);
+ void setVolume(uint8 volume);
+ void noteOff(uint8 note, uint8 velocity);
+ void noteOn(uint8 note, uint8 velocity);
+ void stopSounds(); ///< Clears the channel of any sounds
+ void removeStoppedSounds(); ///< Removes all stopped sounds from this MIDI channel
+public:
+ typedef Common::Array<IIgsChannelInfo>::const_iterator const_iterator;
+ typedef Common::Array<IIgsChannelInfo>::iterator iterator;
+ Common::Array<IIgsChannelInfo> _gsChannels; ///< Apple IIGS channels playing on this MIDI channel
+protected:
+ const IIgsInstrumentHeader *_instrument; ///< Instrument used on this MIDI channel
+ const int8 *_sample; ///< Sample data used on this MIDI channel
+ uint8 _volume; ///< MIDI controller number 7 (Volume)
+};
+
+class SoundGen2GS : public SoundGen, public Audio::AudioStream {
+public:
+ SoundGen2GS(AgiEngine *vm, Audio::Mixer *pMixer);
+ ~SoundGen2GS();
+
+ void play(int resnum);
+ void stop(void);
+
+ // AudioStream API
+ int readBuffer(int16 *buffer, const int numSamples);
+
+ bool isStereo() const {
+ return false;
+ }
+
+ bool endOfData() const {
+ return false;
+ }
+
+ int getRate() const {
+ // FIXME: Ideally, we should use _sampleRate.
+ return 22050;
+ }
+
+private:
+ bool _disabledMidi;
+ int _playingSound;
+ bool _playing;
+
+ int16 *_sndBuffer;
+
+/**
+ * Class for managing Apple IIGS sound channels.
+ * TODO: Check what instruments are used by default on the MIDI channels
+ * FIXME: Some instrument choices sound wrong
+ */
+private:
+ typedef Common::Array<IIgsMidiChannel>::const_iterator const_iterator;
+ typedef Common::Array<IIgsMidiChannel>::iterator iterator;
+ static const uint kSfxMidiChannel = 0; ///< The MIDI channel used for playing sound effects
+
+ bool loadInstruments();
+ const IIgsExeInfo *getIIgsExeInfo(enum AgiGameID gameid) const;
+
+ void setProgramChangeMapping(const MidiProgramChangeMapping *mapping);
+ bool loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo);
+ bool loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo);
+
+ // Miscellaneous methods
+ void fillAudio(int16 *stream, uint len);
+ uint32 mixSound();
+ void playSound();
+ uint activeSounds() const; ///< How many active sounds are playing?
+ void stopSounds(); ///< Stops all sounds
+ void removeStoppedSounds(); ///< Removes all stopped sounds from the MIDI channels
+
+ // For playing Apple IIGS AGI samples (Sound effects etc)
+ bool playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample);
+ void playMidiSound();
+ void playSampleSound();
+
+ // MIDI commands
+ void midiNoteOff(uint8 channel, uint8 note, uint8 velocity);
+ void midiNoteOn(uint8 channel, uint8 note, uint8 velocity);
+ void midiController(uint8 channel, uint8 controller, uint8 value);
+ void midiProgramChange(uint8 channel, uint8 program);
+ void midiPitchWheel(uint8 wheelPos);
+ //protected:
+ const IIgsInstrumentHeader* getInstrument(uint8 program) const;
+ //public:
+ Common::Array<IIgsMidiChannel> _midiChannels; ///< Information about each MIDI channel
+ //protected:
+ Common::Array<int8> _wave; ///< Sample data used by the Apple IIGS MIDI instruments
+ const MidiProgramChangeMapping *_midiProgToInst; ///< MIDI program change to instrument number mapping
+ Common::Array<IIgsInstrumentHeader> _instruments; ///< Instruments used by the Apple IIGS AGI
+};
+
+} // End of namespace Agi
+
+#endif /* AGI_SOUND_2GS_H */
diff --git a/engines/agi/sound_coco3.cpp b/engines/agi/sound_coco3.cpp
new file mode 100644
index 0000000000..f054be0682
--- /dev/null
+++ b/engines/agi/sound_coco3.cpp
@@ -0,0 +1,80 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "agi/agi.h"
+
+#include "agi/sound_coco3.h"
+
+namespace Agi {
+
+static int cocoFrequencies[] = {
+ 130, 138, 146, 155, 164, 174, 184, 195, 207, 220, 233, 246,
+ 261, 277, 293, 311, 329, 349, 369, 391, 415, 440, 466, 493,
+ 523, 554, 587, 622, 659, 698, 739, 783, 830, 880, 932, 987,
+ 1046, 1108, 1174, 1244, 1318, 1396, 1479, 1567, 1661, 1760, 1864, 1975,
+ 2093, 2217, 2349, 2489, 2637, 2793, 2959, 3135, 3322, 3520, 3729, 3951
+};
+
+SoundGenCoCo3::SoundGenCoCo3(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) {
+}
+
+SoundGenCoCo3::~SoundGenCoCo3() {
+}
+
+void SoundGenCoCo3::play(int resnum) {
+ int i = cocoFrequencies[0]; // Silence warning
+
+ i = i + 1;
+
+#if 0
+ int i = 0;
+ CoCoNote note;
+
+ do {
+ note.read(_chn[i].ptr);
+
+ if (note.freq != 0xff) {
+ playNote(0, cocoFrequencies[note.freq], note.volume);
+
+ uint32 start_time = _vm->_system->getMillis();
+
+ while (_vm->_system->getMillis() < start_time + note.duration) {
+ _vm->_system->updateScreen();
+
+ _vm->_system->delayMillis(10);
+ }
+ }
+ } while (note.freq != 0xff);
+#endif
+}
+
+void SoundGenCoCo3::stop() {
+}
+
+int SoundGenCoCo3::readBuffer(int16 *buffer, const int numSamples) {
+ return numSamples;
+}
+
+} // End of namespace Agi
diff --git a/engines/sci/graphics/gui32.h b/engines/agi/sound_coco3.h
index 99eb03b321..b60f1937cd 100644
--- a/engines/sci/graphics/gui32.h
+++ b/engines/agi/sound_coco3.h
@@ -23,46 +23,51 @@
*
*/
-#ifndef SCI_GRAPHICS_GUI32_H
-#define SCI_GRAPHICS_GUI32_H
+#ifndef AGI_SOUND_COCO3_H
+#define AGI_SOUND_COCO3_H
-#include "sci/graphics/helpers.h"
+#include "sound/audiostream.h"
-namespace Sci {
+namespace Agi {
-class GfxCursor;
-class GfxScreen;
-class GfxPalette;
-class GfxCache;
-class GfxCoordAdjuster32;
-class GfxCompare;
-class GfxFrameout;
-class GfxPaint32;
+struct CoCoNote {
+ uint8 freq;
+ uint8 volume;
+ uint16 duration; ///< Note duration
-class SciGui32 {
+ /** Reads a CoCoNote through the given pointer. */
+ void read(const uint8 *ptr) {
+ freq = *ptr;
+ volume = *(ptr + 1);
+ duration = READ_LE_UINT16(ptr + 2);
+ }
+};
+
+class SoundGenCoCo3 : public SoundGen, public Audio::AudioStream {
public:
- SciGui32(SegManager *segMan, SciEvent *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor);
- ~SciGui32();
+ SoundGenCoCo3(AgiEngine *vm, Audio::Mixer *pMixer);
+ ~SoundGenCoCo3();
- void init();
+ void play(int resnum);
+ void stop(void);
- void textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
+ // AudioStream API
+ int readBuffer(int16 *buffer, const int numSamples);
- void drawRobot(GuiResourceId robotId);
+ bool isStereo() const {
+ return false;
+ }
-protected:
- GfxCursor *_cursor;
- GfxScreen *_screen;
- GfxPalette *_palette;
- GfxCache *_cache;
- GfxCoordAdjuster32 *_coordAdjuster;
- GfxCompare *_compare;
- GfxFrameout *_frameout;
- GfxPaint32 *_paint32;
+ bool endOfData() const {
+ return false;
+ }
-private:
+ int getRate() const {
+ // FIXME: Ideally, we should use _sampleRate.
+ return 22050;
+ }
};
-} // End of namespace Sci
+} // End of namespace Agi
-#endif
+#endif /* AGI_SOUND_COCO3_H */
diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp
new file mode 100644
index 0000000000..57c5d54b27
--- /dev/null
+++ b/engines/agi/sound_midi.cpp
@@ -0,0 +1,345 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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$
+ *
+ */
+
+// Code is based on:
+//
+// A very simple program, that converts an AGI-song into a MIDI-song.
+// Feel free to use it for anything.
+//
+// The default instrument is "piano" for all the channels, what gives
+// good results on most games. But I found, that some songs are interesting
+// with other instruments. If you want to experiment, modify the "instr"
+// array.
+//
+// Timing is not perfect, yet. It plays correct, when I use the
+// Gravis-Midiplayer, but the songs are too fast when I use playmidi on
+// Linux.
+//
+// Original program developed by Jens. Christian Restemeier
+//
+
+// MIDI and digital music class
+
+#include "sound/audiostream.h"
+#include "sound/mididrv.h"
+#include "sound/midiparser.h"
+#include "common/config-manager.h"
+#include "common/file.h"
+#include "common/stream.h"
+
+#include "agi/agi.h"
+
+#include "agi/sound.h"
+#include "agi/sound_midi.h"
+
+#define SPEED_FACTOR 6
+
+namespace Agi {
+
+static uint32 convertSND2MIDI(byte *snddata, byte **data);
+
+MIDISound::MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) {
+ _data = data; // Save the resource pointer
+ _len = len; // Save the resource's length
+ _type = READ_LE_UINT16(data); // Read sound resource's type
+ _isValid = (_type == AGI_SOUND_4CHN) && (_data != NULL) && (_len >= 2);
+
+ if (!_isValid) // Check for errors
+ warning("Error creating MIDI sound from resource %d (Type %d, length %d)", resnum, _type, len);
+}
+
+SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _parser(0), _isPlaying(false), _passThrough(false), _isGM(false) {
+ DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB);
+ _driver = MidiDriver::createMidi(dev);
+
+ memset(_channel, 0, sizeof(_channel));
+ memset(_channelVolume, 255, sizeof(_channelVolume));
+ _masterVolume = 0;
+ this->open();
+ _smfParser = MidiParser::createParser_SMF();
+ _midiMusicData = NULL;
+}
+
+SoundGenMIDI::~SoundGenMIDI() {
+ _driver->setTimerCallback(NULL, NULL);
+ stop();
+ this->close();
+ _smfParser->setMidiDriver(NULL);
+ delete _smfParser;
+ delete[] _midiMusicData;
+}
+
+void SoundGenMIDI::setChannelVolume(int channel) {
+ int newVolume = _channelVolume[channel] * _masterVolume / 255;
+ _channel[channel]->volume(newVolume);
+}
+
+void SoundGenMIDI::setVolume(int volume) {
+ Common::StackLock lock(_mutex);
+
+ volume = CLIP(volume, 0, 255);
+ if (_masterVolume == volume)
+ return;
+ _masterVolume = volume;
+
+ for (int i = 0; i < 16; ++i) {
+ if (_channel[i]) {
+ setChannelVolume(i);
+ }
+ }
+}
+
+int SoundGenMIDI::open() {
+ // Don't ever call open without first setting the output driver!
+ if (!_driver)
+ return 255;
+
+ int ret = _driver->open();
+ if (ret)
+ return ret;
+
+ _driver->setTimerCallback(this, &onTimer);
+ return 0;
+}
+
+void SoundGenMIDI::close() {
+ stop();
+ if (_driver)
+ _driver->close();
+ _driver = 0;
+}
+
+void SoundGenMIDI::send(uint32 b) {
+ if (_passThrough) {
+ _driver->send(b);
+ return;
+ }
+
+ byte channel = (byte)(b & 0x0F);
+ if ((b & 0xFFF0) == 0x07B0) {
+ // Adjust volume changes by master volume
+ byte volume = (byte)((b >> 16) & 0x7F);
+ _channelVolume[channel] = volume;
+ volume = volume * _masterVolume / 255;
+ b = (b & 0xFF00FFFF) | (volume << 16);
+ } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+ else if ((b & 0xFFF0) == 0x007BB0) {
+ //Only respond to All Notes Off if this channel
+ //has currently been allocated
+ if (_channel[b & 0x0F])
+ return;
+ }
+
+ if (!_channel[channel]) {
+ _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ // If a new channel is allocated during the playback, make sure
+ // its volume is correctly initialized.
+ if (_channel[channel])
+ setChannelVolume(channel);
+ }
+
+ if (_channel[channel])
+ _channel[channel]->send(b);
+}
+
+void SoundGenMIDI::metaEvent(byte type, byte *data, uint16 length) {
+
+ switch (type) {
+ case 0x2F: // End of Track
+ stop();
+ _vm->_sound->soundIsFinished();
+ break;
+ default:
+ //warning("Unhandled meta event: %02x", type);
+ break;
+ }
+}
+
+void SoundGenMIDI::onTimer(void *refCon) {
+ SoundGenMIDI *music = (SoundGenMIDI *)refCon;
+ Common::StackLock lock(music->_mutex);
+
+ if (music->_parser)
+ music->_parser->onTimer();
+}
+
+void SoundGenMIDI::play(int resnum) {
+ MIDISound *track;
+
+ stop();
+
+ _isGM = true;
+
+ track = (MIDISound *)_vm->_game.sounds[resnum];
+
+ // Convert AGI Sound data to MIDI
+ int midiMusicSize = convertSND2MIDI(track->_data, &_midiMusicData);
+
+ if (_smfParser->loadMusic(_midiMusicData, midiMusicSize)) {
+ MidiParser *parser = _smfParser;
+ parser->setTrack(0);
+ parser->setMidiDriver(this);
+ parser->setTimerRate(getBaseTempo());
+ parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+
+ _parser = parser;
+
+ syncVolume();
+
+ _isPlaying = true;
+ }
+}
+
+void SoundGenMIDI::stop() {
+ Common::StackLock lock(_mutex);
+
+ if (!_isPlaying)
+ return;
+
+ _isPlaying = false;
+ if (_parser) {
+ _parser->unloadMusic();
+ _parser = NULL;
+ }
+}
+
+void SoundGenMIDI::pause() {
+ setVolume(-1);
+ _isPlaying = false;
+}
+
+void SoundGenMIDI::resume() {
+ syncVolume();
+ _isPlaying = true;
+}
+
+void SoundGenMIDI::syncVolume() {
+ int volume = ConfMan.getInt("music_volume");
+ if (ConfMan.getBool("mute")) {
+ volume = -1;
+ }
+ setVolume(volume);
+}
+
+/* channel / intrument setup: */
+
+/* most songs are good with this: */
+unsigned char instr[] = {0, 0, 0};
+
+/* cool for sq2:
+unsigned char instr[] = {50, 51, 19};
+*/
+
+static void writeDelta(Common::MemoryWriteStreamDynamic *st, int32 delta) {
+ int32 i;
+
+ i = delta >> 21; if (i > 0) st->writeByte((i & 127) | 128);
+ i = delta >> 14; if (i > 0) st->writeByte((i & 127) | 128);
+ i = delta >> 7; if (i > 0) st->writeByte((i & 127) | 128);
+ st->writeByte(delta & 127);
+}
+
+static uint32 convertSND2MIDI(byte *snddata, byte **data) {
+ int32 lp, ep;
+ int n;
+ double ll;
+
+ Common::MemoryWriteStreamDynamic st;
+
+ ll = log10(pow(2.0, 1.0 / 12.0));
+
+ /* Header */
+ st.write("MThd", 4);
+ st.writeUint32BE(6);
+ st.writeUint16BE(1); /* mode */
+ st.writeUint16BE(3); /* number of tracks */
+ st.writeUint16BE(192); /* ticks / quarter */
+
+ for (n = 0; n < 3; n++) {
+ uint16 start, end, pos;
+
+ st.write("MTrk", 4);
+ lp = st.pos();
+ st.writeUint32BE(0); /* chunklength */
+ writeDelta(&st, 0); /* set instrument */
+ st.writeByte(0xc0 + n);
+ st.writeByte(instr[n]);
+ start = snddata[n * 2 + 0] | (snddata[n * 2 + 1] << 8);
+ end = ((snddata[n * 2 + 2] | (snddata[n * 2 + 3] << 8))) - 5;
+
+ for (pos = start; pos < end; pos += 5) {
+ uint16 freq, dur;
+ dur = (snddata[pos + 0] | (snddata[pos + 1] << 8)) * SPEED_FACTOR;
+ freq = ((snddata[pos + 2] & 0x3F) << 4) + (snddata[pos + 3] & 0x0F);
+ if (snddata[pos + 2] > 0) {
+ double fr;
+ int note;
+ /* I don't know, what frequency equals midi note 0 ... */
+ /* This moves the song 4 octaves down: */
+ fr = (log10(111860.0 / (double)freq) / ll) - 48;
+ note = (int)floor(fr + 0.5);
+ if (note < 0) note = 0;
+ if (note > 127) note = 127;
+ /* note on */
+ writeDelta(&st, 0);
+ st.writeByte(144 + n);
+ st.writeByte(note);
+ st.writeByte(100);
+ /* note off */
+ writeDelta(&st, dur);
+ st.writeByte(128 + n);
+ st.writeByte(note);
+ st.writeByte(0);
+ } else {
+ /* note on */
+ writeDelta(&st, 0);
+ st.writeByte(144 + n);
+ st.writeByte(0);
+ st.writeByte(0);
+ /* note off */
+ writeDelta(&st, dur);
+ st.writeByte(128 + n);
+ st.writeByte(0);
+ st.writeByte(0);
+ }
+ }
+ writeDelta(&st, 0);
+ st.writeByte(0xff);
+ st.writeByte(0x2f);
+ st.writeByte(0x0);
+ ep = st.pos();
+ st.seek(lp, SEEK_SET);
+ st.writeUint32BE((ep - lp) - 4);
+ st.seek(ep, SEEK_SET);
+ }
+
+ *data = st.getData();
+
+ return st.pos();
+}
+
+} // End of namespace Agi
diff --git a/engines/agi/sound_midi.h b/engines/agi/sound_midi.h
new file mode 100644
index 0000000000..26b75e0d70
--- /dev/null
+++ b/engines/agi/sound_midi.h
@@ -0,0 +1,114 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+// Music class
+
+#ifndef AGI_SOUND_MIDI_H
+#define AGI_SOUND_MIDI_H
+
+#include "sound/mididrv.h"
+#include "sound/midiparser.h"
+#include "common/mutex.h"
+
+namespace Agi {
+
+class MIDISound : public AgiSound {
+public:
+ MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
+ ~MIDISound() { free(_data); }
+ virtual uint16 type() { return _type; }
+ uint8 *_data; ///< Raw sound resource data
+ uint32 _len; ///< Length of the raw sound resource
+
+protected:
+ uint16 _type; ///< Sound resource type
+};
+
+class SoundGenMIDI : public SoundGen, public MidiDriver {
+public:
+ SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer);
+ ~SoundGenMIDI();
+
+ void play(int resnum);
+ void stop();
+
+ bool isPlaying() { return _isPlaying; }
+ void setPlaying(bool playing) { _isPlaying = playing; }
+
+ void setVolume(int volume);
+ int getVolume() { return _masterVolume; }
+ void syncVolume();
+
+ void setNativeMT32(bool b) { _nativeMT32 = b; }
+ bool hasNativeMT32() { return _nativeMT32; }
+ void pause();
+ void resume();
+ void setLoop(bool loop) { _looping = loop; }
+ void setPassThrough(bool b) { _passThrough = b; }
+
+ void setGM(bool isGM) { _isGM = isGM; }
+
+ // MidiDriver interface implementation
+ int open();
+ void close();
+ void send(uint32 b);
+
+ void metaEvent(byte type, byte *data, uint16 length);
+
+ void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
+ uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
+
+ // Channel allocation functions
+ MidiChannel *allocateChannel() { return 0; }
+ MidiChannel *getPercussionChannel() { return 0; }
+
+ MidiParser *_parser;
+ Common::Mutex _mutex;
+
+private:
+
+ static void onTimer(void *data);
+ void setChannelVolume(int channel);
+
+ MidiChannel *_channel[16];
+ MidiDriver *_driver;
+ MidiParser *_smfParser;
+ byte _channelVolume[16];
+ bool _nativeMT32;
+ bool _isGM;
+ bool _passThrough;
+
+ bool _isPlaying;
+ bool _looping;
+ byte _masterVolume;
+
+ byte *_midiMusicData;
+
+ SoundMgr *_manager;
+};
+
+} // End of namespace Agi
+
+#endif
diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp
new file mode 100644
index 0000000000..b9d701d7f7
--- /dev/null
+++ b/engines/agi/sound_pcjr.cpp
@@ -0,0 +1,512 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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$
+ *
+ */
+
+/* Heavily based on code from NAGI
+ *
+ * COPYRIGHT AND PERMISSION NOTICE
+ *
+ * Copyright (c) 2001, 2001, 2002 Nick Sonneveld
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * 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
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+ * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ *
+ */
+
+#include "agi/agi.h"
+#include "agi/sound.h"
+#include "agi/sound_pcjr.h"
+
+namespace Agi {
+
+// "fade out" or possibly "dissolve"
+// v2.9xx
+const int8 dissolveDataV2[] = {
+ -2, -3, -2, -1,
+ 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x04, 0x04, 0x04, 0x04,
+ 0x05, 0x05, 0x05, 0x05,
+ 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08,
+ 0x09, 0x09, 0x09, 0x09,
+ 0x0A, 0x0A, 0x0A, 0x0A,
+ 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0D,
+ -100
+};
+
+// v3
+const int8 dissolveDataV3[] = {
+ -2, -3, -2, -1,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08,
+ 0x09, 0x09, 0x09, 0x09,
+ 0x0A, 0x0A, 0x0A, 0x0A,
+ 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0D,
+ -100
+};
+
+
+SoundGenPCJr::SoundGenPCJr(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) {
+ _chanAllocated = 10240; // preallocate something which will most likely fit
+ _chanData = (int16 *)malloc(_chanAllocated << 1);
+
+ // Pick dissolve method
+ //
+ // 0 = no dissolve.. just play for as long as it's meant to be played
+ // this was used in older v2.4 and under games i THINK
+ // 1 = not used
+ // 2 = v2.9+ games used a shorter dissolve
+ // 3 (default) = v3 games used this dissolve pattern.. slightly longer
+ if (_vm->getVersion() >= 0x3000)
+ _dissolveMethod = 3;
+ else if (_vm->getVersion() >= 0x2900)
+ _dissolveMethod = 2;
+ else
+ _dissolveMethod = 0;
+
+ _dissolveMethod = 3;
+
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+}
+
+SoundGenPCJr::~SoundGenPCJr() {
+ free(_chanData);
+
+ _mixer->stopHandle(_soundHandle);
+}
+
+void SoundGenPCJr::play(int resnum) {
+ PCjrSound *pcjrSound = (PCjrSound *)_vm->_game.sounds[resnum];
+
+ for (int i = 0; i < CHAN_MAX; i++) {
+ _channel[i].data = pcjrSound->getVoicePointer(i % 4);
+ _channel[i].duration = 0;
+ _channel[i].avail = 0xffff;
+ _channel[i].dissolveCount = 0xFFFF;
+ _channel[i].attenuation = 0;
+ _channel[i].attenuationCopy = 0;
+
+ _tchannel[i].avail = 1;
+ _tchannel[i].noteCount = 0;
+ _tchannel[i].freqCount = 250;
+ _tchannel[i].freqCountPrev = -1;
+ _tchannel[i].atten = 0xF; // silence
+ _tchannel[i].genType = kGenTone;
+ _tchannel[i].genTypePrev = -1;
+ }
+}
+
+void SoundGenPCJr::stop(void) {
+ int i;
+
+ for (i = 0; i < CHAN_MAX ; i++) {
+ _channel[i].avail = 0;
+ _tchannel[i].avail = 0;
+ }
+}
+
+int SoundGenPCJr::volumeCalc(SndGenChan *chan) {
+ int8 attenuation, dissolveValue;
+
+ const int8 *dissolveData;
+
+ switch (_dissolveMethod) {
+ case 2:
+ dissolveData = dissolveDataV2;
+ break;
+ case 3:
+ default:
+ dissolveData = dissolveDataV3;
+ break;
+ }
+
+ assert(chan);
+
+ attenuation = chan->attenuation;
+ if (attenuation != 0x0F) { // != silence
+ if (chan->dissolveCount != 0xFFFF) {
+ dissolveValue = dissolveData[chan->dissolveCount];
+ if (dissolveValue == -100) { // if at end of list
+ chan->dissolveCount = 0xFFFF;
+ chan->attenuation = chan->attenuationCopy;
+ attenuation = chan->attenuation;
+ } else {
+ chan->dissolveCount++;
+
+ attenuation += dissolveValue;
+ if (attenuation < 0)
+ attenuation = 0;
+ if (attenuation > 0x0F)
+ attenuation = 0x0F;
+
+ chan->attenuationCopy = attenuation;
+
+ attenuation &= 0x0F;
+ attenuation += _vm->getvar(vVolume);
+ if (attenuation > 0x0F)
+ attenuation = 0x0F;
+ }
+ }
+ //if (computer_type == 2) && (attenuation < 8)
+ if (attenuation < 8)
+ attenuation += 2;
+ }
+
+ return attenuation;
+}
+
+// read the next channel data.. fill it in *tone
+// if tone isn't touched.. it should be inited so it just plays silence
+// return 0 if it's passing more data
+// return -1 if it's passing nothing (end of data)
+int SoundGenPCJr::getNextNote(int ch, Tone *tone) {
+ SndGenChan *chan;
+ const byte *data;
+
+ assert(tone);
+ assert(ch < CHAN_MAX);
+
+ if (!_vm->getflag(fSoundOn))
+ return -1;
+
+ chan = &_channel[ch];
+ if (!chan->avail)
+ return -1;
+
+ while ((chan->duration == 0) && (chan->duration != 0xFFFF)) {
+ data = chan->data;
+
+ // read the duration of the note
+ chan->duration = READ_LE_UINT16(data); // duration
+
+ // if it's 0 then it's not going to be played
+ // if it's 0xFFFF then the channel data has finished.
+ if ((chan->duration != 0) && (chan->duration != 0xFFFF)) {
+ // only tone channels dissolve
+ if ((ch != 3) && (_dissolveMethod != 0)) // != noise??
+ chan->dissolveCount = 0;
+
+ // attenuation (volume)
+ chan->attenuation = data[4] & 0xF;
+
+ // frequency
+ if (ch < (CHAN_MAX - 1)) {
+ chan->freqCount = (uint16)data[2] & 0x3F;
+ chan->freqCount <<= 4;
+ chan->freqCount |= data[3] & 0x0F;
+
+ chan->genType = kGenTone;
+ } else {
+ int noiseFreq;
+
+ // check for white noise (1) or periodic (0)
+ chan->genType = (data[3] & 0x04) ? kGenWhite : kGenPeriod;
+
+ noiseFreq = data[3] & 0x03;
+
+ switch (noiseFreq) {
+ case 0:
+ chan->freqCount = 32;
+ break;
+ case 1:
+ chan->freqCount = 64;
+ break;
+ case 2:
+ chan->freqCount = 128;
+ break;
+ case 3:
+ chan->freqCount = _channel[2].freqCount * 2;
+ break;
+ }
+ }
+ }
+ // data now points to the next data seg-a-ment
+ chan->data += 5;
+ }
+
+ if (chan->duration != 0xFFFF) {
+ tone->freqCount = chan->freqCount;
+ tone->atten = volumeCalc(chan); // calc volume, sent vol is different from saved vol
+ tone->type = chan->genType;
+ chan->duration--;
+ } else {
+ // kill channel
+ chan->avail = 0;
+ chan->attenuation = 0x0F; // silent
+ chan->attenuationCopy = 0x0F; // dunno really
+
+ return -1;
+ }
+
+ return 0;
+}
+
+// Formulas for noise generator
+// bit0 = output
+
+// noise feedback for white noise mode
+#define FB_WNOISE 0x12000 // bit15.d(16bits) = bit0(out) ^ bit2
+//#define FB_WNOISE 0x14000 // bit15.d(16bits) = bit0(out) ^ bit1
+//#define FB_WNOISE 0x28000 // bit16.d(17bits) = bit0(out) ^ bit2 (same to AY-3-8910)
+//#define FB_WNOISE 0x50000 // bit17.d(18bits) = bit0(out) ^ bit2
+
+// noise feedback for periodic noise mode
+// it is correct maybe (it was in the Megadrive sound manual)
+//#define FB_PNOISE 0x10000 // 16bit rorate
+#define FB_PNOISE 0x08000
+
+// noise generator start preset (for periodic noise)
+#define NG_PRESET 0x0f35
+
+//#define WAVE_HEIGHT (0x7FFF)
+
+// Volume table.
+//
+// 2dB = 20*log(a/b)
+// 10^(2/20)*b = a;
+// value = 0x7fff;
+// value /= 1.258925411794;
+const int16 volTable[16] = {
+ 32767, 26027, 20674, 16422, 13044, 10361, 8230, 6537, 5193, 4125, 3276, 2602, 2067, 1642, 1304, 0
+};
+
+#define FREQ_DIV 111844
+#define MULT FREQ_DIV
+
+// fill buff
+int SoundGenPCJr::chanGen(int chan, int16 *stream, int len) {
+ ToneChan *tpcm;
+ Tone toneNew;
+ int fillSize;
+ int retVal;
+
+ tpcm = &_tchannel[chan];
+
+ retVal = -1;
+
+ while (len > 0) {
+ if (tpcm->noteCount <= 0) {
+ // get new tone data
+ toneNew.freqCount = 0;
+ toneNew.atten = 0xF;
+ toneNew.type = kGenTone;
+ if ((tpcm->avail) && (getNextNote(chan, &toneNew) == 0)) {
+ tpcm->atten = toneNew.atten;
+ tpcm->freqCount = toneNew.freqCount;
+ tpcm->genType = toneNew.type;
+
+ // setup counters 'n stuff
+ // SAMPLE_RATE samples per sec.. tone changes 60 times per sec
+ tpcm->noteCount = SAMPLE_RATE / 60;
+ retVal = 0;
+ } else {
+ // if it doesn't return an
+ tpcm->genType = kGenSilence;
+ tpcm->noteCount = len;
+ tpcm->avail = 0;
+ }
+ }
+
+ // write nothing
+ if ((tpcm->freqCount == 0) || (tpcm->atten == 0xf)) {
+ tpcm->genType = kGenSilence;
+ }
+
+ // find which is smaller.. the buffer or the
+ fillSize = (tpcm->noteCount <= len) ? tpcm->noteCount : len;
+
+ switch (tpcm->genType) {
+ case kGenTone:
+ fillSize = fillSquare(tpcm, stream, fillSize);
+ break;
+ case kGenPeriod:
+ case kGenWhite:
+ fillSize = fillNoise(tpcm, stream, fillSize);
+ break;
+ case kGenSilence:
+ default:
+ // fill with whitespace
+ memset(stream, 0, fillSize * sizeof(int16));
+ break;
+ }
+
+ tpcm->noteCount -= fillSize;
+ stream += fillSize;
+ len -= fillSize;
+ }
+
+ return retVal;
+}
+
+int SoundGenPCJr::fillSquare(ToneChan *t, int16 *buf, int len) {
+ int count;
+
+ if (t->genType != t->genTypePrev) {
+ // make sure the freqCount is checked
+ t->freqCountPrev = -1;
+ t->sign = 1;
+ t->genTypePrev = t->genType;
+ }
+
+ if (t->freqCount != t->freqCountPrev) {
+ //t->scale = (int)( (double)t->samp->freq*t->freqCount/FREQ_DIV * MULT + 0.5);
+ t->scale = (SAMPLE_RATE / 2) * t->freqCount;
+ t->count = t->scale;
+ t->freqCountPrev = t->freqCount;
+ }
+
+ count = len;
+
+ while (count > 0) {
+ *(buf++) = t->sign ? volTable[t->atten] : -volTable[t->atten];
+ count--;
+
+ // get next sample
+ t->count -= MULT;
+ while (t->count <= 0) {
+ t->sign ^= 1;
+ t->count += t->scale;
+ }
+ }
+
+ return len;
+}
+
+int SoundGenPCJr::fillNoise(ToneChan *t, int16 *buf, int len) {
+ int count;
+
+ if (t->genType != t->genTypePrev) {
+ // make sure the freqCount is checked
+ t->freqCountPrev = -1;
+ t->genTypePrev = t->genType;
+ }
+
+ if (t->freqCount != t->freqCountPrev) {
+ //t->scale = (int)( (double)t->samp->freq*t->freqCount/FREQ_DIV * MULT + 0.5);
+ t->scale = (SAMPLE_RATE / 2) * t->freqCount;
+ t->count = t->scale;
+ t->freqCountPrev = t->freqCount;
+
+ t->feedback = (t->genType == kGenWhite) ? FB_WNOISE : FB_PNOISE;
+ // reset noise shifter
+ t->noiseState = NG_PRESET;
+ t->sign = t->noiseState & 1;
+ }
+
+ count = len;
+
+ while (count > 0) {
+ *(buf++) = t->sign ? volTable[t->atten] : -volTable[t->atten];
+ count--;
+
+ // get next sample
+ t->count -= MULT;
+ while (t->count <= 0) {
+ if (t->noiseState & 1)
+ t->noiseState ^= t->feedback;
+
+ t->noiseState >>= 1;
+ t->sign = t->noiseState & 1;
+ t->count += t->scale;
+ }
+ }
+
+ return len;
+}
+
+int SoundGenPCJr::readBuffer(int16 *stream, const int len) {
+ int streamCount;
+ int16 *sPtr, *cPtr;
+
+ if (_chanAllocated < len) {
+ free(_chanData);
+ _chanData = (int16 *)malloc(len << 1);
+ _chanAllocated = len;
+ }
+ memset(stream, 0, len << 1);
+
+ assert(stream);
+
+ bool finished = true;
+
+ for (int i = 0; i < CHAN_MAX; i++) {
+ // get channel data(chan.userdata)
+ if (chanGen(i, _chanData, len) == 0) {
+ // divide by number of channels then add to stream
+ streamCount = len;
+ sPtr = stream;
+ cPtr = _chanData;
+
+ while (streamCount--)
+ *(sPtr++) += *(cPtr++) / CHAN_MAX;
+
+ finished = false;
+ }
+ }
+
+ if (finished)
+ _vm->_sound->soundIsFinished();
+
+ return len;
+}
+
+} // End of namespace Agi
diff --git a/engines/agi/sound_pcjr.h b/engines/agi/sound_pcjr.h
new file mode 100644
index 0000000000..fe0e762f4e
--- /dev/null
+++ b/engines/agi/sound_pcjr.h
@@ -0,0 +1,127 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef AGI_SOUND_PCJR_H
+#define AGI_SOUND_PCJR_H
+
+#include "sound/audiostream.h"
+
+namespace Agi {
+
+#define CHAN_MAX 4
+
+#define SAMPLE_RATE 22050
+
+enum GenType {
+ kGenSilence,
+ kGenTone,
+ kGenPeriod,
+ kGenWhite
+};
+
+struct SndGenChan {
+ const byte *data;
+ uint16 duration;
+ uint16 avail; // turned on (1) but when the channel's data runs out, it's set to (0)
+ uint16 dissolveCount;
+ byte attenuation;
+ byte attenuationCopy;
+
+ GenType genType;
+
+ // for the sample mixer
+ int freqCount;
+};
+
+struct ToneChan {
+ int avail;
+
+ int noteCount; // length of tone.. duration
+
+ int freqCount;
+ int freqCountPrev;
+ int atten; // volume
+
+ GenType genType;
+ int genTypePrev;
+
+ int count;
+ int scale;
+ int sign;
+ unsigned int noiseState; /* noise generator */
+ int feedback; /* noise feedback mask */
+};
+
+struct Tone {
+ int freqCount;
+ int atten;
+ GenType type;
+};
+
+class SoundGenPCJr : public SoundGen, public Audio::AudioStream {
+public:
+ SoundGenPCJr(AgiEngine *vm, Audio::Mixer *pMixer);
+ ~SoundGenPCJr();
+
+ void play(int resnum);
+ void stop(void);
+
+ // AudioStream API
+ int readBuffer(int16 *buffer, const int numSamples);
+
+ bool isStereo() const {
+ return false;
+ }
+
+ bool endOfData() const {
+ return false;
+ }
+
+ int getRate() const {
+ // FIXME: Ideally, we should use _sampleRate.
+ return 22050;
+ }
+
+private:
+ int getNextNote(int ch, Tone *tone);
+ int volumeCalc(SndGenChan *chan);
+
+ int chanGen(int chan, int16 *stream, int len);
+
+ int fillNoise(ToneChan *t, int16 *buf, int len);
+ int fillSquare(ToneChan *t, int16 *buf, int len);
+
+private:
+ SndGenChan _channel[CHAN_MAX];
+ ToneChan _tchannel[CHAN_MAX];
+ int16 *_chanData;
+ int _chanAllocated;
+
+ int _dissolveMethod;
+};
+
+} // End of namespace Agi
+
+#endif /* AGI_SOUND_PCJR_H */
diff --git a/engines/agi/sound_sarien.cpp b/engines/agi/sound_sarien.cpp
new file mode 100644
index 0000000000..08bdd47497
--- /dev/null
+++ b/engines/agi/sound_sarien.cpp
@@ -0,0 +1,357 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/md5.h"
+#include "common/config-manager.h"
+#include "common/fs.h"
+#include "common/random.h"
+#include "common/str-array.h"
+
+#include "sound/mididrv.h"
+
+#include "agi/agi.h"
+
+#include "agi/sound_sarien.h"
+
+namespace Agi {
+
+#define USE_INTERPOLATION
+
+static const int16 waveformRamp[WAVEFORM_SIZE] = {
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 64, 72, 80, 88, 96, 104, 112, 120,
+ 128, 136, 144, 152, 160, 168, 176, 184,
+ 192, 200, 208, 216, 224, 232, 240, 255,
+ 0, -248, -240, -232, -224, -216, -208, -200,
+ -192, -184, -176, -168, -160, -152, -144, -136,
+ -128, -120, -112, -104, -96, -88, -80, -72,
+ -64, -56, -48, -40, -32, -24, -16, -8 // Ramp up
+};
+
+static const int16 waveformSquare[WAVEFORM_SIZE] = {
+ 255, 230, 220, 220, 220, 220, 220, 220,
+ 220, 220, 220, 220, 220, 220, 220, 220,
+ 220, 220, 220, 220, 220, 220, 220, 220,
+ 220, 220, 220, 220, 220, 220, 220, 110,
+ -255, -230, -220, -220, -220, -220, -220, -220,
+ -220, -220, -220, -220, -220, -220, -220, -220,
+ -220, -220, -220, -220, -220, -220, -220, -220,
+ -220, -220, -220, -110, 0, 0, 0, 0 // Square
+};
+
+static const int16 waveformMac[WAVEFORM_SIZE] = {
+ 45, 110, 135, 161, 167, 173, 175, 176,
+ 156, 137, 123, 110, 91, 72, 35, -2,
+ -60, -118, -142, -165, -170, -176, -177, -179,
+ -177, -176, -164, -152, -117, -82, -17, 47,
+ 92, 137, 151, 166, 170, 173, 171, 169,
+ 151, 133, 116, 100, 72, 43, -7, -57,
+ -99, -141, -156, -170, -174, -177, -178, -179,
+ -175, -172, -165, -159, -137, -114, -67, -19
+};
+
+SoundGenSarien::SoundGenSarien(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _chn() {
+ _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE);
+
+ memset(_sndBuffer, 0, BUFFER_SIZE << 1);
+ _env = false;
+ _playingSound = -1;
+ _playing = false;
+ _useChorus = true; // FIXME: Currently always true?
+
+ switch (_vm->_soundemu) {
+ case SOUND_EMU_NONE:
+ _waveform = waveformRamp;
+ _env = true;
+ break;
+ case SOUND_EMU_AMIGA:
+ case SOUND_EMU_PC:
+ _waveform = waveformSquare;
+ break;
+ case SOUND_EMU_MAC:
+ _waveform = waveformMac;
+ break;
+ }
+
+ report("Initializing sound:\n");
+
+ report("sound: envelopes ");
+ if (_env) {
+ report("enabled (decay=%d, sustain=%d)\n", ENV_DECAY, ENV_SUSTAIN);
+ } else {
+ report("disabled\n");
+ }
+
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+}
+
+SoundGenSarien::~SoundGenSarien() {
+ _mixer->stopHandle(_soundHandle);
+
+ free(_sndBuffer);
+}
+
+int SoundGenSarien::readBuffer(int16 *buffer, const int numSamples) {
+ fillAudio(buffer, numSamples / 2);
+
+ return numSamples;
+}
+
+void SoundGenSarien::play(int resnum) {
+ AgiSoundEmuType type;
+
+ type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type();
+
+ assert(type == AGI_SOUND_4CHN);
+
+ _playingSound = resnum;
+
+ PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum];
+
+ // Initialize channel info
+ for (int i = 0; i < NUM_CHANNELS; i++) {
+ _chn[i].type = type;
+ _chn[i].flags = AGI_SOUND_LOOP;
+
+ if (_env) {
+ _chn[i].flags |= AGI_SOUND_ENVELOPE;
+ _chn[i].adsr = AGI_SOUND_ENV_ATTACK;
+ }
+
+ _chn[i].ins = _waveform;
+ _chn[i].size = WAVEFORM_SIZE;
+ _chn[i].ptr = pcjrSound->getVoicePointer(i % 4);
+ _chn[i].timer = 0;
+ _chn[i].vol = 0;
+ _chn[i].end = 0;
+ }
+
+ memset(_sndBuffer, 0, BUFFER_SIZE << 1);
+}
+
+void SoundGenSarien::stop() {
+ _playingSound = -1;
+
+ for (int i = 0; i < NUM_CHANNELS; i++)
+ stopNote(i);
+}
+
+void SoundGenSarien::stopNote(int i) {
+ _chn[i].adsr = AGI_SOUND_ENV_RELEASE;
+
+ if (_useChorus) {
+ // Stop chorus ;)
+ if (_chn[i].type == AGI_SOUND_4CHN &&
+ _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
+ stopNote(i + 4);
+ }
+ }
+}
+
+void SoundGenSarien::playNote(int i, int freq, int vol) {
+ if (!_vm->getflag(fSoundOn))
+ vol = 0;
+ else if (vol && _vm->_soundemu == SOUND_EMU_PC)
+ vol = 160;
+
+ _chn[i].phase = 0;
+ _chn[i].freq = freq;
+ _chn[i].vol = vol;
+ _chn[i].env = 0x10000;
+ _chn[i].adsr = AGI_SOUND_ENV_ATTACK;
+
+ if (_useChorus) {
+ // Add chorus ;)
+ if (_chn[i].type == AGI_SOUND_4CHN &&
+ _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
+
+ int newfreq = freq * 1007 / 1000;
+
+ if (freq == newfreq)
+ newfreq++;
+
+ playNote(i + 4, newfreq, vol * 2 / 3);
+ }
+ }
+}
+
+void SoundGenSarien::playSound() {
+ int i;
+ AgiNote note;
+
+ if (_playingSound == -1)
+ return;
+
+ _playing = false;
+ for (i = 0; i < (_vm->_soundemu == SOUND_EMU_PC ? 1 : 4); i++) {
+ _playing |= !_chn[i].end;
+ note.read(_chn[i].ptr); // Read a single note (Doesn't advance the pointer)
+
+ if (_chn[i].end)
+ continue;
+
+ if ((--_chn[i].timer) <= 0) {
+ stopNote(i);
+
+ if (note.freqDiv != 0) {
+ int volume = (note.attenuation == 0x0F) ? 0 : (0xFF - note.attenuation * 2);
+ playNote(i, note.freqDiv * 10, volume);
+ }
+
+ _chn[i].timer = note.duration;
+
+ if (_chn[i].timer == 0xffff) {
+ _chn[i].end = 1;
+ _chn[i].vol = 0;
+ _chn[i].env = 0;
+
+ if (_useChorus) {
+ // chorus
+ if (_chn[i].type == AGI_SOUND_4CHN && _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
+ _chn[i + 4].vol = 0;
+ _chn[i + 4].env = 0;
+ }
+ }
+ }
+ _chn[i].ptr += 5; // Advance the pointer to the next note data (5 bytes per note)
+ }
+ }
+
+ if (!_playing) {
+ _vm->_sound->soundIsFinished();
+
+ _playingSound = -1;
+ }
+}
+
+uint32 SoundGenSarien::mixSound() {
+ register int i, p;
+ const int16 *src;
+ int c, b, m;
+
+ memset(_sndBuffer, 0, BUFFER_SIZE << 1);
+
+ if (!_playing || _playingSound == -1)
+ return BUFFER_SIZE;
+
+ // Handle PCjr 4-channel sound mixing here
+ for (c = 0; c < NUM_CHANNELS; c++) {
+ if (!_chn[c].vol)
+ continue;
+
+ m = _chn[c].flags & AGI_SOUND_ENVELOPE ?
+ _chn[c].vol * _chn[c].env >> 16 : _chn[c].vol;
+
+ if (_chn[c].type != AGI_SOUND_4CHN || c != 3) {
+ src = _chn[c].ins;
+
+ p = _chn[c].phase;
+ for (i = 0; i < BUFFER_SIZE; i++) {
+ b = src[p >> 8];
+#ifdef USE_INTERPOLATION
+ b += ((src[((p >> 8) + 1) % _chn[c].size] - src[p >> 8]) * (p & 0xff)) >> 8;
+#endif
+ _sndBuffer[i] += (b * m) >> 4;
+
+ p += (uint32) 118600 *4 / _chn[c].freq;
+
+ // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what
+ // needs fixing, or remove it!
+ // FIXME
+ if (_chn[c].flags & AGI_SOUND_LOOP) {
+ p %= _chn[c].size << 8;
+ } else {
+ if (p >= _chn[c].size << 8) {
+ p = _chn[c].vol = 0;
+ _chn[c].end = 1;
+ break;
+ }
+ }
+
+ }
+ _chn[c].phase = p;
+ } else {
+ // Add white noise
+ for (i = 0; i < BUFFER_SIZE; i++) {
+ b = _vm->_rnd->getRandomNumber(255) - 128;
+ _sndBuffer[i] += (b * m) >> 4;
+ }
+ }
+
+ switch (_chn[c].adsr) {
+ case AGI_SOUND_ENV_ATTACK:
+ // not implemented
+ _chn[c].adsr = AGI_SOUND_ENV_DECAY;
+ break;
+ case AGI_SOUND_ENV_DECAY:
+ if (_chn[c].env > _chn[c].vol * ENV_SUSTAIN + ENV_DECAY) {
+ _chn[c].env -= ENV_DECAY;
+ } else {
+ _chn[c].env = _chn[c].vol * ENV_SUSTAIN;
+ _chn[c].adsr = AGI_SOUND_ENV_SUSTAIN;
+ }
+ break;
+ case AGI_SOUND_ENV_SUSTAIN:
+ break;
+ case AGI_SOUND_ENV_RELEASE:
+ if (_chn[c].env >= ENV_RELEASE) {
+ _chn[c].env -= ENV_RELEASE;
+ } else {
+ _chn[c].env = 0;
+ }
+ }
+ }
+
+ return BUFFER_SIZE;
+}
+
+void SoundGenSarien::fillAudio(int16 *stream, uint len) {
+ uint32 p = 0;
+
+ // current number of audio bytes in _sndBuffer
+ static uint32 data_available = 0;
+ // offset of start of audio bytes in _sndBuffer
+ static uint32 data_offset = 0;
+
+ len <<= 2;
+
+ debugC(5, kDebugLevelSound, "(%p, %d)", (void *)stream, len);
+
+ while (len > data_available) {
+ memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, data_available);
+ p += data_available;
+ len -= data_available;
+
+ playSound();
+ data_available = mixSound() << 1;
+ data_offset = 0;
+ }
+
+ memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, len);
+ data_offset += len;
+ data_available -= len;
+}
+
+} // End of namespace Agi
diff --git a/engines/agi/sound_sarien.h b/engines/agi/sound_sarien.h
new file mode 100644
index 0000000000..54222ba624
--- /dev/null
+++ b/engines/agi/sound_sarien.h
@@ -0,0 +1,120 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef AGI_SOUND_SARIEN_H
+#define AGI_SOUND_SARIEN_H
+
+#include "sound/audiostream.h"
+
+namespace Agi {
+
+#define BUFFER_SIZE 410
+
+#define WAVEFORM_SIZE 64
+#define ENV_ATTACK 10000 /**< envelope attack rate */
+#define ENV_DECAY 1000 /**< envelope decay rate */
+#define ENV_SUSTAIN 100 /**< envelope sustain level */
+#define ENV_RELEASE 7500 /**< envelope release rate */
+#define NUM_CHANNELS 7 /**< number of sound channels */
+
+enum AgiSoundFlags {
+ AGI_SOUND_LOOP = 0x0001,
+ AGI_SOUND_ENVELOPE = 0x0002
+};
+enum AgiSoundEnv {
+ AGI_SOUND_ENV_ATTACK = 3,
+ AGI_SOUND_ENV_DECAY = 2,
+ AGI_SOUND_ENV_SUSTAIN = 1,
+ AGI_SOUND_ENV_RELEASE = 0
+};
+
+
+/**
+ * AGI engine sound channel structure.
+ */
+struct ChannelInfo {
+ AgiSoundEmuType type;
+ const uint8 *ptr; // Pointer to the AgiNote data
+ const int16 *ins;
+ int32 size;
+ uint32 phase;
+ uint32 flags; // ORs values from AgiSoundFlags
+ AgiSoundEnv adsr;
+ int32 timer;
+ uint32 end;
+ uint32 freq;
+ uint32 vol;
+ uint32 env;
+};
+
+class SoundGenSarien : public SoundGen, public Audio::AudioStream {
+public:
+ SoundGenSarien(AgiEngine *vm, Audio::Mixer *pMixer);
+ ~SoundGenSarien();
+
+ void play(int resnum);
+ void stop(void);
+
+ // AudioStream API
+ int readBuffer(int16 *buffer, const int numSamples);
+
+ bool isStereo() const {
+ return false;
+ }
+
+ bool endOfData() const {
+ return false;
+ }
+
+ int getRate() const {
+ // FIXME: Ideally, we should use _sampleRate.
+ return 22050;
+ }
+
+private:
+ ChannelInfo _chn[NUM_CHANNELS];
+ uint8 _env;
+
+ int16 *_sndBuffer;
+ const int16 *_waveform;
+
+ bool _useChorus;
+
+ bool _playing;
+ int _playingSound;
+
+private:
+ void playSound();
+ uint32 mixSound();
+ void fillAudio(int16 *stream, uint len);
+
+ void stopNote(int i);
+ void playNote(int i, int freq, int vol);
+
+};
+
+} // End of namespace Agi
+
+#endif /* AGI_SOUND_SARIEN_H */
diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp
index 63ac880267..569481d772 100644
--- a/engines/agi/sprite.cpp
+++ b/engines/agi/sprite.cpp
@@ -241,6 +241,14 @@ void SpritesMgr::objsRestoreArea(Sprite *s) {
q += xSize;
pos0 += _WIDTH;
}
+
+ // WORKAROUND (see ScummVM bug #1945716)
+ // When set.view command is called, current code cannot detect this situation while updating
+ // Thus we force removal of the old sprite
+ if (s->v && s->v->viewReplaced) {
+ commitBlock(xPos, yPos, xPos + xSize, yPos + ySize);
+ s->v->viewReplaced = false;
+ }
}
@@ -332,6 +340,8 @@ void SpritesMgr::buildList(SpriteList &l, bool (*test)(VtEntry *, AgiEngine *))
}
}
+ debugC(5, kDebugLevelSprites, "buildList() --> entries %d", i);
+
// now look for the smallest y value in the array and put that
// sprite in the list
for (j = 0; j < i; j++) {
@@ -381,38 +391,20 @@ void SpritesMgr::freeList(SpriteList &l) {
* Copy sprites from the pic buffer to the screen buffer, and check if
* sprites of the given list have moved.
*/
-void SpritesMgr::commitSprites(SpriteList &l) {
+void SpritesMgr::commitSprites(SpriteList &l, bool immediate) {
SpriteList::iterator iter;
for (iter = l.begin(); iter != l.end(); ++iter) {
Sprite *s = *iter;
- int x1, y1, x2, y2, w, h;
+ int x1, y1, x2, y2;
- w = (s->v->celData->width > s->v->celData2->width) ?
- s->v->celData->width : s->v->celData2->width;
-
- h = (s->v->celData->height >
- s->v->celData2->height) ? s->v->celData->
- height : s->v->celData2->height;
+ x1 = MIN((int)MIN(s->v->xPos, s->v->xPos2), MIN(s->v->xPos + s->v->celData->width, s->v->xPos2 + s->v->celData2->width));
+ x2 = MAX((int)MAX(s->v->xPos, s->v->xPos2), MAX(s->v->xPos + s->v->celData->width, s->v->xPos2 + s->v->celData2->width));
+ y1 = MIN((int)MIN(s->v->yPos, s->v->yPos2), MIN(s->v->yPos - s->v->celData->height, s->v->yPos2 - s->v->celData2->height));
+ y2 = MAX((int)MAX(s->v->yPos, s->v->yPos2), MAX(s->v->yPos - s->v->celData->height, s->v->yPos2 - s->v->celData2->height));
s->v->celData2 = s->v->celData;
- if (s->v->xPos < s->v->xPos2) {
- x1 = s->v->xPos;
- x2 = s->v->xPos2 + w - 1;
- } else {
- x1 = s->v->xPos2;
- x2 = s->v->xPos + w - 1;
- }
-
- if (s->v->yPos < s->v->yPos2) {
- y1 = s->v->yPos - h + 1;
- y2 = s->v->yPos2;
- } else {
- y1 = s->v->yPos2 - h + 1;
- y2 = s->v->yPos;
- }
-
- commitBlock(x1, y1, x2, y2);
+ commitBlock(x1, y1, x2, y2, immediate);
if (s->v->stepTimeCount != s->v->stepTime)
continue;
@@ -452,7 +444,7 @@ void SpritesMgr::blitSprites(SpriteList& l) {
Sprite *s = *iter;
objsSaveArea(s);
- debugC(8, kDebugLevelSprites, "s->v->entry = %d (prio %d)", s->v->entry, s->v->priority);
+ debugC(8, kDebugLevelSprites, "blitSprites(): s->v->entry = %d (prio %d)", s->v->entry, s->v->priority);
hidden = blitCel(s->xPos, s->yPos, s->v->priority, s->v->celData, s->v->viewData->agi256_2);
if (s->v->entry == 0) { // if ego, update f1
@@ -528,7 +520,7 @@ void SpritesMgr::eraseBoth() {
* @see blit_both()
*/
void SpritesMgr::blitUpdSprites() {
- debugC(7, kDebugLevelSprites, "blit updating");
+ debugC(7, kDebugLevelSprites, "blitUpdSprites()");
buildUpdBlitlist();
blitSprites(_sprUpd);
}
@@ -542,7 +534,7 @@ void SpritesMgr::blitUpdSprites() {
* @see blit_both()
*/
void SpritesMgr::blitNonupdSprites() {
- debugC(7, kDebugLevelSprites, "blit non-updating");
+ debugC(7, kDebugLevelSprites, "blitNonupdSprites()");
buildNonupdBlitlist();
blitSprites(_sprNonupd);
}
@@ -578,7 +570,7 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in
int x1, y1, x2, y2, y3;
uint8 *p1, *p2;
- debugC(3, kDebugLevelSprites, "v=%d, l=%d, c=%d, x=%d, y=%d, p=%d, m=%d", view, loop, cel, x, y, pri, mar);
+ debugC(3, kDebugLevelSprites, "addToPic(view=%d, loop=%d, cel=%d, x=%d, y=%d, pri=%d, mar=%d)", view, loop, cel, x, y, pri, mar);
_vm->recordImageStackCall(ADD_VIEW, view, loop, cel, x, y, pri, mar);
@@ -609,7 +601,7 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in
eraseBoth();
- debugC(4, kDebugLevelSprites, "blit_cel (%d, %d, %d, c)", x, y, pri);
+ debugC(4, kDebugLevelSprites, "blitCel(%d, %d, %d, c)", x, y, pri);
blitCel(x1, y1, pri, c, _vm->_game.views[view].agi256_2);
// If margin is 0, 1, 2, or 3, the base of the cel is
@@ -659,8 +651,7 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in
blitBoth();
- debugC(4, kDebugLevelSprites, "commit_block (%d, %d, %d, %d)", x1, y1, x2, y2);
- commitBlock(x1, y1, x2, y2);
+ commitBlock(x1, y1, x2, y2, true);
}
/**
@@ -688,18 +679,19 @@ void SpritesMgr::showObj(int n) {
s.xSize = c->width;
s.ySize = c->height;
s.buffer = (uint8 *)malloc(s.xSize * s.ySize);
+ s.v = 0;
objsSaveArea(&s);
blitCel(x1, y1, 15, c, _vm->_game.views[n].agi256_2);
- commitBlock(x1, y1, x2, y2);
+ commitBlock(x1, y1, x2, y2, true);
_vm->messageBox(_vm->_game.views[n].descr);
objsRestoreArea(&s);
- commitBlock(x1, y1, x2, y2);
+ commitBlock(x1, y1, x2, y2, true);
free(s.buffer);
}
-void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) {
+void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2, bool immediate) {
int i, w, offset;
uint8 *q;
@@ -711,7 +703,7 @@ void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) {
y1 = CLIP(y1, 0, _HEIGHT - 1);
y2 = CLIP(y2, 0, _HEIGHT - 1);
- debugC(7, kDebugLevelSprites, "%d, %d, %d, %d", x1, y1, x2, y2);
+ debugC(7, kDebugLevelSprites, "commitBlock(%d, %d, %d, %d)", x1, y1, x2, y2);
w = x2 - x1 + 1;
q = &_vm->_game.sbuf16c[x1 + _WIDTH * y1];
@@ -723,6 +715,9 @@ void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) {
}
_gfx->flushBlockA(x1, y1 + offset, x2, y2 + offset);
+
+ if (immediate)
+ _gfx->doUpdate();
}
SpritesMgr::SpritesMgr(AgiEngine *agi, GfxMgr *gfx) {
diff --git a/engines/agi/sprite.h b/engines/agi/sprite.h
index 7d6d7bb97e..57fd0dacf2 100644
--- a/engines/agi/sprite.h
+++ b/engines/agi/sprite.h
@@ -65,7 +65,7 @@ private:
void buildUpdBlitlist();
void buildNonupdBlitlist();
void freeList(SpriteList &l);
- void commitSprites(SpriteList &l);
+ void commitSprites(SpriteList &l, bool immediate = false);
void eraseSprites(SpriteList &l);
void blitSprites(SpriteList &l);
static bool testUpdating(VtEntry *v, AgiEngine *);
@@ -88,7 +88,7 @@ public:
void commitBoth();
void addToPic(int, int, int, int, int, int, int);
void showObj(int);
- void commitBlock(int, int, int, int);
+ void commitBlock(int x1, int y1, int x2, int y2, bool immediate = false);
};
} // End of namespace Agi
diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp
index ee9aebf240..778da0a527 100644
--- a/engines/agi/text.cpp
+++ b/engines/agi/text.cpp
@@ -135,8 +135,8 @@ void AgiEngine::blitTextbox(const char *p, int y, int x, int len) {
if (x == 0 && y == 0 && len == 0)
x = y = -1;
- if (len <= 0 || len >= 40)
- len = 32;
+ if (len <= 0)
+ len = 30;
xoff = x * CHAR_COLS;
yoff = y * CHAR_LINES;
@@ -214,6 +214,7 @@ void AgiEngine::printTextConsole(const char *msg, int x, int y, int len, int fg,
x *= CHAR_COLS;
y *= 10;
+ debugC(4, kDebugLevelText, "printTextConsole(): %s, %d, %d, %d, %d, %d", msg, x, y, len, fg, bg);
printText2(1, msg, 0, x, y, len, fg, bg);
}
@@ -488,7 +489,7 @@ int AgiEngine::print(const char *p, int lin, int col, int len) {
_game.keypress = 0;
break;
}
- } while (_game.msgBoxTicks > 0);
+ } while (_game.msgBoxTicks > 0 && !(shouldQuit() || _restartGame));
setvar(vWindowReset, 0);
@@ -655,11 +656,8 @@ void AgiEngine::writePrompt() {
int l, fg, bg, pos;
int promptLength = strlen(agiSprintf(_game.strings[0]));
- if (!_game.inputEnabled || _game.inputMode != INPUT_NORMAL) {
- clearPrompt();
-
+ if (!_game.inputEnabled || _game.inputMode != INPUT_NORMAL)
return;
- }
l = _game.lineUserInput;
fg = _game.colorFg;
@@ -699,6 +697,8 @@ void AgiEngine::clearLines(int l1, int l2, int c) {
// inc for endline so it matches the correct num
// ie, from 22 to 24 is 3 lines, not 2 lines.
+ debugC(4, kDebugLevelText, "clearLines(%d, %d, %d)", l1, l2, c);
+
l1 *= CHAR_LINES;
l2 *= CHAR_LINES;
l2 += CHAR_LINES - 1;
diff --git a/engines/agi/view.cpp b/engines/agi/view.cpp
index fb417e86a9..fcca1e2a79 100644
--- a/engines/agi/view.cpp
+++ b/engines/agi/view.cpp
@@ -157,8 +157,7 @@ int AgiEngine::decodeView(int n) {
return errNoLoopsInView;
// allocate memory for all views
- _game.views[n].loop = (ViewLoop *)
- calloc(_game.views[n].numLoops, sizeof(ViewLoop));
+ _game.views[n].loop = (ViewLoop *)calloc(_game.views[n].numLoops, sizeof(ViewLoop));
if (_game.views[n].loop == NULL)
return errNotEnoughMemory;
@@ -294,37 +293,10 @@ void AgiEngine::setLoop(VtEntry *v, int n) {
* @param n number of AGI view resource
*/
void AgiEngine::setView(VtEntry *v, int n) {
-
- uint16 viewFlags = 0;
-
- // When setting a view to the view table, if there's already another view set in that
- // view table entry and it's still drawn, erase the existing view before setting the new one
- // Fixes bug #1658643: AGI: SQ1 (2.2 DOS ENG) Graphic error, ego leaves behind copy
- // Update: Apparently, this makes ego dissapear at times, e.g. when textboxes are shown
- // Therefore, it's limited to view 118 in SQ1 (Roger climbing the ladder)
- // Fixes bug #1715284: Roger sometimes disappears
- if (v->viewData != NULL) {
- if (v->currentView == 118 && v->flags & DRAWN && getGameID() == GID_SQ1) {
- viewFlags = v->flags; // Store the flags for the view
- _sprites->eraseUpdSprites();
-
- if (v->flags & UPDATE) {
- v->flags &= ~DRAWN;
- } else {
- _sprites->eraseNonupdSprites();
- v->flags &= ~DRAWN;
- _sprites->blitNonupdSprites();
- }
- _sprites->blitUpdSprites();
-
- _sprites->commitBlock(v->xPos, v->yPos - v->ySize + 1, v->xPos + v->xSize - 1, v->yPos);
- v->flags = viewFlags; // Restore the view's flags
- }
- }
-
v->viewData = &_game.views[n];
v->currentView = n;
v->numLoops = v->viewData->numLoops;
+ v->viewReplaced = true;
setLoop(v, v->currentLoop >= v->numLoops ? 0 : v->currentLoop);
}
@@ -338,6 +310,7 @@ void AgiEngine::startUpdate(VtEntry *v) {
v->flags |= UPDATE;
_sprites->blitBoth();
+ _sprites->commitBoth();
}
}
@@ -351,6 +324,7 @@ void AgiEngine::stopUpdate(VtEntry *v) {
v->flags &= ~UPDATE;
_sprites->blitBoth();
+ _sprites->commitBoth();
}
}
@@ -393,7 +367,7 @@ void AgiEngine::updateViewtable() {
break;
default:
// for KQ4
- if (getVersion() == 0x3086)
+ if (getVersion() == 0x3086 || getGameID() == GID_KQ4)
loop = loopTable4[v->direction];
break;
}
diff --git a/engines/agi/view.h b/engines/agi/view.h
index f9017ec4ae..85f2d6eaf9 100644
--- a/engines/agi/view.h
+++ b/engines/agi/view.h
@@ -63,6 +63,7 @@ struct VtEntry {
int16 xPos;
int16 yPos;
uint8 currentView;
+ bool viewReplaced;
struct AgiView *viewData;
uint8 currentLoop;
uint8 numLoops;
diff --git a/engines/agi/wagparser.cpp b/engines/agi/wagparser.cpp
index 1d60524070..22de66712d 100644
--- a/engines/agi/wagparser.cpp
+++ b/engines/agi/wagparser.cpp
@@ -100,10 +100,8 @@ void WagProperty::setDefaults() {
}
void WagProperty::deleteData() {
- if (_propData != NULL) {
- delete _propData;
- _propData = NULL;
- }
+ delete _propData;
+ _propData = NULL;
}
WagFileParser::WagFileParser() :
diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp
index c8b22956f4..464c218ae8 100644
--- a/engines/agi/words.cpp
+++ b/engines/agi/words.cpp
@@ -76,10 +76,8 @@ int AgiEngine::loadWords(const char *fname) {
}
void AgiEngine::unloadWords() {
- if (words != NULL) {
- free(words);
- words = NULL;
- }
+ free(words);
+ words = NULL;
}
/**
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index 926b3a8972..670c701198 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -202,19 +202,19 @@ AGOSEngine::AGOSEngine(OSystem *syst)
_scanFlag = false;
_scriptVar2 = 0;
- _runScriptReturn1 = 0;
- _skipVgaWait = 0;
- _noParentNotify = 0;
- _beardLoaded = 0;
- _litBoxFlag = 0;
- _mortalFlag = 0;
+ _runScriptReturn1 = false;
+ _skipVgaWait = false;
+ _noParentNotify = false;
+ _beardLoaded = false;
+ _litBoxFlag = false;
+ _mortalFlag = false;
_displayFlag = 0;
- _syncFlag2 = 0;
- _inCallBack = 0;
- _cepeFlag = 0;
- _fastMode = 0;
+ _syncFlag2 = false;
+ _inCallBack = false;
+ _cepeFlag = false;
+ _fastMode = false;
- _backFlag = 0;
+ _backFlag = false;
_debugMode = 0;
_dumpScripts = false;
@@ -557,10 +557,10 @@ Common::Error AGOSEngine::init() {
(getPlatform() == Common::kPlatformPC)) {
// Setup midi driver
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_ADLIB | MDT_MIDI);
- _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | (getGameType() == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM));
+ _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
- _driver = MidiDriver::createMidi(midiDriver);
+ _driver = MidiDriver::createMidi(dev);
if (_nativeMT32) {
_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
@@ -631,9 +631,11 @@ Common::Error AGOSEngine::init() {
if (ConfMan.hasKey("sfx_mute") && ConfMan.getBool("sfx_mute") == 1) {
if (getGameId() == GID_SIMON1DOS)
- _midi._enable_sfx ^= 1;
- else
- _sound->effectsPause(_effectsPaused ^= 1);
+ _midi._enable_sfx = !_midi._enable_sfx;
+ else {
+ _effectsPaused = !_effectsPaused;
+ _sound->effectsPause(_effectsPaused);
+ }
}
_copyProtection = ConfMan.getBool("copy_protection");
@@ -648,7 +650,7 @@ Common::Error AGOSEngine::init() {
if (getGameType() == GType_SIMON1) {
// English and German versions don't have full subtitles
- if (_language == Common::EN_ANY || _language == Common::DE_DEU)
+ if (_language == Common::EN_ANY || _language == Common::DE_DEU)
_subtitles = false;
// Other versions require speech to be enabled
else
@@ -1037,12 +1039,21 @@ uint32 AGOSEngine::getTime() const {
}
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"));
+ // Sync the engine with the config manager
+ int soundVolumeMusic = ConfMan.getInt("music_volume");
+ int soundVolumeSFX = ConfMan.getInt("sfx_volume");
+ int soundVolumeSpeech = ConfMan.getInt("speech_volume");
+
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (mute ? 0 : (_musicPaused ? 0 : soundVolumeMusic)));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, (mute ? 0 : soundVolumeSFX));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, (mute ? 0 : soundVolumeSpeech));
if (_midiEnabled)
- _midi.setVolume(ConfMan.getInt("music_volume"), ConfMan.getInt("sfx_volume"));
+ _midi.setVolume((mute ? 0 : soundVolumeMusic), (mute ? 0 : soundVolumeSFX));
}
} // End of namespace AGOS
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index ab1009e02a..b12bf09d62 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -393,7 +393,7 @@ protected:
Common::Point _mouseOld;
byte *_mouseData;
- byte _animatePointer;
+ bool _animatePointer;
byte _maxCursorWidth, _maxCursorHeight;
byte _mouseAnim, _mouseAnimMax, _mouseCursor;
byte _currentMouseAnim, _currentMouseCursor;
diff --git a/engines/agos/cursor.cpp b/engines/agos/cursor.cpp
index 109184e9c7..5ff2f014a6 100644
--- a/engines/agos/cursor.cpp
+++ b/engines/agos/cursor.cpp
@@ -459,7 +459,7 @@ void AGOSEngine_Simon1::handleMouseMoved() {
_leftButtonDown = false;
x = 1;
} else {
- if (_litBoxFlag == 0 && _needHitAreaRecalc == 0)
+ if (!_litBoxFlag && _needHitAreaRecalc == 0)
goto get_out;
}
@@ -473,7 +473,7 @@ get_out:
drawMousePointer();
_needHitAreaRecalc = 0;
- _litBoxFlag = 0;
+ _litBoxFlag = false;
}
void AGOSEngine_PN::handleMouseMoved() {
@@ -538,7 +538,7 @@ void AGOSEngine_PN::handleMouseMoved() {
drawMousePointer();
_needHitAreaRecalc = 0;
- _litBoxFlag = 0;
+ _litBoxFlag = false;
}
void AGOSEngine::handleMouseMoved() {
@@ -610,7 +610,7 @@ void AGOSEngine::handleMouseMoved() {
_oneClick = 0;
x = 1;
} else {
- if (_litBoxFlag == 0 && _needHitAreaRecalc == 0)
+ if (!_litBoxFlag && _needHitAreaRecalc == 0)
goto get_out;
}
@@ -622,7 +622,7 @@ get_out:
drawMousePointer();
_needHitAreaRecalc = 0;
- _litBoxFlag = 0;
+ _litBoxFlag = false;
}
void AGOSEngine::mouseOff() {
@@ -706,10 +706,10 @@ void AGOSEngine_Feeble::drawMousePointer() {
uint cursor;
int image, offs;
- if (_animatePointer != 0) {
+ if (_animatePointer) {
if (getBitFlag(99)) {
- _mouseToggle ^= 1;
- if (_mouseToggle != 0)
+ _mouseToggle = !_mouseToggle;
+ if (_mouseToggle)
_mouseAnim++;
} else {
_mouseAnim++;
@@ -720,7 +720,7 @@ void AGOSEngine_Feeble::drawMousePointer() {
cursor = _mouseCursor;
- if (_animatePointer == 0 && getBitFlag(99)) {
+ if (!_animatePointer && getBitFlag(99)) {
_mouseAnim = 1;
cursor = 6;
} else if (_mouseCursor != 5 && getBitFlag(72)) {
diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp
index 39974f9d53..646e63dacf 100644
--- a/engines/agos/detection.cpp
+++ b/engines/agos/detection.cpp
@@ -84,6 +84,11 @@ static const PlainGameDescriptor simonGames[] = {
#include "agos/detection_tables.h"
+static const char *directoryGlobs[] = {
+ "execute", // Used by Simon1 Acorn CD
+ 0
+};
+
static const ADParams detectionParams = {
// Pointer to ADGameDescription or its superset structure
(const byte *)AGOS::gameDescriptions,
@@ -102,7 +107,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NOLAUNCHLOAD
+ Common::GUIO_NOLAUNCHLOAD,
+ // Maximum directory depth
+ 2,
+ // List of directory globs
+ directoryGlobs
};
using namespace AGOS;
diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp
index 300ed4c52b..4d32b4521d 100644
--- a/engines/agos/draw.cpp
+++ b/engines/agos/draw.cpp
@@ -176,9 +176,9 @@ void AGOSEngine::animateSprites() {
_windowNum = 4;
- _backFlag = 1;
+ _backFlag = true;
drawImage(&state);
- _backFlag = 0;
+ _backFlag = false;
_vgaSpriteChanged++;
}
@@ -451,14 +451,14 @@ void AGOSEngine::restoreBackGround() {
state.paletteMod = 0;
state.flags = kDFNonTrans;
- _backFlag = 1;
+ _backFlag = true;
drawImage(&state);
if (getGameType() != GType_SIMON1 && getGameType() != GType_SIMON2) {
animTable->srcPtr = 0;
}
}
- _backFlag = 0;
+ _backFlag = false;
if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
AnimTable *animTableTmp;
diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp
index 1340d85236..95c9db906a 100644
--- a/engines/agos/event.cpp
+++ b/engines/agos/event.cpp
@@ -431,8 +431,7 @@ void AGOSEngine::delay(uint amount) {
AudioCD.updateCD();
- if (_debugger->isAttached())
- _debugger->onFrame();
+ _debugger->onFrame();
vgaPeriod = (_fastMode) ? 10 : _vgaPeriod;
if (getGameType() == GType_PP && getGameId() != GID_DIMP) {
@@ -481,7 +480,7 @@ void AGOSEngine::delay(uint amount) {
_aboutDialog = new GUI::AboutDialog();
_aboutDialog->runModal();
} else if (event.kbd.keycode == Common::KEYCODE_f) {
- _fastMode ^= 1;
+ _fastMode = !_fastMode;
} else if (event.kbd.keycode == Common::KEYCODE_d) {
_debugger->attach();
} else if (event.kbd.keycode == Common::KEYCODE_s) {
@@ -568,7 +567,7 @@ void AGOSEngine_Feeble::timerProc() {
_videoLockOut |= 2;
if (!(_videoLockOut & 0x10)) {
- _syncFlag2 ^= 1;
+ _syncFlag2 = !_syncFlag2;
if (!_syncFlag2) {
processVgaEvents();
} else {
@@ -637,7 +636,7 @@ void AGOSEngine_PN::timerProc() {
processVgaEvents();
processVgaEvents();
- _cepeFlag ^= 1;
+ _cepeFlag = !_cepeFlag;
if (!_cepeFlag)
processVgaEvents();
}
@@ -663,7 +662,7 @@ void AGOSEngine::timerProc() {
if (!(_videoLockOut & 0x10)) {
processVgaEvents();
processVgaEvents();
- _cepeFlag ^= 1;
+ _cepeFlag = !_cepeFlag;
if (!_cepeFlag)
processVgaEvents();
}
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index e2c634007c..82a4cb714b 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -730,7 +730,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
state->paletteMod = 208;
}
- if (_backFlag == 1) {
+ if (_backFlag) {
drawBackGroundImage(state);
} else if (state->flags & kDFMasked) {
drawMaskedImage(state);
@@ -947,7 +947,7 @@ void AGOSEngine::drawImage(VC10_state *state) {
if (getGameType() == GType_ELVIRA2 && getPlatform() == Common::kPlatformAtariST && yoffs > 133)
state->palette = 208;
- if (_backFlag == 1) {
+ if (_backFlag) {
drawBackGroundImage(state);
} else {
drawVertImage(state);
@@ -1351,7 +1351,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
if (getGameType() == GType_FF || getGameType() == GType_PP) {
fillBackGroundFromBack();
- _syncFlag2 = 1;
+ _syncFlag2 = true;
} else {
_copyScnFlag = 2;
_vgaSpriteChanged++;
diff --git a/engines/agos/icons.cpp b/engines/agos/icons.cpp
index fdc5d1707e..08a3d4e2f0 100644
--- a/engines/agos/icons.cpp
+++ b/engines/agos/icons.cpp
@@ -448,7 +448,7 @@ void AGOSEngine_Feeble::drawIconArray(uint num, Item *itemRef, int line, int cla
setupIconHitArea(window, k++, xp, yp, itemRef);
} else {
/*
- * Just remember the overflow has occured
+ * Just remember the overflow has occurred
*/
window->iconPtr->iconArray[icount].item = NULL; /* END MARKINGS */
_iOverflow = 1;
diff --git a/engines/agos/input.cpp b/engines/agos/input.cpp
index 35ed045675..1246149aa5 100644
--- a/engines/agos/input.cpp
+++ b/engines/agos/input.cpp
@@ -99,7 +99,7 @@ void AGOSEngine::setup_cond_c_helper() {
animMax = 9;
}
- _animatePointer = 0;
+ _animatePointer = false;
_mouseCursor = cursor;
_mouseAnimMax = animMax;
_mouseAnim = 1;
@@ -574,13 +574,13 @@ bool AGOSEngine::processSpecialKeys() {
if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE)) ||
((getFeatures() & GF_TALKIE) && _language != Common::EN_ANY && _language != Common::DE_DEU)) {
if (_speech)
- _subtitles ^= 1;
+ _subtitles = !_subtitles;
}
break;
case 'v':
if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE))) {
if (_subtitles)
- _speech ^= 1;
+ _speech = !_speech;
}
break;
case '+':
@@ -598,22 +598,24 @@ bool AGOSEngine::processSpecialKeys() {
syncSoundSettings();
break;
case 'm':
- _musicPaused ^= 1;
+ _musicPaused = !_musicPaused;
if (_midiEnabled) {
_midi.pause(_musicPaused);
}
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (_musicPaused) ? 0 : ConfMan.getInt("music_volume"));
+ syncSoundSettings();
break;
case 's':
if (getGameId() == GID_SIMON1DOS) {
- _midi._enable_sfx ^= 1;
+ _midi._enable_sfx = !_midi._enable_sfx;
} else {
- _sound->effectsPause(_effectsPaused ^= 1);
+ _effectsPaused = !_effectsPaused;
+ _sound->effectsPause(_effectsPaused);
}
break;
case 'b':
if (getGameType() == GType_SIMON2) {
- _sound->ambientPause(_ambientPaused ^= 1);
+ _ambientPaused = !_ambientPaused;
+ _sound->ambientPause(_ambientPaused);
}
break;
default:
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index ed3e3d801b..ab5bfc4c94 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -346,15 +346,11 @@ void MidiPlayer::clearConstructs(MusicInfo &info) {
info.num_songs = 0;
}
- if (info.data) {
- free(info.data);
- info.data = 0;
- } // end if
-
- if (info.parser) {
- delete info.parser;
- info.parser = 0;
- }
+ free(info.data);
+ info.data = 0;
+
+ delete info.parser;
+ info.parser = 0;
if (_driver) {
for (i = 0; i < 16; ++i) {
diff --git a/engines/agos/verb.cpp b/engines/agos/verb.cpp
index a85c1627bf..b05bac1e57 100644
--- a/engines/agos/verb.cpp
+++ b/engines/agos/verb.cpp
@@ -207,7 +207,7 @@ static const char *const czech_verb_prep_names[] = {
void AGOSEngine_Feeble::clearName() {
stopAnimateSimon2(2, 6);
_lastNameOn = NULL;
- _animatePointer = 0;
+ _animatePointer = false;
_mouseAnim = 1;
return;
}
@@ -898,7 +898,7 @@ void AGOSEngine::displayName(HitArea *ha) {
if (getBitFlag(99))
_animatePointer = ((ha->flags & kBFTextBox) == 0);
else
- _animatePointer = 1;
+ _animatePointer = true;
if (!getBitFlag(73))
return;
@@ -933,7 +933,7 @@ void AGOSEngine_Feeble::invertBox(HitArea *ha, bool state) {
_mouseCursor = _oldMouseCursor;
} else if (_mouseCursor != 18) {
_oldMouseCursor = _mouseCursor;
- _animatePointer = 0;
+ _animatePointer = false;
_oldMouseAnimMax = _mouseAnimMax;
_mouseAnimMax = 2;
_mouseCursor = 18;
diff --git a/engines/agos/vga_e2.cpp b/engines/agos/vga_e2.cpp
index 1bbc7f4849..54ec45b967 100644
--- a/engines/agos/vga_e2.cpp
+++ b/engines/agos/vga_e2.cpp
@@ -265,7 +265,7 @@ void AGOSEngine::vc53_dissolveIn() {
*dst &= color;
*dst |= *src & 0xF;
- _system->unlockScreen();
+ _system->unlockScreen();
dissolveCount--;
if (!dissolveCount) {
@@ -319,7 +319,7 @@ void AGOSEngine::vc54_dissolveOut() {
dst += xoffs;
*dst = color;
- _system->unlockScreen();
+ _system->unlockScreen();
dissolveCount--;
if (!dissolveCount) {
@@ -388,7 +388,7 @@ void AGOSEngine::vc56_fullScreen() {
src += 320;
dst += screen->pitch;
}
- _system->unlockScreen();
+ _system->unlockScreen();
fullFade();
}
diff --git a/engines/agos/vga_s2.cpp b/engines/agos/vga_s2.cpp
index 4eb739e974..db3a7c18f3 100644
--- a/engines/agos/vga_s2.cpp
+++ b/engines/agos/vga_s2.cpp
@@ -138,7 +138,7 @@ void AGOSEngine::vc69_playSeq() {
// This is a "play track". The original
// design stored the track to play if one was
// already in progress, so that the next time a
- // "fill MIDI stream" event occured, the MIDI
+ // "fill MIDI stream" event occurred, the MIDI
// player would find the change and switch
// tracks. We use a different architecture that
// allows for an immediate response here, but
diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp
index 5ddc5d625f..747c9221ee 100644
--- a/engines/cine/anim.cpp
+++ b/engines/cine/anim.cpp
@@ -49,8 +49,6 @@ struct AnimHeader2Struct {
uint16 field_E;
};
-Common::Array<AnimData> animDataTable;
-
static const AnimDataEntry transparencyData[] = {
{"ALPHA", 0xF},
{"TITRE2", 0xF},
@@ -400,7 +398,7 @@ void AnimData::save(Common::OutSaveFile &fHandle) const {
*/
void freeAnimDataRange(byte startIdx, byte numIdx) {
for (byte i = 0; i < numIdx; i++) {
- animDataTable[startIdx + i].clear();
+ g_cine->_animDataTable[startIdx + i].clear();
}
}
@@ -514,7 +512,7 @@ void loadAnimHeader(AnimHeaderStruct &animHeader, Common::MemoryReadStream readS
*/
int emptyAnimSpace(int start = 0) {
for (; start < NUM_MAX_ANIMDATA; start++) {
- if (!animDataTable[start].data()) {
+ if (!g_cine->_animDataTable[start].data()) {
return start;
}
}
@@ -540,7 +538,7 @@ int loadSpl(const char *resourceName, int16 idx) {
entry = idx < 0 ? emptyAnimSpace() : idx;
assert(entry >= 0);
- animDataTable[entry].load(dataPtr, ANIM_RAW, partBuffer[foundFileIdx].unpackedSize, 1, foundFileIdx, 0, currentPartName);
+ g_cine->_animDataTable[entry].load(dataPtr, ANIM_RAW, g_cine->_partBuffer[foundFileIdx].unpackedSize, 1, foundFileIdx, 0, currentPartName);
free(dataPtr);
return entry + 1;
@@ -570,7 +568,7 @@ int loadMsk(const char *resourceName, int16 idx) {
entry = idx < 0 ? emptyAnimSpace() : idx;
assert(entry >= 0);
for (int16 i = 0; i < animHeader.numFrames; i++, entry++) {
- animDataTable[entry].load(ptr, ANIM_MASK, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName);
+ g_cine->_animDataTable[entry].load(ptr, ANIM_MASK, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName);
ptr += animHeader.frameWidth * animHeader.frameHeight;
}
@@ -621,7 +619,7 @@ int loadAni(const char *resourceName, int16 idx) {
transparentColor = i < 1 ? 0xE : 0;
}
- animDataTable[entry].load(ptr, ANIM_MASKSPRITE, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName, transparentColor);
+ g_cine->_animDataTable[entry].load(ptr, ANIM_MASKSPRITE, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName, transparentColor);
ptr += animHeader.frameWidth * animHeader.frameHeight;
}
@@ -737,7 +735,7 @@ int loadSet(const char *resourceName, int16 idx) {
type = ANIM_FULLSPRITE;
}
- animDataTable[entry].load(dataPtr, type, header2.width, header2.height, foundFileIdx, i, currentPartName);
+ g_cine->_animDataTable[entry].load(dataPtr, type, header2.width, header2.height, foundFileIdx, i, currentPartName);
}
free(origDataPtr);
@@ -759,7 +757,7 @@ int loadSeq(const char *resourceName, int16 idx) {
byte *dataPtr = readBundleFile(foundFileIdx);
int entry = idx < 0 ? emptyAnimSpace() : idx;
- animDataTable[entry].load(dataPtr+0x16, ANIM_RAW, partBuffer[foundFileIdx].unpackedSize-0x16, 1, foundFileIdx, 0, currentPartName);
+ g_cine->_animDataTable[entry].load(dataPtr+0x16, ANIM_RAW, g_cine->_partBuffer[foundFileIdx].unpackedSize-0x16, 1, foundFileIdx, 0, currentPartName);
free(dataPtr);
return entry + 1;
}
diff --git a/engines/cine/anim.h b/engines/cine/anim.h
index e67237aac0..2012ef875e 100644
--- a/engines/cine/anim.h
+++ b/engines/cine/anim.h
@@ -99,8 +99,6 @@ public:
#define NUM_MAX_ANIMDATA 255
-extern Common::Array<AnimData> animDataTable;
-
void freeAnimDataTable();
void freeAnimDataRange(byte startIdx, byte numIdx);
int loadResource(const char *resourceName, int16 idx = -1);
diff --git a/engines/cine/bg_list.cpp b/engines/cine/bg_list.cpp
index 26351becf1..3ecda4125d 100644
--- a/engines/cine/bg_list.cpp
+++ b/engines/cine/bg_list.cpp
@@ -36,14 +36,13 @@
namespace Cine {
uint32 var8;
-Common::List<BGIncrust> bgIncrustList;
/**
* Add masked sprite to the background
* @param objIdx Sprite description
*/
void addToBGList(int16 objIdx) {
- renderer->incrustSprite(objectTable[objIdx]);
+ renderer->incrustSprite(g_cine->_objectTable[objIdx]);
createBgIncrustListElement(objIdx, 0);
}
@@ -53,7 +52,7 @@ void addToBGList(int16 objIdx) {
* @param objIdx Sprite description
*/
void addSpriteFilledToBGList(int16 objIdx) {
- renderer->incrustMask(objectTable[objIdx]);
+ renderer->incrustMask(g_cine->_objectTable[objIdx]);
createBgIncrustListElement(objIdx, 1);
}
@@ -69,12 +68,12 @@ void createBgIncrustListElement(int16 objIdx, int16 param) {
tmp.unkPtr = 0;
tmp.objIdx = objIdx;
tmp.param = param;
- tmp.x = objectTable[objIdx].x;
- tmp.y = objectTable[objIdx].y;
- tmp.frame = objectTable[objIdx].frame;
- tmp.part = objectTable[objIdx].part;
+ tmp.x = g_cine->_objectTable[objIdx].x;
+ tmp.y = g_cine->_objectTable[objIdx].y;
+ tmp.frame = g_cine->_objectTable[objIdx].frame;
+ tmp.part = g_cine->_objectTable[objIdx].part;
- bgIncrustList.push_back(tmp);
+ g_cine->_bgIncrustList.push_back(tmp);
}
/**
@@ -104,12 +103,12 @@ void loadBgIncrustFromSave(Common::SeekableReadStream &fHandle) {
tmp.frame = fHandle.readUint16BE();
tmp.part = fHandle.readUint16BE();
- bgIncrustList.push_back(tmp);
+ g_cine->_bgIncrustList.push_back(tmp);
if (tmp.param == 0) {
- renderer->incrustSprite(objectTable[tmp.objIdx]);
+ renderer->incrustSprite(g_cine->_objectTable[tmp.objIdx]);
} else {
- renderer->incrustMask(objectTable[tmp.objIdx]);
+ renderer->incrustMask(g_cine->_objectTable[tmp.objIdx]);
}
}
}
diff --git a/engines/cine/bg_list.h b/engines/cine/bg_list.h
index 409b16dbd5..8c1b3cb6ec 100644
--- a/engines/cine/bg_list.h
+++ b/engines/cine/bg_list.h
@@ -42,7 +42,6 @@ struct BGIncrust {
int16 part;
};
-extern Common::List<BGIncrust> bgIncrustList;
extern uint32 var8;
void addToBGList(int16 objIdx);
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index c50af52901..5c2119c1e4 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -48,10 +48,9 @@
namespace Cine {
-Sound *g_sound;
-Common::SaveFileManager *g_saveFileMan;
+Sound *g_sound = 0;
-CineEngine *g_cine;
+CineEngine *g_cine = 0;
CineEngine::CineEngine(OSystem *syst, const CINEGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
DebugMan.addDebugChannel(kCineDebugScript, "Script", "Script debug level");
@@ -72,7 +71,7 @@ CineEngine::CineEngine(OSystem *syst, const CINEGameDescription *gameDesc) : Eng
}
CineEngine::~CineEngine() {
- if (g_cine->getGameType() == Cine::GType_OS) {
+ if (getGameType() == Cine::GType_OS) {
freeErrmessDat();
}
DebugMan.clearAllDebugChannels();
@@ -82,13 +81,12 @@ Common::Error CineEngine::run() {
// Initialize backend
initGraphics(320, 200, false);
- if (g_cine->getPlatform() == Common::kPlatformPC) {
+ if (getPlatform() == Common::kPlatformPC) {
g_sound = new PCSound(_mixer, this);
} else {
// Paula chipset for Amiga and Atari versions
g_sound = new PaulaSound(_mixer, this);
}
- g_saveFileMan = _saveFileMan;
_restartRequested = false;
@@ -125,31 +123,33 @@ int CineEngine::modifyGameSpeed(int speedChange) {
}
void CineEngine::initialize() {
+ _globalVars.reinit(NUM_MAX_VAR + 1);
+
// Initialize all savegames' descriptions to empty strings
memset(currentSaveName, 0, sizeof(currentSaveName));
// Resize object table to its correct size and reset all its elements
- objectTable.resize(NUM_MAX_OBJECT);
+ g_cine->_objectTable.resize(NUM_MAX_OBJECT);
resetObjectTable();
// Resize animation data table to its correct size and reset all its elements
- animDataTable.resize(NUM_MAX_ANIMDATA);
+ g_cine->_animDataTable.resize(NUM_MAX_ANIMDATA);
freeAnimDataTable();
// Resize zone data table to its correct size and reset all its elements
- zoneData.resize(NUM_MAX_ZONE);
- Common::set_to(zoneData.begin(), zoneData.end(), 0);
+ g_cine->_zoneData.resize(NUM_MAX_ZONE);
+ Common::set_to(g_cine->_zoneData.begin(), g_cine->_zoneData.end(), 0);
// Resize zone query table to its correct size and reset all its elements
- zoneQuery.resize(NUM_MAX_ZONE);
- Common::set_to(zoneQuery.begin(), zoneQuery.end(), 0);
+ g_cine->_zoneQuery.resize(NUM_MAX_ZONE);
+ Common::set_to(g_cine->_zoneQuery.begin(), g_cine->_zoneQuery.end(), 0);
_timerDelayMultiplier = 12; // Set default speed
setupOpcodes();
- initLanguage(g_cine->getLanguage());
+ initLanguage(getLanguage());
- if (g_cine->getGameType() == Cine::GType_OS) {
+ if (getGameType() == Cine::GType_OS) {
renderer = new OSRenderer;
} else {
renderer = new FWRenderer;
@@ -161,28 +161,28 @@ void CineEngine::initialize() {
// Clear part buffer as there's nothing loaded into it yet.
// Its size will change when loading data into it with the loadPart function.
- partBuffer.clear();
+ g_cine->_partBuffer.clear();
- if (g_cine->getGameType() == Cine::GType_OS) {
+ if (getGameType() == Cine::GType_OS) {
readVolCnf();
}
loadTextData("texte.dat");
- if (g_cine->getGameType() == Cine::GType_OS && !(g_cine->getFeatures() & GF_DEMO)) {
+ if (getGameType() == Cine::GType_OS && !(getFeatures() & GF_DEMO)) {
loadPoldatDat("poldat.dat");
loadErrmessDat("errmess.dat");
}
// in case ScummVM engines can be restarted in the future
- scriptTable.clear();
- relTable.clear();
- objectScripts.clear();
- globalScripts.clear();
- bgIncrustList.clear();
+ g_cine->_scriptTable.clear();
+ g_cine->_relTable.clear();
+ g_cine->_objectScripts.clear();
+ g_cine->_globalScripts.clear();
+ g_cine->_bgIncrustList.clear();
freeAnimDataTable();
- overlayList.clear();
- messageTable.clear();
+ g_cine->_overlayList.clear();
+ g_cine->_messageTable.clear();
resetObjectTable();
var8 = 0;
diff --git a/engines/cine/cine.h b/engines/cine/cine.h
index 6f7b409ad7..114d98d442 100644
--- a/engines/cine/cine.h
+++ b/engines/cine/cine.h
@@ -47,6 +47,8 @@
#include "cine/pal.h"
#include "cine/gfx.h"
#include "cine/anim.h"
+#include "cine/bg_list.h"
+#include "cine/various.h"
//#define DUMP_SCRIPTS
@@ -93,6 +95,7 @@ enum CineGameFeatures {
};
struct CINEGameDescription;
+struct SeqListElement;
typedef Common::HashMap<Common::String, const char *> StringPtrHashMap;
@@ -150,6 +153,36 @@ private:
bool _preLoad;
int _timerDelayMultiplier;
+
+ public:
+ // TODO: These are pseudo-global vars
+ // They better belong to appropriate classes
+ Common::Array<AnimData> _animDataTable;
+ Common::List<BGIncrust> _bgIncrustList;
+ Common::StringArray _messageTable;
+ Common::Array<ObjectStruct> _objectTable;
+ Common::List<overlay> _overlayList;
+ Common::Array<PalEntry> _palArray;
+ Common::Array<PartBuffer> _partBuffer;
+ ScriptList _globalScripts;
+ ScriptList _objectScripts;
+ RawObjectScriptArray _relTable; ///< Object script bytecode table
+
+ /**
+ * Global variables.
+ * 255 of these are saved, but there's one more that's used for bypassing the copy protection.
+ * In CineEngine::mainLoop(int bootScriptIdx) there's this code: globalVars[VAR_BYPASS_PROTECTION] = 0;
+ * And as VAR_BYPASS_PROTECTION is 255 that's why we're allocating one more than we otherwise would.
+ */
+ ScriptVars _globalVars;
+ RawScriptArray _scriptTable; ///< Table of script bytecode
+
+ Common::Array<uint16> _zoneData;
+ Common::Array<uint16> _zoneQuery; ///< Only exists in Operation Stealth
+
+ Common::List<SeqListElement> _seqList;
+
+ Common::String _commandBuffer;
};
extern CineEngine *g_cine;
@@ -190,8 +223,6 @@ enum {
};
-extern Common::SaveFileManager *g_saveFileMan; // TEMP
-
} // End of namespace Cine
#endif
diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp
index fcfa1f7f20..9dfa2f71ea 100644
--- a/engines/cine/detection.cpp
+++ b/engines/cine/detection.cpp
@@ -23,8 +23,6 @@
*
*/
-
-
#include "base/plugins.h"
#include "engines/advancedDetector.h"
@@ -62,494 +60,7 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = {
{0, 0, Common::kPlatformUnknown}
};
-namespace Cine {
-
-using Common::GUIO_NONE;
-
-static const CINEGameDescription gameDescriptions[] = {
- {
- {
- "fw",
- "",
- AD_ENTRY1("part01", "61d003202d301c29dd399acfb1354310"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- 0,
- },
-
- // This is a CD version of Future Wars published by Sony.
- // This version has a crypted AUTO00.PRC.
- {
- {
- "fw",
- "Sony CD version",
- {
- { "AUTO00.PRC", 0, "4fe1e7930b38e3c63f0f2474d471bf8f", -1},
- { "PART01", 0, "61d003202d301c29dd399acfb1354310", -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_USA,
- Common::kPlatformPC,
- ADGF_CD,
- GUIO_NONE
- },
- GType_FW,
- GF_CD | GF_CRYPTED_BOOT_PRC,
- },
-
- {
- // This is the version included in the UK "Classic Collection"
- {
- "fw",
- "",
- AD_ENTRY1("part01", "91d7271155520eae6915a9dd2dac120c"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- 0,
- },
-
- {
- {
- "fw",
- "",
- AD_ENTRY1("part01", "f5e98fcca3fb5e7afa284c81c39d8b14"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- GF_ALT_FONT,
- },
-
- {
- {
- "fw",
- "",
- AD_ENTRY1("part01", "570109f965c7f53984b98c83d86eb206"),
- Common::ES_ESP,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- GF_ALT_FONT,
- },
-
- {
- {
- "fw",
- "",
- AD_ENTRY1("part01", "5d1acb97abe9591f9008e00d07add95a"),
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- 0,
- },
-
- {
- {
- "fw",
- "",
- AD_ENTRY1("part01", "57afd280b598b4180fda6689fbedc4b8"),
- Common::EN_ANY,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- 0,
- },
-
- { // Amiga "Interplay" labeled version
- {
- "fw",
- "",
- AD_ENTRY1("part01", "a17a5eb15200c63276d486a88263ccd0"),
- Common::EN_USA,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- 0,
- },
-
- {
- {
- "fw",
- "",
- AD_ENTRY1("part01", "3a87a913e0e33963a48a7f822ca0eb0e"),
- Common::DE_DEU,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- GF_ALT_FONT,
- },
-
- {
- {
- "fw",
- "",
- AD_ENTRY1("part01", "5ad0007ccd5f7b3dd6b15ea7f281f9e1"),
- Common::ES_ESP,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- 0,
- },
-
- {
- {
- "fw",
- "",
- AD_ENTRY1("part01", "460f2da8793bc581a2d4b6fc19ccb5ae"),
- Common::FR_FRA,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- 0,
- },
-
- {
- {
- "fw",
- "",
- AD_ENTRY1("part01", "1c8e5207743172134409ac58860021af"),
- Common::IT_ITA,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- 0,
- },
-
- {
- {
- "fw",
- "Demo",
- {
- { "demo", 0, "0f50767cd964e302d3af0ba2528df8c4", -1},
- { "demo.prc", 0, "d2ac3a743d288359c63644ea7071edae", -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformAmiga,
- ADGF_DEMO,
- GUIO_NONE
- },
- GType_FW,
- 0,
- },
-
- {
- {
- "fw",
- "",
- AD_ENTRY1("part01", "36050db13af57e462ca1adc4df99de4e"),
- Common::EN_ANY,
- Common::kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- 0,
- },
-
- {
- {
- "fw",
- "",
- AD_ENTRY1("part01", "ef245573b7dab0d4825ceb98e37cef4d"),
- Common::FR_FRA,
- Common::kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_FW,
- 0,
- },
-
- {
- {
- "os",
- "256 colors",
- AD_ENTRY1("procs00", "d6752e7d25924cb866b61eb7cb0c8b56"),
- Common::EN_GRB,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- // This is a 16 color PC version (It came on three 720kB 3.5" disks).
- // The protagonist is named John Glames in this version.
- {
- "os",
- "",
- AD_ENTRY1("procs1", "9629129b86979fa592c1787385bf3695"),
- Common::EN_GRB,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "",
- AD_ENTRY1("procs1", "d8c3a9d05a63e4cfa801826a7063a126"),
- Common::EN_USA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "256 colors",
- AD_ENTRY1("procs00", "862a75d76fb7fffec30e52be9ad1c474"),
- Common::EN_USA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- GF_CD,
- },
-
- {
- {
- "os",
- "",
- AD_ENTRY1("procs1", "39b91ae35d1297ce0a76a1a803ca1593"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "",
- AD_ENTRY1("procs1", "74c2dabd9d212525fca8875a5f6d8994"),
- Common::ES_ESP,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "256 colors",
- {
- { "procs1", 0, "74c2dabd9d212525fca8875a5f6d8994", -1},
- { "sds1", 0, "75443ba39cdc95667e07d7118e5c151c", -1},
- { NULL, 0, NULL, 0}
- },
- Common::ES_ESP,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- GF_CD,
- },
-
- {
- {
- "os",
- "256 colors",
- AD_ENTRY1("procs00", "f143567f08cfd1a9b1c9a41c89eadfef"),
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "",
- AD_ENTRY1("procs1", "da066e6b8dd93f2502c2a3755f08dc12"),
- Common::IT_ITA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "",
- AD_ENTRY1("procs0", "a9da5531ead0ebf9ad387fa588c0cbb0"),
- Common::EN_GRB,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "alt",
- AD_ENTRY1("procs0", "8a429ced2f4acff8a15ae125174042e8"),
- Common::EN_GRB,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "",
- AD_ENTRY1("procs0", "d5f27e33fc29c879f36f15b86ccfa58c"),
- Common::EN_USA,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "",
- AD_ENTRY1("procs0", "8b7dce249821d3a62b314399c4334347"),
- Common::DE_DEU,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "",
- AD_ENTRY1("procs0", "35fc295ddd0af9da932d256ba799a4b0"),
- Common::ES_ESP,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "",
- AD_ENTRY1("procs0", "d4ea4a97e01fa67ea066f9e785050ed2"),
- Common::FR_FRA,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "Demo",
- AD_ENTRY1("demo", "8d3a750d1c840b1b1071e42f9e6f6aa2"),
- Common::EN_GRB,
- Common::kPlatformAmiga,
- ADGF_DEMO,
- GUIO_NONE
- },
- GType_OS,
- GF_DEMO,
- },
-
- {
- {
- "os",
- "",
- AD_ENTRY1("procs0", "1501d5ae364b2814a33ed19347c3fcae"),
- Common::EN_GRB,
- Common::kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- {
- {
- "os",
- "",
- AD_ENTRY1("procs0", "2148d25de3219dd4a36580ca735d0afa"),
- Common::FR_FRA,
- Common::kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GType_OS,
- 0,
- },
-
- { AD_TABLE_END_MARKER, 0, 0 }
-};
-
-} // End of namespace Cine
+#include "cine/detection_tables.h"
static const ADParams detectionParams = {
// Pointer to ADGameDescription or its superset structure
@@ -569,7 +80,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI
+ Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class CineMetaEngine : public AdvancedMetaEngine {
@@ -736,7 +251,7 @@ Common::Error CineEngine::saveGameState(int slot, const char *desc) {
char indexFile[80];
snprintf(indexFile, 80, "%s.dir", _targetName.c_str());
- Common::OutSaveFile *fHandle = g_saveFileMan->openForSaving(indexFile);
+ Common::OutSaveFile *fHandle = _saveFileMan->openForSaving(indexFile);
if (!fHandle) {
warning("Unable to open file %s for saving", indexFile);
return Common::kUnknownError;
diff --git a/engines/cine/detection_tables.h b/engines/cine/detection_tables.h
new file mode 100644
index 0000000000..6e450ebc80
--- /dev/null
+++ b/engines/cine/detection_tables.h
@@ -0,0 +1,513 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Cine {
+
+using Common::GUIO_NONE;
+
+static const CINEGameDescription gameDescriptions[] = {
+ {
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "61d003202d301c29dd399acfb1354310"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ 0,
+ },
+
+ // This is a CD version of Future Wars published by Sony.
+ // This version has a crypted AUTO00.PRC.
+ {
+ {
+ "fw",
+ "Sony CD version",
+ {
+ { "AUTO00.PRC", 0, "4fe1e7930b38e3c63f0f2474d471bf8f", -1},
+ { "PART01", 0, "61d003202d301c29dd399acfb1354310", -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_USA,
+ Common::kPlatformPC,
+ ADGF_CD,
+ GUIO_NONE
+ },
+ GType_FW,
+ GF_CD | GF_CRYPTED_BOOT_PRC,
+ },
+
+ {
+ // This is the version included in the UK "Classic Collection"
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "91d7271155520eae6915a9dd2dac120c"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ 0,
+ },
+
+ {
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "f5e98fcca3fb5e7afa284c81c39d8b14"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ GF_ALT_FONT,
+ },
+
+ {
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "570109f965c7f53984b98c83d86eb206"),
+ Common::ES_ESP,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ GF_ALT_FONT,
+ },
+
+ {
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "5d1acb97abe9591f9008e00d07add95a"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ 0,
+ },
+
+ {
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "57afd280b598b4180fda6689fbedc4b8"),
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ 0,
+ },
+
+ { // Amiga "Interplay" labeled version
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "a17a5eb15200c63276d486a88263ccd0"),
+ Common::EN_USA,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ 0,
+ },
+
+ {
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "3a87a913e0e33963a48a7f822ca0eb0e"),
+ Common::DE_DEU,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ GF_ALT_FONT,
+ },
+
+ {
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "5ad0007ccd5f7b3dd6b15ea7f281f9e1"),
+ Common::ES_ESP,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ 0,
+ },
+
+ {
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "460f2da8793bc581a2d4b6fc19ccb5ae"),
+ Common::FR_FRA,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ 0,
+ },
+
+ {
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "1c8e5207743172134409ac58860021af"),
+ Common::IT_ITA,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ 0,
+ },
+
+ {
+ {
+ "fw",
+ "Demo",
+ {
+ { "demo", 0, "0f50767cd964e302d3af0ba2528df8c4", -1},
+ { "demo.prc", 0, "d2ac3a743d288359c63644ea7071edae", -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ ADGF_DEMO,
+ GUIO_NONE
+ },
+ GType_FW,
+ 0,
+ },
+
+ {
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "36050db13af57e462ca1adc4df99de4e"),
+ Common::EN_ANY,
+ Common::kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ 0,
+ },
+
+ {
+ {
+ "fw",
+ "",
+ AD_ENTRY1("part01", "ef245573b7dab0d4825ceb98e37cef4d"),
+ Common::FR_FRA,
+ Common::kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_FW,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "256 colors",
+ AD_ENTRY1("procs00", "d6752e7d25924cb866b61eb7cb0c8b56"),
+ Common::EN_GRB,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ // This is a 16 color PC version (It came on three 720kB 3.5" disks).
+ // The protagonist is named John Glames in this version.
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs1", "9629129b86979fa592c1787385bf3695"),
+ Common::EN_GRB,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs1", "d8c3a9d05a63e4cfa801826a7063a126"),
+ Common::EN_USA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "256 colors",
+ AD_ENTRY1("procs00", "862a75d76fb7fffec30e52be9ad1c474"),
+ Common::EN_USA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ GF_CD,
+ },
+
+ {
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs1", "39b91ae35d1297ce0a76a1a803ca1593"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs1", "74c2dabd9d212525fca8875a5f6d8994"),
+ Common::ES_ESP,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "256 colors",
+ {
+ { "procs1", 0, "74c2dabd9d212525fca8875a5f6d8994", -1},
+ { "sds1", 0, "75443ba39cdc95667e07d7118e5c151c", -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::ES_ESP,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ GF_CD,
+ },
+
+ {
+ {
+ "os",
+ "256 colors",
+ AD_ENTRY1("procs00", "f143567f08cfd1a9b1c9a41c89eadfef"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs1", "da066e6b8dd93f2502c2a3755f08dc12"),
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs0", "a9da5531ead0ebf9ad387fa588c0cbb0"),
+ Common::EN_GRB,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "alt",
+ AD_ENTRY1("procs0", "8a429ced2f4acff8a15ae125174042e8"),
+ Common::EN_GRB,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs0", "d5f27e33fc29c879f36f15b86ccfa58c"),
+ Common::EN_USA,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs0", "8b7dce249821d3a62b314399c4334347"),
+ Common::DE_DEU,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs0", "35fc295ddd0af9da932d256ba799a4b0"),
+ Common::ES_ESP,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs0", "d4ea4a97e01fa67ea066f9e785050ed2"),
+ Common::FR_FRA,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "Demo",
+ AD_ENTRY1("demo", "8d3a750d1c840b1b1071e42f9e6f6aa2"),
+ Common::EN_GRB,
+ Common::kPlatformAmiga,
+ ADGF_DEMO,
+ GUIO_NONE
+ },
+ GType_OS,
+ GF_DEMO,
+ },
+
+ {
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs0", "1501d5ae364b2814a33ed19347c3fcae"),
+ Common::EN_GRB,
+ Common::kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ {
+ {
+ "os",
+ "",
+ AD_ENTRY1("procs0", "2148d25de3219dd4a36580ca735d0afa"),
+ Common::FR_FRA,
+ Common::kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GType_OS,
+ 0,
+ },
+
+ { AD_TABLE_END_MARKER, 0, 0 }
+};
+
+} // End of namespace Cine
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index a4220e6e35..4d61be102b 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -160,13 +160,13 @@ void FWRenderer::clear() {
* @param fillColor Sprite color
*/
void FWRenderer::fillSprite(const ObjectStruct &obj, uint8 color) {
- const byte *data = animDataTable[obj.frame].data();
+ const byte *data = g_cine->_animDataTable[obj.frame].data();
int x, y, width, height;
x = obj.x;
y = obj.y;
- width = animDataTable[obj.frame]._realWidth;
- height = animDataTable[obj.frame]._height;
+ width = g_cine->_animDataTable[obj.frame]._realWidth;
+ height = g_cine->_animDataTable[obj.frame]._height;
gfxFillSprite(data, width, height, _backBuffer, x, y, color);
}
@@ -177,13 +177,13 @@ void FWRenderer::fillSprite(const ObjectStruct &obj, uint8 color) {
* @param fillColor Sprite color
*/
void FWRenderer::incrustMask(const ObjectStruct &obj, uint8 color) {
- const byte *data = animDataTable[obj.frame].data();
+ const byte *data = g_cine->_animDataTable[obj.frame].data();
int x, y, width, height;
x = obj.x;
y = obj.y;
- width = animDataTable[obj.frame]._realWidth;
- height = animDataTable[obj.frame]._height;
+ width = g_cine->_animDataTable[obj.frame]._realWidth;
+ height = g_cine->_animDataTable[obj.frame]._height;
gfxFillSprite(data, width, height, _background, x, y, color);
}
@@ -194,13 +194,13 @@ void FWRenderer::incrustMask(const ObjectStruct &obj, uint8 color) {
* @param mask External mask
*/
void FWRenderer::drawMaskedSprite(const ObjectStruct &obj, const byte *mask) {
- const byte *data = animDataTable[obj.frame].data();
+ const byte *data = g_cine->_animDataTable[obj.frame].data();
int x, y, width, height;
x = obj.x;
y = obj.y;
- width = animDataTable[obj.frame]._realWidth;
- height = animDataTable[obj.frame]._height;
+ width = g_cine->_animDataTable[obj.frame]._realWidth;
+ height = g_cine->_animDataTable[obj.frame]._height;
assert(mask);
@@ -212,7 +212,7 @@ void FWRenderer::drawMaskedSprite(const ObjectStruct &obj, const byte *mask) {
* @param obj Object info
*/
void FWRenderer::drawSprite(const ObjectStruct &obj) {
- const byte *mask = animDataTable[obj.frame].mask();
+ const byte *mask = g_cine->_animDataTable[obj.frame].mask();
drawMaskedSprite(obj, mask);
}
@@ -221,14 +221,14 @@ void FWRenderer::drawSprite(const ObjectStruct &obj) {
* @param obj Object info
*/
void FWRenderer::incrustSprite(const ObjectStruct &obj) {
- const byte *data = animDataTable[obj.frame].data();
- const byte *mask = animDataTable[obj.frame].mask();
+ const byte *data = g_cine->_animDataTable[obj.frame].data();
+ const byte *mask = g_cine->_animDataTable[obj.frame].mask();
int x, y, width, height;
x = obj.x;
y = obj.y;
- width = animDataTable[obj.frame]._realWidth;
- height = animDataTable[obj.frame]._height;
+ width = g_cine->_animDataTable[obj.frame]._realWidth;
+ height = g_cine->_animDataTable[obj.frame]._height;
// There was an assert(mask) here before but it made savegame loading
// in Future Wars sometimes fail the assertion (e.g. see bug #2055912).
@@ -502,27 +502,27 @@ void FWRenderer::drawLine(int x, int y, int width, int height, byte color) {
* @param it Overlay info from overlayList
*/
void FWRenderer::remaskSprite(byte *mask, Common::List<overlay>::iterator it) {
- AnimData &sprite = animDataTable[objectTable[it->objIdx].frame];
+ AnimData &sprite = g_cine->_animDataTable[g_cine->_objectTable[it->objIdx].frame];
int x, y, width, height, idx;
int mx, my, mw, mh;
- x = objectTable[it->objIdx].x;
- y = objectTable[it->objIdx].y;
+ x = g_cine->_objectTable[it->objIdx].x;
+ y = g_cine->_objectTable[it->objIdx].y;
width = sprite._realWidth;
height = sprite._height;
- for (++it; it != overlayList.end(); ++it) {
+ for (++it; it != g_cine->_overlayList.end(); ++it) {
if (it->type != 5) {
continue;
}
- idx = ABS(objectTable[it->objIdx].frame);
- mx = objectTable[it->objIdx].x;
- my = objectTable[it->objIdx].y;
- mw = animDataTable[idx]._realWidth;
- mh = animDataTable[idx]._height;
+ idx = ABS(g_cine->_objectTable[it->objIdx].frame);
+ mx = g_cine->_objectTable[it->objIdx].x;
+ my = g_cine->_objectTable[it->objIdx].y;
+ mw = g_cine->_animDataTable[idx]._realWidth;
+ mh = g_cine->_animDataTable[idx]._height;
- gfxUpdateSpriteMask(mask, x, y, width, height, animDataTable[idx].data(), mx, my, mw, mh);
+ gfxUpdateSpriteMask(mask, x, y, width, height, g_cine->_animDataTable[idx].data(), mx, my, mw, mh);
}
}
@@ -547,26 +547,26 @@ void FWRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
switch (it->type) {
// color sprite
case 0:
- if (objectTable[it->objIdx].frame < 0) {
+ if (g_cine->_objectTable[it->objIdx].frame < 0) {
return;
}
- sprite = &animDataTable[objectTable[it->objIdx].frame];
+ sprite = &g_cine->_animDataTable[g_cine->_objectTable[it->objIdx].frame];
len = sprite->_realWidth * sprite->_height;
mask = new byte[len];
memcpy(mask, sprite->mask(), len);
remaskSprite(mask, it);
- drawMaskedSprite(objectTable[it->objIdx], mask);
+ drawMaskedSprite(g_cine->_objectTable[it->objIdx], mask);
delete[] mask;
break;
// game message
case 2:
- if (it->objIdx >= messageTable.size()) {
+ if (it->objIdx >= g_cine->_messageTable.size()) {
return;
}
- _messageLen += messageTable[it->objIdx].size();
- drawMessage(messageTable[it->objIdx].c_str(), it->x, it->y, it->width, it->color);
+ _messageLen += g_cine->_messageTable[it->objIdx].size();
+ drawMessage(g_cine->_messageTable[it->objIdx].c_str(), it->x, it->y, it->width, it->color);
waitForPlayerClick = 1;
break;
@@ -585,13 +585,13 @@ void FWRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
// bitmap
case 4:
assert(it->objIdx < NUM_MAX_OBJECT);
- obj = &objectTable[it->objIdx];
+ obj = &g_cine->_objectTable[it->objIdx];
if (obj->frame < 0) {
return;
}
- if (!animDataTable[obj->frame].data()) {
+ if (!g_cine->_animDataTable[obj->frame].data()) {
return;
}
@@ -606,7 +606,7 @@ void FWRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
void FWRenderer::drawOverlays() {
Common::List<overlay>::iterator it;
- for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
renderOverlay(it);
}
}
@@ -772,7 +772,7 @@ const char *FWRenderer::getBgName(uint idx) const {
* Restore active and backup palette from save
* @param fHandle Savefile open for reading
*/
-void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle) {
+void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle, int version) {
byte buf[kLowPalNumBytes];
// Load the active 16 color palette from file
@@ -819,9 +819,8 @@ void FWRenderer::savePalette(Common::OutSaveFile &fHandle) {
void OSRenderer::savePalette(Common::OutSaveFile &fHandle) {
byte buf[kHighPalNumBytes];
- // Make sure the active palette has the correct format and color count
- assert(_activePal.colorFormat() == kHighPalFormat);
- assert(_activePal.colorCount() == kHighPalNumColors);
+ // We can have 16 color palette in many cases
+ fHandle.writeUint16LE(_activePal.colorCount());
// Write the active 256 color palette.
_activePal.save(buf, sizeof(buf), CINE_LITTLE_ENDIAN);
@@ -836,12 +835,18 @@ void OSRenderer::savePalette(Common::OutSaveFile &fHandle) {
* Restore active and backup palette from save
* @param fHandle Savefile open for reading
*/
-void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle) {
+void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle, int version) {
byte buf[kHighPalNumBytes];
+ uint colorCount = (version > 0) ? fHandle.readUint16LE() : kHighPalNumBytes;
- // Load the active 256 color palette from file
fHandle.read(buf, kHighPalNumBytes);
- _activePal.load(buf, sizeof(buf), kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN);
+
+ if (colorCount == kHighPalNumBytes) {
+ // Load the active 256 color palette from file
+ _activePal.load(buf, sizeof(buf), kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN);
+ } else {
+ _activePal.load(buf, sizeof(buf), kLowPalFormat, kLowPalNumColors, CINE_LITTLE_ENDIAN);
+ }
// Jump over the backup 256 color palette.
// FIXME: Load the backup 256 color palette and use it properly.
@@ -1117,13 +1122,13 @@ void OSRenderer::clear() {
* @param fillColor Sprite color
*/
void OSRenderer::incrustMask(const ObjectStruct &obj, uint8 color) {
- const byte *data = animDataTable[obj.frame].data();
+ const byte *data = g_cine->_animDataTable[obj.frame].data();
int x, y, width, height;
x = obj.x;
y = obj.y;
- width = animDataTable[obj.frame]._realWidth;
- height = animDataTable[obj.frame]._height;
+ width = g_cine->_animDataTable[obj.frame]._realWidth;
+ height = g_cine->_animDataTable[obj.frame]._height;
if (_bgTable[_currentBg].bg) {
gfxFillSprite(data, width, height, _bgTable[_currentBg].bg, x, y, color);
@@ -1135,14 +1140,14 @@ void OSRenderer::incrustMask(const ObjectStruct &obj, uint8 color) {
* @param obj Object info
*/
void OSRenderer::drawSprite(const ObjectStruct &obj) {
- const byte *data = animDataTable[obj.frame].data();
+ const byte *data = g_cine->_animDataTable[obj.frame].data();
int x, y, width, height, transColor;
x = obj.x;
y = obj.y;
transColor = obj.part;
- width = animDataTable[obj.frame]._realWidth;
- height = animDataTable[obj.frame]._height;
+ width = g_cine->_animDataTable[obj.frame]._realWidth;
+ height = g_cine->_animDataTable[obj.frame]._height;
drawSpriteRaw2(data, transColor, width, height, _backBuffer, x, y);
}
@@ -1152,14 +1157,14 @@ void OSRenderer::drawSprite(const ObjectStruct &obj) {
* @param obj Object info
*/
void OSRenderer::incrustSprite(const ObjectStruct &obj) {
- const byte *data = animDataTable[obj.frame].data();
+ const byte *data = g_cine->_animDataTable[obj.frame].data();
int x, y, width, height, transColor;
x = obj.x;
y = obj.y;
transColor = obj.part;
- width = animDataTable[obj.frame]._realWidth;
- height = animDataTable[obj.frame]._height;
+ width = g_cine->_animDataTable[obj.frame]._realWidth;
+ height = g_cine->_animDataTable[obj.frame]._height;
if (_bgTable[_currentBg].bg) {
drawSpriteRaw2(data, transColor, width, height, _bgTable[_currentBg].bg, x, y);
@@ -1228,26 +1233,26 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
switch (it->type) {
// color sprite
case 0:
- if (objectTable[it->objIdx].frame < 0) {
+ if (g_cine->_objectTable[it->objIdx].frame < 0) {
break;
}
- sprite = &animDataTable[objectTable[it->objIdx].frame];
+ sprite = &g_cine->_animDataTable[g_cine->_objectTable[it->objIdx].frame];
len = sprite->_realWidth * sprite->_height;
mask = new byte[len];
- generateMask(sprite->data(), mask, len, objectTable[it->objIdx].part);
+ generateMask(sprite->data(), mask, len, g_cine->_objectTable[it->objIdx].part);
remaskSprite(mask, it);
- drawMaskedSprite(objectTable[it->objIdx], mask);
+ drawMaskedSprite(g_cine->_objectTable[it->objIdx], mask);
delete[] mask;
break;
// game message
case 2:
- if (it->objIdx >= messageTable.size()) {
+ if (it->objIdx >= g_cine->_messageTable.size()) {
return;
}
- _messageLen += messageTable[it->objIdx].size();
- drawMessage(messageTable[it->objIdx].c_str(), it->x, it->y, it->width, it->color);
+ _messageLen += g_cine->_messageTable[it->objIdx].size();
+ drawMessage(g_cine->_messageTable[it->objIdx].c_str(), it->x, it->y, it->width, it->color);
if (it->color >= 0) { // This test isn't in Future Wars's implementation
waitForPlayerClick = 1;
}
@@ -1268,7 +1273,7 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
// bitmap
case 4:
- if (objectTable[it->objIdx].frame >= 0) {
+ if (g_cine->_objectTable[it->objIdx].frame >= 0) {
FWRenderer::renderOverlay(it);
}
break;
@@ -1277,8 +1282,8 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
case 20:
assert(it->objIdx < NUM_MAX_OBJECT);
var5 = it->x; // A global variable updated here!
- obj = &objectTable[it->objIdx];
- sprite = &animDataTable[obj->frame];
+ obj = &g_cine->_objectTable[it->objIdx];
+ sprite = &g_cine->_animDataTable[obj->frame];
if (obj->frame < 0 || it->x < 0 || it->x > 8 || !_bgTable[it->x].bg || sprite->_bpp != 1) {
break;
@@ -1298,7 +1303,7 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
case 22:
// TODO: Check it this implementation really works correctly (Some things might be wrong, needs testing).
assert(it->objIdx < NUM_MAX_OBJECT);
- obj = &objectTable[it->objIdx];
+ obj = &g_cine->_objectTable[it->objIdx];
color = obj->part & 0x0F;
width = obj->frame;
height = obj->costume;
@@ -1792,17 +1797,17 @@ void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 he
maskPtr = backup;
// incrust pass
- for (it = bgIncrustList.begin(); it != bgIncrustList.end(); ++it) {
- tmpWidth = animDataTable[it->frame]._realWidth;
- tmpHeight = animDataTable[it->frame]._height;
+ for (it = g_cine->_bgIncrustList.begin(); it != g_cine->_bgIncrustList.end(); ++it) {
+ tmpWidth = g_cine->_animDataTable[it->frame]._realWidth;
+ tmpHeight = g_cine->_animDataTable[it->frame]._height;
mask = (byte*)malloc(tmpWidth * tmpHeight);
if (it->param == 0) {
- generateMask(animDataTable[it->frame].data(), mask, tmpWidth * tmpHeight, it->part);
+ generateMask(g_cine->_animDataTable[it->frame].data(), mask, tmpWidth * tmpHeight, it->part);
gfxUpdateIncrustMask(mask, it->x, it->y, tmpWidth, tmpHeight, maskPtr, x, y, width, height);
- gfxDrawMaskedSprite(animDataTable[it->frame].data(), mask, tmpWidth, tmpHeight, page, it->x, it->y);
+ gfxDrawMaskedSprite(g_cine->_animDataTable[it->frame].data(), mask, tmpWidth, tmpHeight, page, it->x, it->y);
} else {
- memcpy(mask, animDataTable[it->frame].data(), tmpWidth * tmpHeight);
+ memcpy(mask, g_cine->_animDataTable[it->frame].data(), tmpWidth * tmpHeight);
gfxUpdateIncrustMask(mask, it->x, it->y, tmpWidth, tmpHeight, maskPtr, x, y, width, height);
gfxFillSprite(mask, tmpWidth, tmpHeight, page, it->x, it->y);
}
diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h
index 56ba6885f4..da7e3dd572 100644
--- a/engines/cine/gfx.h
+++ b/engines/cine/gfx.h
@@ -197,7 +197,7 @@ public:
virtual void refreshPalette();
virtual void reloadPalette();
- virtual void restorePalette(Common::SeekableReadStream &fHandle);
+ virtual void restorePalette(Common::SeekableReadStream &fHandle, int version);
virtual void savePalette(Common::OutSaveFile &fHandle);
virtual void rotatePalette(int a, int b, int c);
virtual void transformPalette(int first, int last, int r, int g, int b);
@@ -257,7 +257,7 @@ public:
const char *getBgName(uint idx = 0) const;
void reloadPalette();
- void restorePalette(Common::SeekableReadStream &fHandle);
+ void restorePalette(Common::SeekableReadStream &fHandle, int version);
void savePalette(Common::OutSaveFile &fHandle);
void transformPalette(int first, int last, int r, int g, int b);
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index 414aed394c..3d280c20ef 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -241,11 +241,11 @@ int getKeyData() {
/** Removes elements from seqList that have their member variable var4 set to value -1. */
void purgeSeqList() {
- Common::List<SeqListElement>::iterator it = seqList.begin();
- while (it != seqList.end()) {
+ Common::List<SeqListElement>::iterator it = g_cine->_seqList.begin();
+ while (it != g_cine->_seqList.end()) {
if (it->var4 == -1) {
// Erase the element and jump to the next element
- it = seqList.erase(it);
+ it = g_cine->_seqList.erase(it);
} else {
// Let the element be and jump to the next element
it++;
@@ -283,15 +283,15 @@ void CineEngine::mainLoop(int bootScriptIdx) {
menuCommandLen = 0;
playerCommand = -1;
- commandBuffer = "";
+ g_cine->_commandBuffer = "";
- globalVars[VAR_MOUSE_X_POS] = 0;
- globalVars[VAR_MOUSE_Y_POS] = 0;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = 0;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = 0;
if (g_cine->getGameType() == Cine::GType_OS) {
- globalVars[VAR_MOUSE_X_POS_2ND] = 0;
- globalVars[VAR_MOUSE_Y_POS_2ND] = 0;
- globalVars[VAR_BYPASS_PROTECTION] = 0; // set to 1 to bypass the copy protection
- globalVars[VAR_LOW_MEMORY] = 0; // set to 1 to disable some animations, sounds etc.
+ g_cine->_globalVars[VAR_MOUSE_X_POS_2ND] = 0;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS_2ND] = 0;
+ g_cine->_globalVars[VAR_BYPASS_PROTECTION] = 0; // set to 1 to bypass the copy protection
+ g_cine->_globalVars[VAR_LOW_MEMORY] = 0; // set to 1 to disable some animations, sounds etc.
}
strcpy(newPrcName, "");
@@ -315,7 +315,7 @@ void CineEngine::mainLoop(int bootScriptIdx) {
if (bgName == "28.PI1" || bgName == "29.PI1" || bgName == "30.PI1") {
static const uint oxygenObjNum = 202, maxOxygen = 264;
// Force the amount of oxygen left to the maximum.
- objectTable[oxygenObjNum].x = maxOxygen;
+ g_cine->_objectTable[oxygenObjNum].x = maxOxygen;
}
}
@@ -332,8 +332,8 @@ void CineEngine::mainLoop(int bootScriptIdx) {
// flower shop scene is AIRPORT.PRC's 13th script.
// FIXME: Remove the hack and solve what's really causing the problem in the first place.
if (g_cine->getGameType() == Cine::GType_OS) {
- if (scumm_stricmp(renderer->getBgName(), "21.PI1") == 0 && objectTable[1].x == 204 && objectTable[1].y == 110) {
- objectTable[1].y--; // Move the player character upward on-screen by one pixel
+ if (scumm_stricmp(renderer->getBgName(), "21.PI1") == 0 && g_cine->_objectTable[1].x == 204 && g_cine->_objectTable[1].y == 110) {
+ g_cine->_objectTable[1].y--; // Move the player character upward on-screen by one pixel
}
}
@@ -342,7 +342,7 @@ void CineEngine::mainLoop(int bootScriptIdx) {
// Clear the zoneQuery table (Operation Stealth specific)
if (g_cine->getGameType() == Cine::GType_OS) {
- Common::set_to(zoneQuery.begin(), zoneQuery.end(), 0);
+ Common::set_to(g_cine->_zoneQuery.begin(), g_cine->_zoneQuery.end(), 0);
}
if (g_cine->getGameType() == Cine::GType_OS) {
diff --git a/engines/cine/msg.cpp b/engines/cine/msg.cpp
index 45f81f7d05..a01afd147b 100644
--- a/engines/cine/msg.cpp
+++ b/engines/cine/msg.cpp
@@ -31,15 +31,11 @@
namespace Cine {
-// FIXME: Global C++ objects affect portability negatively.
-// Turn this into a class member instead.
-Common::StringArray messageTable;
-
void loadMsg(char *pMsgName) {
uint32 sourceSize;
checkDataDisk(-1);
- messageTable.clear();
+ g_cine->_messageTable.clear();
byte *dataPtr = readBundleFile(findFileInBundle(pMsgName), &sourceSize);
setMouseCursor(MOUSE_CURSOR_DISK);
@@ -58,7 +54,7 @@ void loadMsg(char *pMsgName) {
// This code works around input data that has empty strings residing outside the input
// buffer (e.g. message indexes 58-254 in BATEAU.MSG in PROCS08 in Operation Stealth).
if (messageDataPos < sourceSize) {
- messageTable.push_back((const char *)(dataPtr + messageDataPos));
+ g_cine->_messageTable.push_back((const char *)(dataPtr + messageDataPos));
} else {
if (messageLen > 0) { // Only warn about overflowing non-empty strings
warning("loadMsg(%s): message (%d. / %d) is overflowing the input buffer. Replacing it with an empty string", pMsgName, i + 1, count);
@@ -66,7 +62,7 @@ void loadMsg(char *pMsgName) {
debugC(5, kCineDebugPart, "loadMsg(%s): empty message (%d. / %d) resides outside input buffer", pMsgName, i + 1, count);
}
// Message resides outside the input buffer so we replace it with an empty string
- messageTable.push_back("");
+ g_cine->_messageTable.push_back("");
}
// Jump to the next message
messageDataPos += messageLen;
diff --git a/engines/cine/msg.h b/engines/cine/msg.h
index cf51cdb48f..fbf99d4b44 100644
--- a/engines/cine/msg.h
+++ b/engines/cine/msg.h
@@ -32,8 +32,6 @@ namespace Cine {
#define NUM_MAX_MESSAGE 255
-extern Common::StringArray messageTable;
-
void loadMsg(char *pMsgName);
} // End of namespace Cine
diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp
index 116b57c267..82dc0a6ef1 100644
--- a/engines/cine/object.cpp
+++ b/engines/cine/object.cpp
@@ -35,12 +35,9 @@
namespace Cine {
-Common::Array<ObjectStruct> objectTable;
-Common::List<overlay> overlayList;
-
/** Resets all elements in the object table. */
void resetObjectTable() {
- for (Common::Array<ObjectStruct>::iterator it = objectTable.begin(); it != objectTable.end(); ++it) {
+ for (Common::Array<ObjectStruct>::iterator it = g_cine->_objectTable.begin(); it != g_cine->_objectTable.end(); ++it) {
it->clear();
}
}
@@ -64,23 +61,23 @@ void loadObject(char *pObjectName) {
assert(numEntry <= NUM_MAX_OBJECT);
for (i = 0; i < numEntry; i++) {
- if (objectTable[i].costume != -2) { // flag is keep ?
+ if (g_cine->_objectTable[i].costume != -2) { // flag is keep ?
Common::MemoryReadStream readS(ptr, entrySize);
- objectTable[i].x = readS.readSint16BE();
- objectTable[i].y = readS.readSint16BE();
- objectTable[i].mask = readS.readUint16BE();
- objectTable[i].frame = readS.readSint16BE();
- objectTable[i].costume = readS.readSint16BE();
- readS.read(objectTable[i].name, 20);
- objectTable[i].part = readS.readUint16BE();
+ g_cine->_objectTable[i].x = readS.readSint16BE();
+ g_cine->_objectTable[i].y = readS.readSint16BE();
+ g_cine->_objectTable[i].mask = readS.readUint16BE();
+ g_cine->_objectTable[i].frame = readS.readSint16BE();
+ g_cine->_objectTable[i].costume = readS.readSint16BE();
+ readS.read(g_cine->_objectTable[i].name, 20);
+ g_cine->_objectTable[i].part = readS.readUint16BE();
}
ptr += entrySize;
}
if (!strcmp(pObjectName, "INTRO.OBJ")) {
for (i = 0; i < 10; i++) {
- objectTable[i].costume = 0;
+ g_cine->_objectTable[i].costume = 0;
}
}
@@ -95,9 +92,9 @@ void loadObject(char *pObjectName) {
int removeOverlay(uint16 objIdx, uint16 param) {
Common::List<overlay>::iterator it;
- for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
if (it->objIdx == objIdx && it->type == param) {
- overlayList.erase(it);
+ g_cine->_overlayList.erase(it);
return 1;
}
}
@@ -115,9 +112,9 @@ void addOverlay(uint16 objIdx, uint16 type) {
Common::List<overlay>::iterator it;
overlay tmp;
- for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
// This is done for both Future Wars and Operation Stealth
- if (objectTable[it->objIdx].mask >= objectTable[objIdx].mask) {
+ if (g_cine->_objectTable[it->objIdx].mask >= g_cine->_objectTable[objIdx].mask) {
break;
}
@@ -128,7 +125,7 @@ void addOverlay(uint16 objIdx, uint16 type) {
}
// In Operation Stealth's implementation we might bail out early
- if (g_cine->getGameType() == Cine::GType_OS && it != overlayList.end() && it->objIdx == objIdx && it->type == type) {
+ if (g_cine->getGameType() == Cine::GType_OS && it != g_cine->_overlayList.end() && it->objIdx == objIdx && it->type == type) {
return;
}
@@ -139,7 +136,7 @@ void addOverlay(uint16 objIdx, uint16 type) {
tmp.width = 0;
tmp.color = 0;
- overlayList.insert(it, tmp);
+ g_cine->_overlayList.insert(it, tmp);
}
/**
@@ -151,13 +148,13 @@ void addGfxElement(int16 objIdx, int16 param, int16 type) {
Common::List<overlay>::iterator it;
overlay tmp;
- for (it = overlayList.begin(); it != overlayList.end(); ++it) {
- if (objectTable[it->objIdx].mask >= objectTable[objIdx].mask || it->type == 2 || it->type == 3) {
+ for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
+ if (g_cine->_objectTable[it->objIdx].mask >= g_cine->_objectTable[objIdx].mask || it->type == 2 || it->type == 3) {
break;
}
}
- if (it != overlayList.end() && it->objIdx == objIdx && it->type == type && it->x == param) {
+ if (it != g_cine->_overlayList.end() && it->objIdx == objIdx && it->type == type && it->x == param) {
return;
}
@@ -168,7 +165,7 @@ void addGfxElement(int16 objIdx, int16 param, int16 type) {
tmp.width = 0;
tmp.color = 0;
- overlayList.insert(it, tmp);
+ g_cine->_overlayList.insert(it, tmp);
}
/**
@@ -180,19 +177,19 @@ void addGfxElement(int16 objIdx, int16 param, int16 type) {
void removeGfxElement(int16 objIdx, int16 param, int16 type) {
Common::List<overlay>::iterator it;
- for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
if (it->objIdx == objIdx && it->type == type && it->x == param) {
- overlayList.erase(it);
+ g_cine->_overlayList.erase(it);
return;
}
}
}
void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint16 param4) {
- objectTable[objIdx].x = param1;
- objectTable[objIdx].y = param2;
- objectTable[objIdx].mask = param3;
- objectTable[objIdx].frame = param4;
+ g_cine->_objectTable[objIdx].x = param1;
+ g_cine->_objectTable[objIdx].y = param2;
+ g_cine->_objectTable[objIdx].mask = param3;
+ g_cine->_objectTable[objIdx].frame = param4;
if (g_cine->getGameType() == Cine::GType_OS) {
resetGfxEntityEntry(objIdx);
@@ -219,13 +216,13 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) {
switch (paramIdx) {
case 1:
- objectTable[objIdx].x = newValue;
+ g_cine->_objectTable[objIdx].x = newValue;
break;
case 2:
- objectTable[objIdx].y = newValue;
+ g_cine->_objectTable[objIdx].y = newValue;
break;
case 3:
- objectTable[objIdx].mask = newValue;
+ g_cine->_objectTable[objIdx].mask = newValue;
if (g_cine->getGameType() == Cine::GType_OS) { // Operation Stealth specific
resetGfxEntityEntry(objIdx);
@@ -236,18 +233,18 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) {
}
break;
case 4:
- objectTable[objIdx].frame = newValue;
+ g_cine->_objectTable[objIdx].frame = newValue;
break;
case 5:
// TODO: Test if this really breaks the newspaper machine on the airport in Operation Stealth.
if (g_cine->getGameType() == Cine::GType_FW && newValue == -1) {
- objectTable[objIdx].costume = globalVars[0];
+ g_cine->_objectTable[objIdx].costume = g_cine->_globalVars[0];
} else {
- objectTable[objIdx].costume = newValue;
+ g_cine->_objectTable[objIdx].costume = newValue;
}
break;
case 6:
- objectTable[objIdx].part = newValue;
+ g_cine->_objectTable[objIdx].part = newValue;
break;
}
}
@@ -263,8 +260,8 @@ bool compareRanges(uint16 aStart, uint16 aEnd, uint16 bStart, uint16 bEnd) {
uint16 compareObjectParamRanges(uint16 objIdx1, uint16 xAdd1, uint16 yAdd1, uint16 maskAdd1, uint16 objIdx2, uint16 xAdd2, uint16 yAdd2, uint16 maskAdd2) {
assert(objIdx1 < NUM_MAX_OBJECT && objIdx2 < NUM_MAX_OBJECT);
- const ObjectStruct &obj1 = objectTable[objIdx1];
- const ObjectStruct &obj2 = objectTable[objIdx2];
+ const ObjectStruct &obj1 = g_cine->_objectTable[objIdx1];
+ const ObjectStruct &obj2 = g_cine->_objectTable[objIdx2];
if (compareRanges(obj1.x, obj1.x + xAdd1, obj2.x, obj2.x + xAdd2) &&
compareRanges(obj1.y, obj1.y + yAdd1, obj2.y, obj2.y + yAdd2) &&
@@ -304,17 +301,17 @@ int16 getObjectParam(uint16 objIdx, uint16 paramIdx) {
switch (paramIdx) {
case 0:
- return objectTable[objIdx].x;
+ return g_cine->_objectTable[objIdx].x;
case 1:
- return objectTable[objIdx].y;
+ return g_cine->_objectTable[objIdx].y;
case 2:
- return objectTable[objIdx].mask;
+ return g_cine->_objectTable[objIdx].mask;
case 3:
- return objectTable[objIdx].frame;
+ return g_cine->_objectTable[objIdx].frame;
case 4:
- return objectTable[objIdx].costume;
+ return g_cine->_objectTable[objIdx].costume;
case 5:
- return objectTable[objIdx].part;
+ return g_cine->_objectTable[objIdx].part;
}
return 0;
diff --git a/engines/cine/object.h b/engines/cine/object.h
index daf515bf0f..5a5ea91286 100644
--- a/engines/cine/object.h
+++ b/engines/cine/object.h
@@ -63,9 +63,6 @@ struct overlay {
#define NUM_MAX_OBJECT 255
#define NUM_MAX_VAR 255
-extern Common::Array<ObjectStruct> objectTable;
-extern Common::List<overlay> overlayList;
-
void resetObjectTable();
void loadObject(char *pObjectName);
void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint16 param4);
diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp
index 6e730aedd9..27d0e593da 100644
--- a/engines/cine/pal.cpp
+++ b/engines/cine/pal.cpp
@@ -30,7 +30,6 @@
namespace Cine {
-Common::Array<PalEntry> palArray;
static byte paletteBuffer1[16];
static byte paletteBuffer2[16];
@@ -40,7 +39,7 @@ void loadPal(const char *fileName) {
removeExtention(buffer, fileName);
strcat(buffer, ".PAL");
- palArray.clear();
+ g_cine->_palArray.clear();
Common::File palFileHandle;
if (!palFileHandle.open(buffer))
@@ -49,11 +48,11 @@ void loadPal(const char *fileName) {
uint16 palEntriesCount = palFileHandle.readUint16LE();
palFileHandle.readUint16LE(); // entry size
- palArray.resize(palEntriesCount);
- for (uint i = 0; i < palArray.size(); ++i) {
- palFileHandle.read(palArray[i].name, 10);
- palFileHandle.read(palArray[i].pal1, 16);
- palFileHandle.read(palArray[i].pal2, 16);
+ g_cine->_palArray.resize(palEntriesCount);
+ for (uint i = 0; i < g_cine->_palArray.size(); ++i) {
+ palFileHandle.read(g_cine->_palArray[i].name, 10);
+ palFileHandle.read(g_cine->_palArray[i].pal1, 16);
+ palFileHandle.read(g_cine->_palArray[i].pal2, 16);
}
palFileHandle.close();
}
@@ -73,8 +72,8 @@ int16 findPaletteFromName(const char *fileName) {
position++;
}
- for (i = 0; i < palArray.size(); i++) {
- if (!strcmp(buffer, palArray[i].name)) {
+ for (i = 0; i < g_cine->_palArray.size(); i++) {
+ if (!strcmp(buffer, g_cine->_palArray[i].name)) {
return i;
}
}
@@ -97,9 +96,9 @@ void loadRelatedPalette(const char *fileName) {
paletteBuffer1[i] = paletteBuffer2[i] = (i << 4) + i;
}
} else {
- assert(paletteIndex < (int32)palArray.size());
- memcpy(paletteBuffer1, palArray[paletteIndex].pal1, 16);
- memcpy(paletteBuffer2, palArray[paletteIndex].pal2, 16);
+ assert(paletteIndex < (int32)g_cine->_palArray.size());
+ memcpy(paletteBuffer1, g_cine->_palArray[paletteIndex].pal1, 16);
+ memcpy(paletteBuffer2, g_cine->_palArray[paletteIndex].pal2, 16);
}
}
diff --git a/engines/cine/pal.h b/engines/cine/pal.h
index 0086711636..e5b318b24d 100644
--- a/engines/cine/pal.h
+++ b/engines/cine/pal.h
@@ -49,8 +49,6 @@ struct PalEntry {
byte pal2[16];
};
-extern Common::Array<PalEntry> palArray;
-
void loadPal(const char *fileName);
void loadRelatedPalette(const char *fileName);
diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp
index ad5aaf54b0..95f3789abd 100644
--- a/engines/cine/part.cpp
+++ b/engines/cine/part.cpp
@@ -32,10 +32,8 @@
namespace Cine {
-Common::Array<PartBuffer> partBuffer;
-
void loadPart(const char *partName) {
- partBuffer.clear();
+ g_cine->_partBuffer.clear();
g_cine->_partFileHandle.close();
@@ -47,17 +45,17 @@ void loadPart(const char *partName) {
setMouseCursor(MOUSE_CURSOR_DISK);
uint16 numElementInPart = g_cine->_partFileHandle.readUint16BE();
- partBuffer.resize(numElementInPart);
+ g_cine->_partBuffer.resize(numElementInPart);
g_cine->_partFileHandle.readUint16BE(); // entry size
if (currentPartName != partName)
strcpy(currentPartName, partName);
- for (uint16 i = 0; i < partBuffer.size(); i++) {
- g_cine->_partFileHandle.read(partBuffer[i].partName, 14);
- partBuffer[i].offset = g_cine->_partFileHandle.readUint32BE();
- partBuffer[i].packedSize = g_cine->_partFileHandle.readUint32BE();
- partBuffer[i].unpackedSize = g_cine->_partFileHandle.readUint32BE();
+ for (uint16 i = 0; i < g_cine->_partBuffer.size(); i++) {
+ g_cine->_partFileHandle.read(g_cine->_partBuffer[i].partName, 14);
+ g_cine->_partBuffer[i].offset = g_cine->_partFileHandle.readUint32BE();
+ g_cine->_partBuffer[i].packedSize = g_cine->_partFileHandle.readUint32BE();
+ g_cine->_partBuffer[i].unpackedSize = g_cine->_partFileHandle.readUint32BE();
g_cine->_partFileHandle.readUint32BE(); // unused
}
@@ -189,8 +187,8 @@ void CineEngine::readVolCnf() {
int16 findFileInBundle(const char *fileName) {
if (g_cine->getGameType() == Cine::GType_OS) {
// look first in currently loaded resource file
- for (uint i = 0; i < partBuffer.size(); i++) {
- if (!scumm_stricmp(fileName, partBuffer[i].partName)) {
+ for (uint i = 0; i < g_cine->_partBuffer.size(); i++) {
+ if (!scumm_stricmp(fileName, g_cine->_partBuffer[i].partName)) {
return i;
}
}
@@ -203,8 +201,8 @@ int16 findFileInBundle(const char *fileName) {
const char *part = (*it)._value;
loadPart(part);
}
- for (uint i = 0; i < partBuffer.size(); i++) {
- if (!scumm_stricmp(fileName, partBuffer[i].partName)) {
+ for (uint i = 0; i < g_cine->_partBuffer.size(); i++) {
+ if (!scumm_stricmp(fileName, g_cine->_partBuffer[i].partName)) {
return i;
}
}
@@ -212,31 +210,31 @@ int16 findFileInBundle(const char *fileName) {
}
void readFromPart(int16 idx, byte *dataPtr, uint32 maxSize) {
- assert(maxSize >= partBuffer[idx].packedSize);
+ assert(maxSize >= g_cine->_partBuffer[idx].packedSize);
setMouseCursor(MOUSE_CURSOR_DISK);
- g_cine->_partFileHandle.seek(partBuffer[idx].offset, SEEK_SET);
- g_cine->_partFileHandle.read(dataPtr, partBuffer[idx].packedSize);
+ g_cine->_partFileHandle.seek(g_cine->_partBuffer[idx].offset, SEEK_SET);
+ g_cine->_partFileHandle.read(dataPtr, g_cine->_partBuffer[idx].packedSize);
}
byte *readBundleFile(int16 foundFileIdx, uint32 *size) {
- assert(foundFileIdx >= 0 && foundFileIdx < (int32)partBuffer.size());
+ assert(foundFileIdx >= 0 && foundFileIdx < (int32)g_cine->_partBuffer.size());
bool error = false;
- byte *dataPtr = (byte *)calloc(partBuffer[foundFileIdx].unpackedSize, 1);
- byte *packedData = (byte *)calloc(partBuffer[foundFileIdx].packedSize, 1);
+ byte *dataPtr = (byte *)calloc(g_cine->_partBuffer[foundFileIdx].unpackedSize, 1);
+ byte *packedData = (byte *)calloc(g_cine->_partBuffer[foundFileIdx].packedSize, 1);
assert(dataPtr && packedData);
- readFromPart(foundFileIdx, packedData, partBuffer[foundFileIdx].packedSize);
+ readFromPart(foundFileIdx, packedData, g_cine->_partBuffer[foundFileIdx].packedSize);
CineUnpacker cineUnpacker;
- error = !cineUnpacker.unpack(packedData, partBuffer[foundFileIdx].packedSize, dataPtr, partBuffer[foundFileIdx].unpackedSize);
+ error = !cineUnpacker.unpack(packedData, g_cine->_partBuffer[foundFileIdx].packedSize, dataPtr, g_cine->_partBuffer[foundFileIdx].unpackedSize);
free(packedData);
if (error) {
- warning("Error unpacking '%s' from bundle file '%s'", partBuffer[foundFileIdx].partName, currentPartName);
+ warning("Error unpacking '%s' from bundle file '%s'", g_cine->_partBuffer[foundFileIdx].partName, currentPartName);
}
// Set the size variable if a pointer to it has been given
if (size != NULL) {
- *size = partBuffer[foundFileIdx].unpackedSize;
+ *size = g_cine->_partBuffer[foundFileIdx].unpackedSize;
}
return dataPtr;
@@ -255,7 +253,7 @@ byte *readBundleSoundFile(const char *entryName, uint32 *size) {
if (index != -1) {
data = readBundleFile(index);
if (size) {
- *size = partBuffer[index].unpackedSize;
+ *size = g_cine->_partBuffer[index].unpackedSize;
}
}
if (g_cine->getGameType() == Cine::GType_FW) {
@@ -305,14 +303,14 @@ void dumpBundle(const char *fileName) {
strcpy(tmpPart, currentPartName);
loadPart(fileName);
- for (uint i = 0; i < partBuffer.size(); i++) {
+ for (uint i = 0; i < g_cine->_partBuffer.size(); i++) {
byte *data = readBundleFile(i);
- debug(0, "%s", partBuffer[i].partName);
+ debug(0, "%s", g_cine->_partBuffer[i].partName);
Common::DumpFile out;
- if (out.open(Common::String("dumps/") + partBuffer[i].partName)) {
- out.write(data, partBuffer[i].unpackedSize);
+ if (out.open(Common::String("dumps/") + g_cine->_partBuffer[i].partName)) {
+ out.write(data, g_cine->_partBuffer[i].unpackedSize);
out.close();
}
diff --git a/engines/cine/part.h b/engines/cine/part.h
index 2f1af7141f..53ebafaa37 100644
--- a/engines/cine/part.h
+++ b/engines/cine/part.h
@@ -37,8 +37,6 @@ struct PartBuffer {
#define NUM_MAX_PARTDATA 255
-extern Common::Array<PartBuffer> partBuffer;
-
void loadPart(const char *partName);
void closePart();
diff --git a/engines/cine/prc.cpp b/engines/cine/prc.cpp
index e1ef14bbbf..183a537416 100644
--- a/engines/cine/prc.cpp
+++ b/engines/cine/prc.cpp
@@ -35,9 +35,6 @@
namespace Cine {
-ScriptList globalScripts;
-ScriptList objectScripts;
-
//char currentPrcName[20];
/**
@@ -52,8 +49,8 @@ bool loadPrc(const char *pPrcName) {
assert(pPrcName);
- globalScripts.clear();
- scriptTable.clear();
+ g_cine->_globalScripts.clear();
+ g_cine->_scriptTable.clear();
// This is copy protection. Used to hang the machine
if (!scumm_stricmp(pPrcName, COPY_PROT_FAIL_PRC_NAME)) {
@@ -83,14 +80,14 @@ bool loadPrc(const char *pPrcName) {
RawScriptPtr tmp(new RawScript(READ_BE_UINT16(scriptPtr)));
scriptPtr += 2;
assert(tmp);
- scriptTable.push_back(tmp);
+ g_cine->_scriptTable.push_back(tmp);
}
for (i = 0; i < numScripts; i++) {
- uint16 size = scriptTable[i]->_size;
+ uint16 size = g_cine->_scriptTable[i]->_size;
// TODO: delete the test?
if (size) {
- scriptTable[i]->setData(*scriptInfo, scriptPtr);
+ g_cine->_scriptTable[i]->setData(*scriptInfo, scriptPtr);
scriptPtr += size;
}
}
diff --git a/engines/cine/prc.h b/engines/cine/prc.h
index 05bb240372..84058426fa 100644
--- a/engines/cine/prc.h
+++ b/engines/cine/prc.h
@@ -28,9 +28,6 @@
namespace Cine {
-extern ScriptList globalScripts;
-extern ScriptList objectScripts;
-
bool loadPrc(const char *pPrcName);
} // End of namespace Cine
diff --git a/engines/cine/rel.cpp b/engines/cine/rel.cpp
index 17ab14bfe5..4a11995ee1 100644
--- a/engines/cine/rel.cpp
+++ b/engines/cine/rel.cpp
@@ -31,8 +31,6 @@
namespace Cine {
-RawObjectScriptArray relTable; ///< Object script bytecode table
-
/**
* @todo Is script size of 0 valid?
* @todo Fix script dump code
@@ -45,8 +43,8 @@ void loadRel(char *pRelName) {
checkDataDisk(-1);
- objectScripts.clear();
- relTable.clear();
+ g_cine->_objectScripts.clear();
+ g_cine->_relTable.clear();
ptr = dataPtr = readBundleFile(findFileInBundle(pRelName));
@@ -61,14 +59,14 @@ void loadRel(char *pRelName) {
p3 = READ_BE_UINT16(ptr); ptr += 2;
RawObjectScriptPtr tmp(new RawObjectScript(size, p1, p2, p3));
assert(tmp);
- relTable.push_back(tmp);
+ g_cine->_relTable.push_back(tmp);
}
for (i = 0; i < numEntry; i++) {
- size = relTable[i]->_size;
+ size = g_cine->_relTable[i]->_size;
// TODO: delete the test?
if (size) {
- relTable[i]->setData(*scriptInfo, ptr);
+ g_cine->_relTable[i]->setData(*scriptInfo, ptr);
ptr += size;
}
}
@@ -82,10 +80,10 @@ void loadRel(char *pRelName) {
char buffer[256];
for (s = 0; s < numEntry; s++) {
- if (relTable[s]->_size) {
+ if (g_cine->_relTable[s]->_size) {
sprintf(buffer, "%s_%03d.txt", pRelName, s);
- decompileScript((const byte *)relTable[s]->getString(0), relTable[s]->_size, s);
+ decompileScript((const byte *)g_cine->_relTable[s]->getString(0), g_cine->_relTable[s]->_size, s);
dumpScript(buffer);
}
}
diff --git a/engines/cine/rel.h b/engines/cine/rel.h
index 84926f76c4..8d712dc416 100644
--- a/engines/cine/rel.h
+++ b/engines/cine/rel.h
@@ -29,8 +29,6 @@
#include "cine/script.h"
namespace Cine {
-extern RawObjectScriptArray relTable;
-
void loadRel(char *pRelName);
} // End of namespace Cine
diff --git a/engines/cine/saveload.cpp b/engines/cine/saveload.cpp
index c76bed3f8e..0f7c50b7e5 100644
--- a/engines/cine/saveload.cpp
+++ b/engines/cine/saveload.cpp
@@ -200,13 +200,13 @@ void loadScriptFromSave(Common::SeekableReadStream &fHandle, bool isGlobal) {
// original code loaded everything into globalScripts, this should be
// the correct behavior
if (isGlobal) {
- ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx, labels, localVars, compare, pos));
+ ScriptPtr tmp(scriptInfo->create(*g_cine->_scriptTable[idx], idx, labels, localVars, compare, pos));
assert(tmp);
- globalScripts.push_back(tmp);
+ g_cine->_globalScripts.push_back(tmp);
} else {
- ScriptPtr tmp(scriptInfo->create(*relTable[idx], idx, labels, localVars, compare, pos));
+ ScriptPtr tmp(scriptInfo->create(*g_cine->_relTable[idx], idx, labels, localVars, compare, pos));
assert(tmp);
- objectScripts.push_back(tmp);
+ g_cine->_objectScripts.push_back(tmp);
}
}
@@ -227,7 +227,7 @@ void loadOverlayFromSave(Common::SeekableReadStream &fHandle) {
tmp.width = fHandle.readSint16BE();
tmp.color = fHandle.readSint16BE();
- overlayList.push_back(tmp);
+ g_cine->_overlayList.push_back(tmp);
}
bool loadObjectTable(Common::SeekableReadStream &in) {
@@ -235,20 +235,20 @@ bool loadObjectTable(Common::SeekableReadStream &in) {
in.readUint16BE(); // Entry size
for (int i = 0; i < NUM_MAX_OBJECT; i++) {
- objectTable[i].x = in.readSint16BE();
- objectTable[i].y = in.readSint16BE();
- objectTable[i].mask = in.readUint16BE();
- objectTable[i].frame = in.readSint16BE();
- objectTable[i].costume = in.readSint16BE();
- in.read(objectTable[i].name, 20);
- objectTable[i].part = in.readUint16BE();
+ g_cine->_objectTable[i].x = in.readSint16BE();
+ g_cine->_objectTable[i].y = in.readSint16BE();
+ g_cine->_objectTable[i].mask = in.readUint16BE();
+ g_cine->_objectTable[i].frame = in.readSint16BE();
+ g_cine->_objectTable[i].costume = in.readSint16BE();
+ in.read(g_cine->_objectTable[i].name, 20);
+ g_cine->_objectTable[i].part = in.readUint16BE();
}
return !(in.eos() || in.err());
}
bool loadZoneData(Common::SeekableReadStream &in) {
for (int i = 0; i < 16; i++) {
- zoneData[i] = in.readUint16BE();
+ g_cine->_zoneData[i] = in.readUint16BE();
}
return !(in.eos() || in.err());
}
@@ -313,14 +313,14 @@ bool loadSeqList(Common::SeekableReadStream &in) {
tmp.var1A = in.readSint16BE();
tmp.var1C = in.readSint16BE();
tmp.var1E = in.readSint16BE();
- seqList.push_back(tmp);
+ g_cine->_seqList.push_back(tmp);
}
return !(in.eos() || in.err());
}
bool loadZoneQuery(Common::SeekableReadStream &in) {
for (int i = 0; i < 16; i++) {
- zoneQuery[i] = in.readUint16BE();
+ g_cine->_zoneQuery[i] = in.readUint16BE();
}
return !(in.eos() || in.err());
}
@@ -330,19 +330,19 @@ void saveObjectTable(Common::OutSaveFile &out) {
out.writeUint16BE(0x20); // Entry size
for (int i = 0; i < NUM_MAX_OBJECT; i++) {
- out.writeUint16BE(objectTable[i].x);
- out.writeUint16BE(objectTable[i].y);
- out.writeUint16BE(objectTable[i].mask);
- out.writeUint16BE(objectTable[i].frame);
- out.writeUint16BE(objectTable[i].costume);
- out.write(objectTable[i].name, 20);
- out.writeUint16BE(objectTable[i].part);
+ out.writeUint16BE(g_cine->_objectTable[i].x);
+ out.writeUint16BE(g_cine->_objectTable[i].y);
+ out.writeUint16BE(g_cine->_objectTable[i].mask);
+ out.writeUint16BE(g_cine->_objectTable[i].frame);
+ out.writeUint16BE(g_cine->_objectTable[i].costume);
+ out.write(g_cine->_objectTable[i].name, 20);
+ out.writeUint16BE(g_cine->_objectTable[i].part);
}
}
void saveZoneData(Common::OutSaveFile &out) {
for (int i = 0; i < 16; i++) {
- out.writeUint16BE(zoneData[i]);
+ out.writeUint16BE(g_cine->_zoneData[i]);
}
}
@@ -356,8 +356,8 @@ void saveCommandVariables(Common::OutSaveFile &out) {
void saveCommandBuffer(Common::OutSaveFile &out) {
// Let's make sure there's space for the trailing zero
// (That's why we subtract one from the maximum command buffer size here).
- uint32 size = MIN<uint32>(commandBuffer.size(), kMaxCommandBufferSize - 1);
- out.write(commandBuffer.c_str(), size);
+ uint32 size = MIN<uint32>(g_cine->_commandBuffer.size(), kMaxCommandBufferSize - 1);
+ out.write(g_cine->_commandBuffer.c_str(), size);
// Write the rest as zeroes (Here we also write the string's trailing zero)
for (uint i = 0; i < kMaxCommandBufferSize - size; i++) {
out.writeByte(0);
@@ -369,7 +369,7 @@ void saveAnimDataTable(Common::OutSaveFile &out) {
out.writeUint16BE(0x1E); // Entry size
for (int i = 0; i < NUM_MAX_ANIMDATA; i++) {
- animDataTable[i].save(out);
+ g_cine->_animDataTable[i].save(out);
}
}
@@ -385,16 +385,16 @@ void saveScreenParams(Common::OutSaveFile &out) {
void saveGlobalScripts(Common::OutSaveFile &out) {
ScriptList::const_iterator it;
- out.writeUint16BE(globalScripts.size());
- for (it = globalScripts.begin(); it != globalScripts.end(); ++it) {
+ out.writeUint16BE(g_cine->_globalScripts.size());
+ for (it = g_cine->_globalScripts.begin(); it != g_cine->_globalScripts.end(); ++it) {
(*it)->save(out);
}
}
void saveObjectScripts(Common::OutSaveFile &out) {
ScriptList::const_iterator it;
- out.writeUint16BE(objectScripts.size());
- for (it = objectScripts.begin(); it != objectScripts.end(); ++it) {
+ out.writeUint16BE(g_cine->_objectScripts.size());
+ for (it = g_cine->_objectScripts.begin(); it != g_cine->_objectScripts.end(); ++it) {
(*it)->save(out);
}
}
@@ -402,9 +402,9 @@ void saveObjectScripts(Common::OutSaveFile &out) {
void saveOverlayList(Common::OutSaveFile &out) {
Common::List<overlay>::const_iterator it;
- out.writeUint16BE(overlayList.size());
+ out.writeUint16BE(g_cine->_overlayList.size());
- for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
out.writeUint32BE(0); // next
out.writeUint32BE(0); // previous?
out.writeUint16BE(it->objIdx);
@@ -418,9 +418,9 @@ void saveOverlayList(Common::OutSaveFile &out) {
void saveBgIncrustList(Common::OutSaveFile &out) {
Common::List<BGIncrust>::const_iterator it;
- out.writeUint16BE(bgIncrustList.size());
+ out.writeUint16BE(g_cine->_bgIncrustList.size());
- for (it = bgIncrustList.begin(); it != bgIncrustList.end(); ++it) {
+ for (it = g_cine->_bgIncrustList.begin(); it != g_cine->_bgIncrustList.end(); ++it) {
out.writeUint32BE(0); // next
out.writeUint32BE(0); // previous?
out.writeUint16BE(it->objIdx);
@@ -434,15 +434,15 @@ void saveBgIncrustList(Common::OutSaveFile &out) {
void saveZoneQuery(Common::OutSaveFile &out) {
for (int i = 0; i < 16; i++) {
- out.writeUint16BE(zoneQuery[i]);
+ out.writeUint16BE(g_cine->_zoneQuery[i]);
}
}
void saveSeqList(Common::OutSaveFile &out) {
Common::List<SeqListElement>::const_iterator it;
- out.writeUint16BE(seqList.size());
+ out.writeUint16BE(g_cine->_seqList.size());
- for (it = seqList.begin(); it != seqList.end(); ++it) {
+ for (it = g_cine->_seqList.begin(); it != g_cine->_seqList.end(); ++it) {
out.writeSint16BE(it->var4);
out.writeUint16BE(it->objIdx);
out.writeSint16BE(it->var8);
@@ -465,7 +465,7 @@ bool CineEngine::loadSaveDirectory() {
char tmp[80];
snprintf(tmp, 80, "%s.dir", _targetName.c_str());
- fHandle = g_saveFileMan->openForLoading(tmp);
+ fHandle = _saveFileMan->openForLoading(tmp);
if (!fHandle) {
return false;
@@ -566,14 +566,14 @@ bool CineEngine::loadTempSaveOS(Common::SeekableReadStream &in) {
}
loadObjectTable(in);
- renderer->restorePalette(in);
- globalVars.load(in, NUM_MAX_VAR);
+ renderer->restorePalette(in, hdr.version);
+ g_cine->_globalVars.load(in, NUM_MAX_VAR);
loadZoneData(in);
loadCommandVariables(in);
char tempCommandBuffer[kMaxCommandBufferSize];
in.read(tempCommandBuffer, kMaxCommandBufferSize);
- commandBuffer = tempCommandBuffer;
- renderer->setCommand(commandBuffer);
+ g_cine->_commandBuffer = tempCommandBuffer;
+ renderer->setCommand(g_cine->_commandBuffer);
loadZoneQuery(in);
// TODO: Use the loaded string (Current music name (String, 13 bytes)).
@@ -698,10 +698,10 @@ bool CineEngine::loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFor
loadObjectTable(in);
// At 0x2043 (i.e. 0x005F + 2 * 2 + 255 * 32):
- renderer->restorePalette(in);
+ renderer->restorePalette(in, 0);
// At 0x2083 (i.e. 0x2043 + 16 * 2 * 2):
- globalVars.load(in, NUM_MAX_VAR);
+ g_cine->_globalVars.load(in, NUM_MAX_VAR);
// At 0x2281 (i.e. 0x2083 + 255 * 2):
loadZoneData(in);
@@ -712,8 +712,8 @@ bool CineEngine::loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFor
// At 0x22A9 (i.e. 0x22A1 + 4 * 2):
char tempCommandBuffer[kMaxCommandBufferSize];
in.read(tempCommandBuffer, kMaxCommandBufferSize);
- commandBuffer = tempCommandBuffer;
- renderer->setCommand(commandBuffer);
+ g_cine->_commandBuffer = tempCommandBuffer;
+ renderer->setCommand(g_cine->_commandBuffer);
// At 0x22F9 (i.e. 0x22A9 + 0x50):
renderer->_cmdY = in.readUint16BE();
@@ -771,7 +771,7 @@ bool CineEngine::loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFor
}
bool CineEngine::makeLoad(char *saveName) {
- Common::SharedPtr<Common::InSaveFile> saveFile(g_saveFileMan->openForLoading(saveName));
+ Common::SharedPtr<Common::InSaveFile> saveFile(_saveFileMan->openForLoading(saveName));
if (!saveFile) {
renderer->drawString(otherMessages[0], 0);
@@ -855,7 +855,7 @@ void CineEngine::makeSaveFW(Common::OutSaveFile &out) {
saveObjectTable(out);
renderer->savePalette(out);
- globalVars.save(out, NUM_MAX_VAR);
+ g_cine->_globalVars.save(out, NUM_MAX_VAR);
saveZoneData(out);
saveCommandVariables(out);
saveCommandBuffer(out);
@@ -912,7 +912,7 @@ void CineEngine::makeSaveOS(Common::OutSaveFile &out) {
saveObjectTable(out);
renderer->savePalette(out);
- globalVars.save(out, NUM_MAX_VAR);
+ g_cine->_globalVars.save(out, NUM_MAX_VAR);
saveZoneData(out);
saveCommandVariables(out);
saveCommandBuffer(out);
@@ -966,7 +966,7 @@ void CineEngine::makeSaveOS(Common::OutSaveFile &out) {
}
void CineEngine::makeSave(char *saveFileName) {
- Common::SharedPtr<Common::OutSaveFile> fHandle(g_saveFileMan->openForSaving(saveFileName));
+ Common::SharedPtr<Common::OutSaveFile> fHandle(_saveFileMan->openForSaving(saveFileName));
setMouseCursor(MOUSE_CURSOR_DISK);
@@ -976,7 +976,7 @@ void CineEngine::makeSave(char *saveFileName) {
// restoreScreen();
checkDataDisk(-1);
} else {
- if (g_cine->getGameType() == GType_FW) {
+ if (getGameType() == GType_FW) {
makeSaveFW(*fHandle);
} else {
makeSaveOS(*fHandle);
@@ -1045,7 +1045,7 @@ void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGam
loadPart(name);
}
- animName = partBuffer[foundFileIdx].partName;
+ animName = g_cine->_partBuffer[foundFileIdx].partName;
loadRelatedPalette(animName); // Is this for Future Wars only?
const int16 prevAnim = currentAnim;
currentAnim = loadResource(animName, currentAnim);
diff --git a/engines/cine/saveload.h b/engines/cine/saveload.h
index 65f24f838d..a6e0e3f1ab 100644
--- a/engines/cine/saveload.h
+++ b/engines/cine/saveload.h
@@ -74,7 +74,7 @@ enum CineSaveGameFormat {
static const uint32 TEMP_OS_FORMAT_ID = MKID_BE('TEMP');
/** The current version number of Operation Stealth's savegame format. */
-static const uint32 CURRENT_OS_SAVE_VER = 0;
+static const uint32 CURRENT_OS_SAVE_VER = 1;
/** Chunk header used by the temporary Operation Stealth savegame format. */
struct ChunkHeader {
diff --git a/engines/cine/script.h b/engines/cine/script.h
index 1c3b496375..756bc930e8 100644
--- a/engines/cine/script.h
+++ b/engines/cine/script.h
@@ -67,6 +67,7 @@ public:
ScriptVars(const ScriptVars &src);
~ScriptVars();
+ void reinit(unsigned int len);
ScriptVars &operator=(const ScriptVars &src);
int16 &operator[](unsigned int idx);
int16 operator[](unsigned int idx) const;
@@ -368,9 +369,7 @@ typedef Common::Array<RawObjectScriptPtr> RawObjectScriptArray;
#define NUM_MAX_SCRIPT 50
-extern RawScriptArray scriptTable;
extern FWScriptInfo *scriptInfo;
-extern ScriptVars globalVars;
void setupOpcodes();
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
index e71fec8898..430a32ac69 100644
--- a/engines/cine/script_fw.cpp
+++ b/engines/cine/script_fw.cpp
@@ -38,14 +38,6 @@
namespace Cine {
-/**
- * Global variables.
- * 255 of these are saved, but there's one more that's used for bypassing the copy protection.
- * In CineEngine::mainLoop(int bootScriptIdx) there's this code: globalVars[VAR_BYPASS_PROTECTION] = 0;
- * And as VAR_BYPASS_PROTECTION is 255 that's why we're allocating one more than we otherwise would.
- */
-ScriptVars globalVars(NUM_MAX_VAR + 1);
-
uint16 compareVars(int16 a, int16 b);
@@ -216,7 +208,6 @@ void FWScript::setupTable() {
}
FWScriptInfo *scriptInfo; ///< Script factory
-RawScriptArray scriptTable; ///< Table of script bytecode
/**
* @todo replace with script subsystem
@@ -257,6 +248,14 @@ ScriptVars::ScriptVars(Common::SeekableReadStream &fHandle, unsigned int len)
load(fHandle);
}
+void ScriptVars::reinit(unsigned int len) {
+ delete _vars;
+
+ _size = len;
+ _vars = new int16[len];
+ reset();
+}
+
/**
* Copy constructor
*/
@@ -606,7 +605,7 @@ RawObjectScript::RawObjectScript(const FWScriptInfo &info, const byte *data,
FWScript::FWScript(const RawScript &script, int16 idx) : _script(script),
_pos(0), _line(0), _compare(0), _index(idx),
_labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
- _globalVars(globalVars), _info(new FWScriptInfo) { }
+ _globalVars(g_cine->_globalVars), _info(new FWScriptInfo) { }
/**
* Copy constructor
@@ -624,7 +623,7 @@ FWScript::FWScript(const FWScript &src) : _script(src._script), _pos(src._pos),
FWScript::FWScript(const RawScript &script, int16 idx, FWScriptInfo *info) :
_script(script), _pos(0), _line(0), _compare(0), _index(idx),
_labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
- _globalVars(globalVars), _info(info) { }
+ _globalVars(g_cine->_globalVars), _info(info) { }
/**
* Constructor for object scripts in derived classes
@@ -634,7 +633,7 @@ FWScript::FWScript(const RawScript &script, int16 idx, FWScriptInfo *info) :
FWScript::FWScript(RawObjectScript &script, int16 idx, FWScriptInfo *info) :
_script(script), _pos(0), _line(0), _compare(0), _index(idx),
_labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
- _globalVars(globalVars), _info(info) {
+ _globalVars(g_cine->_globalVars), _info(info) {
_localVars[0] = script.run();
}
@@ -964,11 +963,11 @@ int FWScript::o1_loadVar() {
break;
case 8:
debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _line, varIdx, dataIdx);
- _localVars[varIdx] = partBuffer[dataIdx].packedSize;
+ _localVars[varIdx] = g_cine->_partBuffer[dataIdx].packedSize;
break;
case 9:
debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _line, varIdx, dataIdx);
- _localVars[varIdx] = partBuffer[dataIdx].unpackedSize;
+ _localVars[varIdx] = g_cine->_partBuffer[dataIdx].unpackedSize;
break;
default:
error("executeScript: o1_loadVar: Unknown variable type %d", varType);
@@ -1196,7 +1195,7 @@ int FWScript::o1_addSpriteFilledToBgList() {
int FWScript::o1_op1B() {
debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _line);
- bgIncrustList.clear();
+ g_cine->_bgIncrustList.clear();
return 0;
}
@@ -1343,9 +1342,9 @@ int FWScript::o1_endGlobalScript() {
debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _line, scriptIdx);
- ScriptList::iterator it = globalScripts.begin();
+ ScriptList::iterator it = g_cine->_globalScripts.begin();
- for (; it != globalScripts.end(); ++it) {
+ for (; it != g_cine->_globalScripts.end(); ++it) {
if ((*it)->_index == scriptIdx) {
(*it)->_index = -1;
}
@@ -1369,7 +1368,7 @@ int FWScript::o1_loadBg() {
debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _line, param);
loadBg(param);
- bgIncrustList.clear();
+ g_cine->_bgIncrustList.clear();
bgVar0 = 0;
return 0;
}
@@ -1627,7 +1626,7 @@ int FWScript::o1_freePartRange() {
int FWScript::o1_unloadAllMasks() {
debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _line);
- overlayList.clear();
+ g_cine->_overlayList.clear();
return 0;
}
@@ -1656,7 +1655,7 @@ int FWScript::o1_initializeZoneData() {
debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _line);
for (int i = 0; i < NUM_MAX_ZONE; i++) {
- zoneData[i] = i;
+ g_cine->_zoneData[i] = i;
}
return 0;
}
@@ -1666,7 +1665,7 @@ int FWScript::o1_setZoneDataEntry() {
uint16 var = getNextWord();
debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _line, zoneIdx, var);
- zoneData[zoneIdx] = var;
+ g_cine->_zoneData[zoneIdx] = var;
return 0;
}
@@ -1674,7 +1673,7 @@ int FWScript::o1_getZoneDataEntry() {
byte zoneIdx = getNextByte();
byte var = getNextByte();
- _localVars[var] = zoneData[zoneIdx];
+ _localVars[var] = g_cine->_zoneData[zoneIdx];
return 0;
}
@@ -1796,7 +1795,7 @@ int FWScript::o1_playSample() {
int16 volume = getNextWord();
uint16 size = getNextWord();
- const byte *data = animDataTable[anim].data();
+ const byte *data = g_cine->_animDataTable[anim].data();
if (!data) {
return 0;
@@ -1804,7 +1803,7 @@ int FWScript::o1_playSample() {
if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
if (size == 0xFFFF) {
- size = animDataTable[anim]._width * animDataTable[anim]._height;
+ size = g_cine->_animDataTable[anim]._width * g_cine->_animDataTable[anim]._height;
}
if (channel < 10) { // || _currentOpcode == 0x78
int channel1, channel2;
@@ -1874,9 +1873,9 @@ int FWScript::o1_unloadMask5() {
//-----------------------------------------------------------------------
void addScriptToGlobalScripts(uint16 idx) {
- ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx));
+ ScriptPtr tmp(scriptInfo->create(*g_cine->_scriptTable[idx], idx));
assert(tmp);
- globalScripts.push_back(tmp);
+ g_cine->_globalScripts.push_back(tmp);
}
int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) {
@@ -1916,8 +1915,8 @@ int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) {
}
int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) {
- int16 lx = objectTable[objIdx].x + x;
- int16 ly = objectTable[objIdx].y + y;
+ int16 lx = g_cine->_objectTable[objIdx].x + x;
+ int16 ly = g_cine->_objectTable[objIdx].y + y;
int16 idx;
int16 result = 0;
@@ -1935,12 +1934,12 @@ int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneI
// The zoneQuery table is updated here only in Operation Stealth
if (g_cine->getGameType() == Cine::GType_OS) {
- if (zoneData[idx] < NUM_MAX_ZONE) {
- zoneQuery[zoneData[idx]]++;
+ if (g_cine->_zoneData[idx] < NUM_MAX_ZONE) {
+ g_cine->_zoneQuery[g_cine->_zoneData[idx]]++;
}
}
- if (zoneData[idx] == zoneIdx) {
+ if (g_cine->_zoneData[idx] == zoneIdx) {
result = 1;
// Future Wars breaks out early on the first match, but
// Operation Stealth doesn't because it needs to update
@@ -1969,10 +1968,10 @@ uint16 compareVars(int16 a, int16 b) {
}
void executeObjectScripts() {
- ScriptList::iterator it = objectScripts.begin();
- for (; it != objectScripts.end();) {
+ ScriptList::iterator it = g_cine->_objectScripts.begin();
+ for (; it != g_cine->_objectScripts.end();) {
if ((*it)->_index < 0 || (*it)->execute() < 0) {
- it = objectScripts.erase(it);
+ it = g_cine->_objectScripts.erase(it);
} else {
++it;
}
@@ -1980,10 +1979,10 @@ void executeObjectScripts() {
}
void executeGlobalScripts() {
- ScriptList::iterator it = globalScripts.begin();
- for (; it != globalScripts.end();) {
+ ScriptList::iterator it = g_cine->_globalScripts.begin();
+ for (; it != g_cine->_globalScripts.end();) {
if ((*it)->_index < 0 || (*it)->execute() < 0) {
- it = globalScripts.erase(it);
+ it = g_cine->_globalScripts.erase(it);
} else {
++it;
}
diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp
index d03b118443..ab1ad7ff9c 100644
--- a/engines/cine/script_os.cpp
+++ b/engines/cine/script_os.cpp
@@ -420,16 +420,16 @@ int FWScript::o2_playSampleAlt() {
uint16 size = getNextWord();
if (size == 0xFFFF) {
- size = animDataTable[num]._width * animDataTable[num]._height;
+ size = g_cine->_animDataTable[num]._width * g_cine->_animDataTable[num]._height;
}
- if (animDataTable[num].data()) {
+ if (g_cine->_animDataTable[num].data()) {
if (g_cine->getPlatform() == Common::kPlatformPC) {
// if speaker output is available, play sound on it
// if it's another device, don't play anything
// TODO: implement this, it's used in the introduction for example
// on each letter displayed
} else {
- g_sound->playSound(channel, frequency, animDataTable[num].data(), size, 0, 0, 63, 0);
+ g_sound->playSound(channel, frequency, g_cine->_animDataTable[num].data(), size, 0, 0, 63, 0);
}
}
return 0;
@@ -611,9 +611,9 @@ int FWScript::o2_stopObjectScript() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _line, param);
- ScriptList::iterator it = objectScripts.begin();
+ ScriptList::iterator it = g_cine->_objectScripts.begin();
- for (; it != objectScripts.end(); ++it) {
+ for (; it != g_cine->_objectScripts.end(); ++it) {
if ((*it)->_index == param) {
(*it)->_index = -1;
}
@@ -699,7 +699,7 @@ int FWScript::o2_loadBg() {
int FWScript::o2_wasZoneChecked() {
byte param = getNextByte();
- _compare = (param < NUM_MAX_ZONE && zoneQuery[param]) ? 1 : 0;
+ _compare = (param < NUM_MAX_ZONE && g_cine->_zoneQuery[param]) ? 1 : 0;
debugC(5, kCineDebugScript, "Line: %d: o2_wasZoneChecked(%d)", _line, param);
return 0;
}
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 9a10c2b5d7..cf7135a6b5 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -81,7 +81,6 @@ uint16 _messageLen;
int16 playerCommand;
-Common::String commandBuffer;
char currentPrcName[20];
char currentRelName[20];
char currentObjectName[20];
@@ -137,9 +136,6 @@ static const int16 canUseOnItemTable[] = { 1, 0, 0, 1, 1, 0, 0 };
CommandeType objectListCommand[20];
int16 objListTab[20];
-Common::Array<uint16> zoneData;
-Common::Array<uint16> zoneQuery; ///< Only exists in Operation Stealth
-
/**
* Move the player character using the keyboard
* @param x Negative values move left, positive right, zero not at all
@@ -174,9 +170,9 @@ void stopMusicAfterFadeOut() {
}
void runObjectScript(int16 entryIdx) {
- ScriptPtr tmp(scriptInfo->create(*relTable[entryIdx], entryIdx));
+ ScriptPtr tmp(scriptInfo->create(*g_cine->_relTable[entryIdx], entryIdx));
assert(tmp);
- objectScripts.push_back(tmp);
+ g_cine->_objectScripts.push_back(tmp);
}
/**
@@ -190,19 +186,19 @@ void addPlayerCommandMessage(int16 cmd) {
tmp.objIdx = cmd;
tmp.type = 3;
- overlayList.push_back(tmp);
+ g_cine->_overlayList.push_back(tmp);
}
int16 getRelEntryForObject(uint16 param1, uint16 param2, SelectedObjStruct *pSelectedObject) {
int16 i;
int16 found = -1;
- for (i = 0; i < (int16)relTable.size(); i++) {
- if (relTable[i]->_param1 == param1 && relTable[i]->_param2 == pSelectedObject->idx) {
+ for (i = 0; i < (int16)g_cine->_relTable.size(); i++) {
+ if (g_cine->_relTable[i]->_param1 == param1 && g_cine->_relTable[i]->_param2 == pSelectedObject->idx) {
if (param2 == 1) {
found = i;
} else if (param2 == 2) {
- if (relTable[i]->_param3 == pSelectedObject->param) {
+ if (g_cine->_relTable[i]->_param3 == pSelectedObject->param) {
found = i;
}
}
@@ -228,19 +224,19 @@ int16 getObjectUnderCursor(uint16 x, uint16 y) {
int width;
// reverse_iterator would be nice
- for (it = overlayList.reverse_begin(); it != overlayList.end(); --it) {
- if (it->type >= 2 || !objectTable[it->objIdx].name[0]) {
+ for (it = g_cine->_overlayList.reverse_begin(); it != g_cine->_overlayList.end(); --it) {
+ if (it->type >= 2 || !g_cine->_objectTable[it->objIdx].name[0]) {
continue;
}
- objX = objectTable[it->objIdx].x;
- objY = objectTable[it->objIdx].y;
+ objX = g_cine->_objectTable[it->objIdx].x;
+ objY = g_cine->_objectTable[it->objIdx].y;
- frame = ABS((int16)(objectTable[it->objIdx].frame));
- part = objectTable[it->objIdx].part;
+ frame = ABS((int16)(g_cine->_objectTable[it->objIdx].frame));
+ part = g_cine->_objectTable[it->objIdx].part;
// Additional case for negative frame values in Operation Stealth
- if (g_cine->getGameType() == Cine::GType_OS && objectTable[it->objIdx].frame < 0) {
+ if (g_cine->getGameType() == Cine::GType_OS && g_cine->_objectTable[it->objIdx].frame < 0) {
if ((it->type == 1) && (x >= objX) && (objX + frame >= x) && (y >= objY) && (objY + part >= y)) {
return it->objIdx;
} else {
@@ -249,18 +245,18 @@ int16 getObjectUnderCursor(uint16 x, uint16 y) {
}
if (it->type == 0) {
- threshold = animDataTable[frame]._var1;
+ threshold = g_cine->_animDataTable[frame]._var1;
} else {
- threshold = animDataTable[frame]._width / 2;
+ threshold = g_cine->_animDataTable[frame]._width / 2;
}
- height = animDataTable[frame]._height;
- width = animDataTable[frame]._realWidth;
+ height = g_cine->_animDataTable[frame]._height;
+ width = g_cine->_animDataTable[frame]._realWidth;
xdif = x - objX;
ydif = y - objY;
- if ((xdif < 0) || ((threshold << 4) <= xdif) || (ydif <= 0) || (ydif >= height) || !animDataTable[frame].data()) {
+ if ((xdif < 0) || ((threshold << 4) <= xdif) || (ydif <= 0) || (ydif >= height) || !g_cine->_animDataTable[frame].data()) {
continue;
}
@@ -272,17 +268,17 @@ int16 getObjectUnderCursor(uint16 x, uint16 y) {
continue;
}
- if (it->type == 0 && animDataTable[frame].getColor(xdif, ydif) != (part & 0x0F)) {
+ if (it->type == 0 && g_cine->_animDataTable[frame].getColor(xdif, ydif) != (part & 0x0F)) {
return it->objIdx;
- } else if (it->type == 1 && gfxGetBit(xdif, ydif, animDataTable[frame].data(), animDataTable[frame]._width * 4)) {
+ } else if (it->type == 1 && gfxGetBit(xdif, ydif, g_cine->_animDataTable[frame].data(), g_cine->_animDataTable[frame]._width * 4)) {
return it->objIdx;
}
} else if (it->type == 0) { // use generated mask
- if (gfxGetBit(xdif, ydif, animDataTable[frame].mask(), animDataTable[frame]._width)) {
+ if (gfxGetBit(xdif, ydif, g_cine->_animDataTable[frame].mask(), g_cine->_animDataTable[frame]._width)) {
return it->objIdx;
}
} else if (it->type == 1) { // is mask
- if (gfxGetBit(xdif, ydif, animDataTable[frame].data(), animDataTable[frame]._width * 4)) {
+ if (gfxGetBit(xdif, ydif, g_cine->_animDataTable[frame].data(), g_cine->_animDataTable[frame]._width * 4)) {
return it->objIdx;
}
}
@@ -294,18 +290,18 @@ int16 getObjectUnderCursor(uint16 x, uint16 y) {
void CineEngine::resetEngine() {
g_sound->stopMusic();
freeAnimDataTable();
- overlayList.clear();
- bgIncrustList.clear();
+ g_cine->_overlayList.clear();
+ g_cine->_bgIncrustList.clear();
closePart();
- objectScripts.clear();
- globalScripts.clear();
- relTable.clear();
- scriptTable.clear();
- messageTable.clear();
+ g_cine->_objectScripts.clear();
+ g_cine->_globalScripts.clear();
+ g_cine->_relTable.clear();
+ g_cine->_scriptTable.clear();
+ g_cine->_messageTable.clear();
resetObjectTable();
- globalVars.reset();
+ g_cine->_globalVars.reset();
var2 = var3 = var4 = var5 = 0;
@@ -320,10 +316,10 @@ void CineEngine::resetEngine() {
playerCommand = -1;
isDrawCommandEnabled = 0;
- commandBuffer = "";
+ g_cine->_commandBuffer = "";
- globalVars[VAR_MOUSE_X_POS] = 0;
- globalVars[VAR_MOUSE_Y_POS] = 0;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = 0;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = 0;
fadeRequired = false;
@@ -332,7 +328,7 @@ void CineEngine::resetEngine() {
checkForPendingDataLoadSwitch = 0;
if (g_cine->getGameType() == Cine::GType_OS) {
- seqList.clear();
+ g_cine->_seqList.clear();
currentAdditionalBgIdx = 0;
currentAdditionalBgIdx2 = 0;
// TODO: Add resetting of the following variables
@@ -450,7 +446,7 @@ void CineEngine::makeSystemMenu() {
snprintf(tmp, 80, "%s.dir", _targetName.c_str());
- Common::OutSaveFile *fHandle = g_saveFileMan->openForSaving(tmp);
+ Common::OutSaveFile *fHandle = _saveFileMan->openForSaving(tmp);
if (!fHandle) {
warning("Unable to open file %s for saving", tmp);
break;
@@ -539,8 +535,8 @@ int16 buildObjectListCommand(int16 param) {
}
for (i = 0; i < 255; i++) {
- if (objectTable[i].name[0] && objectTable[i].costume == param) {
- strcpy(objectListCommand[j], objectTable[i].name);
+ if (g_cine->_objectTable[i].name[0] && g_cine->_objectTable[i].costume == param) {
+ strcpy(objectListCommand[j], g_cine->_objectTable[i].name);
objListTab[j] = i;
j++;
}
@@ -581,9 +577,9 @@ void makeCommandLine() {
commandVar2 = -10;
if (playerCommand != -1) {
- commandBuffer = defaultActionCommand[playerCommand];
+ g_cine->_commandBuffer = defaultActionCommand[playerCommand];
} else {
- commandBuffer = "";
+ g_cine->_commandBuffer = "";
}
if ((playerCommand != -1) && (choiceResultTable[playerCommand] == 2)) { // need object selection ?
@@ -602,7 +598,7 @@ void makeCommandLine() {
canUseOnObject = 0;
} else { // Future Wars
playerCommand = -1;
- commandBuffer = "";
+ g_cine->_commandBuffer = "";
}
} else {
if (g_cine->getGameType() == Cine::GType_OS) {
@@ -616,13 +612,13 @@ void makeCommandLine() {
commandVar3[0] = si;
commandVar1 = 1;
- commandBuffer += " ";
- commandBuffer += objectTable[commandVar3[0]].name;
- commandBuffer += " ";
+ g_cine->_commandBuffer += " ";
+ g_cine->_commandBuffer += g_cine->_objectTable[commandVar3[0]].name;
+ g_cine->_commandBuffer += " ";
if (g_cine->getGameType() == Cine::GType_OS) {
- commandBuffer += commandPrepositionTable[playerCommand];
+ g_cine->_commandBuffer += commandPrepositionTable[playerCommand];
} else { // Future Wars
- commandBuffer += defaultCommandPreposition;
+ g_cine->_commandBuffer += defaultCommandPreposition;
}
}
}
@@ -634,7 +630,7 @@ void makeCommandLine() {
processInventory(x, y + 8);
playerCommand = -1;
commandVar1 = 0;
- commandBuffer = "";
+ g_cine->_commandBuffer = "";
CursorMan.showMouse(true);
}
}
@@ -654,8 +650,8 @@ void makeCommandLine() {
commandVar3[commandVar1] = si;
commandVar1++;
- commandBuffer += " ";
- commandBuffer += objectTable[si].name;
+ g_cine->_commandBuffer += " ";
+ g_cine->_commandBuffer += g_cine->_objectTable[si].name;
}
}
@@ -673,13 +669,13 @@ void makeCommandLine() {
playerCommand = -1;
commandVar1 = 0;
- commandBuffer = "";
+ g_cine->_commandBuffer = "";
}
}
if (g_cine->getGameType() == Cine::GType_OS || !disableSystemMenu) {
isDrawCommandEnabled = 1;
- renderer->setCommand(commandBuffer);
+ renderer->setCommand(g_cine->_commandBuffer);
}
}
@@ -858,7 +854,7 @@ uint16 executePlayerInput() {
if (allowPlayerInput) { // Player input is allowed
if (isDrawCommandEnabled) {
- renderer->setCommand(commandBuffer);
+ renderer->setCommand(g_cine->_commandBuffer);
}
isDrawCommandEnabled = 0;
limitMouseCheckCount = true;
@@ -906,8 +902,8 @@ uint16 executePlayerInput() {
commandVar3[commandVar1] = si;
commandVar1++;
- commandBuffer += " ";
- commandBuffer += objectTable[si].name;
+ g_cine->_commandBuffer += " ";
+ g_cine->_commandBuffer += g_cine->_objectTable[si].name;
isDrawCommandEnabled = 1;
@@ -929,27 +925,27 @@ uint16 executePlayerInput() {
playerCommand = -1;
commandVar1 = 0;
- commandBuffer = "";
+ g_cine->_commandBuffer = "";
} else if (g_cine->getGameType() == Cine::GType_OS) {
isDrawCommandEnabled = 1;
- commandBuffer += commandPrepositionTable[playerCommand];
+ g_cine->_commandBuffer += commandPrepositionTable[playerCommand];
}
- renderer->setCommand(commandBuffer);
+ renderer->setCommand(g_cine->_commandBuffer);
} else {
- globalVars[VAR_MOUSE_X_POS] = mouseX;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = mouseX;
if (!mouseX) {
- globalVars[VAR_MOUSE_X_POS]++;
+ g_cine->_globalVars[VAR_MOUSE_X_POS]++;
}
- globalVars[VAR_MOUSE_Y_POS] = mouseY;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = mouseY;
if (g_cine->getGameType() == Cine::GType_OS) {
if (!mouseY) {
- globalVars[VAR_MOUSE_Y_POS]++;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS]++;
}
- globalVars[VAR_MOUSE_X_POS_2ND] = globalVars[VAR_MOUSE_X_POS];
- globalVars[VAR_MOUSE_Y_POS_2ND] = globalVars[VAR_MOUSE_Y_POS];
+ g_cine->_globalVars[VAR_MOUSE_X_POS_2ND] = g_cine->_globalVars[VAR_MOUSE_X_POS];
+ g_cine->_globalVars[VAR_MOUSE_Y_POS_2ND] = g_cine->_globalVars[VAR_MOUSE_Y_POS];
}
}
}
@@ -961,7 +957,7 @@ uint16 executePlayerInput() {
if (g_cine->getGameType() == Cine::GType_OS || commandVar2 != objIdx) {
if (objIdx != -1) {
- renderer->setCommand(commandBuffer + " " + objectTable[objIdx].name);
+ renderer->setCommand(g_cine->_commandBuffer + " " + g_cine->_objectTable[objIdx].name);
} else {
isDrawCommandEnabled = 1;
}
@@ -976,19 +972,19 @@ uint16 executePlayerInput() {
int16 objIdx;
int16 relEntry;
- globalVars[VAR_MOUSE_X_POS] = mouseX;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = mouseX;
if (!mouseX) {
- globalVars[VAR_MOUSE_X_POS]++;
+ g_cine->_globalVars[VAR_MOUSE_X_POS]++;
}
- globalVars[VAR_MOUSE_Y_POS] = mouseY;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = mouseY;
if (g_cine->getGameType() == Cine::GType_OS) {
if (!mouseY) {
- globalVars[VAR_MOUSE_Y_POS]++;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS]++;
}
- globalVars[VAR_MOUSE_X_POS_2ND] = globalVars[VAR_MOUSE_X_POS];
- globalVars[VAR_MOUSE_Y_POS_2ND] = globalVars[VAR_MOUSE_Y_POS];
+ g_cine->_globalVars[VAR_MOUSE_X_POS_2ND] = g_cine->_globalVars[VAR_MOUSE_X_POS];
+ g_cine->_globalVars[VAR_MOUSE_Y_POS_2ND] = g_cine->_globalVars[VAR_MOUSE_Y_POS];
}
objIdx = getObjectUnderCursor(mouseX, mouseY);
@@ -1020,97 +1016,97 @@ uint16 executePlayerInput() {
// Handle possible horizontal movement by keyboard
if (xMoveKeyb != kKeybMoveCenterX && allowPlayerInput) {
if (xMoveKeyb == kKeybMoveRight) { // moving right
- const int16 playerFrame = objectTable[1].frame;
- const int16 playerX = objectTable[1].x;
+ const int16 playerFrame = g_cine->_objectTable[1].frame;
+ const int16 playerX = g_cine->_objectTable[1].x;
// TODO: Check if multiplying _width by two here is correct or not
- const int16 newX = animDataTable[playerFrame]._width * 2 + playerX + 8;
- globalVars[VAR_MOUSE_X_POS] = globalVars[VAR_MOUSE_X_POS_2ND] = newX;
+ const int16 newX = g_cine->_animDataTable[playerFrame]._width * 2 + playerX + 8;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = g_cine->_globalVars[VAR_MOUSE_X_POS_2ND] = newX;
} else { // moving left
- const int16 playerX = objectTable[1].x;
+ const int16 playerX = g_cine->_objectTable[1].x;
const int16 newX = playerX - 8;
- globalVars[VAR_MOUSE_X_POS] = globalVars[VAR_MOUSE_X_POS_2ND] = newX;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = g_cine->_globalVars[VAR_MOUSE_X_POS_2ND] = newX;
}
// Restrain horizontal position to range 0-319
- if (globalVars[VAR_MOUSE_X_POS] < 0) {
- globalVars[VAR_MOUSE_X_POS] = globalVars[VAR_MOUSE_X_POS_2ND] = 0;
- } else if (globalVars[VAR_MOUSE_X_POS] > 319) {
- globalVars[VAR_MOUSE_X_POS] = globalVars[VAR_MOUSE_X_POS_2ND] = 319;
+ if (g_cine->_globalVars[VAR_MOUSE_X_POS] < 0) {
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = g_cine->_globalVars[VAR_MOUSE_X_POS_2ND] = 0;
+ } else if (g_cine->_globalVars[VAR_MOUSE_X_POS] > 319) {
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = g_cine->_globalVars[VAR_MOUSE_X_POS_2ND] = 319;
}
}
// Handle possible vertical movement by keyboard
if (yMoveKeyb != kKeybMoveCenterY && allowPlayerInput) {
if (yMoveKeyb == kKeybMoveDown) { // moving down
- const int16 playerFrame = objectTable[1].frame;
- const int16 playerY = objectTable[1].y;
+ const int16 playerFrame = g_cine->_objectTable[1].frame;
+ const int16 playerY = g_cine->_objectTable[1].y;
// TODO: Check if multiplying _height by two here is correct or not
- const int16 newY = animDataTable[playerFrame]._height * 2 + playerY - 1;
- globalVars[VAR_MOUSE_Y_POS] = globalVars[VAR_MOUSE_Y_POS_2ND] = newY;
+ const int16 newY = g_cine->_animDataTable[playerFrame]._height * 2 + playerY - 1;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = g_cine->_globalVars[VAR_MOUSE_Y_POS_2ND] = newY;
} else { // moving up
- const int16 playerY = objectTable[1].y;
+ const int16 playerY = g_cine->_objectTable[1].y;
const int16 newY = playerY - 8;
- globalVars[VAR_MOUSE_Y_POS] = globalVars[VAR_MOUSE_Y_POS_2ND] = newY;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = g_cine->_globalVars[VAR_MOUSE_Y_POS_2ND] = newY;
}
// Restrain vertical position to range 0-199
- if (globalVars[VAR_MOUSE_Y_POS] < 0) {
- globalVars[VAR_MOUSE_Y_POS] = globalVars[VAR_MOUSE_Y_POS_2ND] = 0;
- } else if (globalVars[VAR_MOUSE_Y_POS] > 199) {
- globalVars[VAR_MOUSE_Y_POS] = globalVars[VAR_MOUSE_Y_POS_2ND] = 199;
+ if (g_cine->_globalVars[VAR_MOUSE_Y_POS] < 0) {
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = g_cine->_globalVars[VAR_MOUSE_Y_POS_2ND] = 0;
+ } else if (g_cine->_globalVars[VAR_MOUSE_Y_POS] > 199) {
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = g_cine->_globalVars[VAR_MOUSE_Y_POS_2ND] = 199;
}
}
} else if (egoMovedWithKeyboard && allowPlayerInput) { // FW: Move using keyboard
egoMovedWithKeyboard = false;
- switch (globalVars[VAR_MOUSE_X_MODE]) {
+ switch (g_cine->_globalVars[VAR_MOUSE_X_MODE]) {
case 1:
- mouseX = objectTable[1].x + 12;
+ mouseX = g_cine->_objectTable[1].x + 12;
break;
case 2:
- mouseX = objectTable[1].x + 7;
+ mouseX = g_cine->_objectTable[1].x + 7;
break;
default:
- mouseX = globalVars[VAR_MOUSE_X_POS];
+ mouseX = g_cine->_globalVars[VAR_MOUSE_X_POS];
break;
}
- switch (globalVars[VAR_MOUSE_Y_MODE]) {
+ switch (g_cine->_globalVars[VAR_MOUSE_Y_MODE]) {
case 1:
- mouseY = objectTable[1].y + 34;
+ mouseY = g_cine->_objectTable[1].y + 34;
break;
case 2:
- mouseY = objectTable[1].y + 28;
+ mouseY = g_cine->_objectTable[1].y + 28;
break;
default:
- mouseY = globalVars[VAR_MOUSE_Y_POS];
+ mouseY = g_cine->_globalVars[VAR_MOUSE_Y_POS];
break;
}
if (var_5E == bgVar0) {
var_5E = 0;
- globalVars[VAR_MOUSE_X_POS] = mouseX;
- globalVars[VAR_MOUSE_Y_POS] = mouseY;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = mouseX;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = mouseY;
} else {
if (xMoveKeyb) {
if (xMoveKeyb == kKeybMoveLeft) {
- globalVars[VAR_MOUSE_X_POS] = 1;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = 1;
} else {
- globalVars[VAR_MOUSE_X_POS] = 320;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = 320;
}
} else {
- globalVars[VAR_MOUSE_X_POS] = mouseX;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = mouseX;
}
if (yMoveKeyb) {
if (yMoveKeyb == kKeybMoveUp) {
- globalVars[VAR_MOUSE_Y_POS] = 1;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = 1;
} else {
- globalVars[VAR_MOUSE_Y_POS] = 200;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = 200;
}
} else {
- globalVars[VAR_MOUSE_Y_POS] = mouseY;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = mouseY;
}
}
@@ -1167,27 +1163,27 @@ void drawSprite(Common::List<overlay>::iterator it, const byte *spritePtr, const
msk = (byte *)malloc(width * height);
if (g_cine->getGameType() == Cine::GType_OS) {
- generateMask(spritePtr, msk, width * height, objectTable[it->objIdx].part);
+ generateMask(spritePtr, msk, width * height, g_cine->_objectTable[it->objIdx].part);
} else {
memcpy(msk, maskPtr, width * height);
}
- for (++it; it != overlayList.end(); ++it) {
+ for (++it; it != g_cine->_overlayList.end(); ++it) {
if (it->type != 5) {
continue;
}
- maskX = objectTable[it->objIdx].x;
- maskY = objectTable[it->objIdx].y;
+ maskX = g_cine->_objectTable[it->objIdx].x;
+ maskY = g_cine->_objectTable[it->objIdx].y;
- maskSpriteIdx = ABS((int16)(objectTable[it->objIdx].frame));
+ maskSpriteIdx = ABS((int16)(g_cine->_objectTable[it->objIdx].frame));
- maskWidth = animDataTable[maskSpriteIdx]._realWidth;
- maskHeight = animDataTable[maskSpriteIdx]._height;
- gfxUpdateSpriteMask(msk, x, y, width, height, animDataTable[maskSpriteIdx].data(), maskX, maskY, maskWidth, maskHeight);
+ maskWidth = g_cine->_animDataTable[maskSpriteIdx]._realWidth;
+ maskHeight = g_cine->_animDataTable[maskSpriteIdx]._height;
+ gfxUpdateSpriteMask(msk, x, y, width, height, g_cine->_animDataTable[maskSpriteIdx].data(), maskX, maskY, maskWidth, maskHeight);
#ifdef DEBUG_SPRITE_MASK
- gfxFillSprite(animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, page, maskX, maskY, 1);
+ gfxFillSprite(g_cine->_animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, page, maskX, maskY, 1);
#endif
}
@@ -1199,7 +1195,7 @@ void removeMessages() {
Common::List<overlay>::iterator it;
bool remove;
- for (it = overlayList.begin(); it != overlayList.end(); ) {
+ for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ) {
if (g_cine->getGameType() == Cine::GType_OS) {
// NOTE: These are really removeOverlay calls that have been deferred.
// In Operation Stealth's disassembly elements are removed from the
@@ -1213,7 +1209,7 @@ void removeMessages() {
}
if (remove) {
- it = overlayList.erase(it);
+ it = g_cine->_overlayList.erase(it);
} else {
++it;
}
@@ -1255,7 +1251,7 @@ void checkForPendingDataLoad() {
}
if (newObjectName[0] != 0) {
- overlayList.clear();
+ g_cine->_overlayList.clear();
loadObject(newObjectName);
@@ -1294,15 +1290,13 @@ void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 par
tmp.width = param4;
tmp.color = param5;
- overlayList.push_back(tmp);
+ g_cine->_overlayList.push_back(tmp);
}
-Common::List<SeqListElement> seqList;
-
void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
Common::List<SeqListElement>::iterator it;
- for (it = seqList.begin(); it != seqList.end(); ++it) {
+ for (it = g_cine->_seqList.begin(); it != g_cine->_seqList.end(); ++it) {
if (it->objIdx == param1 && it->var4 == param2 && it->varE == param3) {
it->var4 = -1;
break;
@@ -1313,7 +1307,7 @@ void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
bool isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
Common::List<SeqListElement>::iterator it;
- for (it = seqList.begin(); it != seqList.end(); ++it) {
+ for (it = g_cine->_seqList.begin(); it != g_cine->_seqList.end(); ++it) {
if (it->objIdx == param1 && it->var4 == param2 && it->varE == param3) {
// Just to be on the safe side there's a restriction of the
// addition's result to 16-bit arithmetic here like in the
@@ -1329,7 +1323,7 @@ void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, i
Common::List<SeqListElement>::iterator it;
SeqListElement tmp;
- for (it = seqList.begin(); it != seqList.end() && it->varE < param7; ++it) ;
+ for (it = g_cine->_seqList.begin(); it != g_cine->_seqList.end() && it->varE < param7; ++it) ;
tmp.objIdx = objIdx;
tmp.var4 = param1;
@@ -1346,12 +1340,12 @@ void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, i
tmp.var1C = 0;
tmp.var1E = 0;
- seqList.insert(it, tmp);
+ g_cine->_seqList.insert(it, tmp);
}
void modifySeqListElement(uint16 objIdx, int16 var4Test, int16 param1, int16 param2, int16 param3, int16 param4) {
// Find a suitable list element and modify it
- for (Common::List<SeqListElement>::iterator it = seqList.begin(); it != seqList.end(); ++it) {
+ for (Common::List<SeqListElement>::iterator it = g_cine->_seqList.begin(); it != g_cine->_seqList.end(); ++it) {
if (it->objIdx == objIdx && it->var4 == var4Test) {
it->varC = param1;
it->var18 = param2;
@@ -1425,7 +1419,7 @@ uint16 addAni(uint16 param1, uint16 objIdx, const int8 *ptr, SeqListElement &ele
// In the original an error string is set and 0 is returned if the following doesn't hold
assert(*ptrData);
- di = (objectTable[objIdx].costume + 1) % (*ptrData);
+ di = (g_cine->_objectTable[objIdx].costume + 1) % (*ptrData);
++ptrData; // Jump over the just read byte
// Here ptr2 seems to be indexing a table of structs (8 bytes per struct):
// struct {
@@ -1446,18 +1440,18 @@ uint16 addAni(uint16 param1, uint16 objIdx, const int8 *ptr, SeqListElement &ele
return 0;
}
- objectTable[objIdx].x += ptr2[4];
- objectTable[objIdx].y += ptr2[5];
- objectTable[objIdx].mask += ptr2[6];
+ g_cine->_objectTable[objIdx].x += ptr2[4];
+ g_cine->_objectTable[objIdx].y += ptr2[5];
+ g_cine->_objectTable[objIdx].mask += ptr2[6];
if (ptr2[6]) {
resetGfxEntityEntry(objIdx);
}
- objectTable[objIdx].frame = ptr2[7] + element.var8;
+ g_cine->_objectTable[objIdx].frame = ptr2[7] + element.var8;
if (param3 || !element.var14) {
- objectTable[objIdx].costume = di;
+ g_cine->_objectTable[objIdx].costume = di;
} else {
assert(param4);
*param4 = di;
@@ -1476,7 +1470,7 @@ void resetGfxEntityEntry(uint16 objIdx) {
bool foundCutPoint = false;
// Go through the overlay list and partition the whole list into two categories (Type A and type B objects)
- for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
if (it->objIdx == objIdx && it->type != 2 && it->type != 3) { // Type A object
aReverseObjs.push_front(*it);
} else { // Type B object
@@ -1485,10 +1479,10 @@ void resetGfxEntityEntry(uint16 objIdx) {
if (it->type == 2 || it->type == 3) {
objectMask = 10000;
} else {
- objectMask = objectTable[it->objIdx].mask;
+ objectMask = g_cine->_objectTable[it->objIdx].mask;
}
- if (objectTable[objIdx].mask > objectMask) { // Check for B objects' cut point
+ if (g_cine->_objectTable[objIdx].mask > objectMask) { // Check for B objects' cut point
bObjsCutPoint = bObjs.reverse_begin();
foundCutPoint = true;
}
@@ -1496,26 +1490,26 @@ void resetGfxEntityEntry(uint16 objIdx) {
}
// Recreate the overlay list in a different order.
- overlayList.clear();
+ g_cine->_overlayList.clear();
if (foundCutPoint) {
// If a cut point was found the order is:
// B objects before the cut point, the cut point, A objects in reverse order, B objects after cut point.
++bObjsCutPoint; // Include the cut point in the first list insertion
- overlayList.insert(overlayList.end(), bObjs.begin(), bObjsCutPoint);
- overlayList.insert(overlayList.end(), aReverseObjs.begin(), aReverseObjs.end());
- overlayList.insert(overlayList.end(), bObjsCutPoint, bObjs.end());
+ g_cine->_overlayList.insert(g_cine->_overlayList.end(), bObjs.begin(), bObjsCutPoint);
+ g_cine->_overlayList.insert(g_cine->_overlayList.end(), aReverseObjs.begin(), aReverseObjs.end());
+ g_cine->_overlayList.insert(g_cine->_overlayList.end(), bObjsCutPoint, bObjs.end());
} else {
// If no cut point was found the order is:
// A objects in reverse order, B objects.
- overlayList.insert(overlayList.end(), aReverseObjs.begin(), aReverseObjs.end());
- overlayList.insert(overlayList.end(), bObjs.begin(), bObjs.end());
+ g_cine->_overlayList.insert(g_cine->_overlayList.end(), aReverseObjs.begin(), aReverseObjs.end());
+ g_cine->_overlayList.insert(g_cine->_overlayList.end(), bObjs.begin(), bObjs.end());
}
}
void processSeqListElement(SeqListElement &element) {
- int16 x = objectTable[element.objIdx].x;
- int16 y = objectTable[element.objIdx].y;
- const int8 *ptr1 = (const int8 *) animDataTable[element.frame].data();
+ int16 x = g_cine->_objectTable[element.objIdx].x;
+ int16 y = g_cine->_objectTable[element.objIdx].y;
+ const int8 *ptr1 = (const int8 *) g_cine->_animDataTable[element.frame].data();
int16 var_10;
int16 var_4;
int16 var_2;
@@ -1548,8 +1542,8 @@ void processSeqListElement(SeqListElement &element) {
int16 x2 = element.var18;
int16 y2 = element.var1A;
if (element.varC) {
- x2 += objectTable[element.varC].x;
- y2 += objectTable[element.varC].y;
+ x2 += g_cine->_objectTable[element.varC].x;
+ y2 += g_cine->_objectTable[element.varC].y;
}
computeMove1(element, ptr1[4] + x, ptr1[5] + y, param1, param2, x2, y2);
} else {
@@ -1558,7 +1552,7 @@ void processSeqListElement(SeqListElement &element) {
if (xMoveKeyb != kKeybMoveRight) {
adder = -adder;
}
- globalVars[VAR_MOUSE_X_POS] = globalVars[VAR_MOUSE_X_POS_2ND] = ptr1[4] + x + adder;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = g_cine->_globalVars[VAR_MOUSE_X_POS_2ND] = ptr1[4] + x + adder;
}
if (yMoveKeyb && allowPlayerInput) {
@@ -1566,11 +1560,11 @@ void processSeqListElement(SeqListElement &element) {
if (yMoveKeyb != kKeybMoveDown) {
adder = -adder;
}
- globalVars[VAR_MOUSE_Y_POS] = globalVars[VAR_MOUSE_Y_POS_2ND] = ptr1[5] + y + adder;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = g_cine->_globalVars[VAR_MOUSE_Y_POS_2ND] = ptr1[5] + y + adder;
}
- if (globalVars[VAR_MOUSE_X_POS] || globalVars[VAR_MOUSE_Y_POS]) {
- computeMove1(element, ptr1[4] + x, ptr1[5] + y, param1, param2, globalVars[VAR_MOUSE_X_POS], globalVars[VAR_MOUSE_Y_POS]);
+ if (g_cine->_globalVars[VAR_MOUSE_X_POS] || g_cine->_globalVars[VAR_MOUSE_Y_POS]) {
+ computeMove1(element, ptr1[4] + x, ptr1[5] + y, param1, param2, g_cine->_globalVars[VAR_MOUSE_X_POS], g_cine->_globalVars[VAR_MOUSE_Y_POS]);
} else {
element.var16 = 0;
element.var14 = 0;
@@ -1590,27 +1584,27 @@ void processSeqListElement(SeqListElement &element) {
&& !addAni(3, element.objIdx, ptr1, element, 0, &var_4)) || (element.var16 == 2 && !addAni(2, element.objIdx, ptr1, element, 0,
&var_4))) {
if (element.varC == 255) {
- globalVars[VAR_MOUSE_Y_POS] = 0;
+ g_cine->_globalVars[VAR_MOUSE_Y_POS] = 0;
}
}
if ((element.var14 == 1
&& !addAni(0, element.objIdx, ptr1, element, 1, &var_2))) {
if (element.varC == 255) {
- globalVars[VAR_MOUSE_X_POS] = 0;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = 0;
if (var_4 != -1) {
- objectTable[element.objIdx].costume = var_4;
+ g_cine->_objectTable[element.objIdx].costume = var_4;
}
}
}
if ((element.var14 == 2 && !addAni(1, element.objIdx, ptr1, element, 1, &var_2))) {
if (element.varC == 255) {
- globalVars[VAR_MOUSE_X_POS] = 0;
+ g_cine->_globalVars[VAR_MOUSE_X_POS] = 0;
if (var_4 != -1) {
- objectTable[element.objIdx].costume = var_4;
+ g_cine->_objectTable[element.objIdx].costume = var_4;
}
}
}
@@ -1618,7 +1612,7 @@ void processSeqListElement(SeqListElement &element) {
if (element.var16 + element.var14 == 0) {
if (element.var1C) {
if (element.var1E) {
- objectTable[element.objIdx].costume = 0;
+ g_cine->_objectTable[element.objIdx].costume = 0;
element.var1E = 0;
}
@@ -1633,7 +1627,7 @@ void processSeqListElement(SeqListElement &element) {
void processSeqList() {
Common::List<SeqListElement>::iterator it;
- for (it = seqList.begin(); it != seqList.end(); ++it) {
+ for (it = g_cine->_seqList.begin(); it != g_cine->_seqList.end(); ++it) {
if (it->var4 == -1) {
continue;
}
diff --git a/engines/cine/various.h b/engines/cine/various.h
index 3f362b1ad6..3a14328035 100644
--- a/engines/cine/various.h
+++ b/engines/cine/various.h
@@ -66,8 +66,6 @@ struct SeqListElement {
int16 var1E;
};
-extern Common::List<SeqListElement> seqList;
-
extern uint16 var2;
extern uint16 var3;
extern uint16 var4;
@@ -95,8 +93,6 @@ extern uint16 _messageLen;
extern int16 playerCommand;
-extern Common::String commandBuffer;
-
extern char currentPrcName[20];
extern char currentRelName[20];
extern char currentObjectName[20];
@@ -137,8 +133,6 @@ struct SelectedObjStruct {
};
#define NUM_MAX_ZONE 16
-extern Common::Array<uint16> zoneData;
-extern Common::Array<uint16> zoneQuery;
void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 param5);
diff --git a/engines/cruise/actor.cpp b/engines/cruise/actor.cpp
index 87b7f0a27f..9cbc3dd9ae 100644
--- a/engines/cruise/actor.cpp
+++ b/engines/cruise/actor.cpp
@@ -74,8 +74,8 @@ int flag_aff_chemin;
void getPixel(int x, int y) {
- for (uint i = 0; i < polyStructs->size(); ++i) {
- CtStruct &ct = (*polyStructs)[i];
+ for (uint i = 0; i < _vm->_polyStructs->size(); ++i) {
+ CtStruct &ct = (*_vm->_polyStructs)[i];
numPoly = ct.num;
if (walkboxState[numPoly] == 0 && ct.bounds.contains(x, y)) {
@@ -293,7 +293,7 @@ int point_proche(int16 table[][2]) {
int x1, y1, i, x, y, p;
int d1 = 1000;
- polyStructs = &CVars.polyStructNorm;
+ _vm->_polyStructs = &_vm->_polyStructNorm;
if (nclick_noeud == 1) {
x = x_mouse;
@@ -301,19 +301,19 @@ int point_proche(int16 table[][2]) {
x1 = table_ptselect[0][0];
y1 = table_ptselect[0][1];
- polyStructs = &CVars.polyStructExp;
+ _vm->_polyStructs = &_vm->_polyStructExp;
getPixel(x, y);
if (!flag_obstacle) {
- polyStructs = &CVars.polyStructNorm;
+ _vm->_polyStructs = &_vm->_polyStructNorm;
getPixel(x, y);
if (flag_obstacle) {
polydroite(x1, y1, x, y);
}
- polyStructs = &CVars.polyStructExp;
+ _vm->_polyStructs = &_vm->_polyStructExp;
}
if (!flag_obstacle) { /* dans flag_obstacle --> couleur du point */
x1 = table_ptselect[0][0];
@@ -325,7 +325,7 @@ int point_proche(int16 table[][2]) {
y_mouse = Y;
}
}
- polyStructs = &CVars.polyStructNorm;
+ _vm->_polyStructs = &_vm->_polyStructNorm;
p = -1;
for (i = 0; i < ctp_routeCoordCount; i++) {
@@ -453,7 +453,7 @@ void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2
table_ptselect[*nclick][0] = x_mouse;
table_ptselect[*nclick][1] = y_mouse;
(*nclick)++;
- polyStructs = &CVars.polyStructNorm;
+ _vm->_polyStructs = &_vm->_polyStructNorm;
if (*nclick == 2) { // second point
x1 = table_ptselect[0][0];
@@ -464,7 +464,7 @@ void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2
return;
}
flag_aff_chemin = 1;
- polyStructs = &CVars.polyStructExp;
+ _vm->_polyStructs = &_vm->_polyStructExp;
// can we go there directly ?
polydroite(x1, y1, x2, y2);
@@ -472,7 +472,7 @@ void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2
if (!flag_obstacle) {
solution0[0][0] = x1;
solution0[0][1] = y1;
- polyStructs = &CVars.polyStructExp;
+ _vm->_polyStructs = &_vm->_polyStructExp;
poly2(x2, y2, ctp_routeCoords[select_noeud[1]][0],
ctp_routeCoords[select_noeud[1]][1]);
@@ -516,7 +516,7 @@ void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2
solution0[++i][1] =
ctp_routeCoords[p1][1];
}
- polyStructs = &CVars.polyStructExp;
+ _vm->_polyStructs = &_vm->_polyStructExp;
poly2(x2, y2,
ctp_routeCoords[select_noeud[1]][0],
ctp_routeCoords[select_noeud[1]][1]);
@@ -541,7 +541,7 @@ void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2
while (flag_obstacle && i != d) {
x2 = solution0[i][0];
y2 = solution0[i][1];
- polyStructs = &CVars.polyStructExp;
+ _vm->_polyStructs = &_vm->_polyStructExp;
polydroite(x1, y1, x2, y2);
i--;
}
@@ -569,7 +569,7 @@ int16 computePathfinding(MovementEntry &moveInfo, int16 x, int16 y, int16 destX,
persoStruct *perso;
int num;
- if (!polyStruct) {
+ if (!_vm->_polyStruct) {
moveInfo.x = -1;
moveInfo.y = -1;
@@ -621,7 +621,7 @@ int16 computePathfinding(MovementEntry &moveInfo, int16 x, int16 y, int16 destX,
}
nclick_noeud = 0;
- polyStructs = &CVars.polyStructNorm;
+ _vm->_polyStructs = &_vm->_polyStructNorm;
flag_aff_chemin = 0;
if (x == destX && y == destY) {
diff --git a/engines/cruise/background.cpp b/engines/cruise/background.cpp
index da6a35aff0..3ac57cc376 100644
--- a/engines/cruise/background.cpp
+++ b/engines/cruise/background.cpp
@@ -47,10 +47,10 @@ int loadMEN(uint8 **ptr) {
if (!strcmp(localPtr, "MEN")) {
localPtr += 4;
- CVars.titleColor = *(localPtr++);
- CVars.selectColor = *(localPtr++);
- CVars.itemColor = *(localPtr++);
- CVars.subColor = *(localPtr++);
+ titleColor = *(localPtr++);
+ selectColor = *(localPtr++);
+ itemColor = *(localPtr++);
+ subColor = *(localPtr++);
*ptr = (uint8 *) localPtr;
@@ -104,9 +104,9 @@ int loadBackground(const char *name, int idx) {
backgroundChanged[idx] = true;
- ptrToFree = CVars.pPage10;
+ ptrToFree = gfxModuleData.pPage10;
if (loadFileSub1(&ptrToFree, name, NULL) < 0) {
- if (ptrToFree != CVars.pPage10)
+ if (ptrToFree != gfxModuleData.pPage10)
MemFree(ptrToFree);
return (-18);
diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp
index 964f22af3d..3af77f3ef3 100644
--- a/engines/cruise/cruise.cpp
+++ b/engines/cruise/cruise.cpp
@@ -52,10 +52,6 @@ CruiseEngine *_vm;
CruiseEngine::CruiseEngine(OSystem * syst, const CRUISEGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
-#ifdef PALMOS_MODE
- _currentVolumeFile = new Common::File();
-#endif
-
DebugMan.addDebugChannel(kCruiseDebugScript, "scripts", "Scripts debug level");
DebugMan.addDebugChannel(kCruiseDebugSound, "sound", "Sound debug level");
@@ -137,8 +133,8 @@ void CruiseEngine::initialize() {
}
void CruiseEngine::deinitialise() {
- CVars.polyStructNorm.clear();
- CVars.polyStructExp.clear();
+ _vm->_polyStructNorm.clear();
+ _vm->_polyStructExp.clear();
// Clear any backgrounds
for (int i = 0; i < 8; ++i) {
@@ -205,7 +201,7 @@ void CruiseEngine::pauseEngine(bool pause) {
if (pause) {
// Draw the 'Paused' message
drawSolidBox(64, 100, 256, 117, 0);
- drawString(10, 100, langString(ID_PAUSED), CVars.pPage00, CVars.itemColor, 300);
+ drawString(10, 100, langString(ID_PAUSED), gfxModuleData.pPage00, itemColor, 300);
gfxModuleData_flipScreen();
_savedCursor = currentCursor;
diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h
index 0428240167..94f5c68ca0 100644
--- a/engines/cruise/cruise.h
+++ b/engines/cruise/cruise.h
@@ -40,10 +40,10 @@
/**
* This is the namespace of the Cruise engine.
*
- * Status of this engine: ???
+ * Status of this engine: Game is completable, engine needs objectifying
*
* Supported games:
- * - ???
+ * - Cruise for a Corpse
*/
namespace Cruise {
@@ -112,6 +112,22 @@ public:
void initAllData();
Common::RandomSource _rnd;
+
+ Common::List<byte *> _memList;
+
+ typedef Common::List<Common::Rect> RectList;
+
+ RectList _dirtyRects;
+ RectList _priorFrameRects;
+
+ Common::File _currentVolumeFile;
+
+ Common::Array<CtStruct> _polyStructNorm;
+ Common::Array<CtStruct> _polyStructExp;
+ Common::Array<CtStruct> *_polyStructs;
+ Common::Array<CtStruct> *_polyStruct;
+
+ Common::File _PAL_file;
};
extern CruiseEngine *_vm;
diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp
index ceab9bf706..aa78f84e3d 100644
--- a/engines/cruise/cruise_main.cpp
+++ b/engines/cruise/cruise_main.cpp
@@ -38,15 +38,15 @@ namespace Cruise {
enum RelationType {RT_REL = 30, RT_MSG = 50};
static int playerDontAskQuit;
-#if !defined(__DS__)
-//unsigned int timer = 0;
-#endif
+unsigned int timer = 0;
+
+gfxEntryStruct* linkedMsgList = NULL;
void MemoryList() {
- if (!CVars.memList.empty()) {
+ if (!_vm->_memList.empty()) {
printf("Current list of un-freed memory blocks:\n");
Common::List<byte *>::iterator i;
- for (i = CVars.memList.begin(); i != CVars.memList.end(); ++i) {
+ for (i = _vm->_memList.begin(); i != _vm->_memList.end(); ++i) {
byte *v = *i;
printf("%s - %d\n", (const char *)(v - 68), *((int32 *)(v - 72)));
}
@@ -71,7 +71,7 @@ void *MemoryAlloc(uint32 size, bool clearFlag, int32 lineNum, const char *fname)
// Add the block to the memory list
result = v + 64 + 8;
- CVars.memList.push_back(result);
+ _vm->_memList.push_back(result);
} else
result = (byte *)malloc(size);
@@ -89,7 +89,7 @@ void MemoryFree(void *v) {
byte *p = (byte *)v;
assert(*((uint32 *) (p - 4)) == 0x41424344);
- CVars.memList.remove(p);
+ _vm->_memList.remove(p);
free(p - 8 - 64);
} else
free(v);
@@ -103,8 +103,8 @@ void drawBlackSolidBoxSmall() {
void loadPackedFileToMem(int fileIdx, uint8 *buffer) {
changeCursor(CURSOR_DISK);
- currentVolumeFile.seek(volumePtrToFileDescriptor[fileIdx].offset, SEEK_SET);
- currentVolumeFile.read(buffer, volumePtrToFileDescriptor[fileIdx].size);
+ _vm->_currentVolumeFile.seek(volumePtrToFileDescriptor[fileIdx].offset, SEEK_SET);
+ _vm->_currentVolumeFile.read(buffer, volumePtrToFileDescriptor[fileIdx].size);
}
int getNumObjectsByClass(int scriptIdx, int param) {
@@ -951,7 +951,7 @@ bool createDialog(int objOvl, int objIdx, int x, int y) {
int color;
if (objectState2 == -2)
- color = CVars.subColor;
+ color = subColor;
else
color = -1;
@@ -1388,12 +1388,12 @@ void closeAllMenu() {
freeMenu(menuTable[1]);
menuTable[1] = NULL;
}
- if (CVars.linkedMsgList) {
+ if (linkedMsgList) {
ASSERT(0);
-// freeMsgList(CVars.linkedMsgList);
+// freeMsgList(linkedMsgList);
}
- CVars.linkedMsgList = NULL;
+ linkedMsgList = NULL;
linkedRelation = NULL;
}
@@ -1543,12 +1543,12 @@ int CruiseEngine::processInput() {
freeMenu(menuTable[0]);
menuTable[0] = NULL;
- if (CVars.linkedMsgList) {
+ if (linkedMsgList) {
ASSERT(0);
- // freeMsgList(CVars.linkedMsgList);
+ // freeMsgList(linkedMsgList);
}
- CVars.linkedMsgList = NULL;
+ linkedMsgList = NULL;
linkedRelation = NULL;
changeCursor(CURSOR_NORMAL);
@@ -1580,10 +1580,10 @@ int CruiseEngine::processInput() {
menuTable[0] = NULL;
}
- if (CVars.linkedMsgList) {
-// freeMsgList(CVars.linkedMsgList);
+ if (linkedMsgList) {
+// freeMsgList(linkedMsgList);
}
- CVars.linkedMsgList = NULL;
+ linkedMsgList = NULL;
linkedRelation = NULL;
changeCursor(CURSOR_NORMAL);
} else { // call sub relation when clicking in inventory
@@ -1653,7 +1653,7 @@ int CruiseEngine::processInput() {
strcpy(text, menuTable[0]->stringPtr);
strcat(text, ":");
strcat(text, currentMenuElement->string);
- CVars.linkedMsgList = renderText(320, (const char *)text);
+ linkedMsgList = renderText(320, (const char *)text);
changeCursor(CURSOR_CROSS);
}
}
@@ -1831,19 +1831,17 @@ void CruiseEngine::mainLoop() {
if (!skipEvents)
skipEvents = manageEvents();
- if (playerDontAskQuit) break;
+ if (playerDontAskQuit)
+ break;
- if (_vm->getDebugger()->isAttached())
- _vm->getDebugger()->onFrame();
+ _vm->getDebugger()->onFrame();
} while (currentTick < lastTick + _gameSpeed);
} else {
manageEvents();
if (currentTick >= (lastTickDebug + 10)) {
lastTickDebug = currentTick;
-
- if (_vm->getDebugger()->isAttached())
- _vm->getDebugger()->onFrame();
+ _vm->getDebugger()->onFrame();
}
}
if (playerDontAskQuit)
diff --git a/engines/cruise/cruise_main.h b/engines/cruise/cruise_main.h
index 406ebfaa2b..8657b4bc21 100644
--- a/engines/cruise/cruise_main.h
+++ b/engines/cruise/cruise_main.h
@@ -81,7 +81,7 @@ enum ResType {
OBJ_TYPE_EXIT = 9
};
-//extern gfxEntryStruct* linkedMsgList;
+extern gfxEntryStruct* linkedMsgList;
extern int buttonDown;
extern int selectDown;
diff --git a/engines/cruise/ctp.cpp b/engines/cruise/ctp.cpp
index 1ee29917d1..4f6c21e0e4 100644
--- a/engines/cruise/ctp.cpp
+++ b/engines/cruise/ctp.cpp
@@ -23,14 +23,14 @@
*
*/
+#include "cruise/cruise.h"
#include "cruise/cruise_main.h"
#include "common/endian.h"
#include "common/util.h"
namespace Cruise {
-Common::Array<CtStruct> *polyStructs = NULL;
-Common::Array<CtStruct> *polyStruct = NULL;
+uint8 *ctpVar17;
int currentWalkBoxCenterX;
int currentWalkBoxCenterY;
@@ -320,16 +320,16 @@ int initCt(const char *ctpName) {
// Load the polyStructNorm list
for (int i = numberOfWalkboxes - 1; i >= 0; i--) {
- makeCtStruct(CVars.polyStructNorm, ctp_walkboxTable, i, 0);
+ makeCtStruct(_vm->_polyStructNorm, ctp_walkboxTable, i, 0);
}
// Load the polyStructExp list
for (int i = numberOfWalkboxes - 1; i >= 0; i--) {
- makeCtStruct(CVars.polyStructExp, ctp_walkboxTable, i, walkboxZoom[i] * 20);
+ makeCtStruct(_vm->_polyStructExp, ctp_walkboxTable, i, walkboxZoom[i] * 20);
}
- polyStruct = polyStructs = &CVars.polyStructNorm;
+ _vm->_polyStruct = _vm->_polyStructs = &_vm->_polyStructNorm;
return (1);
}
diff --git a/engines/cruise/ctp.h b/engines/cruise/ctp.h
index f6968e184a..3c6c9582cc 100644
--- a/engines/cruise/ctp.h
+++ b/engines/cruise/ctp.h
@@ -62,8 +62,7 @@ public:
Common::Array<CtEntry> slices;
};
-extern Common::Array<CtStruct> *polyStructs;
-extern Common::Array<CtStruct> *polyStruct;
+extern uint8 *ctpVar17;
int initCt(const char * ctpName);
int computeDistance(int varX, int varY, int paramX, int paramY);
diff --git a/engines/cruise/decompiler.cpp b/engines/cruise/decompiler.cpp
index ba4ade56a7..31d9dcef9b 100644
--- a/engines/cruise/decompiler.cpp
+++ b/engines/cruise/decompiler.cpp
@@ -760,8 +760,6 @@ int decompFunction() {
char *var1;
char *objIdxStr;
char *ovlStr;
- char varName[256];
- int i;
var1 = popDecomp();
objIdxStr = popDecomp();
diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp
index e1f12b734e..e43fadf598 100644
--- a/engines/cruise/detection.cpp
+++ b/engines/cruise/detection.cpp
@@ -237,7 +237,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI
+ Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class CruiseMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/cruise/font.cpp b/engines/cruise/font.cpp
index aecadab193..3a609cb8d4 100644
--- a/engines/cruise/font.cpp
+++ b/engines/cruise/font.cpp
@@ -30,7 +30,6 @@
#include "cruise/cruise_main.h"
#include "cruise/mouse.h"
#include "cruise/staticres.h"
-#include "cruise/vars.h"
namespace Cruise {
@@ -99,7 +98,7 @@ int32 getTextLineCount(int32 rightBorder_X, int16 wordSpacingWidth,
void loadFNT(const char *fileName) {
uint8 header[4];
- CVars._systemFNT = NULL;
+ _systemFNT = NULL;
Common::File fontFileHandle;
@@ -113,20 +112,20 @@ void loadFNT(const char *fileName) {
if (strcmp((char*)header, "FNT") == 0) {
uint32 fontSize = fontFileHandle.readUint32BE();
- CVars._systemFNT = (uint8 *)mallocAndZero(fontSize);
+ _systemFNT = (uint8 *)mallocAndZero(fontSize);
- if (CVars._systemFNT != NULL) {
+ if (_systemFNT != NULL) {
fontFileHandle.seek(4);
- fontFileHandle.read(CVars._systemFNT, fontSize);
+ fontFileHandle.read(_systemFNT, fontSize);
// Flip structure values from BE to LE for font files - this is for consistency
// with font resources, which are in LE formatt
- FontInfo *f = (FontInfo *)CVars._systemFNT;
+ FontInfo *f = (FontInfo *)_systemFNT;
bigEndianLongToNative(&f->offset);
bigEndianLongToNative(&f->size);
flipGen(&f->numChars, 6); // numChars, hSpacing, and vSpacing
- FontEntry *fe = (FontEntry *)(CVars._systemFNT + sizeof(FontInfo));
+ FontEntry *fe = (FontEntry *)(_systemFNT + sizeof(FontInfo));
for (int i = 0; i < f->numChars; ++i, ++fe) {
bigEndianLongToNative(&fe->offset); // Flip 32-bit offset field
@@ -141,10 +140,10 @@ void loadFNT(const char *fileName) {
void initSystem() {
int32 i;
- CVars.itemColor = 15;
- CVars.titleColor = 9;
- CVars.selectColor = 13;
- CVars.subColor = 10;
+ itemColor = 15;
+ titleColor = 9;
+ selectColor = 13;
+ subColor = 10;
for (i = 0; i < 64; i++) {
strcpy(preloadData[i].name, "");
@@ -170,7 +169,7 @@ void initSystem() {
}
void freeSystem() {
- MemFree(CVars._systemFNT);
+ MemFree(_systemFNT);
}
void bigEndianShortToNative(void *var) {
@@ -310,10 +309,10 @@ gfxEntryStruct *renderText(int inRightBorder_X, const char *string) {
fontPtr = (const FontInfo *)filesDatabase[fontFileIndex].subData.ptr;
if (!fontPtr) {
- fontPtr = (const FontInfo *)CVars._systemFNT;
+ fontPtr = (const FontInfo *)_systemFNT;
}
} else {
- fontPtr = (const FontInfo *)CVars._systemFNT;
+ fontPtr = (const FontInfo *)_systemFNT;
}
if (!fontPtr) {
diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp
index a25a54c562..3d07abf441 100644
--- a/engines/cruise/function.cpp
+++ b/engines/cruise/function.cpp
@@ -446,8 +446,8 @@ int16 Op_KillMenu() {
}
// Free the message list
-// if (CVars.linkedMsgList) freeMsgList(CVars.linkedMsgList);
- CVars.linkedMsgList = NULL;
+// if (linkedMsgList) freeMsgList(linkedMsgList);
+ linkedMsgList = NULL;
linkedRelation = NULL;
return 0;
@@ -1268,10 +1268,10 @@ int16 Op_regenerateBackgroundIncrust() {
int16 Op_SetStringColors() {
// TODO: here ignore if low color mode
- CVars.subColor = (uint8) popVar();
- CVars.itemColor = (uint8) popVar();
- CVars.selectColor = (uint8) popVar();
- CVars.titleColor = (uint8) popVar();
+ subColor = (uint8) popVar();
+ itemColor = (uint8) popVar();
+ selectColor = (uint8) popVar();
+ titleColor = (uint8) popVar();
return 0;
}
diff --git a/engines/cruise/gfxModule.cpp b/engines/cruise/gfxModule.cpp
index 1e77037e84..4a88e6ed5e 100644
--- a/engines/cruise/gfxModule.cpp
+++ b/engines/cruise/gfxModule.cpp
@@ -34,16 +34,25 @@
namespace Cruise {
-typedef Common::List<Common::Rect> RectList;
+uint8 page00[320 * 200];
+uint8 page10[320 * 200];
-/*gfxModuleDataStruct gfxModuleData = {
+char screen[320 * 200];
+palEntry lpalette[256];
+
+int palDirtyMin = 256;
+int palDirtyMax = -1;
+
+bool _dirtyRectScreen = false;
+
+gfxModuleDataStruct gfxModuleData = {
0, // use Tandy
0, // use EGA
1, // use VGA
- CVars.page00, // pPage00
- CVars.page10, // pPage10
-};*/
+ page00, // pPage00
+ page10, // pPage10
+};
void gfxModuleData_gfxClearFrameBuffer(uint8 *ptr) {
memset(ptr, 0, 64000);
@@ -99,16 +108,16 @@ void convertGfxFromMode5(const uint8 *sourcePtr, int width, int height, uint8 *d
}
void gfxModuleData_setDirtyColors(int min, int max) {
- if (min < CVars.palDirtyMin)
- CVars.palDirtyMin = min;
- if (max > CVars.palDirtyMax)
- CVars.palDirtyMax = max;
+ if (min < palDirtyMin)
+ palDirtyMin = min;
+ if (max > palDirtyMax)
+ palDirtyMax = max;
}
void gfxModuleData_setPalColor(int idx, int r, int g, int b) {
- CVars.lpalette[idx].R = r;
- CVars.lpalette[idx].G = g;
- CVars.lpalette[idx].B = b;
+ lpalette[idx].R = r;
+ lpalette[idx].G = g;
+ lpalette[idx].B = b;
gfxModuleData_setDirtyColors(idx, idx);
}
@@ -120,10 +129,10 @@ void gfxModuleData_setPalEntries(const byte *ptr, int start, int num) {
G = *(ptr++);
B = *(ptr++);
- CVars.lpalette[i].R = R;
- CVars.lpalette[i].G = G;
- CVars.lpalette[i].B = B;
- CVars.lpalette[i].A = 255;
+ lpalette[i].R = R;
+ lpalette[i].G = G;
+ lpalette[i].B = B;
+ lpalette[i].A = 255;
}
gfxModuleData_setDirtyColors(start, start + num - 1);
@@ -156,10 +165,10 @@ void gfxModuleData_setPal256(const byte *ptr) {
if (B > 0xFF)
B = 0xFF;
- CVars.lpalette[i].R = R;
- CVars.lpalette[i].G = G;
- CVars.lpalette[i].B = B;
- CVars.lpalette[i].A = 255;
+ lpalette[i].R = R;
+ lpalette[i].G = G;
+ lpalette[i].B = B;
+ lpalette[i].A = 255;
}
gfxModuleData_setDirtyColors(0, 16);
@@ -214,18 +223,18 @@ void gfxCopyRect(const uint8 *sourceBuffer, int width, int height, byte *dest, i
void gfxModuleData_Init() {
memset(globalScreen, 0, 320 * 200);
- memset(CVars.page00, 0, 320 * 200);
- memset(CVars.page10, 0, 320 * 200);
+ memset(page00, 0, 320 * 200);
+ memset(page10, 0, 320 * 200);
}
void gfxModuleData_flipScreen() {
- memcpy(globalScreen, CVars.pPage00, 320 * 200);
+ memcpy(globalScreen, gfxModuleData.pPage00, 320 * 200);
flip();
}
void gfxModuleData_addDirtyRect(const Common::Rect &r) {
- CVars._dirtyRects.push_back(Common::Rect( MAX(r.left, (int16)0), MAX(r.top, (int16)0),
+ _vm->_dirtyRects.push_back(Common::Rect( MAX(r.left, (int16)0), MAX(r.top, (int16)0),
MIN(r.right, (int16)320), MIN(r.bottom, (int16)200)));
}
@@ -242,11 +251,11 @@ static bool unionRectangle(Common::Rect &pDest, const Common::Rect &pSrc1, const
}
static void mergeClipRects() {
- RectList::iterator rOuter, rInner;
+ CruiseEngine::RectList::iterator rOuter, rInner;
- for (rOuter = CVars._dirtyRects.begin(); rOuter != CVars._dirtyRects.end(); ++rOuter) {
+ for (rOuter = _vm->_dirtyRects.begin(); rOuter != _vm->_dirtyRects.end(); ++rOuter) {
rInner = rOuter;
- while (++rInner != CVars._dirtyRects.end()) {
+ while (++rInner != _vm->_dirtyRects.end()) {
if ((*rOuter).intersects(*rInner)) {
// these two rectangles overlap, so translate it to a bigger rectangle
@@ -254,7 +263,7 @@ static void mergeClipRects() {
unionRectangle(*rOuter, *rOuter, *rInner);
// remove the inner rect from the list
- CVars._dirtyRects.erase(rInner);
+ _vm->_dirtyRects.erase(rInner);
// move back to beginning of list
rInner = rOuter;
@@ -266,16 +275,16 @@ static void mergeClipRects() {
void gfxModuleData_updatePalette() {
byte paletteRGBA[256 * 4];
- if (CVars.palDirtyMax != -1) {
- for (int i = CVars.palDirtyMin; i <= CVars.palDirtyMax; i++) {
- paletteRGBA[i * 4 + 0] = CVars.lpalette[i].R;
- paletteRGBA[i * 4 + 1] = CVars.lpalette[i].G;
- paletteRGBA[i * 4 + 2] = CVars.lpalette[i].B;
+ if (palDirtyMax != -1) {
+ for (int i = palDirtyMin; i <= palDirtyMax; i++) {
+ paletteRGBA[i * 4 + 0] = lpalette[i].R;
+ paletteRGBA[i * 4 + 1] = lpalette[i].G;
+ paletteRGBA[i * 4 + 2] = lpalette[i].B;
paletteRGBA[i * 4 + 3] = 0xFF;
}
- g_system->setPalette(paletteRGBA + CVars.palDirtyMin*4, CVars.palDirtyMin, CVars.palDirtyMax - CVars.palDirtyMin + 1);
- CVars.palDirtyMin = 256;
- CVars.palDirtyMax = -1;
+ g_system->setPalette(paletteRGBA + palDirtyMin*4, palDirtyMin, palDirtyMax - palDirtyMin + 1);
+ palDirtyMin = 256;
+ palDirtyMax = -1;
}
}
@@ -285,32 +294,32 @@ void gfxModuleData_updateScreen() {
}
void flip() {
- RectList::iterator dr;
+ CruiseEngine::RectList::iterator dr;
// Update the palette
gfxModuleData_updatePalette();
// Make a copy of the prior frame's dirty rects, and then backup the current frame's rects
- RectList tempList = CVars._priorFrameRects;
- CVars._priorFrameRects = CVars._dirtyRects;
+ CruiseEngine::RectList tempList = _vm->_priorFrameRects;
+ _vm->_priorFrameRects = _vm->_dirtyRects;
// Merge the prior frame's dirty rects into the current frame's list
for (dr = tempList.begin(); dr != tempList.end(); ++dr) {
Common::Rect &r = *dr;
- CVars._dirtyRects.push_back(Common::Rect(r.left, r.top, r.right, r.bottom));
+ _vm->_dirtyRects.push_back(Common::Rect(r.left, r.top, r.right, r.bottom));
}
// Merge any overlapping rects to simplify the drawing process
mergeClipRects();
// Copy any modified areas
- for (dr = CVars._dirtyRects.begin(); dr != CVars._dirtyRects.end(); ++dr) {
+ for (dr = _vm->_dirtyRects.begin(); dr != _vm->_dirtyRects.end(); ++dr) {
Common::Rect &r = *dr;
g_system->copyRectToScreen(globalScreen + 320 * r.top + r.left, 320,
r.left, r.top, r.width(), r.height());
}
- CVars._dirtyRects.clear();
+ _vm->_dirtyRects.clear();
// Allow the screen to update
g_system->updateScreen();
@@ -318,7 +327,7 @@ void flip() {
void drawSolidBox(int32 x1, int32 y1, int32 x2, int32 y2, uint8 colour) {
for (int y = y1; y < y2; ++y) {
- byte *p = &CVars.pPage00[y * 320 + x1];
+ byte *p = &gfxModuleData.pPage00[y * 320 + x1];
Common::set_to(p, p + (x2 - x1), colour);
}
}
@@ -332,7 +341,7 @@ void resetBitmap(uint8 *dataPtr, int32 dataSize) {
* to figure out rectangles of changed areas for dirty rectangles
*/
void switchBackground(const byte *newBg) {
- const byte *bg = CVars.pPage00;
+ const byte *bg = gfxModuleData.pPage00;
int sliceXStart, sliceXEnd;
// If both the upper corners are different, presume it's a full screen change
diff --git a/engines/cruise/gfxModule.h b/engines/cruise/gfxModule.h
index 289cc24d98..1dbc5afc9b 100644
--- a/engines/cruise/gfxModule.h
+++ b/engines/cruise/gfxModule.h
@@ -28,14 +28,14 @@
namespace Cruise {
-/*struct gfxModuleDataStruct {
+struct gfxModuleDataStruct {
int useTandy;
int useEGA;
int useVGA;
uint8 *pPage00;
uint8 *pPage10;
-};*/
+};
struct palEntry {
uint8 R;
@@ -44,7 +44,7 @@ struct palEntry {
uint8 A;
};
-//extern gfxModuleDataStruct gfxModuleData;
+extern gfxModuleDataStruct gfxModuleData;
void gfxModuleData_gfxClearFrameBuffer(uint8 *ptr);
void gfxModuleData_setDirtyColors(int min, int max);
diff --git a/engines/cruise/mainDraw.cpp b/engines/cruise/mainDraw.cpp
index 67c6d96455..aaa6f987b6 100644
--- a/engines/cruise/mainDraw.cpp
+++ b/engines/cruise/mainDraw.cpp
@@ -135,7 +135,7 @@ void flipScreen() {
gfxModuleData_setPal256(workpal);
}
- SWAP(CVars.pPage00, CVars.pPage10);
+ SWAP(gfxModuleData.pPage00, gfxModuleData.pPage10);
gfxModuleData_flipScreen();
@@ -1330,7 +1330,7 @@ void drawMenu(menuStruct *pMenu) {
int wx = x + (nbcol - 1) * (160 / 2);
if (wx <= 320 - 160) {
- drawMessage(pMenu->gfx, wx, y - hline, 160, CVars.titleColor, CVars.pPage10);
+ drawMessage(pMenu->gfx, wx, y - hline, 160, titleColor, gfxModuleData.pPage10);
}
wx = x;
@@ -1348,17 +1348,17 @@ void drawMenu(menuStruct *pMenu) {
int color;
if (p1->selected) {
- color = CVars.selectColor;
+ color = selectColor;
} else {
if (p1->color != 255) {
color = p1->color;
} else {
- color = CVars.itemColor;
+ color = itemColor;
}
}
if (wx <= (320 - 160)) {
- drawMessage(p2, wx, wy, 160, color, CVars.pPage10);
+ drawMessage(p2, wx, wy, 160, color, gfxModuleData.pPage10);
}
wy += hline;
@@ -1418,7 +1418,7 @@ void mainDraw(int16 param) {
bgPtr = backgroundScreens[masterScreen];
if (bgPtr) {
- gfxModuleData_gfxCopyScreen(bgPtr, CVars.pPage10);
+ gfxModuleData_gfxCopyScreen(bgPtr, gfxModuleData.pPage10);
if (backgroundChanged[masterScreen]) {
backgroundChanged[masterScreen] = false;
switchBackground(bgPtr);
@@ -1469,7 +1469,7 @@ void mainDraw(int16 param) {
if ((params.state >= 0) && (objZ2 >= 0) && filesDatabase[objZ2].subData.ptr) {
if (filesDatabase[objZ2].subData.resourceType == 8) { // Poly
- mainDrawPolygons(objZ2, currentObjPtr, objX2, params.scale, objY2, (char *)CVars.pPage10, (char *)filesDatabase[objZ2].subData.ptr); // poly
+ mainDrawPolygons(objZ2, currentObjPtr, objX2, params.scale, objY2, (char *)gfxModuleData.pPage10, (char *)filesDatabase[objZ2].subData.ptr); // poly
} else if (filesDatabase[objZ2].subData.resourceType == OBJ_TYPE_SOUND) {
} else if (filesDatabase[objZ2].resType == OBJ_TYPE_MASK) {
} else if (filesDatabase[objZ2].subData.resourceType == OBJ_TYPE_SPRITE) {
@@ -1477,7 +1477,7 @@ void mainDraw(int16 param) {
spriteHeight = filesDatabase[objZ2].height; // height
if (filesDatabase[objZ2].subData.ptr) {
- drawSprite(objX1, spriteHeight, currentObjPtr, filesDatabase[objZ2].subData.ptr, objY2, objX2, CVars.pPage10, filesDatabase[objZ2].subData.ptrMask);
+ drawSprite(objX1, spriteHeight, currentObjPtr, filesDatabase[objZ2].subData.ptr, objY2, objX2, gfxModuleData.pPage10, filesDatabase[objZ2].subData.ptrMask);
}
}
}
@@ -1573,7 +1573,7 @@ void mainDraw(int16 param) {
while (currentObjPtr) {
if (currentObjPtr->type == OBJ_TYPE_MESSAGE && currentObjPtr->freeze == 0) {
- drawMessage(currentObjPtr->gfxPtr, currentObjPtr->x, currentObjPtr->field_C, currentObjPtr->spriteIdx, currentObjPtr->color, CVars.pPage10);
+ drawMessage(currentObjPtr->gfxPtr, currentObjPtr->x, currentObjPtr->field_C, currentObjPtr->spriteIdx, currentObjPtr->color, gfxModuleData.pPage10);
isMessage = 1;
}
currentObjPtr = currentObjPtr->next;
@@ -1586,16 +1586,16 @@ void mainDraw(int16 param) {
drawMenu(menuTable[currentActiveMenu]);
return;
}
- } else if ((linkedRelation) && (CVars.linkedMsgList)) {
+ } else if ((linkedRelation) && (linkedMsgList)) {
int16 mouseX;
int16 mouseY;
int16 button;
getMouseStatus(&main10, &mouseX, &button, &mouseY);
- if (mouseY > (CVars.linkedMsgList->height)*2)
- drawMessage(CVars.linkedMsgList, 0, 0, 320, findHighColor(), CVars.pPage10);
+ if (mouseY > (linkedMsgList->height)*2)
+ drawMessage(linkedMsgList, 0, 0, 320, findHighColor(), gfxModuleData.pPage10);
else
- drawMessage(CVars.linkedMsgList, 0, 200, 320, findHighColor(), CVars.pPage10);
+ drawMessage(linkedMsgList, 0, 200, 320, findHighColor(), gfxModuleData.pPage10);
}
}
diff --git a/engines/cruise/perso.cpp b/engines/cruise/perso.cpp
index 1e92b8bc3e..e86daa5bef 100644
--- a/engines/cruise/perso.cpp
+++ b/engines/cruise/perso.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "cruise/cruise.h"
#include "cruise/cruise_main.h"
#include "common/util.h"
@@ -45,14 +46,14 @@ void freeCTP() {
freePerso(i);
}
- if (polyStruct) {
- CVars.polyStructNorm.clear();
- CVars.polyStructExp.clear();
- polyStruct = NULL;
+ if (_vm->_polyStruct) {
+ _vm->_polyStructNorm.clear();
+ _vm->_polyStructExp.clear();
+ _vm->_polyStruct = NULL;
}
- CVars.ctpVar17 = NULL;
- polyStruct = NULL;
+ ctpVar17 = NULL;
+ _vm->_polyStruct = NULL;
strcpy((char *)currentCtpName, "");
}
diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp
index bfbf808168..24ea2facfe 100644
--- a/engines/cruise/saveload.cpp
+++ b/engines/cruise/saveload.cpp
@@ -113,10 +113,10 @@ static void syncBasicInfo(Common::Serializer &s) {
s.syncAsSint16LE(isMessage);
s.syncAsSint16LE(fadeFlag);
s.syncAsSint16LE(automaticMode);
- s.syncAsSint16LE(CVars.titleColor);
- s.syncAsSint16LE(CVars.itemColor);
- s.syncAsSint16LE(CVars.selectColor);
- s.syncAsSint16LE(CVars.subColor);
+ s.syncAsSint16LE(titleColor);
+ s.syncAsSint16LE(itemColor);
+ s.syncAsSint16LE(selectColor);
+ s.syncAsSint16LE(subColor);
s.syncAsSint16LE(narratorOvl);
s.syncAsSint16LE(narratorIdx);
s.syncAsSint16LE(aniX);
@@ -579,10 +579,10 @@ static void syncPerso(Common::Serializer &s, persoStruct &p) {
}
static void syncCT(Common::Serializer &s) {
- int v = (polyStruct) ? 1 : 0;
+ int v = (_vm->_polyStruct) ? 1 : 0;
s.syncAsSint32LE(v);
if (s.isLoading())
- polyStruct = (v != 0) ? &CVars.polyStructNorm : NULL;
+ _vm->_polyStruct = (v != 0) ? &_vm->_polyStructNorm : NULL;
if (v == 0)
// There is no further data to load or save
@@ -762,10 +762,10 @@ void initVars() {
// video param (vga and mcga mode)
- CVars.titleColor = 2;
- CVars.itemColor = 1;
- CVars.selectColor = 3;
- CVars.subColor = 5;
+ titleColor = 2;
+ itemColor = 1;
+ selectColor = 3;
+ subColor = 5;
//
diff --git a/engines/cruise/script.cpp b/engines/cruise/script.cpp
index f2877a7730..d6c1aa47f3 100644
--- a/engines/cruise/script.cpp
+++ b/engines/cruise/script.cpp
@@ -618,13 +618,13 @@ int executeScripts(scriptInstanceStruct *ptr) {
positionInStack = 0;
do {
-#ifdef SKIP_INTRO
+//#ifdef SKIP_INTRO
if (currentScriptPtr->scriptOffset == 290
&& currentScriptPtr->overlayNumber == 4
&& currentScriptPtr->scriptNumber == 0) {
currentScriptPtr->scriptOffset = 923;
}
-#endif
+//#endif
opcodeType = getByteFromScript();
debugC(5, kCruiseDebugScript, "Script %s/%d ip=%d opcode=%d",
diff --git a/engines/cruise/vars.cpp b/engines/cruise/vars.cpp
index 87f0626355..c61cedc503 100644
--- a/engines/cruise/vars.cpp
+++ b/engines/cruise/vars.cpp
@@ -24,36 +24,15 @@
*/
#include "cruise/cruise_main.h"
-#include "cruise/vars.h"
-
-DECLARE_SINGLETON(Cruise::CruiseVars)
namespace Cruise {
-CruiseVars::CruiseVars() {
- _systemFNT = NULL;
-
- itemColor = 1;
- selectColor = 3;
- titleColor = 2;
- subColor = 5;
-
- linkedMsgList = NULL;
-
- palDirtyMin = 256;
- palDirtyMax = -1;
+uint8 *_systemFNT = NULL;
- _dirtyRectScreen = false;
-
- useTandy = 0;
- useEGA = 0;
- useVGA = 1;
-
- pPage00 = page00;
- pPage10 = page10;
-}
-
-CruiseVars::~CruiseVars() {}
+uint8 itemColor = 1;
+uint8 selectColor = 3;
+uint8 titleColor = 2;
+uint8 subColor = 5;
int16 lowMemory;
int16 scroll;
@@ -85,12 +64,6 @@ int16 autoTrack;
int16 currentDiskNumber = 1;
-#ifdef PALMOS_MODE
-Common::File *_currentVolumeFile;
-#else
-Common::File currentVolumeFile;
-#endif
-
int16 volumeNumEntry;
fileEntry *volumePtrToFileDescriptor = NULL;
diff --git a/engines/cruise/vars.h b/engines/cruise/vars.h
index 06b479128b..af39993f2f 100644
--- a/engines/cruise/vars.h
+++ b/engines/cruise/vars.h
@@ -27,16 +27,9 @@
#define CRUISE_VARS_H
#include "common/file.h"
-#include "common/list.h"
-#include "common/singleton.h"
-#include "common/endian.h"
-#include "common/util.h"
-#include "gfxModule.h"
namespace Cruise {
-typedef Common::List<Common::Rect> RectList;
-
#define NBCOLORS 256
#define NBSCREENS 8
@@ -61,50 +54,13 @@ struct menuElementStruct {
typedef int32(*opcodeTypeFunction)();
typedef int16(*opcodeFunction)();
+extern uint8 *_systemFNT;
extern int16 fontFileIndex;
-class CruiseVars : public Common::Singleton<CruiseVars> {
-public:
- uint8 *_systemFNT;
-
- uint8 itemColor;
- uint8 selectColor;
- uint8 titleColor;
- uint8 subColor;
-
- gfxEntryStruct* linkedMsgList;
-
- Common::List<byte *> memList;
-
- uint8 *ctpVar17;
-
- Common::Array<CtStruct> polyStructNorm;
- Common::Array<CtStruct> polyStructExp;
-
- uint8 page00[320 * 200];
- uint8 page10[320 * 200];
- char screen[320 * 200];
-
- palEntry lpalette[256];
-
- int palDirtyMin;
- int palDirtyMax;
-
- RectList _dirtyRects;
- RectList _priorFrameRects;
- bool _dirtyRectScreen;
-
- int useTandy;
- int useEGA;
- int useVGA;
-
- uint8 *pPage00;
- uint8 *pPage10;
-
- ~CruiseVars();
- CruiseVars();
-
-};
+extern uint8 itemColor;
+extern uint8 selectColor;
+extern uint8 titleColor;
+extern uint8 subColor;
extern int16 lowMemory;
extern int16 scroll;
@@ -211,13 +167,6 @@ extern int16 autoTrack;
extern int16 currentDiskNumber;
-#ifdef PALMOS_MODE
-extern Common::File *_currentVolumeFile;
-#define currentVolumeFile (*_currentVolumeFile)
-#else
-extern Common::File currentVolumeFile;
-#endif
-
extern int16 volumeNumEntry;
extern fileEntry *volumePtrToFileDescriptor;
@@ -345,6 +294,4 @@ extern uint8 globalScreen[320 * 200];
} // End of namespace Cruise
-#define CVars (::Cruise::CruiseVars::instance())
-
#endif
diff --git a/engines/cruise/volume.cpp b/engines/cruise/volume.cpp
index 86b37bb394..5535d5a016 100644
--- a/engines/cruise/volume.cpp
+++ b/engines/cruise/volume.cpp
@@ -23,13 +23,11 @@
*
*/
+#include "cruise/cruise.h"
#include "cruise/cruise_main.h"
namespace Cruise {
-#if !defined(__DS__)
-Common::File PAL_file;
-#endif
uint8 *PAL_ptr = NULL;
int16 numLoadedPal;
@@ -42,26 +40,25 @@ void loadPal(volumeDataStruct *entry) {
#if 0
char name[20];
- if (PAL_file.isOpen())
- PAL_file.close();
+ if (_vm->_PAL_file.isOpen())
+ _vm->_PAL_file.close();
removeExtention(entry->ident, name);
strcat(name, ".PAL");
- if (!PAL_file.open(name))
+ if (!_vm->_PAL_file.open(name))
return;
- numLoadedPal = PAL_file.readSint16BE();
- fileData2 = PAL_file.readSint16BE();
+ numLoadedPal = _vm->_PAL_file.readSint16BE();
+ fileData2 = _vm->_PAL_file.readSint16BE();
PAL_ptr = (uint8 *)MemAlloc(numLoadedPal * fileData2);
#endif
}
void closePal() {
-#if !defined(__DS__)
- if (PAL_file.isOpen()) {
- PAL_file.close();
+ if (_vm->_PAL_file.isOpen()) {
+ _vm->_PAL_file.close();
MemFree(PAL_ptr);
PAL_ptr = NULL;
@@ -69,22 +66,21 @@ void closePal() {
numLoadedPal = 0;
fileData2 = 0;
}
-#endif
}
int closeBase() {
- if (currentVolumeFile.isOpen()) {
- currentVolumeFile.close();
+ if (_vm->_currentVolumeFile.isOpen()) {
+ _vm->_currentVolumeFile.close();
MemFree(volumePtrToFileDescriptor);
strcpy(currentBaseName, "");
}
-#if !defined(__DS__)
- if (PAL_file.isOpen()) {
+
+ if (_vm->_PAL_file.isOpen()) {
closePal();
}
-#endif
+
return 0;
}
@@ -95,7 +91,7 @@ int getVolumeDataEntry(volumeDataStruct *entry) {
volumeNumEntry = 0;
volumeNumberOfEntry = 0;
- if (currentVolumeFile.isOpen()) {
+ if (_vm->_currentVolumeFile.isOpen()) {
freeDisk();
}
@@ -103,16 +99,16 @@ int getVolumeDataEntry(volumeDataStruct *entry) {
strcpy(buffer, entry->ident);
- currentVolumeFile.open(buffer);
+ _vm->_currentVolumeFile.open(buffer);
- if (!currentVolumeFile.isOpen()) {
+ if (!_vm->_currentVolumeFile.isOpen()) {
return (-14);
}
changeCursor(CURSOR_DISK);
- volumeNumberOfEntry = currentVolumeFile.readSint16BE();
- volumeSizeOfEntry = currentVolumeFile.readSint16BE();
+ volumeNumberOfEntry = _vm->_currentVolumeFile.readSint16BE();
+ volumeSizeOfEntry = _vm->_currentVolumeFile.readSint16BE();
volumeNumEntry = volumeNumberOfEntry;
@@ -129,11 +125,11 @@ int getVolumeDataEntry(volumeDataStruct *entry) {
}
for (i = 0; i < volumeNumEntry; i++) {
- currentVolumeFile.read(&volumePtrToFileDescriptor[i].name, 14);
- volumePtrToFileDescriptor[i].offset = currentVolumeFile.readSint32BE();
- volumePtrToFileDescriptor[i].size = currentVolumeFile.readSint32BE();
- volumePtrToFileDescriptor[i].extSize = currentVolumeFile.readSint32BE();
- volumePtrToFileDescriptor[i].unk3 = currentVolumeFile.readSint32BE();
+ _vm->_currentVolumeFile.read(&volumePtrToFileDescriptor[i].name, 14);
+ volumePtrToFileDescriptor[i].offset = _vm->_currentVolumeFile.readSint32BE();
+ volumePtrToFileDescriptor[i].size = _vm->_currentVolumeFile.readSint32BE();
+ volumePtrToFileDescriptor[i].extSize = _vm->_currentVolumeFile.readSint32BE();
+ volumePtrToFileDescriptor[i].unk3 = _vm->_currentVolumeFile.readSint32BE();
}
strcpy(currentBaseName, entry->ident);
@@ -182,8 +178,8 @@ int32 findFileInDisksSub1(const char *fileName) {
}
void freeDisk() {
- if (currentVolumeFile.isOpen()) {
- currentVolumeFile.close();
+ if (_vm->_currentVolumeFile.isOpen()) {
+ _vm->_currentVolumeFile.close();
MemFree(volumePtrToFileDescriptor);
}
@@ -198,7 +194,7 @@ void freeDisk() {
int16 findFileInList(char *fileName) {
int i;
- if (!currentVolumeFile.isOpen()) {
+ if (!_vm->_currentVolumeFile.isOpen()) {
return (-1);
}
@@ -252,7 +248,7 @@ int16 findFileInDisks(const char *name) {
if (!volumeDataLoaded) {
debug(1, "CNF wasn't loaded, reading now...");
- if (currentVolumeFile.isOpen()) {
+ if (_vm->_currentVolumeFile.isOpen()) {
askDisk(-1);
freeDisk();
}
@@ -261,7 +257,7 @@ int16 findFileInDisks(const char *name) {
readVolCnf();
}
- if (currentVolumeFile.isOpen()) {
+ if (_vm->_currentVolumeFile.isOpen()) {
askDisk(-1);
}
@@ -278,7 +274,7 @@ int16 findFileInDisks(const char *name) {
debug(1, "File found on disk %d", disk);
- if (currentVolumeFile.isOpen()) {
+ if (_vm->_currentVolumeFile.isOpen()) {
askDisk(-1);
}
diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp
index 73ba591b4b..2397a474c6 100644
--- a/engines/dialogs.cpp
+++ b/engines/dialogs.cpp
@@ -28,6 +28,7 @@
#include "common/savefile.h"
#include "common/system.h"
#include "common/events.h"
+#include "common/translation.h"
#include "graphics/scaler.h"
@@ -35,8 +36,9 @@
#include "gui/GuiManager.h"
#include "gui/launcher.h"
#include "gui/ListWidget.h"
-#include "gui/ThemeEval.h"
+#include "gui/options.h"
#include "gui/saveload.h"
+#include "gui/ThemeEval.h"
#include "engines/dialogs.h"
#include "engines/engine.h"
@@ -49,16 +51,17 @@
using GUI::CommandSender;
using GUI::StaticTextWidget;
-enum {
- kSaveCmd = 'SAVE',
- kLoadCmd = 'LOAD',
- kPlayCmd = 'PLAY',
- kOptionsCmd = 'OPTN',
- kHelpCmd = 'HELP',
- kAboutCmd = 'ABOU',
- kQuitCmd = 'QUIT',
- kRTLCmd = 'RTL ',
- kChooseCmd = 'CHOS'
+class ConfigDialog : public GUI::OptionsDialog {
+protected:
+#ifdef SMALL_SCREEN_DEVICE
+ GUI::Dialog *_keysDialog;
+#endif
+
+public:
+ ConfigDialog(bool subtitleControls);
+ ~ConfigDialog();
+
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
};
MainMenuDialog::MainMenuDialog(Engine *engine)
@@ -83,31 +86,37 @@ MainMenuDialog::MainMenuDialog(Engine *engine)
StaticTextWidget *version = new StaticTextWidget(this, "GlobalMenu.Version", gScummVMVersionDate);
version->setAlign(Graphics::kTextAlignCenter);
- new GUI::ButtonWidget(this, "GlobalMenu.Resume", "Resume", kPlayCmd, 'P');
+ new GUI::ButtonWidget(this, "GlobalMenu.Resume", _("~R~esume"), 0, kPlayCmd, 'P');
- _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", "Load", kLoadCmd, 'L');
+ _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", _("~L~oad"), 0, kLoadCmd);
// TODO: setEnabled -> setVisible
_loadButton->setEnabled(_engine->hasFeature(Engine::kSupportsLoadingDuringRuntime));
- _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", "Save", kSaveCmd, 'S');
+ _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", _("~S~ave"), 0, kSaveCmd);
// TODO: setEnabled -> setVisible
_saveButton->setEnabled(_engine->hasFeature(Engine::kSupportsSavingDuringRuntime));
- new GUI::ButtonWidget(this, "GlobalMenu.Options", "Options", kOptionsCmd, 'O');
+ new GUI::ButtonWidget(this, "GlobalMenu.Options", _("~O~ptions"), 0, kOptionsCmd);
- new GUI::ButtonWidget(this, "GlobalMenu.About", "About", kAboutCmd, 'A');
+ // The help button is disabled by default.
+ // To enable "Help", an engine needs to use a subclass of MainMenuDialog
+ // (at least for now, we might change how this works in the future).
+ _helpButton = new GUI::ButtonWidget(this, "GlobalMenu.Help", _("~H~elp"), 0, kHelpCmd);
+ _helpButton->setEnabled(false);
- _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", "Return to Launcher", kRTLCmd, 'R');
+ new GUI::ButtonWidget(this, "GlobalMenu.About", _("~A~bout"), 0, kAboutCmd);
+
+ _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", _("~R~eturn to Launcher"), 0, kRTLCmd);
_rtlButton->setEnabled(_engine->hasFeature(Engine::kSupportsRTL));
- new GUI::ButtonWidget(this, "GlobalMenu.Quit", "Quit", kQuitCmd, 'Q');
+ new GUI::ButtonWidget(this, "GlobalMenu.Quit", _("~Q~uit"), 0, kQuitCmd);
_aboutDialog = new GUI::AboutDialog();
_optionsDialog = new ConfigDialog(_engine->hasFeature(Engine::kSupportsSubtitleOptions));
- _loadDialog = new GUI::SaveLoadChooser("Load game:", "Load");
+ _loadDialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load"));
_loadDialog->setSaveMode(false);
- _saveDialog = new GUI::SaveLoadChooser("Save game:", "Save");
+ _saveDialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"));
_saveDialog->setSaveMode(true);
}
@@ -135,6 +144,9 @@ void MainMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
case kAboutCmd:
_aboutDialog->runModal();
break;
+ case kHelpCmd:
+ // Not handled here -- needs to be handled by a subclass (for now)
+ break;
case kRTLCmd: {
Common::Event eventRTL;
eventRTL.type = Common::EVENT_RTL;
@@ -263,13 +275,13 @@ enum {
// "" as value for the domain, and in fact provide a somewhat better user
// experience at the same time.
ConfigDialog::ConfigDialog(bool subtitleControls)
- : GUI::OptionsDialog("", "ScummConfig") {
+ : GUI::OptionsDialog("", "GlobalConfig") {
//
// Sound controllers
//
- addVolumeControls(this, "ScummConfig.");
+ addVolumeControls(this, "GlobalConfig.");
setVolumeSettingsState(true); // could disable controls by GUI options
//
@@ -278,7 +290,7 @@ ConfigDialog::ConfigDialog(bool subtitleControls)
if (subtitleControls) {
// Global talkspeed range of 0-255
- addSubtitleControls(this, "ScummConfig.", 255);
+ addSubtitleControls(this, "GlobalConfig.", 255);
setSubtitleSettingsState(true); // could disable controls by GUI options
}
@@ -286,11 +298,11 @@ ConfigDialog::ConfigDialog(bool subtitleControls)
// Add the buttons
//
- new GUI::ButtonWidget(this, "ScummConfig.Ok", "OK", GUI::kOKCmd, 'O');
- new GUI::ButtonWidget(this, "ScummConfig.Cancel", "Cancel", GUI::kCloseCmd, 'C');
+ new GUI::ButtonWidget(this, "GlobalConfig.Ok", _("~O~K"), 0, GUI::kOKCmd);
+ new GUI::ButtonWidget(this, "GlobalConfig.Cancel", _("~C~ancel"), 0, GUI::kCloseCmd);
#ifdef SMALL_SCREEN_DEVICE
- new GUI::ButtonWidget(this, "ScummConfig.Keys", "Keys", kKeysCmd, 'K');
+ new GUI::ButtonWidget(this, "GlobalConfig.Keys", _("~K~eys"), 0, kKeysCmd);
_keysDialog = NULL;
#endif
}
diff --git a/engines/dialogs.h b/engines/dialogs.h
index 6bee7c5fb1..6e5338b317 100644
--- a/engines/dialogs.h
+++ b/engines/dialogs.h
@@ -27,7 +27,6 @@
#include "common/str.h"
#include "gui/dialog.h"
-#include "gui/options.h"
class Engine;
@@ -39,6 +38,19 @@ namespace GUI {
class MainMenuDialog : public GUI::Dialog {
public:
+ enum {
+ kSaveCmd = 'SAVE',
+ kLoadCmd = 'LOAD',
+ kPlayCmd = 'PLAY',
+ kOptionsCmd = 'OPTN',
+ kHelpCmd = 'HELP',
+ kAboutCmd = 'ABOU',
+ kQuitCmd = 'QUIT',
+ kRTLCmd = 'RTL ',
+ kChooseCmd = 'CHOS'
+ };
+
+public:
MainMenuDialog(Engine *engine);
~MainMenuDialog();
@@ -51,29 +63,20 @@ protected:
void load();
protected:
- Engine *_engine;
+ Engine *_engine;
- GUI::GraphicsWidget *_logo;
- GUI::ButtonWidget *_rtlButton;
- GUI::ButtonWidget *_loadButton;
- GUI::ButtonWidget *_saveButton;
- GUI::Dialog *_aboutDialog;
- GUI::Dialog *_optionsDialog;
- GUI::SaveLoadChooser *_loadDialog;
- GUI::SaveLoadChooser *_saveDialog;
-};
+ GUI::GraphicsWidget *_logo;
-class ConfigDialog : public GUI::OptionsDialog {
-protected:
-#ifdef SMALL_SCREEN_DEVICE
- GUI::Dialog *_keysDialog;
-#endif
+ GUI::ButtonWidget *_rtlButton;
+ GUI::ButtonWidget *_loadButton;
+ GUI::ButtonWidget *_saveButton;
+ GUI::ButtonWidget *_helpButton;
-public:
- ConfigDialog(bool subtitleControls);
- ~ConfigDialog();
+ GUI::Dialog *_aboutDialog;
+ GUI::Dialog *_optionsDialog;
- virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+ GUI::SaveLoadChooser *_loadDialog;
+ GUI::SaveLoadChooser *_saveDialog;
};
#endif
diff --git a/engines/draci/animation.cpp b/engines/draci/animation.cpp
index e46582487c..2bedbe1801 100644
--- a/engines/draci/animation.cpp
+++ b/engines/draci/animation.cpp
@@ -166,10 +166,10 @@ void Animation::drawFrame(Surface *surface) {
const SoundSample *sample = _samples[_currentFrame];
if (_hasChangedFrame && sample) {
+ uint duration = _vm->_sound->playSound(sample, Audio::Mixer::kMaxChannelVolume, false);
debugC(3, kDraciSoundDebugLevel,
- "Playing sample on animation %d, frame %d: %d+%d at %dHz",
- _id, _currentFrame, sample->_offset, sample->_length, sample->_frequency);
- _vm->_sound->playSound(sample, Audio::Mixer::kMaxChannelVolume, false);
+ "Playing sample on animation %d, frame %d: %d+%d at %dHz: %dms",
+ _id, _currentFrame, sample->_offset, sample->_length, sample->_frequency, duration);
}
_hasChangedFrame = false;
}
diff --git a/engines/draci/barchive.cpp b/engines/draci/barchive.cpp
index 2ed2a9b591..8f9e836ba3 100644
--- a/engines/draci/barchive.cpp
+++ b/engines/draci/barchive.cpp
@@ -283,8 +283,7 @@ BAFile *BArchive::loadFileBAR(uint i) {
tmp ^= _files[i]._data[j];
}
- debugC(3, kDraciArchiverDebugLevel, "Cached file %d from archive %s",
- i, _path.c_str());
+ debugC(2, kDraciArchiverDebugLevel, "Read %d bytes", _files[i]._length);
assert(tmp == _files[i]._crc && "CRC checksum mismatch");
return _files + i;
@@ -385,7 +384,7 @@ const BAFile *BArchive::getFile(uint i) {
// Check if file has already been opened and return that
if (_files[i]._data) {
- debugC(2, kDraciArchiverDebugLevel, "Success");
+ debugC(2, kDraciArchiverDebugLevel, "Cached");
return _files + i;
}
diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp
index c3204fc656..07a9928cfa 100644
--- a/engines/draci/detection.cpp
+++ b/engines/draci/detection.cpp
@@ -71,6 +71,16 @@ const ADGameDescription gameDescriptions[] = {
GUIO_NONE
},
+ {
+ "draci",
+ 0,
+ AD_ENTRY1s("INIT.DFW", "9a7115b91cdea361bcaff3e046ac7ded", 906),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+
AD_TABLE_END_MARKER
};
@@ -94,7 +104,11 @@ const ADParams detectionParams = {
// Flags
0,
// Global GUI options
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class DraciMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp
index cbf878279b..cd3920b30d 100644
--- a/engines/draci/draci.cpp
+++ b/engines/draci/draci.cpp
@@ -71,7 +71,7 @@ const char *dubbingPath = "CD.SAM";
const char *musicPathMask = "HUDBA%d.MID";
const uint kSoundsFrequency = 13000;
-const uint kDubbingFrequency = 22000;
+const uint kDubbingFrequency = 22050;
DraciEngine::DraciEngine(OSystem *syst, const ADGameDescription *gameDesc)
: Engine(syst) {
@@ -105,6 +105,39 @@ bool DraciEngine::hasFeature(EngineFeature f) const {
(f == kSupportsSavingDuringRuntime);
}
+static SoundArchive* openAnyPossibleDubbing() {
+ debugC(1, kDraciGeneralDebugLevel, "Trying to find original dubbing");
+ LegacySoundArchive *legacy = new LegacySoundArchive(dubbingPath, kDubbingFrequency);
+ if (legacy->isOpen() && legacy->size()) {
+ debugC(1, kDraciGeneralDebugLevel, "Found original dubbing");
+ return legacy;
+ }
+ delete legacy;
+
+ // The original uncompressed dubbing cannot be found. Try to open the
+ // newer compressed version.
+ debugC(1, kDraciGeneralDebugLevel, "Trying to find compressed dubbing");
+ ZipSoundArchive *zip = new ZipSoundArchive();
+
+ zip->openArchive("dub-raw.zzz", "buf", RAW80, kDubbingFrequency);
+ if (zip->isOpen() && zip->size()) return zip;
+#ifdef USE_FLAC
+ zip->openArchive("dub-flac.zzz", "flac", FLAC);
+ if (zip->isOpen() && zip->size()) return zip;
+#endif
+#ifdef USE_VORBIS
+ zip->openArchive("dub-ogg.zzz", "ogg", OGG);
+ if (zip->isOpen() && zip->size()) return zip;
+#endif
+#ifdef USE_MAD
+ zip->openArchive("dub-mp3.zzz", "mp3", MP3);
+ if (zip->isOpen() && zip->size()) return zip;
+#endif
+
+ // Return an empty (but initialized) archive anyway.
+ return zip;
+}
+
int DraciEngine::init() {
// Initialize graphics using following:
initGraphics(kScreenWidth, kScreenHeight, false);
@@ -123,15 +156,15 @@ int DraciEngine::init() {
_itemImagesArchive = new BArchive(itemImagesPath);
_stringsArchive = new BArchive(stringsPath);
- _soundsArchive = new SoundArchive(soundsPath, kSoundsFrequency);
- _dubbingArchive = new SoundArchive(dubbingPath, kDubbingFrequency);
+ _soundsArchive = new LegacySoundArchive(soundsPath, kSoundsFrequency);
+ _dubbingArchive = openAnyPossibleDubbing();
_sound = new Sound(_mixer);
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
- //bool adlib = (midiDriver == MD_ADLIB);
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+ //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
- _midiDriver = MidiDriver::createMidi(midiDriver);
+ _midiDriver = MidiDriver::createMidi(dev);
if (native_mt32)
_midiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
@@ -253,19 +286,20 @@ void DraciEngine::handleEvents() {
if (escRoom >= 0) {
// Schedule room change
- // TODO: gate 0 (always present) is not
- // always best for returning from the
- // map, e.g. in the starting location.
- // also, after loading the game, we
- // shouldn't run any gate program, but
- // rather restore the state of all
- // objects.
+ // TODO: gate 0 (always present) is not always best for
+ // returning from the map, e.g. in the starting location.
+ // also, after loading the game, we shouldn't run any gate
+ // program, but rather restore the state of all objects.
_game->scheduleEnteringRoomUsingGate(escRoom, 0);
- // Immediately cancel any running animation or dubbing.
+ // Immediately cancel any running animation or dubbing and
+ // end any currently running GPL programs. In the intro it
+ // works as intended---skipping the rest of it.
+ //
+ // In the map, this causes that animation on newly
+ // discovered locations will be re-run next time and
+ // cut-scenes won't be played.
_game->setExitLoop(true);
-
- // End any currently running GPL programs
_script->endCurrentProgram(true);
}
break;
@@ -301,6 +335,16 @@ void DraciEngine::handleEvents() {
openMainMenuDialog();
}
break;
+ case Common::KEYCODE_COMMA:
+ case Common::KEYCODE_PERIOD:
+ case Common::KEYCODE_SLASH:
+ if ((_game->getLoopStatus() == kStatusOrdinary ||
+ _game->getLoopStatus() == kStatusInventory) &&
+ _game->getLoopSubstatus() == kOuterLoop &&
+ _game->getRoomNum() != _game->getMapRoom()) {
+ _game->inventorySwitch(event.kbd.keycode);
+ }
+ break;
default:
break;
}
diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp
index 0e4b3386ec..8f3ad12cfd 100644
--- a/engines/draci/game.cpp
+++ b/engines/draci/game.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "common/keyboard.h"
#include "common/serializer.h"
#include "common/stream.h"
#include "common/system.h"
@@ -174,8 +175,20 @@ void Game::start() {
// Call the outer loop doing all the hard job.
loop(kOuterLoop, false);
- }
+ // Fade out the palette after leaving the location.
+ fadePalette(true);
+
+ if (!isReloaded()) {
+ // We are changing location. Run the hero's LOOK
+ // program to trigger a possible cut-scene. This is
+ // the behavior of the original game player, whose
+ // intention was to run the cut sequences after the
+ // certain location change.
+ const GameObject *dragon = getObject(kDragonObject);
+ _vm->_script->run(dragon->_program, dragon->_look);
+ }
+ }
}
void Game::init() {
@@ -193,7 +206,8 @@ void Game::init() {
_animUnderCursor = NULL;
_currentItem = _itemUnderCursor = NULL;
-
+ _previousItemPosition = -1;
+
_vm->_mouse->setCursorType(kHighlightedCursor); // anything different from kNormalCursor
_objUnderCursor = NULL;
@@ -263,8 +277,8 @@ void Game::handleOrdinaryLoop(int x, int y) {
if (_vm->_mouse->lButtonPressed()) {
_vm->_mouse->lButtonSet(false);
- if (_currentItem) {
- putItem(_currentItem, 0);
+ if (getCurrentItem()) {
+ putItem(getCurrentItem(), getPreviousItemPosition());
updateOrdinaryCursor();
} else {
if (_objUnderCursor) {
@@ -318,6 +332,16 @@ void Game::handleOrdinaryLoop(int x, int y) {
}
}
+int Game::inventoryPositionFromMouse() const {
+ const int column = CLIP(scummvm_lround(
+ (_vm->_mouse->getPosX() - kInventoryX + kInventoryItemWidth / 2.) /
+ kInventoryItemWidth) - 1, 0L, (long) kInventoryColumns - 1);
+ const int line = CLIP(scummvm_lround(
+ (_vm->_mouse->getPosY() - kInventoryY + kInventoryItemHeight / 2.) /
+ kInventoryItemHeight) - 1, 0L, (long) kInventoryLines - 1);
+ return line * kInventoryColumns + column;
+}
+
void Game::handleInventoryLoop() {
if (_loopSubstatus != kOuterLoop) {
return;
@@ -344,19 +368,12 @@ void Game::handleInventoryLoop() {
// If there is an inventory item under the cursor and we aren't
// holding any item, run its look GPL program
- if (_itemUnderCursor && !_currentItem) {
+ if (_itemUnderCursor && !getCurrentItem()) {
_vm->_script->runWrapper(_itemUnderCursor->_program, _itemUnderCursor->_look, true, false);
// Otherwise, if we are holding an item, try to place it inside the
// inventory
- } else if (_currentItem) {
- const int column = CLIP(scummvm_lround(
- (_vm->_mouse->getPosX() - kInventoryX + kInventoryItemWidth / 2.) /
- kInventoryItemWidth) - 1, 0L, (long) kInventoryColumns - 1);
- const int line = CLIP(scummvm_lround(
- (_vm->_mouse->getPosY() - kInventoryY + kInventoryItemHeight / 2.) /
- kInventoryItemHeight) - 1, 0L, (long) kInventoryLines - 1);
- const int index = line * kInventoryColumns + column;
- putItem(_currentItem, index);
+ } else if (getCurrentItem()) {
+ putItem(getCurrentItem(), inventoryPositionFromMouse());
updateInventoryCursor();
}
} else if (_vm->_mouse->rButtonPressed()) {
@@ -372,8 +389,9 @@ void Game::handleInventoryLoop() {
// The first is that there is no item in our hands.
// In that case, just take the inventory item from the inventory.
- if (!_currentItem) {
- _currentItem = _itemUnderCursor;
+ if (!getCurrentItem()) {
+ setCurrentItem(_itemUnderCursor);
+ setPreviousItemPosition(inventoryPositionFromMouse());
removeItem(_itemUnderCursor);
// The second is that there *is* an item in our hands.
@@ -413,6 +431,22 @@ void Game::handleDialogueLoop() {
}
}
+void Game::fadePalette(bool fading_out) {
+ const byte *startPal = NULL;
+ const byte *endPal = _currentRoom._palette >= 0
+ ? _vm->_paletteArchive->getFile(_currentRoom._palette)->_data
+ : NULL;
+ if (fading_out) {
+ startPal = endPal;
+ endPal = NULL;
+ }
+ for (int i = 1; i <= kBlackFadingIterations; ++i) {
+ _vm->_system->delayMillis(kBlackFadingTimeUnit);
+ _vm->_screen->interpolatePalettes(startPal, endPal, 0, kNumColours, i, kBlackFadingIterations);
+ _vm->_screen->copyToScreen();
+ }
+}
+
void Game::advanceAnimationsAndTestLoopExit() {
// Fade the palette if requested
if (_fadePhase > 0 && (_vm->_system->getMillis() - _fadeTick) >= kFadingTimeUnit) {
@@ -470,7 +504,7 @@ void Game::advanceAnimationsAndTestLoopExit() {
// callbacks) and redraw screen
_vm->_anims->drawScene(_vm->_screen->getSurface());
_vm->_screen->copyToScreen();
- _vm->_system->delayMillis(20);
+ _vm->_system->delayMillis(kTimeUnit);
// If the hero has arrived at his destination, after even the last
// phase was correctly animated, run the callback.
@@ -614,10 +648,10 @@ void Game::updateOrdinaryCursor() {
// If there is no game object under the cursor, try using the room itself
if (!_objUnderCursor) {
if (_vm->_script->testExpression(_currentRoom._program, _currentRoom._canUse)) {
- if (!_currentItem) {
+ if (!getCurrentItem()) {
_vm->_mouse->setCursorType(kHighlightedCursor);
} else {
- _vm->_mouse->loadItemCursor(_currentItem, true);
+ _vm->_mouse->loadItemCursor(getCurrentItem(), true);
}
mouseChanged = true;
}
@@ -628,10 +662,10 @@ void Game::updateOrdinaryCursor() {
// update the cursor image (highlight it).
if (_objUnderCursor->_walkDir == 0) {
if (_vm->_script->testExpression(_objUnderCursor->_program, _objUnderCursor->_canUse)) {
- if (!_currentItem) {
+ if (!getCurrentItem()) {
_vm->_mouse->setCursorType(kHighlightedCursor);
} else {
- _vm->_mouse->loadItemCursor(_currentItem, true);
+ _vm->_mouse->loadItemCursor(getCurrentItem(), true);
}
mouseChanged = true;
}
@@ -645,10 +679,10 @@ void Game::updateOrdinaryCursor() {
// Load the appropriate cursor (item image if an item is held or ordinary cursor
// if not)
if (!mouseChanged) {
- if (!_currentItem) {
+ if (!getCurrentItem()) {
_vm->_mouse->setCursorType(kNormalCursor);
} else {
- _vm->_mouse->loadItemCursor(_currentItem, false);
+ _vm->_mouse->loadItemCursor(getCurrentItem(), false);
}
}
}
@@ -659,19 +693,19 @@ void Game::updateInventoryCursor() {
if (_itemUnderCursor) {
if (_vm->_script->testExpression(_itemUnderCursor->_program, _itemUnderCursor->_canUse)) {
- if (!_currentItem) {
+ if (!getCurrentItem()) {
_vm->_mouse->setCursorType(kHighlightedCursor);
} else {
- _vm->_mouse->loadItemCursor(_currentItem, true);
+ _vm->_mouse->loadItemCursor(getCurrentItem(), true);
}
mouseChanged = true;
}
}
if (!mouseChanged) {
- if (!_currentItem) {
+ if (!getCurrentItem()) {
_vm->_mouse->setCursorType(kNormalCursor);
} else {
- _vm->_mouse->loadItemCursor(_currentItem, false);
+ _vm->_mouse->loadItemCursor(getCurrentItem(), false);
}
}
}
@@ -723,6 +757,8 @@ const GameObject *Game::getObjectWithAnimation(const Animation *anim) const {
}
void Game::removeItem(GameItem *item) {
+ if (!item)
+ return;
for (uint i = 0; i < kInventorySlots; ++i) {
if (_inventory[i] == item) {
_inventory[i] = NULL;
@@ -744,7 +780,7 @@ void Game::loadItemAnimation(GameItem *item) {
void Game::putItem(GameItem *item, int position) {
// Empty our hands
- _currentItem = NULL;
+ setCurrentItem(NULL);
if (!item)
return;
@@ -758,6 +794,7 @@ void Game::putItem(GameItem *item, int position) {
break;
}
}
+ setPreviousItemPosition(position);
const int line = position / kInventoryColumns + 1;
const int column = position % kInventoryColumns + 1;
@@ -845,6 +882,55 @@ void Game::inventoryReload() {
for (uint i = 0; i < kInventorySlots; ++i) {
putItem(_inventory[i], i);
}
+ setPreviousItemPosition(0);
+}
+
+void Game::inventorySwitch(int keycode) {
+ switch (keycode) {
+ case Common::KEYCODE_SLASH:
+ // Switch between holding an item and the ordinary mouse cursor.
+ if (!getCurrentItem()) {
+ if (getPreviousItemPosition() >= 0) {
+ GameItem* last_item = _inventory[getPreviousItemPosition()];
+ setCurrentItem(last_item);
+ removeItem(last_item);
+ }
+ } else {
+ putItem(getCurrentItem(), getPreviousItemPosition());
+ }
+ break;
+ case Common::KEYCODE_COMMA:
+ case Common::KEYCODE_PERIOD:
+ // Iterate between the items in the inventory.
+ if (getCurrentItem()) {
+ assert(getPreviousItemPosition() >= 0);
+ int direction = keycode == Common::KEYCODE_PERIOD ? +1 : -1;
+ // Find the next available item.
+ int pos = getPreviousItemPosition() + direction;
+ while (true) {
+ if (pos < 0)
+ pos += kInventorySlots;
+ else if (pos >= kInventorySlots)
+ pos -= kInventorySlots;
+ if (pos == getPreviousItemPosition() || _inventory[pos]) {
+ break;
+ }
+ pos += direction;
+ }
+ // Swap it with the current item.
+ putItem(getCurrentItem(), getPreviousItemPosition());
+ GameItem* new_item = _inventory[pos];
+ setCurrentItem(new_item);
+ setPreviousItemPosition(pos);
+ removeItem(new_item);
+ }
+ break;
+ }
+ if (getLoopStatus() == kStatusOrdinary) {
+ updateOrdinaryCursor();
+ } else {
+ updateInventoryCursor();
+ }
}
void Game::dialogueMenu(int dialogueID) {
@@ -1297,10 +1383,11 @@ void Game::enterNewRoom() {
loadRoomObjects();
loadOverlays();
- // Set room palette
- const BAFile *f;
- f = _vm->_paletteArchive->getFile(_currentRoom._palette);
- _vm->_screen->setPalette(f->_data, 0, kNumColours);
+ // Draw the scene with the black palette and slowly fade into the right palette.
+ _vm->_screen->setPalette(NULL, 0, kNumColours);
+ _vm->_anims->drawScene(_vm->_screen->getSurface());
+ _vm->_screen->copyToScreen();
+ fadePalette(false);
// Run the program for the gate the dragon came through
debugC(6, kDraciLogicDebugLevel, "Running program for gate %d", _newGate);
diff --git a/engines/draci/game.h b/engines/draci/game.h
index 3d02489da7..21baaed5cc 100644
--- a/engines/draci/game.h
+++ b/engines/draci/game.h
@@ -65,9 +65,16 @@ enum SpeechConstants {
kStandardSpeed = 60
};
-// One fading phase is 50ms.
enum FadeConstants {
- kFadingTimeUnit = 50
+ // One fading phase called from the game scripts is 50ms.
+ kFadingTimeUnit = 50,
+ // Fading in/out when entering/leaving a location takes 15 iterations of (at least) 7ms each.
+ kBlackFadingIterations = 15,
+ kBlackFadingTimeUnit = 7
+};
+
+enum AnimationConstants {
+ kTimeUnit = 20
};
/** Inventory related magical constants */
@@ -255,6 +262,8 @@ public:
GameItem *getItem(int id) { return id >= 0 && id < (int) _info._numItems ? &_items[id] : NULL; }
GameItem *getCurrentItem() const { return _currentItem; }
void setCurrentItem(GameItem *item) { _currentItem = item; }
+ int getPreviousItemPosition() const { return _previousItemPosition; }
+ void setPreviousItemPosition(int pos) { _previousItemPosition = pos; }
void removeItem(GameItem *item);
void loadItemAnimation(GameItem *item);
void putItem(GameItem *item, int position);
@@ -292,6 +301,7 @@ public:
void inventoryDraw();
void inventoryDone();
void inventoryReload();
+ void inventorySwitch(int keycode);
void dialogueMenu(int dialogueID);
int dialogueDraw();
@@ -325,11 +335,13 @@ public:
private:
void updateOrdinaryCursor();
void updateInventoryCursor();
+ int inventoryPositionFromMouse() const;
void handleOrdinaryLoop(int x, int y);
void handleInventoryLoop();
void handleDialogueLoop();
void updateTitle(int x, int y);
void updateCursor();
+ void fadePalette(bool fading_out);
void advanceAnimationsAndTestLoopExit();
void handleStatusChangeByMouse();
@@ -353,6 +365,10 @@ private:
GameItem *_currentItem;
GameItem *_itemUnderCursor;
+ // Last position in the inventory of the item currently in the hands, resp. of the item that
+ // was last in our hands.
+ int _previousItemPosition;
+
GameItem *_inventory[kInventorySlots];
Room _currentRoom;
diff --git a/engines/draci/module.mk b/engines/draci/module.mk
index a172e4b939..1f80737135 100644
--- a/engines/draci/module.mk
+++ b/engines/draci/module.mk
@@ -17,9 +17,6 @@ MODULE_OBJS := \
surface.o \
walking.o
-MODULE_DIRS += \
- engines/draci
-
# This module can be built as a plugin
ifeq ($(ENABLE_DRACI), DYNAMIC_PLUGIN)
PLUGIN := 1
diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp
index a366740526..7a6a68618d 100644
--- a/engines/draci/script.cpp
+++ b/engines/draci/script.cpp
@@ -553,6 +553,7 @@ void Script::icoStat(const Common::Array<int> &params) {
// arrow leading outside a location), set it to standard.
if (_vm->_game->getCurrentItem() == item) {
_vm->_game->setCurrentItem(NULL);
+ _vm->_game->setPreviousItemPosition(-1);
if (_vm->_mouse->getCursorType() >= kItemCursor) {
_vm->_mouse->setCursorType(kNormalCursor);
}
@@ -561,6 +562,7 @@ void Script::icoStat(const Common::Array<int> &params) {
} else {
_vm->_game->loadItemAnimation(item);
_vm->_game->setCurrentItem(item);
+ _vm->_game->setPreviousItemPosition(0); // next time, try to place the item from the beginning
_vm->_mouse->loadItemCursor(item, false);
}
}
@@ -727,10 +729,10 @@ void Script::talk(const Common::Array<int> &params) {
// Speak the dubbing if possible
uint dubbingDuration = 0;
if (sample) {
- dubbingDuration = (uint) (1000.0 * sample->_length / sample->_frequency + 500.0);
+ dubbingDuration = _vm->_sound->playVoice(sample);
debugC(3, kDraciSoundDebugLevel, "Playing sentence %d: %d+%d with duration %dms",
sentenceID, sample->_offset, sample->_length, dubbingDuration);
- _vm->_sound->playVoice(sample);
+ dubbingDuration += 500;
}
// Record time
@@ -879,7 +881,7 @@ void Script::setPalette(const Common::Array<int> &params) {
}
// Immediately update the palette
_vm->_screen->copyToScreen();
- _vm->_system->delayMillis(20);
+ _vm->_system->delayMillis(kTimeUnit);
}
void Script::quitGame(const Common::Array<int> &params) {
diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp
index 4fb2fd6309..c9244d7eac 100644
--- a/engines/draci/sound.cpp
+++ b/engines/draci/sound.cpp
@@ -23,11 +23,13 @@
*
*/
+#include "common/archive.h"
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/file.h"
#include "common/str.h"
#include "common/stream.h"
+#include "common/unzip.h"
#include "draci/sound.h"
#include "draci/draci.h"
@@ -36,21 +38,24 @@
#include "sound/audiostream.h"
#include "sound/mixer.h"
#include "sound/decoders/raw.h"
+#include "sound/decoders/mp3.h"
+#include "sound/decoders/vorbis.h"
+#include "sound/decoders/flac.h"
namespace Draci {
-void SoundArchive::openArchive(const Common::String &path) {
+void LegacySoundArchive::openArchive(const char *path) {
// Close previously opened archive (if any)
closeArchive();
- debugCN(2, kDraciArchiverDebugLevel, "Loading samples %s: ", path.c_str());
+ debugCN(1, kDraciArchiverDebugLevel, "Loading samples %s: ", path);
_f = new Common::File();
_f->open(path);
if (_f->isOpen()) {
- debugC(2, kDraciArchiverDebugLevel, "Success");
+ debugC(1, kDraciArchiverDebugLevel, "Success");
} else {
- debugC(2, kDraciArchiverDebugLevel, "Error");
+ debugC(1, kDraciArchiverDebugLevel, "Error");
delete _f;
_f = NULL;
return;
@@ -60,7 +65,7 @@ void SoundArchive::openArchive(const Common::String &path) {
_path = path;
// Read archive header
- debugC(2, kDraciArchiverDebugLevel, "Loading header");
+ debugC(1, kDraciArchiverDebugLevel, "Loading header");
uint totalLength = _f->readUint32LE();
const uint kMaxSamples = 4095; // The no-sound file is exactly 16K bytes long, so don't fail on short reads
@@ -76,26 +81,25 @@ void SoundArchive::openArchive(const Common::String &path) {
break;
}
if (_sampleCount > 0) {
- debugC(2, kDraciArchiverDebugLevel, "Archive info: %d samples, %d total length",
+ debugC(1, kDraciArchiverDebugLevel, "Archive info: %d samples, %d total length",
_sampleCount, totalLength);
_samples = new SoundSample[_sampleCount];
for (uint i = 0; i < _sampleCount; ++i) {
_samples[i]._offset = sampleStarts[i];
_samples[i]._length = sampleStarts[i+1] - sampleStarts[i];
_samples[i]._frequency = 0; // set in getSample()
- _samples[i]._data = NULL;
}
if (_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length != totalLength &&
_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length - _samples[0]._offset != totalLength) {
// WORKAROUND: the stored length is stored with the header for sounds and without the hader for dubbing. Crazy.
- debugC(2, kDraciArchiverDebugLevel, "Broken sound archive: %d != %d",
+ debugC(1, kDraciArchiverDebugLevel, "Broken sound archive: %d != %d",
_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length,
totalLength);
closeArchive();
return;
}
} else {
- debugC(2, kDraciArchiverDebugLevel, "Archive info: empty");
+ debugC(1, kDraciArchiverDebugLevel, "Archive info: empty");
}
// Indicate that the archive has been successfully opened
@@ -103,12 +107,12 @@ void SoundArchive::openArchive(const Common::String &path) {
}
/**
- * @brief SoundArchive close method
+ * @brief LegacySoundArchive close method
*
* Closes the currently opened archive. It can be called explicitly to
* free up memory.
*/
-void SoundArchive::closeArchive() {
+void LegacySoundArchive::closeArchive() {
clearCache();
delete _f;
_f = NULL;
@@ -123,7 +127,7 @@ void SoundArchive::closeArchive() {
* Clears the cache of the open files inside the archive without closing it.
* If the files are subsequently accessed, they are read from the disk.
*/
-void SoundArchive::clearCache() {
+void LegacySoundArchive::clearCache() {
// Delete all cached data
for (uint i = 0; i < _sampleCount; ++i) {
_samples[i].close();
@@ -137,32 +141,121 @@ void SoundArchive::clearCache() {
*
* Loads individual samples from an archive to memory on demand.
*/
-SoundSample *SoundArchive::getSample(int i, uint freq) {
+SoundSample *LegacySoundArchive::getSample(int i, uint freq) {
// Check whether requested file exists
if (i < 0 || i >= (int) _sampleCount) {
return NULL;
}
debugCN(2, kDraciArchiverDebugLevel, "Accessing sample %d from archive %s... ",
- i, _path.c_str());
+ i, _path);
// Check if file has already been opened and return that
if (_samples[i]._data) {
- debugC(2, kDraciArchiverDebugLevel, "Success");
+ debugC(2, kDraciArchiverDebugLevel, "Cached");
} else {
+ // It would be nice to unify the approach with ZipSoundArchive
+ // and allocate a MemoryReadStream with buffer stored inside it
+ // that playSoundBuffer() would just play. Unfortunately,
+ // streams are not thread-safe and the same sample couldn't
+ // thus be played more than once at the same time (this holds
+ // even if we create a SeekableSubReadStream from it as this
+ // just uses the parent). The only thread-safe solution is to
+ // share a read-only buffer and allocate separate
+ // MemoryReadStream's on top of it.
+ _samples[i]._data = new byte[_samples[i]._length];
+ _samples[i]._format = RAW;
+
// Read in the file (without the file header)
_f->seek(_samples[i]._offset);
- _samples[i]._data = new byte[_samples[i]._length];
_f->read(_samples[i]._data, _samples[i]._length);
- debugC(3, kDraciArchiverDebugLevel, "Cached sample %d from archive %s",
- i, _path.c_str());
+ debugC(2, kDraciArchiverDebugLevel, "Read sample %d from archive %s",
+ i, _path);
}
_samples[i]._frequency = freq ? freq : _defaultFreq;
return _samples + i;
}
+void ZipSoundArchive::openArchive(const char *path, const char *extension, SoundFormat format, int raw_frequency) {
+ closeArchive();
+ if ((format == RAW || format == RAW80) && !raw_frequency) {
+ error("openArchive() expects frequency for RAW data");
+ return;
+ }
+
+ debugCN(1, kDraciArchiverDebugLevel, "Trying to open ZIP archive %s: ", path);
+ _archive = Common::makeZipArchive(path);
+ _path = path;
+ _extension = extension;
+ _format = format;
+ _defaultFreq = raw_frequency;
+
+ if (_archive) {
+ Common::ArchiveMemberList files;
+ _archive->listMembers(files);
+ _sampleCount = files.size();
+ debugC(1, kDraciArchiverDebugLevel, "Capacity %d", _sampleCount);
+ } else {
+ debugC(1, kDraciArchiverDebugLevel, "Failed");
+ }
+}
+
+void ZipSoundArchive::closeArchive() {
+ clearCache();
+ delete _archive;
+ _archive = NULL;
+ _path = _extension = NULL;
+ _sampleCount = _defaultFreq = 0;
+ _format = RAW;
+}
+
+void ZipSoundArchive::clearCache() {
+ // Just deallocate the link-list of (very short) headers for each
+ // dubbed sentence played in the current location. If the callers have
+ // not called .close() on any of the items, call them now.
+ for (Common::List<SoundSample>::iterator it = _cache.begin(); it != _cache.end(); ++it) {
+ it->close();
+ }
+ _cache.clear();
+}
+
+SoundSample *ZipSoundArchive::getSample(int i, uint freq) {
+ if (i < 0 || i >= (int) _sampleCount) {
+ return NULL;
+ }
+ debugCN(2, kDraciArchiverDebugLevel, "Accessing sample %d.%s from archive %s (format %d@%d, capacity %d): ",
+ i, _extension, _path, static_cast<int> (_format), _defaultFreq, _sampleCount);
+ if (freq != 0 && (_format != RAW && _format != RAW80)) {
+ error("Cannot resample a sound in compressed format");
+ return NULL;
+ }
+
+ // We cannot really cache anything, because createReadStreamForMember()
+ // returns the data as a ReadStream, which is not thread-safe. We thus
+ // read it again each time even if it has possibly been already cached
+ // a while ago. This is not such a problem for dubbing as for regular
+ // sound samples.
+ SoundSample sample;
+ sample._frequency = freq ? freq : _defaultFreq;
+ sample._format = _format;
+ // Read in the file (without the file header)
+ char file_name[20];
+ sprintf(file_name, "%d.%s", i+1, _extension);
+ sample._stream = _archive->createReadStreamForMember(file_name);
+ if (!sample._stream) {
+ debugC(2, kDraciArchiverDebugLevel, "Doesn't exist");
+ return NULL;
+ } else {
+ debugC(2, kDraciArchiverDebugLevel, "Read");
+ _cache.push_back(sample);
+ // Return a pointer that we own and which we will deallocate
+ // including its contents.
+ return &_cache.back();
+ }
+}
+
Sound::Sound(Audio::Mixer *mixer) : _mixer(mixer), _muteSound(false), _muteVoice(false),
_showSubtitles(true), _talkSpeed(kStandardSpeed) {
@@ -192,28 +285,74 @@ SndHandle *Sound::getHandle() {
return NULL; // for compilers that don't support NORETURN
}
-void Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume,
+uint Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume,
sndHandleType handleType, bool loop) {
+ if (!buffer._stream && !buffer._data) {
+ warning("Empty stream");
+ return 0;
+ }
+ // Create a new SeekableReadStream which will be automatically disposed
+ // after the sample stops playing. Do not dispose the original
+ // data/stream though.
+ // Beware that if the sample comes from an archive (i.e., is stored in
+ // buffer._stream), then you must NOT play it more than once at the
+ // same time, because streams are not thread-safe. Playing it
+ // repeatedly is OK. Currently this is ensured by that archives are
+ // only used for dubbing, which is only played from one place in
+ // script.cpp, which blocks until the dubbed sentence has finished
+ // playing.
+ Common::SeekableReadStream* stream;
+ const int skip = buffer._format == RAW80 ? 80 : 0;
+ if (buffer._stream) {
+ stream = new Common::SeekableSubReadStream(
+ buffer._stream, skip, buffer._stream->size() /* end */, DisposeAfterUse::NO);
+ } else {
+ stream = new Common::MemoryReadStream(
+ buffer._data + skip, buffer._length - skip /* length */, DisposeAfterUse::NO);
+ }
- byte flags = Audio::FLAG_UNSIGNED;
+ Audio::SeekableAudioStream *reader = NULL;
+ switch (buffer._format) {
+ case RAW:
+ case RAW80:
+ reader = Audio::makeRawStream(stream, buffer._frequency, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
+ break;
+#ifdef USE_MAD
+ case MP3:
+ reader = Audio::makeMP3Stream(stream, DisposeAfterUse::YES);
+ break;
+#endif
+#ifdef USE_VORBIS
+ case OGG:
+ reader = Audio::makeVorbisStream(stream, DisposeAfterUse::YES);
+ break;
+#endif
+#ifdef USE_FLAC
+ case FLAC:
+ reader = Audio::makeFLACStream(stream, DisposeAfterUse::YES);
+ break;
+#endif
+ default:
+ error("Unsupported compression format %d", static_cast<int> (buffer._format));
+ delete stream;
+ return 0;
+ }
+ const uint length = reader->getLength().msecs();
const Audio::Mixer::SoundType soundType = (handleType == kVoiceHandle) ?
Audio::Mixer::kSpeechSoundType : Audio::Mixer::kSFXSoundType;
-
- // Don't use DisposeAfterUse::YES, because our caching system deletes samples by itself.
- Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
- Audio::makeRawStream(buffer._data, buffer._length, buffer._frequency, flags, DisposeAfterUse::NO),
- loop ? 0 : 1);
- _mixer->playStream(soundType, handle, stream, -1, volume);
+ Audio::AudioStream *audio_stream = Audio::makeLoopingAudioStream(reader, loop ? 0 : 1);
+ _mixer->playStream(soundType, handle, audio_stream, -1, volume);
+ return length;
}
-void Sound::playSound(const SoundSample *buffer, int volume, bool loop) {
+uint Sound::playSound(const SoundSample *buffer, int volume, bool loop) {
if (!buffer || _muteSound)
- return;
+ return 0;
SndHandle *handle = getHandle();
handle->type = kEffectHandle;
- playSoundBuffer(&handle->handle, *buffer, 2 * volume, handle->type, loop);
+ return playSoundBuffer(&handle->handle, *buffer, 2 * volume, handle->type, loop);
}
void Sound::pauseSound() {
@@ -237,13 +376,13 @@ void Sound::stopSound() {
}
}
-void Sound::playVoice(const SoundSample *buffer) {
+uint Sound::playVoice(const SoundSample *buffer) {
if (!buffer || _muteVoice)
- return;
+ return 0;
SndHandle *handle = getHandle();
handle->type = kVoiceHandle;
- playSoundBuffer(&handle->handle, *buffer, Audio::Mixer::kMaxChannelVolume, handle->type, false);
+ return playSoundBuffer(&handle->handle, *buffer, Audio::Mixer::kMaxChannelVolume, handle->type, false);
}
void Sound::pauseVoice() {
diff --git a/engines/draci/sound.h b/engines/draci/sound.h
index 28379b5429..6e9aae1b6e 100644
--- a/engines/draci/sound.h
+++ b/engines/draci/sound.h
@@ -28,50 +28,101 @@
#include "common/str.h"
#include "common/file.h"
+#include "common/list.h"
#include "sound/mixer.h"
+namespace Common {
+class Archive;
+class SeekableReadStream;
+}
+
namespace Draci {
+enum SoundFormat { RAW, RAW80, MP3, OGG, FLAC }; // RAW80 means skip the first 80 bytes
+
/**
* Represents individual files inside the archive.
*/
struct SoundSample {
- uint _offset;
+ uint _offset; // For internal use of LegacySoundArchive
uint _length;
- uint _frequency;
- byte* _data;
+ uint _frequency; // Only when _format == RAW or RAW80
+ SoundFormat _format;
+
+ byte *_data; // At most one of these two pointer can be non-NULL
+ Common::SeekableReadStream* _stream;
+
+ SoundSample() : _offset(0), _length(0), _frequency(0), _format(RAW), _data(NULL), _stream(NULL) { }
+ // The standard copy constructor is good enough, since we only store numbers and pointers.
+ // Don't call close() automaticall in the destructor, otherwise copying causes SIGSEGV.
void close() {
delete[] _data;
+ delete _stream;
_data = NULL;
+ _stream = NULL;
}
};
+/**
+ * An abstract wrapper around archives of sound samples or dubbing.
+ */
class SoundArchive {
public:
- SoundArchive(const Common::String &path, uint defaultFreq) :
- _path(), _samples(NULL), _sampleCount(0), _defaultFreq(defaultFreq), _opened(false), _f(NULL) {
- openArchive(path);
- }
+ SoundArchive() { }
+ virtual ~SoundArchive() { }
- ~SoundArchive() { closeArchive(); }
-
- void closeArchive();
- void openArchive(const Common::String &path);
- uint size() const { return _sampleCount; }
+ /**
+ * Returns the number of sound samples in the archive. Zero means that
+ * a fake empty archive has been opened and the caller may consider
+ * opening a different one, for example with compressed music.
+ */
+ virtual uint size() const = 0;
/**
* Checks whether there is an archive opened. Should be called before reading
- * from the archive to check whether openArchive() succeeded.
+ * from the archive to check whether opening of the archive has succeeded.
+ */
+ virtual bool isOpen() const = 0;
+
+ /**
+ * Removes cached samples from memory.
*/
- bool isOpen() const { return _opened; }
+ virtual void clearCache() = 0;
+
+ /**
+ * Caches a given sample into memory and returns a pointer into it. We
+ * own the returned pointer, but the user may call .close() on it,
+ * which deallocates the memory of the actual sample data. If freq is
+ * nonzero, then the sample is played at a different frequency (only
+ * works for uncompressed samples).
+ */
+ virtual SoundSample *getSample(int i, uint freq) = 0;
+};
- void clearCache();
+/**
+ * Reads CD.SAM (with dubbing) and CD2.SAM (with sound samples) from the
+ * original game. Caches all read samples in a thread-safe manner.
+ */
+class LegacySoundArchive : public SoundArchive {
+public:
+ LegacySoundArchive(const char *path, uint defaultFreq) :
+ _path(NULL), _samples(NULL), _sampleCount(0), _defaultFreq(defaultFreq), _opened(false), _f(NULL) {
+ openArchive(path);
+ }
+ virtual ~LegacySoundArchive() { closeArchive(); }
- SoundSample *getSample(int i, uint freq);
+ void openArchive(const char *path);
+ void closeArchive();
+
+ virtual uint size() const { return _sampleCount; }
+ virtual bool isOpen() const { return _opened; }
+
+ virtual void clearCache();
+ virtual SoundSample *getSample(int i, uint freq);
private:
- Common::String _path; ///< Path to file
+ const char *_path; ///< Path to file
SoundSample *_samples; ///< Internal array of files
uint _sampleCount; ///< Number of files in archive
uint _defaultFreq; ///< The default sampling frequency of the archived samples
@@ -79,6 +130,44 @@ private:
Common::File *_f; ///< Opened file
};
+/**
+ * Reads ZIP archives with uncompressed files containing lossy-compressed
+ * samples in arbitrary format. Doesn't do any real caching and is
+ * thread-safe.
+ */
+class ZipSoundArchive : public SoundArchive {
+public:
+ ZipSoundArchive() : _archive(NULL), _path(NULL), _extension(NULL), _format(RAW), _sampleCount(0), _defaultFreq(0), _cache() { }
+ virtual ~ZipSoundArchive() { closeArchive(); }
+
+ void openArchive(const char *path, const char *extension, SoundFormat format, int raw_frequency = 0);
+ void closeArchive();
+
+ virtual uint size() const { return _sampleCount; }
+ virtual bool isOpen() const { return _archive != NULL; }
+
+ virtual void clearCache();
+ virtual SoundSample *getSample(int i, uint freq);
+
+private:
+ Common::Archive *_archive;
+ const char *_path;
+ const char *_extension;
+ SoundFormat _format;
+ uint _sampleCount;
+ uint _defaultFreq;
+
+ // Since we typically play at most 1 dubbing at a time, we could get
+ // away with having just 1 record allocated and reusing it each time.
+ // However, that would be thread-unsafe if two samples were played.
+ // Although the player does not do that, it is nicer to allow for it in
+ // principle. For each dubbed sentence, we allocate a new record in
+ // the following link-list, which is cleared during each location
+ // change. The dubbed samples themselves are manually deallocated
+ // after they end.
+ Common::List<SoundSample> _cache;
+};
+
#define SOUND_HANDLES 10
enum sndHandleType {
@@ -100,13 +189,13 @@ public:
Sound(Audio::Mixer *mixer);
~Sound() {}
- void playSound(const SoundSample *buffer, int volume, bool loop);
+ uint playSound(const SoundSample *buffer, int volume, bool loop);
void pauseSound();
void resumeSound();
void stopSound();
bool isMutedSound() const { return _muteSound; }
- void playVoice(const SoundSample *buffer);
+ uint playVoice(const SoundSample *buffer);
void pauseVoice();
void resumeVoice();
void stopVoice();
@@ -120,7 +209,8 @@ public:
int talkSpeed() const { return _talkSpeed; }
private:
- void playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume,
+ // Returns the length of the sound sample in miliseconds.
+ uint playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume,
sndHandleType handleType, bool loop);
SndHandle *getHandle();
diff --git a/engines/draci/walking.cpp b/engines/draci/walking.cpp
index e57972fbc5..02612832d2 100644
--- a/engines/draci/walking.cpp
+++ b/engines/draci/walking.cpp
@@ -324,7 +324,7 @@ void WalkingMap::drawOverlayRectangle(const Common::Point &p, byte colour, byte
}
int WalkingMap::pointsBetween(const Common::Point &p1, const Common::Point &p2) {
- return MAX(abs(p2.x - p1.x), abs(p2.y - p1.y));
+ return MAX(ABS(p2.x - p1.x), ABS(p2.y - p1.y));
}
Common::Point WalkingMap::interpolate(const Common::Point &p1, const Common::Point &p2, int i, int n) {
@@ -636,7 +636,7 @@ bool WalkingState::walkOnNextEdge() {
Movement WalkingState::animationForDirection(const Common::Point &here, const Common::Point &there) {
const int dx = there.x - here.x;
const int dy = there.y - here.y;
- if (abs(dx) >= abs(dy)) {
+ if (ABS(dx) >= ABS(dy)) {
return dx >= 0 ? kMoveRight : kMoveLeft;
} else {
return dy >= 0 ? kMoveDown : kMoveUp;
diff --git a/engines/drascula/actors.cpp b/engines/drascula/actors.cpp
index ff46d8201a..8523b5b158 100644
--- a/engines/drascula/actors.cpp
+++ b/engines/drascula/actors.cpp
@@ -77,6 +77,7 @@ void DrasculaEngine::hiccup(int counter) {
do {
counter--;
+ updateEvents();
updateRoom();
if (currentChapter == 3)
updateScreen(0, 0, 0, y, 320, 200, screenSurface);
@@ -99,6 +100,7 @@ void DrasculaEngine::hiccup(int counter) {
if (y == 0)
trackCharacter = 0;
}
+ pause(3);
} while (counter > 0);
updateRoom();
@@ -310,9 +312,9 @@ void DrasculaEngine::quadrant_2() {
float distanceX, distanceY;
if (currentChapter == 2)
- distanceX = abs(curX + curWidth - roomX);
+ distanceX = ABS(curX + curWidth - roomX);
else
- distanceX = abs(curX + curWidth / 2 - roomX);
+ distanceX = ABS(curX + curWidth / 2 - roomX);
distanceY = (curY + curHeight) - roomY;
@@ -352,9 +354,9 @@ void DrasculaEngine::quadrant_4() {
float distanceX, distanceY;
if (currentChapter == 2)
- distanceX = abs(curX + curWidth - roomX);
+ distanceX = ABS(curX + curWidth - roomX);
else
- distanceX = abs(curX + curWidth / 2 - roomX);
+ distanceX = ABS(curX + curWidth / 2 - roomX);
distanceY = roomY - (curY + curHeight);
@@ -449,6 +451,7 @@ void DrasculaEngine::placeVonBraun(int pointX) {
vonBraunHasMoved = 1;
for (;;) {
+ updateEvents();
updateRoom();
updateScreen();
if (trackVonBraun == 0) {
diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp
index 4a0b82d746..1d6f77b8eb 100644
--- a/engines/drascula/animation.cpp
+++ b/engines/drascula/animation.cpp
@@ -32,17 +32,23 @@ void DrasculaEngine::updateAnim(int y, int destX, int destY, int width, int heig
for (int n = 0; n < count; n++){
x++;
- copyBackground(x, y, destX, destY, width, height, src, screenSurface);
- if (copyRectangle)
+ if (copyRectangle) {
+ copyBackground(destX, destY, destX, destY, width, height, bgSurface, screenSurface);
copyRect(x, y, destX, destY, width, height, src, screenSurface);
+ } else {
+ copyBackground(x, y, destX, destY, width, height, src, screenSurface);
+ }
updateScreen(destX, destY, destX, destY, width, height, screenSurface);
x += width;
+ updateEvents();
pause(delayVal);
}
}
// This is the game's introduction sequence
void DrasculaEngine::animation_1_1() {
+ debug(4, "animation_1_1()");
+
int l, l2, p;
//int pixelPos[6];
@@ -141,9 +147,9 @@ void DrasculaEngine::animation_1_1() {
copyBackground(0, 0, 320 - l, 0, l, 200, drawSurface3, screenSurface);
copyBackground(l, 0, 0, 0, 320 - l, 200, bgSurface, screenSurface);
- copyRect(interf_x[l2], interf_y[l2], 156 - l, 45, 63, 31,
- drawSurface2, screenSurface);
+ copyRect(interf_x[l2], interf_y[l2], 156 - l, 45, 63, 31, drawSurface2, screenSurface);
updateScreen();
+ updateEvents();
p++;
if (p == 6) {
p = 0;
@@ -371,6 +377,8 @@ void DrasculaEngine::animation_1_1() {
// John falls in love with BJ, who is then abducted by Drascula
void DrasculaEngine::animation_2_1() {
+ debug(4, "animation_2_1()");
+
int l;
gotoObject(231, 91);
@@ -560,6 +568,8 @@ void DrasculaEngine::animation_2_1() {
// John Hacker talks with the bartender to book a room
void DrasculaEngine::animation_3_1() {
+ debug(4, "animation_3_1()");
+
loadPic("an11y13.alg", extraSurface);
playTalkSequence(3); // sequence 3, chapter 1
@@ -569,6 +579,8 @@ void DrasculaEngine::animation_3_1() {
// John Hacker talks with the pianist
void DrasculaEngine::animation_4_1() {
+ debug(4, "animation_4_1()");
+
loadPic("an12.alg", extraSurface);
talk(205);
@@ -605,6 +617,8 @@ void DrasculaEngine::animation_4_1() {
}
void DrasculaEngine::animation_2_2() {
+ debug(4, "animation_2_2()");
+
trackProtagonist = 0;
copyBackground();
moveCharacters();
@@ -640,6 +654,8 @@ void DrasculaEngine::animation_2_2() {
}
void DrasculaEngine::animation_4_2() {
+ debug(4, "animation_4_2()");
+
stopMusic();
flags[9] = 1;
@@ -704,6 +720,8 @@ void DrasculaEngine::animation_4_2() {
}
void DrasculaEngine::animation_14_2() {
+ debug(4, "animation_14_2()");
+
int cY = -160;
int l = 0;
@@ -735,6 +753,8 @@ void DrasculaEngine::animation_14_2() {
// The drunk tells us about Von Braun
void DrasculaEngine::animation_16_2() {
+ debug(4, "animation_16_2()");
+
char curPic[20];
talk_drunk(12);
talk(371);
@@ -812,6 +832,8 @@ asco:
}
void DrasculaEngine::animation_20_2() {
+ debug(4, "animation_20_2()");
+
talk_vonBraun(7, kVonBraunDoor);
talk_vonBraun(8, kVonBraunDoor);
talk(383);
@@ -842,6 +864,8 @@ void DrasculaEngine::animation_20_2() {
}
void DrasculaEngine::animation_23_2() {
+ debug(4, "animation_23_2()");
+
loadPic("an24.alg", frontSurface);
flags[21] = 1;
@@ -897,6 +921,8 @@ void DrasculaEngine::animation_23_2() {
}
void DrasculaEngine::animation_23_joined() {
+ debug(4, "animation_23_joined()");
+
int p_x = curX + 2, p_y = curY - 3;
int x[] = {1, 38, 75, 112, 75, 112, 75, 112, 149, 112, 149, 112, 149, 186, 223, 260,
1, 38, 75, 112, 149, 112, 149, 112, 149, 112, 149, 186, 223, 260, 260, 260, 260, 223};
@@ -910,6 +936,7 @@ void DrasculaEngine::animation_23_joined() {
copyRect(x[n], y[n], p_x, p_y, 36, 74, backSurface, screenSurface);
updateRefresh();
updateScreen(p_x, p_y, p_x, p_y, 36, 74, screenSurface);
+ updateEvents();
pause(5);
}
@@ -917,6 +944,8 @@ void DrasculaEngine::animation_23_joined() {
}
void DrasculaEngine::animation_23_joined2() {
+ debug(4, "animation_23_joined2()");
+
int p_x = curX + 4, p_y = curY;
int x[] = {1, 35, 69, 103, 137, 171, 205, 239, 273, 1, 35, 69, 103, 137};
int y[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 73, 73, 73, 73, 73};
@@ -930,6 +959,7 @@ void DrasculaEngine::animation_23_joined2() {
copyRect(x[n], y[n], p_x, p_y, 33, 71, backSurface, screenSurface);
updateRefresh();
updateScreen(p_x,p_y, p_x,p_y, 33,71, screenSurface);
+ updateEvents();
pause(5);
}
@@ -937,6 +967,8 @@ void DrasculaEngine::animation_23_joined2() {
}
void DrasculaEngine::animation_25_2() {
+ debug(4, "animation_25_2()");
+
int cY = 0;
loadPic("an14_2.alg", backSurface);
@@ -959,6 +991,7 @@ void DrasculaEngine::animation_25_2() {
updateRefresh();
updateScreen();
+ updateEvents();
}
finishSound();
@@ -967,6 +1000,8 @@ void DrasculaEngine::animation_25_2() {
}
void DrasculaEngine::animation_27_2() {
+ debug(4, "animation_27_2()");
+
flags[22] = 1;
selectVerb(kVerbNone);
@@ -986,6 +1021,8 @@ void DrasculaEngine::animation_27_2() {
}
void DrasculaEngine::animation_29_2() {
+ debug(4, "animation_29_2()");
+
if (flags[33] == 0) {
playTalkSequence(29); // sequence 29, chapter 2
} else
@@ -1002,6 +1039,8 @@ void DrasculaEngine::animation_29_2() {
}
void DrasculaEngine::animation_31_2() {
+ debug(4, "animation_31_2()");
+
talk_vonBraun(44, kVonBraunNormal);
placeVonBraun(-50);
pause(15);
@@ -1020,6 +1059,8 @@ void DrasculaEngine::animation_31_2() {
}
void DrasculaEngine::animation_35_2() {
+ debug(4, "animation_35_2()");
+
gotoObject(96, 165);
gotoObject(79, 165);
@@ -1049,7 +1090,10 @@ void DrasculaEngine::animation_35_2() {
fadeToBlack(2);
}
+// Use cross on Yoda
void DrasculaEngine::animation_2_3() {
+ debug(4, "animation_2_3()");
+
flags[0] = 1;
playMusic(13);
animation_3_3();
@@ -1070,6 +1114,8 @@ void DrasculaEngine::animation_2_3() {
}
void DrasculaEngine::animation_3_3() {
+ debug(4, "animation_3_3()");
+
int px = curX - 20, py = curY - 1;
loadPic("an2y_1.alg", frontSurface);
@@ -1085,6 +1131,8 @@ void DrasculaEngine::animation_3_3() {
}
void DrasculaEngine::animation_4_3() {
+ debug(4, "animation_4_3()");
+
int px = 120, py = 63;
loadPic("any_1.alg", frontSurface);
@@ -1100,6 +1148,8 @@ void DrasculaEngine::animation_4_3() {
}
void DrasculaEngine::animation_5_3() {
+ debug(4, "animation_5_3()");
+
int px = curX - 20, py = curY - 1;
loadPic("an3y_1.alg", frontSurface);
@@ -1115,6 +1165,8 @@ void DrasculaEngine::animation_5_3() {
}
void DrasculaEngine::animation_6_3() {
+ debug(4, "animation_6_3()");
+
int frame = 0, px = 112, py = 62;
int yoda_x[] = { 3 ,82, 161, 240, 3, 82 };
int yoda_y[] = { 3, 3, 3, 3, 94, 94 };
@@ -1133,6 +1185,7 @@ void DrasculaEngine::animation_6_3() {
copyBackground();
copyRect(yoda_x[frame], yoda_y[frame], px, py, 78, 90, frontSurface, screenSurface);
updateScreen(px, py, px, py, 78, 90, screenSurface);
+ updateEvents();
}
flags[2] = 1;
@@ -1144,6 +1197,8 @@ void DrasculaEngine::animation_6_3() {
}
void DrasculaEngine::animation_ray() {
+ debug(4, "animation_ray()");
+
loadPic("anr_1.alg", frontSurface, HALF_PAL);
loadPic("anr_2.alg", extraSurface);
loadPic("anr_3.alg", backSurface);
@@ -1171,6 +1226,8 @@ void DrasculaEngine::animation_ray() {
}
void DrasculaEngine::animation_7_4() {
+ debug(4, "animation_7_4()");
+
black();
talk(427);
fadeFromBlack(1);
@@ -1184,6 +1241,8 @@ void DrasculaEngine::animation_7_4() {
}
void DrasculaEngine::animation_1_5() {
+ debug(4, "animation_1_5()");
+
if (flags[0] == 0) {
talk(430);
talk_bj(16);
@@ -1212,6 +1271,7 @@ void DrasculaEngine::animation_1_5() {
break;
updateRoom();
updateScreen();
+ updateEvents();
}
trackProtagonist = 1;
@@ -1224,6 +1284,8 @@ void DrasculaEngine::animation_1_5() {
}
void DrasculaEngine::animation_5_5(){
+ debug(4, "animation_5_5(");
+
int h;
int frame = 0;
int boneX[] = {1, 99, 197, 1, 99, 197, 1, 99, 197};
@@ -1247,6 +1309,7 @@ void DrasculaEngine::animation_5_5(){
copyBackground();
copyRect(boneX[frame], boneY[frame], pixelX, pixelY, 97, 64, backSurface, screenSurface);
updateScreen(pixelX, pixelY, pixelX,pixelY, 97,64, screenSurface);
+ updateEvents();
}
copyBackground(52, 161, 198, 81, 26, 24, drawSurface3, screenSurface);
@@ -1257,6 +1320,7 @@ void DrasculaEngine::animation_5_5(){
copyBackground();
copyRect(boneX[frame], boneY[frame], pixelX, pixelY, 97, 64, frontSurface, screenSurface);
updateScreen(pixelX, pixelY, pixelX,pixelY, 97, 64, screenSurface);
+ updateEvents();
}
flags[6] = 1;
@@ -1279,11 +1343,13 @@ void DrasculaEngine::animation_5_5(){
pause(3);
copyBackground(flyX[frame], 1, 174, 79, 61, 109, backSurface, screenSurface);
updateScreen(174, 79, 174, 79, 61, 109, screenSurface);
+ updateEvents();
}
for (frame = 0; frame < 5; frame++) {
pause(3);
copyBackground(flyX[frame], 1, 174, 79, 61, 109, extraSurface, screenSurface);
updateScreen(174, 79, 174, 79, 61, 109, screenSurface);
+ updateEvents();
}
updateScreen(0, 0, 0, 0, 320, 200, bgSurface);
@@ -1299,6 +1365,8 @@ void DrasculaEngine::animation_5_5(){
}
void DrasculaEngine::animation_11_5() {
+ debug(4, "animation_11_5()");
+
flags[9] = 1;
if (flags[2] == 1 && flags[3] == 1 && flags[4] == 1)
animation_12_5();
@@ -1309,6 +1377,8 @@ void DrasculaEngine::animation_11_5() {
}
void DrasculaEngine::animation_12_5() {
+ debug(4, "animation_12_5()");
+
DacPalette256 bgPalette1;
DacPalette256 bgPalette2;
DacPalette256 bgPalette3;
@@ -1367,6 +1437,7 @@ void DrasculaEngine::animation_12_5() {
copyRect(rayX[frame], 1, 41, 0, 44, 44, backSurface, screenSurface);
copyRect(frusky_x[frame], 113, 205, 50, 38, 86, drawSurface3, screenSurface);
updateScreen();
+ updateEvents();
}
stopSound();
@@ -1383,6 +1454,7 @@ void DrasculaEngine::animation_12_5() {
updateRoom();
copyRect(elfrusky_x[frame], 47, 192, 39, 66, 106, backSurface, screenSurface);
updateScreen();
+ updateEvents();
}
animate("frel.bin", 16);
@@ -1415,6 +1487,8 @@ void DrasculaEngine::animation_12_5() {
}
void DrasculaEngine::animation_13_5() {
+ debug(4, "animation_13_5()");
+
int frank_x = 199;
int frame = 0;
int frus_x[] = {1, 46, 91, 136, 181, 226, 271};
@@ -1441,11 +1515,14 @@ void DrasculaEngine::animation_13_5() {
frame = 0;
trackProtagonist = 3;
}
+ updateEvents();
pause(6);
}
}
void DrasculaEngine::animation_14_5() {
+ debug(4, "animation_14_5()");
+
flags[11] = 1;
playSound(3);
updateRoom();
@@ -1469,6 +1546,8 @@ void DrasculaEngine::animation_14_5() {
}
void DrasculaEngine::animation_1_6() {
+ debug(4, "animation_1_6()");
+
trackProtagonist = 0;
curX = 103;
curY = 108;
@@ -1497,11 +1576,15 @@ void DrasculaEngine::animation_1_6() {
talk_drascula(28, 1);
talk(255);
talk_drascula(29, 1);
+ updateEvents();
fadeToBlack(1);
+ updateEvents();
clearRoom();
loadPic("time1.alg", screenSurface);
updateScreen();
+ updateEvents();
delay(930);
+ updateEvents();
clearRoom();
black();
hare_se_ve = 0;
@@ -1513,10 +1596,13 @@ void DrasculaEngine::animation_1_6() {
talk_drascula(30, 1);
talk(257);
fadeToBlack(0);
+ updateEvents();
clearRoom();
loadPic("time1.alg", screenSurface);
updateScreen();
+ updateEvents();
delay(900);
+ updateEvents();
clearRoom();
black();
updateRoom();
@@ -1540,6 +1626,8 @@ void DrasculaEngine::animation_1_6() {
}
void DrasculaEngine::animation_5_6() {
+ debug(4, "animation_5_6()");
+
int pY = -125;
animate("man.bin", 14);
@@ -1553,6 +1641,7 @@ void DrasculaEngine::animation_5_6() {
updateRefresh();
updateScreen();
+ updateEvents();
pause(2);
}
@@ -1560,6 +1649,8 @@ void DrasculaEngine::animation_5_6() {
}
void DrasculaEngine::animation_6_6() {
+ debug(4, "animation_6_6()");
+
animate("rct.bin", 11);
clearRoom();
selectVerb(kVerbNone);
@@ -1584,6 +1675,8 @@ void DrasculaEngine::animation_6_6() {
}
void DrasculaEngine::animation_9_6() {
+ debug(4, "animation_9_6()");
+
int v_cd;
animate("fin.bin", 14);
@@ -1660,6 +1753,8 @@ void DrasculaEngine::animation_9_6() {
}
void DrasculaEngine::animation_19_6() {
+ debug(4, "animation_19_6()");
+
copyBackground();
copyBackground(140, 23, 161, 69, 35, 80, drawSurface3, screenSurface);
@@ -1675,6 +1770,8 @@ void DrasculaEngine::animation_19_6() {
}
void DrasculaEngine::animation_12_2() {
+ debug(4, "animation_12_2()");
+
loadPic("an12.alg", extraSurface);
talk(356);
@@ -1705,6 +1802,8 @@ void DrasculaEngine::animation_12_2() {
}
void DrasculaEngine::animation_26_2() {
+ debug(4, "animation_26_2()");
+
loadPic("an12.alg", extraSurface);
talk(392);
@@ -1745,6 +1844,7 @@ void DrasculaEngine::animation_26_2() {
x = x + 50;
if (n == 2)
playSound(9);
+ updateEvents();
pause(3);
}
@@ -1762,6 +1862,8 @@ void DrasculaEngine::animation_26_2() {
}
void DrasculaEngine::animation_11_2() {
+ debug(4, "animation_11_2()");
+
loadPic("an11y13.alg", extraSurface);
playTalkSequence(11); // sequence 11, chapter 2
@@ -1770,6 +1872,8 @@ void DrasculaEngine::animation_11_2() {
}
void DrasculaEngine::animation_13_2() {
+ debug(4, "animation_13_2()");
+
loadPic("an11y13.alg", frontSurface);
if (flags[41] == 0) {
@@ -1780,6 +1884,8 @@ void DrasculaEngine::animation_13_2() {
}
void DrasculaEngine::animation_24_2() {
+ debug(4, "animation_24_2()");
+
if (curX < 178)
gotoObject(208, 136);
trackProtagonist = 3;
@@ -1810,6 +1916,8 @@ void DrasculaEngine::animation_24_2() {
}
void DrasculaEngine::animation_32_2() {
+ debug(4, "animation_32_2()");
+
loadPic("an32_1.alg", drawSurface3);
loadPic("an32_2.alg", backSurface);
@@ -1825,12 +1933,16 @@ void DrasculaEngine::animation_32_2() {
x = x + 65;
if (n < 2)
pause(4);
+
+ updateEvents();
}
loadPic("aux18.alg", drawSurface3);
}
void DrasculaEngine::animation_34_2() {
+ debug(4, "animation_34_2()");
+
trackProtagonist = 1;
updateRoom();
updateScreen();
@@ -1858,6 +1970,8 @@ void DrasculaEngine::animation_34_2() {
}
void DrasculaEngine::animation_36_2() {
+ debug(4, "animation_36_2()");
+
loadPic("an11y13.alg", extraSurface);
talk(404);
@@ -1871,7 +1985,10 @@ void DrasculaEngine::animation_36_2() {
loadPic(974, extraSurface);
}
+// Use sickle on plant
void DrasculaEngine::animation_7_2() {
+ debug(4, "animation_7_2()");
+
loadPic("an7_1.alg", backSurface);
loadPic("an7_2.alg", extraSurface);
loadPic("an7_3.alg", frontSurface);
@@ -1928,6 +2045,8 @@ void DrasculaEngine::animation_7_2() {
}
void DrasculaEngine::animation_5_2() {
+ debug(4, "animation_5_2()");
+
trackProtagonist = 0;
updateRoom();
updateScreen();
@@ -1964,6 +2083,8 @@ void DrasculaEngine::animation_5_2() {
}
void DrasculaEngine::animation_6_2() {
+ debug(4, "animation_6_2()");
+
stopMusic();
flags[9] = 1;
@@ -2005,6 +2126,8 @@ void DrasculaEngine::animation_6_2() {
}
void DrasculaEngine::animation_33_2() {
+ debug(4, "animation_33_2()");
+
stopMusic();
flags[9] = 1;
@@ -2052,6 +2175,8 @@ void DrasculaEngine::animation_33_2() {
}
void DrasculaEngine::animation_1_4() {
+ debug(4, "animation_1_4()");
+
if (flags[21] == 0) {
strcpy(objName[2], "igor");
talk(275);
@@ -2108,6 +2233,8 @@ void DrasculaEngine::animation_1_4() {
}
void DrasculaEngine::animation_5_4(){
+ debug(4, "animation_5_4(");
+
trackProtagonist = 3;
loadPic("anh_dr.alg", backSurface);
gotoObject(99, 160);
@@ -2136,6 +2263,8 @@ void DrasculaEngine::animation_5_4(){
}
void DrasculaEngine::animation_6_4() {
+ debug(4, "animation_6_4()");
+
int prevRoom = roomNumber;
roomNumber = 26;
@@ -2161,6 +2290,8 @@ void DrasculaEngine::animation_6_4() {
}
void DrasculaEngine::animation_8_4() {
+ debug(4, "animation_8_4()");
+
int bookcaseX[] = {1, 75, 149, 223, 1, 75, 149, 223, 149, 223, 149, 223, 149, 223};
int bookcaseY[] = {1, 1, 1, 1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74};
@@ -2170,6 +2301,7 @@ void DrasculaEngine::animation_8_4() {
pause(2);
copyBackground(bookcaseX[frame], bookcaseY[frame], 77, 45, 73, 72, frontSurface, screenSurface);
updateScreen(77, 45, 77, 45, 73, 72, screenSurface);
+ updateEvents();
}
loadPic(96, frontSurface);
@@ -2177,6 +2309,8 @@ void DrasculaEngine::animation_8_4() {
}
void DrasculaEngine::activatePendulum() {
+ debug(4, "activatePendulum()");
+
flags[1] = 2;
hare_se_ve = 0;
roomNumber = 102;
diff --git a/backends/platform/PalmOS/Src/native/oscalls.h b/engines/drascula/console.cpp
index 071b409130..d017468285 100644
--- a/backends/platform/PalmOS/Src/native/oscalls.h
+++ b/engines/drascula/console.cpp
@@ -23,36 +23,41 @@
*
*/
-#ifndef _OSCALLS_H_
-#define _OSCALLS_H_
+#include "drascula/console.h"
+#include "gui/debugger.h"
+#include "drascula/drascula.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+namespace Drascula {
-#ifdef PALMOS_ARM
-# define __68K(a) __68k_##a
-#else
-# define __68K(a) a
-#endif
+Console::Console(DrasculaEngine *vm) : GUI::Debugger(), _vm(vm) {
+ DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room));
+}
-Err __68k_StatShow();
-Err __68k_StatHide();
+Console::~Console() {
+}
-Err __68k_PINSetInputAreaState(UInt16 state);
-UInt16 __68k_PINGetInputAreaState(void);
+void Console::preEnter() {
+}
+
+void Console::postEnter() {
+}
-Err __68k_PINSetInputTriggerState(UInt16 state);
-UInt16 __68k_PINGetInputTriggerState(void);
+bool Console::Cmd_Room(int argc, const char **argv) {
+ if (argc < 2) {
+ DebugPrintf("Usage: changeCard <card>\n");
+ return true;
+ }
-Err __68k_SysSetOrientation(UInt16 orientation);
-UInt16 __68k_SysGetOrientation(void);
+ int roomNum = atoi(argv[1]);
-Err __68k_SysSetOrientationTriggerState(UInt16 triggerState);
-UInt16 __68k_SysGetOrientationTriggerState(void);
+ _vm->loadedDifferentChapter = 0;
+ _vm->enterRoom(roomNum);
+ _vm->selectVerb(kVerbNone);
+ _vm->clearRoom();
+ _vm->loadPic(roomNum, _vm->bgSurface, HALF_PAL);
+ _vm->selectionMade = 0;
-#ifdef __cplusplus
+ return false;
}
-#endif
-#endif
+} // End of namespace Drascula
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formEditGame.h b/engines/drascula/console.h
index 90d271e115..33e2f626e4 100644
--- a/backends/platform/PalmOS/Src/launcher/forms/formEditGame.h
+++ b/engines/drascula/console.h
@@ -23,17 +23,29 @@
*
*/
-#ifndef __FORMEDITGAME_H__
-#define __FORMEDITGAME_H__
-
-// edit game mode
-enum {
- edtModeAdd,
- edtModeEdit,
- edtModeParams
-};
+#ifndef DRASCULA_CONSOLE_H
+#define DRASCULA_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace Drascula {
+
+class DrasculaEngine;
-extern UInt8 gFormEditMode;
-void EditGameFormDelete(Boolean direct);
+class Console : public GUI::Debugger {
+public:
+ Console(DrasculaEngine *vm);
+ virtual ~Console(void);
+
+protected:
+ virtual void preEnter();
+ virtual void postEnter();
+
+private:
+ DrasculaEngine *_vm;
+
+ bool Cmd_Room(int argc, const char **argv);
+};
+} // End of namespace Drascula
#endif
diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp
index b2a7e217e6..0e70348148 100644
--- a/engines/drascula/converse.cpp
+++ b/engines/drascula/converse.cpp
@@ -131,6 +131,8 @@ void DrasculaEngine::cleanupString(char *string) {
}
void DrasculaEngine::converse(int index) {
+ debug(4, "converse(%d)", index);
+
char fileName[20];
sprintf(fileName, "op_%d.cal", index);
Common::SeekableReadStream *stream = _archives.open(fileName);
@@ -279,9 +281,15 @@ void DrasculaEngine::converse(int index) {
}
void DrasculaEngine::response(int function) {
- playTalkSequence(function);
+ debug(4, "response(%d)", function);
+
+ if (function != 31)
+ playTalkSequence(function);
if (currentChapter == 2) {
+ if (function == 16 || function == 20 || function == 23 || function == 29 || function == 31)
+ loadPic(menuBackground, backSurface);
+
if (function == 16)
animation_16_2();
else if (function == 20)
diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp
index 76d48b7b89..c10222cadd 100644
--- a/engines/drascula/detection.cpp
+++ b/engines/drascula/detection.cpp
@@ -264,7 +264,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NOMIDI
+ Common::GUIO_NOMIDI,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class DrasculaMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp
index 276554a24c..b1f16fa505 100644
--- a/engines/drascula/drascula.cpp
+++ b/engines/drascula/drascula.cpp
@@ -38,6 +38,7 @@
#include "sound/mixer.h"
#include "drascula/drascula.h"
+#include "drascula/console.h"
namespace Drascula {
@@ -114,6 +115,8 @@ DrasculaEngine::~DrasculaEngine() {
freeRoomsTable();
+ delete _console;
+
free(_charMap);
free(_itemLocations);
free(_polX);
@@ -172,6 +175,8 @@ Common::Error DrasculaEngine::run() {
_lang = kEnglish;
}
+ _console = new Console(this);
+
if (!loadDrasculaDat())
return Common::kUnknownError;
@@ -240,6 +245,8 @@ Common::Error DrasculaEngine::run() {
if (currentChapter != 3)
loadPic(96, frontSurface, COMPLETE_PAL);
+ loadPic(99, cursorSurface);
+
if (currentChapter == 1) {
} else if (currentChapter == 2) {
loadPic("pts.alg", drawSurface2);
@@ -271,6 +278,7 @@ Common::Error DrasculaEngine::run() {
loadPic(974, tableSurface);
if (currentChapter != 2) {
+ loadPic(99, cursorSurface);
loadPic(99, backSurface);
loadPic(97, extraSurface);
}
@@ -498,11 +506,15 @@ bool DrasculaEngine::runCurrentChapter() {
#else
if (rightMouseButton == 1 && _menuScreen) {
#endif
+ rightMouseButton = 0;
delay(100);
- if (currentChapter == 2)
+ if (currentChapter == 2) {
+ loadPic(menuBackground, cursorSurface);
loadPic(menuBackground, backSurface);
- else
+ } else {
+ loadPic(99, cursorSurface);
loadPic(99, backSurface);
+ }
setPalette((byte *)&gamePalette);
_menuScreen = false;
#ifndef _WIN32_WCE
@@ -523,18 +535,24 @@ bool DrasculaEngine::runCurrentChapter() {
if (rightMouseButton == 1 && !_menuScreen &&
!(currentChapter == 5 && pickedObject == 16)) {
#endif
+ rightMouseButton = 0;
delay(100);
characterMoved = 0;
if (trackProtagonist == 2)
trackProtagonist = 1;
- if (currentChapter == 4)
+ if (currentChapter == 4) {
loadPic("icons2.alg", backSurface);
- else if (currentChapter == 5)
+ loadPic("icons2.alg", cursorSurface);
+ } else if (currentChapter == 5) {
loadPic("icons3.alg", backSurface);
- else if (currentChapter == 6)
+ loadPic("icons3.alg", cursorSurface);
+ } else if (currentChapter == 6) {
loadPic("iconsp.alg", backSurface);
- else
+ loadPic("iconsp.alg", cursorSurface);
+ } else {
loadPic("icons.alg", backSurface);
+ loadPic("icons.alg", cursorSurface);
+ }
_menuScreen = true;
#ifndef _WIN32_WCE
updateEvents();
@@ -593,6 +611,9 @@ bool DrasculaEngine::runCurrentChapter() {
} else if (key == Common::KEYCODE_ESCAPE) {
if (!confirmExit())
return false;
+ } else if (key == Common::KEYCODE_TILDE || key == Common::KEYCODE_BACKQUOTE) {
+ _console->attach();
+ _console->onFrame();
} else if (currentChapter == 6 && key == Common::KEYCODE_0 && roomNumber == 61) {
loadPic("alcbar.alg", bgSurface, 255);
}
@@ -740,10 +761,10 @@ void DrasculaEngine::updateEvents() {
leftMouseButton = 0;
break;
case Common::EVENT_RBUTTONDOWN:
- rightMouseButton = 1;
+ // We changed semantic and react only on button up event
break;
case Common::EVENT_RBUTTONUP:
- rightMouseButton = 0;
+ rightMouseButton = 1;
break;
case Common::EVENT_QUIT:
// TODO
@@ -757,11 +778,17 @@ void DrasculaEngine::updateEvents() {
}
void DrasculaEngine::delay(int ms) {
- _system->delayMillis(ms * 2); // originally was 1
+ uint32 end = _system->getMillis() + ms * 2; // originally was 1
+
+ do {
+ _system->delayMillis(10);
+ updateEvents();
+ _system->updateScreen();
+ } while (_system->getMillis() < end);
}
void DrasculaEngine::pause(int duration) {
- _system->delayMillis(duration * 30); // was originally 2
+ delay(duration * 15);
}
int DrasculaEngine::getTime() {
diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h
index 4876cf3390..0a8b7c8c9b 100644
--- a/engines/drascula/drascula.h
+++ b/engines/drascula/drascula.h
@@ -317,6 +317,8 @@ static const int interf_y[] = { 51, 51, 51, 51, 83, 83, 83 };
struct RoomHandlers;
+class Console;
+
class DrasculaEngine : public ::Engine {
protected:
// Engine APIs
@@ -389,6 +391,7 @@ public:
// Graphics buffers/pointers
byte *bgSurface;
byte *backSurface;
+ byte *cursorSurface;
byte *drawSurface3;
byte *drawSurface2;
byte *tableSurface;
@@ -733,6 +736,8 @@ public:
private:
int _lang;
+ Console *_console;
+
CharInfo *_charMap;
int _charMapSize;
diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp
index 00399816da..70085b99af 100644
--- a/engines/drascula/graphics.cpp
+++ b/engines/drascula/graphics.cpp
@@ -54,6 +54,7 @@ void DrasculaEngine::allocMemory() {
assert(crosshairCursor);
mouseCursor = (byte *)malloc(OBJWIDTH * OBJHEIGHT);
assert(mouseCursor);
+ cursorSurface = (byte *)malloc(64000);
}
void DrasculaEngine::freeMemory() {
@@ -67,6 +68,7 @@ void DrasculaEngine::freeMemory() {
free(frontSurface);
free(crosshairCursor);
free(mouseCursor);
+ free(cursorSurface);
}
void DrasculaEngine::moveCursor() {
@@ -90,6 +92,8 @@ void DrasculaEngine::moveCursor() {
}
void DrasculaEngine::loadPic(const char *NamePcc, byte *targetSurface, int colorCount) {
+ debug(5, "loadPic(%s)", NamePcc);
+
uint dataSize = 0;
byte *pcxData;
@@ -147,8 +151,7 @@ void DrasculaEngine::showFrame(Common::SeekableReadStream *stream, bool firstFra
free(prevFrame);
}
-void DrasculaEngine::copyBackground(int xorg, int yorg, int xdes, int ydes, int width,
- int height, byte *src, byte *dest) {
+void DrasculaEngine::copyBackground(int xorg, int yorg, int xdes, int ydes, int width, int height, byte *src, byte *dest) {
dest += xdes + ydes * 320;
src += xorg + yorg * 320;
/* Unoptimized code
@@ -190,16 +193,20 @@ void DrasculaEngine::copyRect(int xorg, int yorg, int xdes, int ydes, int width,
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];
+ int ptr = 0;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ if (src[ptr] != 255)
+ dest[ptr] = src[ptr];
+ ptr++;
+ }
+ ptr += 320 - width;
+ }
+
}
void DrasculaEngine::updateScreen(int xorg, int yorg, int xdes, int ydes, int width, int height, byte *buffer) {
- byte *screenBuffer = (byte *)_system->lockScreen()->pixels;
- copyBackground(xorg, yorg, xdes, ydes, width, height, buffer, screenBuffer);
- _system->unlockScreen();
+ _system->copyRectToScreen(buffer + xorg + yorg * 320, 320, xdes, ydes, width, height);
_system->updateScreen();
}
diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp
index 21803a8932..1495694a1b 100644
--- a/engines/drascula/interface.cpp
+++ b/engines/drascula/interface.cpp
@@ -65,6 +65,8 @@ void DrasculaEngine::selectVerbFromBar() {
}
void DrasculaEngine::selectVerb(int verb) {
+ debug(4, "selectVerb(%d)", verb);
+
int c = _menuScreen ? 0 : 171;
if (currentChapter == 5) {
@@ -76,7 +78,7 @@ void DrasculaEngine::selectVerb(int verb) {
}
for (int i = 0; i < OBJHEIGHT; i++)
- memcpy(mouseCursor + i * OBJWIDTH, backSurface + OBJWIDTH * verb + (c + i) * 320, OBJWIDTH);
+ memcpy(mouseCursor + i * OBJWIDTH, cursorSurface + OBJWIDTH * verb + (c + i) * 320, OBJWIDTH);
setCursor(kCursorCurrentItem);
if (verb > 0) {
@@ -126,7 +128,7 @@ void DrasculaEngine::showMenu() {
OBJWIDTH, OBJHEIGHT, srcSurface, screenSurface);
}
copyRect(_x1d_menu[h], _y1d_menu[h], _itemLocations[n].x, _itemLocations[n].y,
- OBJWIDTH, OBJHEIGHT, backSurface, screenSurface);
+ OBJWIDTH, OBJHEIGHT, cursorSurface, screenSurface);
}
if (x < 7)
@@ -140,7 +142,7 @@ void DrasculaEngine::clearMenu() {
if (mouseX > _verbBarX[n] && mouseX < _verbBarX[n + 1])
verbActivated = 0;
copyRect(OBJWIDTH * n, OBJHEIGHT * verbActivated, _verbBarX[n], 2,
- OBJWIDTH, OBJHEIGHT, backSurface, screenSurface);
+ OBJWIDTH, OBJHEIGHT, cursorSurface, screenSurface);
verbActivated = 1;
}
}
diff --git a/engines/drascula/module.mk b/engines/drascula/module.mk
index a9fa257549..20fd900124 100644
--- a/engines/drascula/module.mk
+++ b/engines/drascula/module.mk
@@ -3,6 +3,7 @@ MODULE := engines/drascula
MODULE_OBJS := \
actors.o \
animation.o \
+ console.o \
converse.o \
detection.o \
drascula.o \
diff --git a/engines/drascula/objects.cpp b/engines/drascula/objects.cpp
index c4dc3df1f6..08c1a68a55 100644
--- a/engines/drascula/objects.cpp
+++ b/engines/drascula/objects.cpp
@@ -78,8 +78,11 @@ void DrasculaEngine::gotoObject(int pointX, int pointY) {
for (;;) {
updateRoom();
updateScreen();
+ updateEvents();
if (characterMoved == 0)
break;
+
+ pause(3);
}
if (walkToObject == 1) {
diff --git a/engines/drascula/palette.cpp b/engines/drascula/palette.cpp
index 1e51deffd9..0f75bb7959 100644
--- a/engines/drascula/palette.cpp
+++ b/engines/drascula/palette.cpp
@@ -106,6 +106,8 @@ void DrasculaEngine::fadeToBlack(int fadeSpeed) {
pause(fadeSpeed);
setPalette((byte *)&palFade);
+
+ updateEvents();
}
}
@@ -124,6 +126,8 @@ void DrasculaEngine::fadeFromBlack(int fadeSpeed) {
pause(fadeSpeed);
setPalette((byte *)&palFade);
+
+ updateEvents();
}
}
diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp
index a71545feca..57bfad26af 100644
--- a/engines/drascula/rooms.cpp
+++ b/engines/drascula/rooms.cpp
@@ -1091,7 +1091,7 @@ void DrasculaEngine::updateRefresh() {
sprintf(rm, "update_%d", roomNumber);
for (uint i = 0; i < _roomHandlers->roomUpdaters.size(); i++) {
if (!strcmp(rm, _roomHandlers->roomUpdaters[i]->desc)) {
- debug(4, "Calling room updater %d", roomNumber);
+ debug(8, "Calling room updater %d", roomNumber);
(this->*(_roomHandlers->roomUpdaters[i]->proc))();
break;
}
@@ -1129,7 +1129,7 @@ void DrasculaEngine::updateRefresh_pre() {
sprintf(rm, "update_%d_pre", roomNumber);
for (uint i = 0; i < _roomHandlers->roomPreupdaters.size(); i++) {
if (!strcmp(rm, _roomHandlers->roomPreupdaters[i]->desc)) {
- debug(4, "Calling room preupdater %d", roomNumber);
+ debug(8, "Calling room preupdater %d", roomNumber);
(this->*(_roomHandlers->roomPreupdaters[i]->proc))();
break;
}
diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp
index 54175c5e5b..8cefe0385c 100644
--- a/engines/drascula/talk.cpp
+++ b/engines/drascula/talk.cpp
@@ -170,6 +170,7 @@ void DrasculaEngine::talk_drascula(int index, int talkerType) {
centerText(said, drasculaX + 19, drasculaY);
updateScreen();
+ updateEvents();
pause(3);
@@ -215,6 +216,7 @@ void DrasculaEngine::talk_drascula_big(int index) {
centerText(said, 191, 69);
updateScreen();
+ updateEvents();
pause(3);
@@ -245,7 +247,9 @@ void DrasculaEngine::talk_solo(const char *said, const char *filename) {
else if (currentChapter == 5)
centerText(said, 173, 92);
}
+ updateEvents();
updateScreen();
+ pause(3);
} while (!isTalkFinished());
if (currentChapter == 6) {
@@ -304,6 +308,7 @@ void DrasculaEngine::talk_bartender(int index, int talkerType) {
centerText(said, 132, 45);
updateScreen();
+ updateEvents();
pause(3);
} while (!isTalkFinished());
@@ -331,11 +336,9 @@ void DrasculaEngine::talk_bj(int index) {
updateRefresh_pre();
- copyBackground(bjX + 2, bjY - 1, bjX + 2, bjY - 1, 27, 40,
- bgSurface, screenSurface);
+ copyBackground(bjX + 2, bjY - 1, bjX + 2, bjY - 1, 27, 40, bgSurface, screenSurface);
- copyRect(x_talk[face], 99, bjX + 2, bjY - 1, 27, 40,
- drawSurface3, screenSurface);
+ copyRect(x_talk[face], 99, bjX + 2, bjY - 1, 27, 40, drawSurface3, screenSurface);
moveCharacters();
updateRefresh();
@@ -353,6 +356,7 @@ void DrasculaEngine::talk_bj(int index) {
updateScreen();
}
+ updateEvents();
} while (!isTalkFinished());
updateRoom();
@@ -467,6 +471,7 @@ void DrasculaEngine::talk(const char *said, const char *filename) {
centerText(said, curX, curY);
updateScreen();
+ updateEvents();
pause(3);
} while (!isTalkFinished());
@@ -558,16 +563,15 @@ void DrasculaEngine::talk_vonBraun(int index, int talkerType) {
if (!_subtitlesDisabled)
centerText(said, vonBraunX, 66);
- updateScreen();
- pause(3);
} else {
updateRoom();
if (!_subtitlesDisabled)
centerText(said, 150, 80);
-
- updateScreen();
}
+ updateScreen();
+ updateEvents();
+ pause(3);
} while (!isTalkFinished());
updateRoom();
@@ -621,6 +625,7 @@ void DrasculaEngine::talk_blind(int index) {
centerText(said, 260, 71);
updateScreen();
+ updateEvents();
pause(2);
p++;
} while (!isTalkFinished());
@@ -641,7 +646,9 @@ void DrasculaEngine::talk_hacker(int index) {
do {
if (!_subtitlesDisabled)
centerText(said, 156, 170);
+ updateEvents();
updateScreen();
+ pause(3);
} while (!isTalkFinished());
}
@@ -693,13 +700,13 @@ void DrasculaEngine::talk_pen(const char *said, const char *filename, int talker
copyBackground();
updateRefresh_pre();
+ updateRefresh();
+
if (talkerType == 0)
copyRect(x_talk[face], 145, 145, 105, 25, 29, drawSurface3, screenSurface);
else
copyBackground(x_talk2[face], 171, 173, 116, 25, 28, drawSurface3, screenSurface);
- updateRefresh();
-
if (!_subtitlesDisabled) {
if (talkerType == 0)
centerText(said, 160, 105);
@@ -708,6 +715,7 @@ void DrasculaEngine::talk_pen(const char *said, const char *filename, int talker
}
updateScreen();
+ updateEvents();
pause(3);
} while (!isTalkFinished());
@@ -745,6 +753,7 @@ void DrasculaEngine::talk_bj_bed(int index) {
centerText(said, 104, 102);
updateScreen();
+ updateEvents();
pause(3);
} while (!isTalkFinished());
@@ -781,6 +790,7 @@ void DrasculaEngine::talk_htel(int index) {
centerText(said, 90, 50);
updateScreen();
+ updateEvents();
pause(3);
} while (!isTalkFinished());
@@ -862,6 +872,7 @@ void DrasculaEngine::talk_sync(const char *said, const char *filename, const cha
centerText(said, curX, curY);
updateScreen();
+ updateEvents();
p++;
pause(3);
@@ -895,6 +906,7 @@ void DrasculaEngine::talk_trunk(int index) {
centerText(said, 263, 69);
updateScreen();
+ updateEvents();
pause(4);
} while (!isTalkFinished());
@@ -922,6 +934,7 @@ void DrasculaEngine::talk_generic(const char* said, const char* filename, int* f
centerText(said, coords[5], coords[6]);
updateScreen();
+ updateEvents();
pause(3);
} while (!isTalkFinished());
@@ -944,8 +957,10 @@ void DrasculaEngine::grr() {
updateScreen();
- while (!isTalkFinished())
- ;
+ while (!isTalkFinished()) {
+ updateEvents();
+ pause(3);
+ }
updateRoom();
updateScreen();
diff --git a/engines/engine.cpp b/engines/engine.cpp
index 0f42cd493d..e2c0bb79f3 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -23,6 +23,7 @@
*/
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <direct.h>
// winnt.h defines ARRAYSIZE, but we want our own one...
@@ -77,7 +78,7 @@ static void defaultErrorHandler(const char *msg) {
if (isSmartphone())
debugger = 0;
#endif
- if (debugger && !debugger->isAttached()) {
+ if (debugger && !debugger->isActive()) {
debugger->attach(msg);
debugger->onFrame();
}
diff --git a/engines/game.cpp b/engines/game.cpp
index c7f26019d6..dea6d37485 100644
--- a/engines/game.cpp
+++ b/engines/game.cpp
@@ -73,6 +73,10 @@ void GameDescriptor::setGUIOptions(uint32 guioptions) {
erase("guioptions");
}
+void GameDescriptor::appendGUIOptions(const Common::String &str) {
+ setVal("guioptions", getVal("guioptions", "") + " " + str);
+}
+
void GameDescriptor::updateDesc(const char *extra) {
// TODO: The format used here (LANG/PLATFORM/EXTRA) is not set in stone.
// We may want to change the order (PLATFORM/EXTRA/LANG, anybody?), or
diff --git a/engines/game.h b/engines/game.h
index 49136ecf5a..b125421ff6 100644
--- a/engines/game.h
+++ b/engines/game.h
@@ -83,6 +83,7 @@ public:
void updateDesc(const char *extra = 0);
void setGUIOptions(uint32 options);
+ void appendGUIOptions(const Common::String &str);
Common::String &gameid() { return getVal("gameid"); }
Common::String &description() { return getVal("description"); }
diff --git a/engines/gob/demos/demoplayer.cpp b/engines/gob/demos/demoplayer.cpp
index 38e20a46ee..25cd470f04 100644
--- a/engines/gob/demos/demoplayer.cpp
+++ b/engines/gob/demos/demoplayer.cpp
@@ -152,12 +152,13 @@ void DemoPlayer::playVideo(const char *fileName) {
debugC(1, kDebugDemo, "Playing video \"%s\"", file);
- int16 x = _rebase0 ? 0 : -1;
- int16 y = _rebase0 ? 0 : -1;
- if (_vm->_vidPlayer->primaryOpen(file, x, y)) {
- bool videoSupportsDouble =
- ((_vm->_vidPlayer->getFeatures() & Graphics::CoktelVideo::kFeaturesSupportsDouble) != 0);
+ VideoPlayer::Properties props;
+ props.x = _rebase0 ? 0 : -1;
+ props.y = _rebase0 ? 0 : -1;
+
+ int slot;
+ if ((slot = _vm->_vidPlayer->openVideo(true, file, props)) >= 0) {
if (_autoDouble) {
int16 defX = _rebase0 ? 0 : _vm->_vidPlayer->getDefaultX();
int16 defY = _rebase0 ? 0 : _vm->_vidPlayer->getDefaultY();
@@ -167,16 +168,12 @@ void DemoPlayer::playVideo(const char *fileName) {
_doubleMode = ((right < 320) && (bottom < 200));
}
- if (_doubleMode) {
- if (videoSupportsDouble) {
- _vm->_vidPlayer->slotSetDoubleMode(-1, true);
- playVideoNormal();
- } else
- playVideoDoubled();
- } else
- playVideoNormal();
+ if (_doubleMode)
+ playVideoDoubled(slot);
+ else
+ playVideoNormal(slot);
- _vm->_vidPlayer->primaryClose();
+ _vm->_vidPlayer->closeVideo(slot);
if (waitTime > 0)
_vm->_util->longDelay(waitTime);
@@ -210,51 +207,67 @@ void DemoPlayer::playADL(const char *params) {
playADL(fileName, waitEsc, repeat);
}
-void DemoPlayer::playVideoNormal() {
- _vm->_vidPlayer->primaryPlay();
+void DemoPlayer::playVideoNormal(int slot) {
+ VideoPlayer::Properties props;
+
+ _vm->_vidPlayer->play(slot, props);
}
-void DemoPlayer::playVideoDoubled() {
- Common::String fileNameOpened = _vm->_vidPlayer->getFileName();
- _vm->_vidPlayer->primaryClose();
+void DemoPlayer::playVideoDoubled(int slot) {
+ Common::String fileNameOpened = _vm->_vidPlayer->getFileName(slot);
+ _vm->_vidPlayer->closeVideo(slot);
- int16 x = _rebase0 ? 0 : -1;
- int16 y = _rebase0 ? 0 : -1;
- if (_vm->_vidPlayer->primaryOpen(fileNameOpened.c_str(), x, y,
- VideoPlayer::kFlagScreenSurface)) {
+ VideoPlayer::Properties props;
- for (int i = 0; i < _vm->_vidPlayer->getFramesCount(); i++) {
- _vm->_vidPlayer->playFrame(i);
+ props.x = _rebase0 ? 0 : -1;
+ props.y = _rebase0 ? 0 : -1;
+ props.flags = VideoPlayer::kFlagScreenSurface;
+ props.waitEndFrame = false;
- Graphics::CoktelVideo::State state = _vm->_vidPlayer->getState();
+ _vm->_vidPlayer->evaluateFlags(props);
+
+ slot = _vm->_vidPlayer->openVideo(true, fileNameOpened, props);
+ if (slot < 0)
+ return;
- int16 w = state.right - state.left + 1;
- int16 h = state.bottom - state.top + 1;
- int16 wD = (state.left * 2) + (w * 2);
- int16 hD = (state.top * 2) + (h * 2);
+ for (uint i = 0; i < _vm->_vidPlayer->getFrameCount(slot); i++) {
+ props.startFrame = _vm->_vidPlayer->getCurrentFrame(slot) + 1;
+ props.lastFrame = _vm->_vidPlayer->getCurrentFrame(slot) + 1;
+
+ _vm->_vidPlayer->play(slot, props);
+
+ const Common::List<Common::Rect> *rects = _vm->_vidPlayer->getDirtyRects(slot);
+ if (rects) {
+ for (Common::List<Common::Rect>::const_iterator rect = rects->begin(); rect != rects->end(); ++rect) {
+ int16 w = rect->right - rect->left;
+ int16 h = rect->bottom - rect->top;
+ int16 wD = (rect->left * 2) + (w * 2);
+ int16 hD = (rect->top * 2) + (h * 2);
_vm->_video->drawSpriteDouble(*_vm->_draw->_spritesArray[0], *_vm->_draw->_frontSurface,
- state.left, state.top, state.right, state.bottom, state.left, state.top, 0);
+ rect->left, rect->top, rect->right - 1, rect->bottom - 1, rect->left, rect->top, 0);
_vm->_draw->dirtiedRect(_vm->_draw->_frontSurface,
- state.left * 2, state.top * 2, wD, hD);
- _vm->_video->retrace();
+ rect->left * 2, rect->top * 2, wD, hD);
+ }
+ }
- _vm->_util->processInput();
- if (_vm->shouldQuit())
- break;
+ _vm->_video->retrace();
- int16 key;
- bool end = false;
- while (_vm->_util->checkKey(key))
- if (key == kKeyEscape)
- end = true;
- if (end)
- break;
+ _vm->_util->processInput();
+ if (_vm->shouldQuit())
+ break;
- _vm->_vidPlayer->slotWaitEndFrame();
+ int16 key;
+ bool end = false;
+ while (_vm->_util->checkKey(key))
+ if (key == kKeyEscape)
+ end = true;
+ if (end)
+ break;
- }
+ _vm->_vidPlayer->waitEndFrame(slot);
}
+
}
void DemoPlayer::playADL(const Common::String &fileName, bool waitEsc, int32 repeat) {
diff --git a/engines/gob/demos/demoplayer.h b/engines/gob/demos/demoplayer.h
index f0672b9645..207b050363 100644
--- a/engines/gob/demos/demoplayer.h
+++ b/engines/gob/demos/demoplayer.h
@@ -59,8 +59,8 @@ protected:
void playVideo(const char *fileName);
void playADL(const char *params);
- void playVideoNormal();
- void playVideoDoubled();
+ void playVideoNormal(int slot);
+ void playVideoDoubled(int slot);
void playADL(const Common::String &fileName, bool waitEsc = true, int32 repeat = -1);
private:
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index 1f8bfdc138..a1eb8055aa 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -87,4994 +87,7 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = {
{0, 0, kPlatformUnknown}
};
-namespace Gob {
-
-using Common::GUIO_NOSPEECH;
-using Common::GUIO_NOSUBTITLES;
-using Common::GUIO_NONE;
-
-static const GOBGameDescription gameDescriptions[] = {
- { // Supplied by Florian Zeitz on scummvm-devel
- {
- "gob1",
- "EGA",
- AD_ENTRY1("intro.stk", "c65e9cc8ba23a38456242e1f2b1caad4"),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "EGA",
- AD_ENTRY1("intro.stk", "f9233283a0be2464248d83e14b95f09c"),
- RU_RUS,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesEGA,
- 0, 0, 0
- },
- { // Supplied by Theruler76 in bug report #1201233
- {
- "gob1",
- "VGA",
- AD_ENTRY1("intro.stk", "26a9118c0770fa5ac93a9626761600b2"),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by raziel_ in bug report #1891864
- {
- "gob1",
- "VGA",
- AD_ENTRY1s("intro.stk", "e157cb59c6d330ca70d12ab0ef1dd12b", 288972),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by raina in the forums
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "6d837c6380d8f4d984c9f6cc0026df4f", 192712),
- EN_ANY,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob1",
- "",
- AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
- EN_ANY,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob1",
- "",
- AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
- DE_DEU,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob1",
- "",
- AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
- FR_FRA,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob1",
- "",
- AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
- IT_ITA,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob1",
- "",
- AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
- ES_ESP,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // CD 1.000 version.
- {
- "gob1cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.000 version.
- {
- "gob1cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.000 version.
- {
- "gob1cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.000 version.
- {
- "gob1cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.000 version.
- {
- "gob1cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.02 version. Multilingual
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.02 version. Multilingual
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.02 version. Multilingual
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.02 version. Multilingual
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.02 version. Multilingual
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
- HU_HUN,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "Demo",
- AD_ENTRY1("intro.stk", "972f22c6ff8144a6636423f0354ca549"),
- UNK_LANG,
- kPlatformAmiga,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "Interactive Demo",
- AD_ENTRY1("intro.stk", "e72bd1e3828c7dec4c8a3e58c48bdfdb"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "Interactive Demo",
- AD_ENTRY1s("intro.stk", "a796096280d5efd48cf8e7dfbe426eb5", 193595),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2785958
- {
- "gob1",
- "Interactive Demo",
- AD_ENTRY1s("intro.stk", "35a098571af9a03c04e2303aec7c9249", 116582),
- FR_FRA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "0e022d3f2481b39e9175d37b2c6ad4c6", 2390121),
- FR_FRA,
- kPlatformCDi,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, "AVT003.TOT", 0
- },
- { // Supplied by fac76 in bug report #1883808
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "eebf2810122cfd17399260cd1468e994", 554014),
- EN_ANY,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "d28b9e9b41f31acfa58dcd12406c7b2c"),
- DE_DEU,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2602057
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "686c88f7302a80b744aae9f8413e853d"),
- IT_ITA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by bgk in bug report #1706861
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "4b13c02d1069b86bcfec80f4e474b98b", 554680),
- FR_FRA,
- kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by fac76 in bug report #1673397
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "b45b984ee8017efd6ea965b9becd4d66", 828443},
- {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658},
- {0, 0, 0, 0}
- },
- UNK_LANG,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by koalet in bug report #2478585
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275},
- {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "b45b984ee8017efd6ea965b9becd4d66"),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "dedb5d31d8c8050a8cf77abedcc53dae"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by raziel_ in bug report #1891867
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "25a99827cd59751a80bed9620fb677a0", 893302),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by blackwhiteeagle in bug report #1605235
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "3e4e7db0d201587dd2df4003b2993ef6"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "a13892cdf4badda85a6f6fb47603a128"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2602017
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "c47faf1d406504e6ffe63243610bb1f4"),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "cd3e1df8b273636ee32e34b7064f50e8"),
- RU_RUS,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by arcepi in bug report #1659884
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "5f53c56e3aa2f1e76c2e4f0caa15887f", 829232),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "285d7340f98ebad65d465585da12910b", 837286},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- EN_USA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- EN_USA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "24489330a1d67ff978211f574822a5a6", 883756),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "285d7340f98ebad65d465585da12910b", 837286),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "9de5fbb41cf97182109e5fecc9d90347"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v2.01",
- AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v2.01",
- AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v2.01",
- AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v2.01",
- AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v2.01",
- AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob2cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
- HU_HUN,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob2cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob2cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob2cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob2cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "Non-Interactive Demo",
- AD_ENTRY1("intro.stk", "8b1c98ff2ab2e14f47a1b891e9b92217"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, "usa.tot", 0
- },
- {
- {
- "gob2",
- "Interactive Demo",
- AD_ENTRY1("intro.stk", "cf1c95b2939bd8ff58a25c756cb6125e"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "Interactive Demo",
- AD_ENTRY1("intro.stk", "4b278c2678ea01383fd5ca114d947eea"),
- UNK_LANG,
- kPlatformAmiga,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by polluks in bug report #1895126
- {
- "gob2",
- "Interactive Demo",
- AD_ENTRY1s("intro.stk", "9fa85aea959fa8c582085855fbd99346", 553063),
- UNK_LANG,
- kPlatformAmiga,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by vampir_raziel in bug report #1658373
- {
- "ween",
- "",
- {
- {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
- {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by vampir_raziel in bug report #1658373
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "257fe669705ac4971efdfd5656eef16a", 457719),
- FR_FRA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by vampir_raziel in bug report #1658373
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "dffd1ab98fe76150d6933329ca6f4cc4", 459458),
- FR_FRA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by vampir_raziel in bug report #1658373
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "af83debf2cbea21faa591c7b4608fe92", 458192),
- DE_DEU,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2563539
- {
- "ween",
- "",
- {
- {"intro.stk", 0, "dffd1ab98fe76150d6933329ca6f4cc4", 459458},
- {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800},
- {0, 0, 0, 0}
- },
- IT_ITA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by pwigren in bug report #1764174
- {
- "ween",
- "",
- {
- {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
- {"music__5.snd", 0, "7d1819b9981ecddd53d3aacbc75f1cc8", 13446},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "ween",
- "",
- AD_ENTRY1("intro.stk", "e6d13fb3b858cb4f78a8780d184d5b2c"),
- FR_FRA,
- kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "ween",
- "",
- AD_ENTRY1("intro.stk", "2bb8878a8042244dd2b96ff682381baa"),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "de92e5c6a8c163007ffceebef6e67f7d", 7117568),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by cybot_tmin in bug report #1667743
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "6d60f9205ecfbd8735da2ee7823a70dc", 7014426),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "ween",
- "",
- AD_ENTRY1("intro.stk", "4b10525a3782aa7ecd9d833b5c1d308b"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by cartman_ on #scummvm
- {
- "ween",
- "",
- AD_ENTRY1("intro.stk", "63170e71f04faba88673b3f510f9c4c8"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by glorfindel in bugreport #1722142
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "8b57cd510da8a3bbd99e3a0297a8ebd1", 7018771),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "ween",
- "Demo",
- AD_ENTRY1("intro.stk", "2e9c2898f6bf206ede801e3b2e7ee428"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, "show.tot", 0
- },
- {
- {
- "ween",
- "Demo",
- AD_ENTRY1("intro.stk", "15fb91a1b9b09684b28ac75edf66e504"),
- EN_USA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, "show.tot", 0
- },
- {
- {
- "bargon",
- "",
- AD_ENTRY1("intro.stk", "da3c54be18ab73fbdb32db24624a9c23"),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by Trekky in the forums
- {
- "bargon",
- "",
- AD_ENTRY1s("intro.stk", "2f54b330d21f65b04b7c1f8cca76426c", 262109),
- FR_FRA,
- kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by cesardark in bug #1681649
- {
- "bargon",
- "",
- AD_ENTRY1s("intro.stk", "11103b304286c23945560b391fd37e7d", 3181890),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug #1692667
- {
- "bargon",
- "",
- AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by pwigren in bugreport #1764174
- {
- "bargon",
- "",
- AD_ENTRY1s("intro.stk", "569d679fe41d49972d34c9fce5930dda", 269825),
- EN_ANY,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by kizkoool in bugreport #2089734
- {
- "bargon",
- "",
- AD_ENTRY1s("intro.stk", "00f6b4e2ee26e5c40b488e2df5adcf03", 3975580),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by glorfindel in bugreport #1722142
- {
- "bargon",
- "Fanmade",
- AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- {
- {"intro.stk", 0, "0b72992f5d8b5e6e0330572a5753ea25", 256490},
- {"mod.babayaga", 0, "43484cde74e0860785f8e19f0bc776d1", 60248},
- {0, 0, 0, 0}
- },
- UNK_LANG,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "7b7f48490dedc8a7cb999388e2fadbe3", 3930674),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "e0767783ff662ed93665446665693aef", 4371238),
- HE_ISR,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by cartman_ on #scummvm
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "f1f78b663893b58887add182a77df151", 3944090),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2105220
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "cd322cb3c64ef2ba2f2134aa2122cfe9", 3936700),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by koalet in bug report #2479034
- {
- "lit",
- "",
- {
- {"intro.stk", 0, "af98bcdc70e1f1c1635577fd726fe7f1", 3937310},
- {"musmac1.mid", 0, "ae7229bb09c6abe4e60a2768b24bc890", 9398},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382),
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in french ADI 2.6 Francais-Maths 4e
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "58ee9583a4fb837f02d9a58e5f442656", 3937120),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit1",
- "Full install",
- {
- {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318},
- {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 4396644},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit1",
- "Light install",
- {
- {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318},
- {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 664064},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit2",
- "Light install",
- AD_ENTRY1s("intro.stk", "17acbb212e62addbe48dc8f2282c98cb", 72318),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit2",
- "Full install",
- {
- {"intro.stk", 0, "17acbb212e62addbe48dc8f2282c98cb", 72318},
- {"partie4.itk", 0, "6ce4967e0c79d7daeabc6c1d26783d4c", 2612087},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "Demo",
- AD_ENTRY1("demo.stk", "c06f8cc20eb239d4c71f225ce3093edf"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- "demo.stk", "demo.tot", 0
- },
- {
- {
- "lit",
- "Non-interactive Demo",
- AD_ENTRY1("demo.stk", "2eba8abd9e3878c57307576012dd2fec"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- "demo.stk", "demo.tot", 0
- },
- {
- {
- "fascination",
- "CD Version (Censored)",
- AD_ENTRY1s("disk0.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES
- },
- kGameTypeFascination,
- kFeaturesCD,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "VGA 3 disks edition",
- AD_ENTRY1s("disk0.stk", "a50a8495e1b2d67699fb562cb98fc3e2", 1064387),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeFascination,
- kFeaturesAdLib,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "VGA 3 disks edition",
- AD_ENTRY1s("intro.stk", "d6e45ce548598727e2b5587a99718eba", 1055909),
- HE_ISR,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeFascination,
- kFeaturesAdLib,
- "intro.stk", 0, 0
- },
- { // Supplied by sanguine
- {
- "fascination",
- "VGA 3 disks edition",
- AD_ENTRY1s("disk0.stk", "c14330d052fe4da5a441ac9d81bc5891", 1061955),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeFascination,
- kFeaturesAdLib,
- "disk0.stk", 0, 0
- },
- { // Supplied by windlepoons in bug report #2809247
- {
- "fascination",
- "VGA 3 disks edition",
- AD_ENTRY1s("disk0.stk", "3a24e60a035250189643c86a9ceafb97", 1062480),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeFascination,
- kFeaturesAdLib,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "VGA",
- AD_ENTRY1s("disk0.stk", "e8ab4f200a2304849f462dc901705599", 183337),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeFascination,
- kFeaturesAdLib,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "",
- AD_ENTRY1s("disk0.stk", "68b1c01564f774c0b640075fbad1b695", 189968),
- DE_DEU,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "",
- AD_ENTRY1s("disk0.stk", "7062117e9c5adfb6bfb2dac3ff74df9e", 189951),
- EN_ANY,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "",
- AD_ENTRY1s("disk0.stk", "55c154e5a3e8e98afebdcff4b522e1eb", 190005),
- FR_FRA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "",
- AD_ENTRY1s("disk0.stk", "7691827fff35df7799f14cfd6be178ad", 189931),
- IT_ITA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "",
- AD_ENTRY1s("disk0.stk", "aff9fcc619f4dd19eae228affd0d34c8", 189964),
- EN_ANY,
- kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- {
- {
- "geisha",
- "",
- AD_ENTRY1s("disk1.stk", "6eebbb98ad90cd3c44549fc2ab30f632", 212153),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGeisha,
- kFeaturesNone,
- "disk1.stk", "intro.tot", 0
- },
- {
- {
- "geisha",
- "",
- AD_ENTRY1s("disk1.stk", "f4d4d9d20f7ad1f879fc417d47faba89", 336732),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGeisha,
- kFeaturesNone,
- "disk1.stk", "intro.tot", 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "904fc32032295baa3efb3a41f17db611", 178582),
- HE_ISR,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by raziel_ in bug report #1891869
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "16b014bf32dbd6ab4c5163c44f56fed1", 445104),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by fac76 in bug report #1742716
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "32b0f57f5ae79a9ae97e8011df38af42", 157084},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "1e2f64ec8dfa89f42ee49936a27e66e7"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "f6d225b25a180606fa5dbe6405c97380"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "e42a4f2337d6549487a80864d7826972"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Paranoimia on #scummvm
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "fe8144daece35538085adb59c2d29613", 159402),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "4e3af248a48a2321364736afab868527"),
- RU_RUS,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "8d28ce1591b0e9cc79bf41cad0fc4c9c"),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2098621
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "d3b72938fbbc8159198088811f9e6d19", 160382),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"),
- EN_GRB,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesNone,
- 0, "menu.tot", 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"),
- DE_DEU,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesNone,
- 0, "menu.tot", 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "edd7403e5dc2a14459d2665a4c17714d", 209534},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "edd7403e5dc2a14459d2665a4c17714d", 209534),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "6f2c226c62dd7ab0ab6f850e89d3fc47"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
- HU_HUN,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "Interactive Demo",
- AD_ENTRY1("intro.stk", "7aebd94e49c2c5c518c9e7b74f25de9d"),
- FR_FRA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "Interactive Demo 2",
- AD_ENTRY1("intro.stk", "e5dcbc9f6658ebb1e8fe26bc4da0806d"),
- FR_FRA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "Interactive Demo 3",
- AD_ENTRY1s("intro.stk", "9e20ad7b471b01f84db526da34eaf0a2", 395561),
- EN_ANY,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "Non-interactive Demo",
- AD_ENTRY1("intro.stk", "b9b898fccebe02b69c086052d5024a55"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
- EN_USA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "Non-Interactive Demo",
- {
- {"cons.imd", 0, "f896ba0c4a1ac7f7260d342655980b49", 17804},
- {"conseil.imd", 0, "aaedd5482d5b271e233e86c5a03cf62e", 33999},
- {"int.imd", 0, "6308222fcefbcb20925f01c1aff70dee", 30871},
- {"inter.imd", 0, "39bd6d3540f3bedcc97293f352c7f3fc", 191719},
- {"machu.imd", 0, "c0bc8211d93b467bfd063b63fe61b85c", 34609},
- {"post.imd", 0, "d75cad0e3fc22cb0c8b6faf597f509b2", 1047709},
- {"posta.imd", 0, "2a5b3fe75681ddf4d21ac724db8111b4", 547250},
- {"postb.imd", 0, "24260ce4e80a4c472352b76637265d09", 868312},
- {"postc.imd", 0, "24accbcc8b83a9c2be4bd82849a2bd29", 415637},
- {"tum.imd", 0, "0993d4810ec9deb3f77c5e92095320fd", 20330},
- {"tumi.imd", 0, "bf53f229480d694de0947fe3366fbec6", 248952},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeInca2,
- kFeaturesAdLib | kFeaturesBATDemo,
- 0, 0, 7
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "5f5f4e0a72c33391e67a47674b120cc6", 20296422),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by DjDiabolik in bug report #1971294
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by DjDiabolik in bug report #1971294
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by DjDiabolik in bug report #1971294
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by DjDiabolik in bug report #1971294
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by DjDiabolik in bug report #1971294
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2098838
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "08a96bf061af1fa4f75c6a7cc56b60a4", 20734979),
- PL_POL,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "Non-Interactive Demo",
- {
- {"demo.scn", 0, "16bb85fc5f8e519147b60475dbf33962", 89},
- {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640 | kFeaturesSCNDemo,
- 0, 0, 1
- },
- {
- {
- "dynasty",
- "",
- AD_ENTRY1s("intro.stk", "6190e32404b672f4bbbc39cf76f41fda", 2511470),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeDynasty,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "",
- AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeDynasty,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "",
- AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeDynasty,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "",
- AD_ENTRY1s("intro.stk", "b3f8472484b7a1df94557b51e7b6fca0", 2322644),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeDynasty,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "",
- AD_ENTRY1s("intro.stk", "bdbdac8919200a5e71ffb9fb0709f704", 2446652),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeDynasty,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "Demo",
- AD_ENTRY1s("intro.stk", "464538a17ed39755d7f1ba9c751af1bd", 1847864),
- EN_USA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NONE
- },
- kGameTypeDynasty,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "Demo",
- AD_ENTRY1s("lda1.stk", "0e56a899357cbc0bf503260fd2dd634e", 15032774),
- UNK_LANG,
- kPlatformWindows,
- ADGF_DEMO,
- GUIO_NONE
- },
- kGameTypeDynasty,
- kFeatures640,
- "lda1.stk", 0, 0
- },
- {
- {
- "dynasty",
- "Demo",
- AD_ENTRY1s("lda1.stk", "8669ea2e9a8239c070dc73958fbc8753", 15567724),
- DE_DEU,
- kPlatformWindows,
- ADGF_DEMO,
- GUIO_NONE
- },
- kGameTypeDynasty,
- kFeatures640,
- "lda1.stk", 0, 0
- },
- {
- {
- "urban",
- "",
- AD_ENTRY1s("intro.stk", "3ab2c542bd9216ae5d02cc6f45701ae1", 1252436),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeUrban,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by gamin in the forums
- {
- "urban",
- "",
- AD_ENTRY1s("intro.stk", "b991ed1d31c793e560edefdb349882ef", 1276408),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeUrban,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "urban",
- "",
- AD_ENTRY1s("intro.stk", "4ec3c0864e2b54c5b4ccf9f6ad96528d", 1253328),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeUrban,
- kFeatures640,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2770340
- {
- "urban",
- "",
- AD_ENTRY1s("intro.stk", "4bd31979ea3d77a58a358c09000a85ed", 1253018),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeUrban,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "urban",
- "Non-Interactive Demo",
- {
- {"wdemo.s24", 0, "14ac9bd51db7a075d69ddb144904b271", 87},
- {"demo.vmd", 0, "65d04715d871c292518b56dd160b0161", 9091237},
- {"urband.vmd", 0, "60343891868c91854dd5c82766c70ecc", 922461},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeUrban,
- kFeatures640 | kFeaturesSCNDemo,
- 0, 0, 2
- },
- {
- {
- "playtoons1",
- "",
- {
- {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338},
- {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons1",
- "Pack mes histoires anim\xE9""es",
- {
- {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
- {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons1",
- "",
- {
- {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
- {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- { // Supplied by scoriae in the forums
- {
- "playtoons1",
- "",
- {
- {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
- {"archi.stk", 0, "00d8274519dfcf8a0d8ae3099daea0f8", 5532135},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons1",
- "Non-Interactive Demo",
- {
- {"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258},
- {"archi.vmd", 0, "a410fcc8116bc173f038100f5857191c", 5617210},
- {"chato.vmd", 0, "5a10e39cb66c396f2f9d8fb35e9ac016", 5445937},
- {"genedeb.vmd", 0, "3bb4a45585f88f4d839efdda6a1b582b", 1244228},
- {"generik.vmd", 0, "b46bdd64b063e86927fb2826500ad512", 603242},
- {"genespi.vmd", 0, "b7611916f32a370ae9832962fc17ef72", 758719},
- {"spirou.vmd", 0, "8513dbf7ac51c057b21d371d6b217b47", 2550788},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640 | kFeaturesSCNDemo,
- 0, 0, 3
- },
- {
- {
- "playtoons1",
- "Non-Interactive Demo",
- {
- {"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124},
- {"demarchg.vmd", 0, "d14a95da7d8792faf5503f649ffcbc12", 5619415},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640 | kFeaturesSCNDemo,
- 0, 0, 4
- },
- {
- {
- "playtoons1",
- "Non-Interactive Demo",
- {
- {"i.scn", 0, "8b3294474d39970463663edd22341730", 285},
- {"demarita.vmd", 0, "84c8672b91c7312462603446e224bfec", 5742533},
- {"dembouit.vmd", 0, "7a5fdf0a4dbdfe72e31dd489ea0f8aa2", 3536786},
- {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970},
- {"demoita.vmd", 0, "b4c0622d14c8749965cd0f5dfca4cf4b", 1183566},
- {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
- {0, 0, 0, 0}
- },
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640 | kFeaturesSCNDemo,
- 0, 0, 5
- },
- {
- {
- "playtoons1",
- "Non-Interactive Demo",
- {
- {"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251},
- {"demaresp.vmd", 0, "3f860f944056842b35a5fd05416f208e", 5720619},
- {"demboues.vmd", 0, "3a0caa10c98ef92a15942f8274075b43", 3535838},
- {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970},
- {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
- {0, 0, 0, 0}
- },
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640 | kFeaturesSCNDemo,
- 0, 0, 6
- },
- {
- {
- "playtoons2",
- "",
- {
- {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262},
- {"spirou.stk", 0, "5d9c7644d0c47840169b4d016765cc1a", 9816201},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons2",
- "",
- {
- {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154},
- {"spirou.stk", 0, "e3e1b6148dd72fafc3637f1a8e5764f5", 9812043},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons2",
- "",
- {
- {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
- {"spirou.stk", 0, "91080dc148de1bbd6a97321c1a1facf3", 9817086},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- { // Supplied by scoriae in the forums
- {
- "playtoons2",
- "",
- {
- {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
- {"spirou.stk", 0, "993737f112ca6a9b33c814273280d832", 9825760},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons3",
- "",
- {
- {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338},
- {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons3",
- "",
- {
- {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
- {"chato.stk", 0, "8fc8d0da5b3e758908d1d7298d497d0b", 6041026},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons3",
- "Pack mes histoires anim\xE9""es",
- {
- {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
- {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons3",
- "",
- {
- {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
- {"chato.stk", 0, "3c6cb3ac8a5a7cf681a19971a92a748d", 6033791},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "playtoons3",
- "",
- {
- {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262},
- {"chato.stk", 0, "bdef407387112bfcee90e664865ac3af", 6033867},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons4",
- "",
- {
- {"playtoon.stk", 0, "b7f5afa2dc1b0f75970b7c07d175db1b", 24340406},
- {"manda.stk", 0, "92529e0b927191d9898a34c2892e9a3a", 6485072},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- { //Supplied by goodoldgeorg in bug report #2820006
- {
- "playtoons4",
- "",
- {
- {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
- {"manda.stk", 0, "69a79c9f61b2618e482726f2ff68078d", 6499208},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons5",
- "",
- {
- {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
- {"wakan.stk", 0, "f493bf82851bc5ba74d57de6b7e88df8", 5520153},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "bambou",
- "",
- {
- {"intro.stk", 0, "2f8db6963ff8d72a8331627ebda918f4", 3613238},
- {"bambou.itk", 0, "0875914d31126d0749313428f10c7768", 114440192},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeBambou,
- kFeatures640,
- "intro.stk", "intro.tot", 0
- },
- {
- {
- "playtnck1",
- "",
- {
- {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
- {"dan.itk", 0, "906d67b3e438d5e95ec7ea9e781a94f3", 3000320},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtnck2",
- "",
- {
- {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
- {"dan.itk", 0, "74eeb075bd2cb47b243349730264af01", 3213312},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtnck3",
- "",
- {
- {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
- {"dan.itk", 0, "9a8f62809eca5a52f429b5b6a8e70f8f", 2861056},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- "intro2.stk", 0, 0
- },
- {
- {
- "adi2",
- "Adi 2.0 for Teachers",
- AD_ENTRY1s("adi2.stk", "da6f1fb68bff32260c5eecdf9286a2f5", 1533168),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi2,
- kFeaturesNone,
- "adi2.stk", "ediintro.tot", 0
- },
- { // Found in french ADI 2 Francais-Maths CM1. Exact version not specified.
- {
- "adi2",
- "Adi 2",
- AD_ENTRY1s("adi2.stk", "23f279615c736dc38320f1348e70c36e", 10817668),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi2,
- kFeatures640,
- "adi2.stk", "ediintro.tot", 0
- },
- { // Found in french ADI 2 Francais-Maths CE2. Exact version not specified.
- {
- "adi2",
- "Adi 2",
- AD_ENTRY1s("adi2.stk", "d4162c4298f9423ecc1fb04965557e90", 11531214),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi2,
- kFeatures640,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2",
- AD_ENTRY1s("adi2.stk", "29694c5a649298a42f87ae731d6d6f6d", 311132),
- EN_ANY,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi2,
- kFeaturesNone,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2",
- AD_ENTRY1s("adi2.stk", "2a40bb48ccbd4e6fb3f7f0fc2f069d80", 17720132),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi2,
- kFeatures640,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2.5",
- AD_ENTRY1s("adi2.stk", "fcac60e6627f37aee219575b60859de9", 16944268),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi2,
- kFeatures640,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2.5",
- AD_ENTRY1s("adi2.stk", "072d5e2d7826a7c055865568ebf918bb", 16934596),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi2,
- kFeatures640,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2.6",
- AD_ENTRY1s("adi2.stk", "2fb940eb8105b12871f6b88c8c4d1615", 16780058),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi2,
- kFeatures640,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2.6",
- AD_ENTRY1s("adi2.stk", "fde7d98a67dbf859423b6473796e932a", 18044780),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi2,
- kFeatures640,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2.7.1",
- AD_ENTRY1s("adi2.stk", "6fa5dffebf5c7243c6af6b8c188ee00a", 19278008),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi2,
- kFeatures640,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Non-Interactive Demo",
- {
- {"demo.scn", 0, "8b5ba359fd87d586ad39c1754bf6ea35", 168},
- {"demadi2t.vmd", 0, "08a1b18cfe2015d3b43270da35cc813d", 7250723},
- {"demarch.vmd", 0, "4c4a4616585d40ef3df209e3c3911062", 5622731},
- {"demobou.vmd", 0, "2208b9855775564d15c4a5a559da0aec", 3550511},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeAdi2,
- kFeatures640 | kFeaturesSCNDemo,
- 0, 0, 1
- },
- {
- {
- "adi4",
- "Addy 4 Grundschule Basis CD",
- AD_ENTRY1s("intro.stk", "d2f0fb8909e396328dc85c0e29131ba8", 5847588),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Addy 4 Sekundarstufe Basis CD",
- AD_ENTRY1s("intro.stk", "367340e59c461b4fa36651cd74e32c4e", 5847378),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0",
- AD_ENTRY1s("intro.stk", "a3c35d19b2d28ea261d96321d208cb5a", 6021466),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0",
- AD_ENTRY1s("intro.stk", "44491d85648810bc6fcf84f9b3aa47d5", 5834944),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0",
- AD_ENTRY1s("intro.stk", "29374c0e3c10b17dd8463b06a55ad093", 6012072),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0 Limited Edition",
- AD_ENTRY1s("intro.stk", "ebbbc5e28a4adb695535ed989c1b8d66", 5929644),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "ADI 4.10",
- AD_ENTRY1s("intro.stk", "3e3fa9656e37d802027635ace88c4cc5", 5359144),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "ADI 4.10",
- AD_ENTRY1s("intro.stk", "6afc2590856433b9f5295b032f2b205d", 5923112),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "ADI 4.11",
- AD_ENTRY1s("intro.stk", "6296e4be4e0c270c24d1330881900c7f", 5921234),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Addy 4.21",
- AD_ENTRY1s("intro.stk", "534f0b674cd4830df94a9c32c4ea7225", 6878034),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "ADI 4.21",
- AD_ENTRY1s("intro.stk", "c5b9f6222c0b463f51dab47317c5b687", 5950490),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0 Interactive Demo",
- AD_ENTRY1s("intro.stk", "89ace204dbaac001425c73f394334f6f", 2413102),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0 / Adibou 2 Demo",
- AD_ENTRY1s("intro.stk", "d41d8cd98f00b204e9800998ecf8427e", 0),
- FR_FRA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO_NONE
- },
- kGameTypeAdi4,
- kFeatures640,
- 0, 0, 0
- },
- {
- {
- "ajworld",
- "",
- AD_ENTRY1s("intro.stk", "e453bea7b28a67c930764d945f64d898", 3913628),
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "adibou1",
- "ADIBOU 1 Environnement 4-7 ans",
- AD_ENTRY1s("intro.stk", "6db110188fcb7c5208d9721b5282682a", 4805104),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeAdibou1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2",
- AD_ENTRY1s("intro.stk", "94ae7004348dc8bf99c23a9a6ef81827", 956162),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "Le Jardin Magique d'Adibou",
- AD_ENTRY1s("intro.stk", "a8ff86f3cc40dfe5898e0a741217ef27", 956328),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2",
- AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIB\xD9 2",
- AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU Version Decouverte",
- AD_ENTRY1s("intro.stk", "558c14327b79ed39214b49d567a75e33", 8737856),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2.10 Environnement",
- AD_ENTRY1s("intro.stk", "f2b797819aeedee557e904b0b5ccd82e", 8736454),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2.11 Environnement",
- AD_ENTRY1s("intro.stk", "7b1f1f6f6477f54401e95d913f75e333", 8736904),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2.12 Environnement",
- AD_ENTRY1s("intro.stk", "1e49c39a4a3ce6032a84b712539c2d63", 8738134),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2.13s Environnement",
- AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOO 2.14 Environnement",
- AD_ENTRY1s("intro.stk", "ff63637e3cb7f0a457edf79457b1c6b3", 9333874),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- { AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, 0, 0, 0}
-};
-
-static const GOBGameDescription fallbackDescs[] = {
- { //0
- {
- "gob1",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- { //1
- {
- "gob1cd",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { //2
- {
- "gob2",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { //3
- {
- "gob2mac",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { //4
- {
- "gob2cd",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { //5
- {
- "bargon",
- "",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { //6
- {
- "gob3",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { //7
- {
- "gob3cd",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { //8
- {
- "woodruff",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeWoodruff,
- kFeatures640,
- 0, 0, 0
- },
- { //9
- {
- "lostintime",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { //10
- {
- "lostintime",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { //11
- {
- "lostintime",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { //12
- {
- "urban",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeUrban,
- kFeaturesCD,
- 0, 0, 0
- },
- { //13
- {
- "playtoons1",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- 0, 0, 0
- },
- { //14
- {
- "playtoons2",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- 0, 0, 0
- },
- { //15
- {
- "playtoons3",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- 0, 0, 0
- },
- { //16
- {
- "playtoons4",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- 0, 0, 0
- },
- { //17
- {
- "playtoons5",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- 0, 0, 0
- },
- { //18
- {
- "playtoons construction kit",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypePlaytoons,
- kFeatures640,
- 0, 0, 0
- },
- { //19
- {
- "bambou",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeBambou,
- kFeatures640,
- 0, 0, 0
- },
- { //20
- {
- "fascination",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- { //21
- {
- "geisha",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeGeisha,
- kFeaturesNone,
- "disk1.stk", "intro.tot", 0
- },
- { //22
- {
- "adi2",
- "",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeAdi2,
- kFeatures640,
- "adi2.stk", 0, 0
- },
- { //23
- {
- "adi4",
- "",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSUBTITLES | GUIO_NOSPEECH
- },
- kGameTypeAdi4,
- kFeatures640,
- "adif41.stk", 0, 0
- },
- { //24
- {
- "coktelplayer",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- kGameTypeUrban,
- kFeaturesAdLib | kFeatures640 | kFeaturesSCNDemo,
- "", "", 8
- }
-};
-
-static const ADFileBasedFallback fileBased[] = {
- { &fallbackDescs[ 0], { "intro.stk", "disk1.stk", "disk2.stk", "disk3.stk", "disk4.stk", 0 } },
- { &fallbackDescs[ 1], { "intro.stk", "gob.lic", 0 } },
- { &fallbackDescs[ 2], { "intro.stk", 0 } },
- { &fallbackDescs[ 2], { "intro.stk", "disk2.stk", "disk3.stk", 0 } },
- { &fallbackDescs[ 3], { "intro.stk", "disk2.stk", "disk3.stk", "musmac1.mid", 0 } },
- { &fallbackDescs[ 4], { "intro.stk", "gobnew.lic", 0 } },
- { &fallbackDescs[ 5], { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } },
- { &fallbackDescs[ 6], { "intro.stk", "imd.itk", 0 } },
- { &fallbackDescs[ 7], { "intro.stk", "mus_gob3.lic", 0 } },
- { &fallbackDescs[ 8], { "intro.stk", "woodruff.itk", 0 } },
- { &fallbackDescs[ 9], { "intro.stk", "commun1.itk", 0 } },
- { &fallbackDescs[10], { "intro.stk", "commun1.itk", "musmac1.mid", 0 } },
- { &fallbackDescs[11], { "intro.stk", "commun1.itk", "lost.lic", 0 } },
- { &fallbackDescs[12], { "intro.stk", "cd1.itk", "objet1.itk", 0 } },
- { &fallbackDescs[13], { "playtoon.stk", "archi.stk", 0 } },
- { &fallbackDescs[14], { "playtoon.stk", "spirou.stk", 0 } },
- { &fallbackDescs[15], { "playtoon.stk", "chato.stk", 0 } },
- { &fallbackDescs[16], { "playtoon.stk", "manda.stk", 0 } },
- { &fallbackDescs[17], { "playtoon.stk", "wakan.stk", 0 } },
- { &fallbackDescs[18], { "playtoon.stk", "dan.itk" } },
- { &fallbackDescs[19], { "intro.stk", "bambou.itk", 0 } },
- { &fallbackDescs[20], { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } },
- { &fallbackDescs[21], { "disk1.stk", "disk2.stk", "disk3.stk", 0 } },
- { &fallbackDescs[22], { "adi2.stk", 0 } },
- { &fallbackDescs[23], { "adif41.stk", "adim41.stk", 0 } },
- { &fallbackDescs[24], { "coktelplayer.scn", 0 } },
- { 0, { 0 } }
-};
-
-}
+#include "gob/detection_tables.h"
static const ADParams detectionParams = {
// Pointer to ADGameDescription or its superset structure
@@ -5094,7 +107,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NOLAUNCHLOAD
+ Common::GUIO_NOLAUNCHLOAD,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class GobMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h
new file mode 100644
index 0000000000..20edb9fbc3
--- /dev/null
+++ b/engines/gob/detection_tables.h
@@ -0,0 +1,5013 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Gob {
+
+using Common::GUIO_NOSPEECH;
+using Common::GUIO_NOSUBTITLES;
+using Common::GUIO_NONE;
+
+static const GOBGameDescription gameDescriptions[] = {
+ { // Supplied by Florian Zeitz on scummvm-devel
+ {
+ "gob1",
+ "EGA",
+ AD_ENTRY1("intro.stk", "c65e9cc8ba23a38456242e1f2b1caad4"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesEGA,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "EGA",
+ AD_ENTRY1("intro.stk", "f9233283a0be2464248d83e14b95f09c"),
+ RU_RUS,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesEGA,
+ 0, 0, 0
+ },
+ { // Supplied by Theruler76 in bug report #1201233
+ {
+ "gob1",
+ "VGA",
+ AD_ENTRY1("intro.stk", "26a9118c0770fa5ac93a9626761600b2"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by raziel_ in bug report #1891864
+ {
+ "gob1",
+ "VGA",
+ AD_ENTRY1s("intro.stk", "e157cb59c6d330ca70d12ab0ef1dd12b", 288972),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by raina in the forums
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "6d837c6380d8f4d984c9f6cc0026df4f", 192712),
+ EN_ANY,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 in bug report #1652352
+ {
+ "gob1",
+ "",
+ AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
+ EN_ANY,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 in bug report #1652352
+ {
+ "gob1",
+ "",
+ AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
+ DE_DEU,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 in bug report #1652352
+ {
+ "gob1",
+ "",
+ AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
+ FR_FRA,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 in bug report #1652352
+ {
+ "gob1",
+ "",
+ AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
+ IT_ITA,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 in bug report #1652352
+ {
+ "gob1",
+ "",
+ AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
+ ES_ESP,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // CD 1.000 version.
+ {
+ "gob1cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // CD 1.000 version.
+ {
+ "gob1cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // CD 1.000 version.
+ {
+ "gob1cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // CD 1.000 version.
+ {
+ "gob1cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // CD 1.000 version.
+ {
+ "gob1cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ HU_HUN,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "Demo",
+ AD_ENTRY1("intro.stk", "972f22c6ff8144a6636423f0354ca549"),
+ UNK_LANG,
+ kPlatformAmiga,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "Interactive Demo",
+ AD_ENTRY1("intro.stk", "e72bd1e3828c7dec4c8a3e58c48bdfdb"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "Interactive Demo",
+ AD_ENTRY1s("intro.stk", "a796096280d5efd48cf8e7dfbe426eb5", 193595),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2785958
+ {
+ "gob1",
+ "Interactive Demo",
+ AD_ENTRY1s("intro.stk", "35a098571af9a03c04e2303aec7c9249", 116582),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "0e022d3f2481b39e9175d37b2c6ad4c6", 2390121),
+ FR_FRA,
+ kPlatformCDi,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, "AVT003.TOT", 0
+ },
+ { // Supplied by fac76 in bug report #1883808
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "eebf2810122cfd17399260cd1468e994", 554014),
+ EN_ANY,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "d28b9e9b41f31acfa58dcd12406c7b2c"),
+ DE_DEU,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2602057
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "686c88f7302a80b744aae9f8413e853d"),
+ IT_ITA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by bgk in bug report #1706861
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "4b13c02d1069b86bcfec80f4e474b98b", 554680),
+ FR_FRA,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by fac76 in bug report #1673397
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "b45b984ee8017efd6ea965b9becd4d66", 828443},
+ {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658},
+ {0, 0, 0, 0}
+ },
+ UNK_LANG,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by koalet in bug report #2478585
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275},
+ {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "b45b984ee8017efd6ea965b9becd4d66"),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "dedb5d31d8c8050a8cf77abedcc53dae"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by raziel_ in bug report #1891867
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "25a99827cd59751a80bed9620fb677a0", 893302),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by blackwhiteeagle in bug report #1605235
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "3e4e7db0d201587dd2df4003b2993ef6"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "a13892cdf4badda85a6f6fb47603a128"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2602017
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "c47faf1d406504e6ffe63243610bb1f4"),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "cd3e1df8b273636ee32e34b7064f50e8"),
+ RU_RUS,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by arcepi in bug report #1659884
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "5f53c56e3aa2f1e76c2e4f0caa15887f", 829232),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "285d7340f98ebad65d465585da12910b", 837286},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ EN_USA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ EN_USA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Found in french ADI 2 Francais-Maths CM1
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "24489330a1d67ff978211f574822a5a6", 883756),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "285d7340f98ebad65d465585da12910b", 837286),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "9de5fbb41cf97182109e5fecc9d90347"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2cd",
+ "v2.01",
+ AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2cd",
+ "v2.01",
+ AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2cd",
+ "v2.01",
+ AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2cd",
+ "v2.01",
+ AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2cd",
+ "v2.01",
+ AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ HU_HUN,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "Non-Interactive Demo",
+ AD_ENTRY1("intro.stk", "8b1c98ff2ab2e14f47a1b891e9b92217"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, "usa.tot", 0
+ },
+ {
+ {
+ "gob2",
+ "Interactive Demo",
+ AD_ENTRY1("intro.stk", "cf1c95b2939bd8ff58a25c756cb6125e"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob2",
+ "Interactive Demo",
+ AD_ENTRY1("intro.stk", "4b278c2678ea01383fd5ca114d947eea"),
+ UNK_LANG,
+ kPlatformAmiga,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by polluks in bug report #1895126
+ {
+ "gob2",
+ "Interactive Demo",
+ AD_ENTRY1s("intro.stk", "9fa85aea959fa8c582085855fbd99346", 553063),
+ UNK_LANG,
+ kPlatformAmiga,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by vampir_raziel in bug report #1658373
+ {
+ "ween",
+ "",
+ {
+ {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
+ {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by vampir_raziel in bug report #1658373
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "257fe669705ac4971efdfd5656eef16a", 457719),
+ FR_FRA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by vampir_raziel in bug report #1658373
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "dffd1ab98fe76150d6933329ca6f4cc4", 459458),
+ FR_FRA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by vampir_raziel in bug report #1658373
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "af83debf2cbea21faa591c7b4608fe92", 458192),
+ DE_DEU,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2563539
+ {
+ "ween",
+ "",
+ {
+ {"intro.stk", 0, "dffd1ab98fe76150d6933329ca6f4cc4", 459458},
+ {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by pwigren in bug report #1764174
+ {
+ "ween",
+ "",
+ {
+ {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
+ {"music__5.snd", 0, "7d1819b9981ecddd53d3aacbc75f1cc8", 13446},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "ween",
+ "",
+ AD_ENTRY1("intro.stk", "e6d13fb3b858cb4f78a8780d184d5b2c"),
+ FR_FRA,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "ween",
+ "",
+ AD_ENTRY1("intro.stk", "2bb8878a8042244dd2b96ff682381baa"),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "de92e5c6a8c163007ffceebef6e67f7d", 7117568),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by cybot_tmin in bug report #1667743
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "6d60f9205ecfbd8735da2ee7823a70dc", 7014426),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "ween",
+ "",
+ AD_ENTRY1("intro.stk", "4b10525a3782aa7ecd9d833b5c1d308b"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by cartman_ on #scummvm
+ {
+ "ween",
+ "",
+ AD_ENTRY1("intro.stk", "63170e71f04faba88673b3f510f9c4c8"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by glorfindel in bugreport #1722142
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "8b57cd510da8a3bbd99e3a0297a8ebd1", 7018771),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "ween",
+ "Demo",
+ AD_ENTRY1("intro.stk", "2e9c2898f6bf206ede801e3b2e7ee428"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, "show.tot", 0
+ },
+ {
+ {
+ "ween",
+ "Demo",
+ AD_ENTRY1("intro.stk", "15fb91a1b9b09684b28ac75edf66e504"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, "show.tot", 0
+ },
+ {
+ {
+ "bargon",
+ "",
+ AD_ENTRY1("intro.stk", "da3c54be18ab73fbdb32db24624a9c23"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by Trekky in the forums
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "2f54b330d21f65b04b7c1f8cca76426c", 262109),
+ FR_FRA,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by cesardark in bug #1681649
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "11103b304286c23945560b391fd37e7d", 3181890),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 in bug #1692667
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by pwigren in bugreport #1764174
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "569d679fe41d49972d34c9fce5930dda", 269825),
+ EN_ANY,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by kizkoool in bugreport #2089734
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "00f6b4e2ee26e5c40b488e2df5adcf03", 3975580),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { // Supplied by glorfindel in bugreport #1722142
+ {
+ "bargon",
+ "Fanmade",
+ AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ {
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ {
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ {
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ {
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ {
+ {
+ "littlered",
+ "",
+ {
+ {"intro.stk", 0, "0b72992f5d8b5e6e0330572a5753ea25", 256490},
+ {"mod.babayaga", 0, "43484cde74e0860785f8e19f0bc776d1", 60248},
+ {0, 0, 0, 0}
+ },
+ UNK_LANG,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ {
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ {
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ {
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ {
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ { // Found in french ADI 2 Francais-Maths CM1
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ { // Found in french ADI 2 Francais-Maths CM1
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ { // Found in french ADI 2 Francais-Maths CM1
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ { // Found in french ADI 2 Francais-Maths CM1
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ { // Found in french ADI 2 Francais-Maths CM1
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "7b7f48490dedc8a7cb999388e2fadbe3", 3930674),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "e0767783ff662ed93665446665693aef", 4371238),
+ HE_ISR,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by cartman_ on #scummvm
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "f1f78b663893b58887add182a77df151", 3944090),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2105220
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "cd322cb3c64ef2ba2f2134aa2122cfe9", 3936700),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by koalet in bug report #2479034
+ {
+ "lit",
+ "",
+ {
+ {"intro.stk", 0, "af98bcdc70e1f1c1635577fd726fe7f1", 3937310},
+ {"musmac1.mid", 0, "ae7229bb09c6abe4e60a2768b24bc890", 9398},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Found in french ADI 2.6 Francais-Maths 4e
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "58ee9583a4fb837f02d9a58e5f442656", 3937120),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit1",
+ "Full install",
+ {
+ {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318},
+ {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 4396644},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit1",
+ "Light install",
+ {
+ {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318},
+ {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 664064},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit2",
+ "Light install",
+ AD_ENTRY1s("intro.stk", "17acbb212e62addbe48dc8f2282c98cb", 72318),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit2",
+ "Full install",
+ {
+ {"intro.stk", 0, "17acbb212e62addbe48dc8f2282c98cb", 72318},
+ {"partie4.itk", 0, "6ce4967e0c79d7daeabc6c1d26783d4c", 2612087},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "lit",
+ "Demo",
+ AD_ENTRY1("demo.stk", "c06f8cc20eb239d4c71f225ce3093edf"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ "demo.stk", "demo.tot", 0
+ },
+ {
+ {
+ "lit",
+ "Non-interactive Demo",
+ AD_ENTRY1("demo.stk", "2eba8abd9e3878c57307576012dd2fec"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ "demo.stk", "demo.tot", 0
+ },
+ {
+ {
+ "fascination",
+ "CD Version (Censored)",
+ AD_ENTRY1s("disk0.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES
+ },
+ kGameTypeFascination,
+ kFeaturesCD,
+ "disk0.stk", 0, 0
+ },
+ {
+ {
+ "fascination",
+ "VGA 3 disks edition",
+ AD_ENTRY1s("disk0.stk", "a50a8495e1b2d67699fb562cb98fc3e2", 1064387),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "disk0.stk", 0, 0
+ },
+ {
+ {
+ "fascination",
+ "VGA 3 disks edition",
+ AD_ENTRY1s("intro.stk", "d6e45ce548598727e2b5587a99718eba", 1055909),
+ HE_ISR,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "intro.stk", 0, 0
+ },
+ { // Supplied by sanguine
+ {
+ "fascination",
+ "VGA 3 disks edition",
+ AD_ENTRY1s("disk0.stk", "c14330d052fe4da5a441ac9d81bc5891", 1061955),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "disk0.stk", 0, 0
+ },
+ { // Supplied by windlepoons in bug report #2809247
+ {
+ "fascination",
+ "VGA 3 disks edition",
+ AD_ENTRY1s("disk0.stk", "3a24e60a035250189643c86a9ceafb97", 1062480),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "disk0.stk", 0, 0
+ },
+ {
+ {
+ "fascination",
+ "VGA",
+ AD_ENTRY1s("disk0.stk", "e8ab4f200a2304849f462dc901705599", 183337),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "disk0.stk", 0, 0
+ },
+ {
+ {
+ "fascination",
+ "",
+ AD_ENTRY1s("disk0.stk", "68b1c01564f774c0b640075fbad1b695", 189968),
+ DE_DEU,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesNone,
+ "disk0.stk", 0, 0
+ },
+ {
+ {
+ "fascination",
+ "",
+ AD_ENTRY1s("disk0.stk", "7062117e9c5adfb6bfb2dac3ff74df9e", 189951),
+ EN_ANY,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesNone,
+ "disk0.stk", 0, 0
+ },
+ {
+ {
+ "fascination",
+ "",
+ AD_ENTRY1s("disk0.stk", "55c154e5a3e8e98afebdcff4b522e1eb", 190005),
+ FR_FRA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesNone,
+ "disk0.stk", 0, 0
+ },
+ {
+ {
+ "fascination",
+ "",
+ AD_ENTRY1s("disk0.stk", "7691827fff35df7799f14cfd6be178ad", 189931),
+ IT_ITA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesNone,
+ "disk0.stk", 0, 0
+ },
+ {
+ {
+ "fascination",
+ "",
+ AD_ENTRY1s("disk0.stk", "aff9fcc619f4dd19eae228affd0d34c8", 189964),
+ EN_ANY,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesNone,
+ "disk0.stk", 0, 0
+ },
+ {
+ {
+ "geisha",
+ "",
+ AD_ENTRY1s("disk1.stk", "6eebbb98ad90cd3c44549fc2ab30f632", 212153),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGeisha,
+ kFeaturesNone,
+ "disk1.stk", "intro.tot", 0
+ },
+ {
+ {
+ "geisha",
+ "",
+ AD_ENTRY1s("disk1.stk", "f4d4d9d20f7ad1f879fc417d47faba89", 336732),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGeisha,
+ kFeaturesNone,
+ "disk1.stk", "intro.tot", 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "904fc32032295baa3efb3a41f17db611", 178582),
+ HE_ISR,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by raziel_ in bug report #1891869
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "16b014bf32dbd6ab4c5163c44f56fed1", 445104),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by fac76 in bug report #1742716
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "32b0f57f5ae79a9ae97e8011df38af42", 157084},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "1e2f64ec8dfa89f42ee49936a27e66e7"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 in bug report #1652352
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "f6d225b25a180606fa5dbe6405c97380"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "e42a4f2337d6549487a80864d7826972"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by Paranoimia on #scummvm
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "fe8144daece35538085adb59c2d29613", 159402),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "4e3af248a48a2321364736afab868527"),
+ RU_RUS,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "8d28ce1591b0e9cc79bf41cad0fc4c9c"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Supplied by SiRoCs in bug report #2098621
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "d3b72938fbbc8159198088811f9e6d19", 160382),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"),
+ EN_GRB,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesNone,
+ 0, "menu.tot", 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"),
+ DE_DEU,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesNone,
+ 0, "menu.tot", 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "edd7403e5dc2a14459d2665a4c17714d", 209534},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "edd7403e5dc2a14459d2665a4c17714d", 209534),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "6f2c226c62dd7ab0ab6f850e89d3fc47"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ HU_HUN,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "Interactive Demo",
+ AD_ENTRY1("intro.stk", "7aebd94e49c2c5c518c9e7b74f25de9d"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "Interactive Demo 2",
+ AD_ENTRY1("intro.stk", "e5dcbc9f6658ebb1e8fe26bc4da0806d"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "Interactive Demo 3",
+ AD_ENTRY1s("intro.stk", "9e20ad7b471b01f84db526da34eaf0a2", 395561),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "gob3",
+ "Non-interactive Demo",
+ AD_ENTRY1("intro.stk", "b9b898fccebe02b69c086052d5024a55"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ EN_USA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "inca2",
+ "Non-Interactive Demo",
+ {
+ {"cons.imd", 0, "f896ba0c4a1ac7f7260d342655980b49", 17804},
+ {"conseil.imd", 0, "aaedd5482d5b271e233e86c5a03cf62e", 33999},
+ {"int.imd", 0, "6308222fcefbcb20925f01c1aff70dee", 30871},
+ {"inter.imd", 0, "39bd6d3540f3bedcc97293f352c7f3fc", 191719},
+ {"machu.imd", 0, "c0bc8211d93b467bfd063b63fe61b85c", 34609},
+ {"post.imd", 0, "d75cad0e3fc22cb0c8b6faf597f509b2", 1047709},
+ {"posta.imd", 0, "2a5b3fe75681ddf4d21ac724db8111b4", 547250},
+ {"postb.imd", 0, "24260ce4e80a4c472352b76637265d09", 868312},
+ {"postc.imd", 0, "24accbcc8b83a9c2be4bd82849a2bd29", 415637},
+ {"tum.imd", 0, "0993d4810ec9deb3f77c5e92095320fd", 20330},
+ {"tumi.imd", 0, "bf53f229480d694de0947fe3366fbec6", 248952},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib | kFeaturesBATDemo,
+ 0, 0, 7
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "5f5f4e0a72c33391e67a47674b120cc6", 20296422),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2098838
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "08a96bf061af1fa4f75c6a7cc56b60a4", 20734979),
+ PL_POL,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "woodruff",
+ "Non-Interactive Demo",
+ {
+ {"demo.scn", 0, "16bb85fc5f8e519147b60475dbf33962", 89},
+ {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640 | kFeaturesSCNDemo,
+ 0, 0, 1
+ },
+ {
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "6190e32404b672f4bbbc39cf76f41fda", 2511470),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeDynasty,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeDynasty,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeDynasty,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "b3f8472484b7a1df94557b51e7b6fca0", 2322644),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeDynasty,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "bdbdac8919200a5e71ffb9fb0709f704", 2446652),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeDynasty,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "dynasty",
+ "Demo",
+ AD_ENTRY1s("intro.stk", "464538a17ed39755d7f1ba9c751af1bd", 1847864),
+ EN_USA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NONE
+ },
+ kGameTypeDynasty,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "dynasty",
+ "Demo",
+ AD_ENTRY1s("lda1.stk", "0e56a899357cbc0bf503260fd2dd634e", 15032774),
+ UNK_LANG,
+ kPlatformWindows,
+ ADGF_DEMO,
+ GUIO_NONE
+ },
+ kGameTypeDynasty,
+ kFeatures640,
+ "lda1.stk", 0, 0
+ },
+ {
+ {
+ "dynasty",
+ "Demo",
+ AD_ENTRY1s("lda1.stk", "8669ea2e9a8239c070dc73958fbc8753", 15567724),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_DEMO,
+ GUIO_NONE
+ },
+ kGameTypeDynasty,
+ kFeatures640,
+ "lda1.stk", 0, 0
+ },
+ {
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "3ab2c542bd9216ae5d02cc6f45701ae1", 1252436),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeUrban,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by gamin in the forums
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "b991ed1d31c793e560edefdb349882ef", 1276408),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeUrban,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "4ec3c0864e2b54c5b4ccf9f6ad96528d", 1253328),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeUrban,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { // Supplied by goodoldgeorg in bug report #2770340
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "4bd31979ea3d77a58a358c09000a85ed", 1253018),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeUrban,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "urban",
+ "Non-Interactive Demo",
+ {
+ {"wdemo.s24", 0, "14ac9bd51db7a075d69ddb144904b271", 87},
+ {"demo.vmd", 0, "65d04715d871c292518b56dd160b0161", 9091237},
+ {"urband.vmd", 0, "60343891868c91854dd5c82766c70ecc", 922461},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeUrban,
+ kFeatures640 | kFeaturesSCNDemo,
+ 0, 0, 2
+ },
+ {
+ {
+ "playtoons1",
+ "",
+ {
+ {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338},
+ {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons1",
+ "Pack mes histoires anim\xE9""es",
+ {
+ {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
+ {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons1",
+ "",
+ {
+ {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
+ {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ { // Supplied by scoriae in the forums
+ {
+ "playtoons1",
+ "",
+ {
+ {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
+ {"archi.stk", 0, "00d8274519dfcf8a0d8ae3099daea0f8", 5532135},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons1",
+ "Non-Interactive Demo",
+ {
+ {"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258},
+ {"archi.vmd", 0, "a410fcc8116bc173f038100f5857191c", 5617210},
+ {"chato.vmd", 0, "5a10e39cb66c396f2f9d8fb35e9ac016", 5445937},
+ {"genedeb.vmd", 0, "3bb4a45585f88f4d839efdda6a1b582b", 1244228},
+ {"generik.vmd", 0, "b46bdd64b063e86927fb2826500ad512", 603242},
+ {"genespi.vmd", 0, "b7611916f32a370ae9832962fc17ef72", 758719},
+ {"spirou.vmd", 0, "8513dbf7ac51c057b21d371d6b217b47", 2550788},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640 | kFeaturesSCNDemo,
+ 0, 0, 3
+ },
+ {
+ {
+ "playtoons1",
+ "Non-Interactive Demo",
+ {
+ {"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124},
+ {"demarchg.vmd", 0, "d14a95da7d8792faf5503f649ffcbc12", 5619415},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640 | kFeaturesSCNDemo,
+ 0, 0, 4
+ },
+ {
+ {
+ "playtoons1",
+ "Non-Interactive Demo",
+ {
+ {"i.scn", 0, "8b3294474d39970463663edd22341730", 285},
+ {"demarita.vmd", 0, "84c8672b91c7312462603446e224bfec", 5742533},
+ {"dembouit.vmd", 0, "7a5fdf0a4dbdfe72e31dd489ea0f8aa2", 3536786},
+ {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970},
+ {"demoita.vmd", 0, "b4c0622d14c8749965cd0f5dfca4cf4b", 1183566},
+ {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640 | kFeaturesSCNDemo,
+ 0, 0, 5
+ },
+ {
+ {
+ "playtoons1",
+ "Non-Interactive Demo",
+ {
+ {"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251},
+ {"demaresp.vmd", 0, "3f860f944056842b35a5fd05416f208e", 5720619},
+ {"demboues.vmd", 0, "3a0caa10c98ef92a15942f8274075b43", 3535838},
+ {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970},
+ {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640 | kFeaturesSCNDemo,
+ 0, 0, 6
+ },
+ {
+ {
+ "playtoons2",
+ "",
+ {
+ {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262},
+ {"spirou.stk", 0, "5d9c7644d0c47840169b4d016765cc1a", 9816201},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons2",
+ "",
+ {
+ {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154},
+ {"spirou.stk", 0, "e3e1b6148dd72fafc3637f1a8e5764f5", 9812043},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons2",
+ "",
+ {
+ {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
+ {"spirou.stk", 0, "91080dc148de1bbd6a97321c1a1facf3", 9817086},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ { // Supplied by scoriae in the forums
+ {
+ "playtoons2",
+ "",
+ {
+ {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
+ {"spirou.stk", 0, "993737f112ca6a9b33c814273280d832", 9825760},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons3",
+ "",
+ {
+ {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338},
+ {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons3",
+ "",
+ {
+ {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
+ {"chato.stk", 0, "8fc8d0da5b3e758908d1d7298d497d0b", 6041026},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons3",
+ "Pack mes histoires anim\xE9""es",
+ {
+ {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
+ {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons3",
+ "",
+ {
+ {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
+ {"chato.stk", 0, "3c6cb3ac8a5a7cf681a19971a92a748d", 6033791},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "playtoons3",
+ "",
+ {
+ {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262},
+ {"chato.stk", 0, "bdef407387112bfcee90e664865ac3af", 6033867},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons4",
+ "",
+ {
+ {"playtoon.stk", 0, "b7f5afa2dc1b0f75970b7c07d175db1b", 24340406},
+ {"manda.stk", 0, "92529e0b927191d9898a34c2892e9a3a", 6485072},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ { //Supplied by goodoldgeorg in bug report #2820006
+ {
+ "playtoons4",
+ "",
+ {
+ {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
+ {"manda.stk", 0, "69a79c9f61b2618e482726f2ff68078d", 6499208},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtoons5",
+ "",
+ {
+ {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
+ {"wakan.stk", 0, "f493bf82851bc5ba74d57de6b7e88df8", 5520153},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "bambou",
+ "",
+ {
+ {"intro.stk", 0, "2f8db6963ff8d72a8331627ebda918f4", 3613238},
+ {"bambou.itk", 0, "0875914d31126d0749313428f10c7768", 114440192},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeBambou,
+ kFeatures640,
+ "intro.stk", "intro.tot", 0
+ },
+ {
+ {
+ "playtnck1",
+ "",
+ {
+ {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
+ {"dan.itk", 0, "906d67b3e438d5e95ec7ea9e781a94f3", 3000320},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtnck2",
+ "",
+ {
+ {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
+ {"dan.itk", 0, "74eeb075bd2cb47b243349730264af01", 3213312},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "playtnck3",
+ "",
+ {
+ {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
+ {"dan.itk", 0, "9a8f62809eca5a52f429b5b6a8e70f8f", 2861056},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ "intro2.stk", 0, 0
+ },
+ {
+ {
+ "adi2",
+ "Adi 2.0 for Teachers",
+ AD_ENTRY1s("adi2.stk", "da6f1fb68bff32260c5eecdf9286a2f5", 1533168),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi2,
+ kFeaturesNone,
+ "adi2.stk", "ediintro.tot", 0
+ },
+ { // Found in french ADI 2 Francais-Maths CM1. Exact version not specified.
+ {
+ "adi2",
+ "Adi 2",
+ AD_ENTRY1s("adi2.stk", "23f279615c736dc38320f1348e70c36e", 10817668),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi2,
+ kFeatures640,
+ "adi2.stk", "ediintro.tot", 0
+ },
+ { // Found in french ADI 2 Francais-Maths CE2. Exact version not specified.
+ {
+ "adi2",
+ "Adi 2",
+ AD_ENTRY1s("adi2.stk", "d4162c4298f9423ecc1fb04965557e90", 11531214),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi2,
+ kFeatures640,
+ "adi2.stk", "ediintro.tot", 0
+ },
+ {
+ {
+ "adi2",
+ "Adi 2",
+ AD_ENTRY1s("adi2.stk", "29694c5a649298a42f87ae731d6d6f6d", 311132),
+ EN_ANY,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi2,
+ kFeaturesNone,
+ "adi2.stk", "ediintro.tot", 0
+ },
+ {
+ {
+ "adi2",
+ "Adi 2",
+ AD_ENTRY1s("adi2.stk", "2a40bb48ccbd4e6fb3f7f0fc2f069d80", 17720132),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi2,
+ kFeatures640,
+ "adi2.stk", "ediintro.tot", 0
+ },
+ {
+ {
+ "adi2",
+ "Adi 2.5",
+ AD_ENTRY1s("adi2.stk", "fcac60e6627f37aee219575b60859de9", 16944268),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi2,
+ kFeatures640,
+ "adi2.stk", "ediintro.tot", 0
+ },
+ {
+ {
+ "adi2",
+ "Adi 2.5",
+ AD_ENTRY1s("adi2.stk", "072d5e2d7826a7c055865568ebf918bb", 16934596),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi2,
+ kFeatures640,
+ "adi2.stk", "ediintro.tot", 0
+ },
+ {
+ {
+ "adi2",
+ "Adi 2.6",
+ AD_ENTRY1s("adi2.stk", "2fb940eb8105b12871f6b88c8c4d1615", 16780058),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi2,
+ kFeatures640,
+ "adi2.stk", "ediintro.tot", 0
+ },
+ {
+ {
+ "adi2",
+ "Adi 2.6",
+ AD_ENTRY1s("adi2.stk", "fde7d98a67dbf859423b6473796e932a", 18044780),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi2,
+ kFeatures640,
+ "adi2.stk", "ediintro.tot", 0
+ },
+ {
+ {
+ "adi2",
+ "Adi 2.7.1",
+ AD_ENTRY1s("adi2.stk", "6fa5dffebf5c7243c6af6b8c188ee00a", 19278008),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi2,
+ kFeatures640,
+ "adi2.stk", "ediintro.tot", 0
+ },
+ {
+ {
+ "adi2",
+ "Non-Interactive Demo",
+ {
+ {"demo.scn", 0, "8b5ba359fd87d586ad39c1754bf6ea35", 168},
+ {"demadi2t.vmd", 0, "08a1b18cfe2015d3b43270da35cc813d", 7250723},
+ {"demarch.vmd", 0, "4c4a4616585d40ef3df209e3c3911062", 5622731},
+ {"demobou.vmd", 0, "2208b9855775564d15c4a5a559da0aec", 3550511},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeAdi2,
+ kFeatures640 | kFeaturesSCNDemo,
+ 0, 0, 1
+ },
+ {
+ {
+ "adi4",
+ "Addy 4 Grundschule Basis CD",
+ AD_ENTRY1s("intro.stk", "d2f0fb8909e396328dc85c0e29131ba8", 5847588),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "Addy 4 Sekundarstufe Basis CD",
+ AD_ENTRY1s("intro.stk", "367340e59c461b4fa36651cd74e32c4e", 5847378),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "Adi 4.0",
+ AD_ENTRY1s("intro.stk", "a3c35d19b2d28ea261d96321d208cb5a", 6021466),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "Adi 4.0",
+ AD_ENTRY1s("intro.stk", "44491d85648810bc6fcf84f9b3aa47d5", 5834944),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "Adi 4.0",
+ AD_ENTRY1s("intro.stk", "29374c0e3c10b17dd8463b06a55ad093", 6012072),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "Adi 4.0 Limited Edition",
+ AD_ENTRY1s("intro.stk", "ebbbc5e28a4adb695535ed989c1b8d66", 5929644),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "ADI 4.10",
+ AD_ENTRY1s("intro.stk", "3e3fa9656e37d802027635ace88c4cc5", 5359144),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "ADI 4.10",
+ AD_ENTRY1s("intro.stk", "6afc2590856433b9f5295b032f2b205d", 5923112),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "ADI 4.11",
+ AD_ENTRY1s("intro.stk", "6296e4be4e0c270c24d1330881900c7f", 5921234),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "Addy 4.21",
+ AD_ENTRY1s("intro.stk", "534f0b674cd4830df94a9c32c4ea7225", 6878034),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "ADI 4.21",
+ AD_ENTRY1s("intro.stk", "c5b9f6222c0b463f51dab47317c5b687", 5950490),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "Adi 4.0 Interactive Demo",
+ AD_ENTRY1s("intro.stk", "89ace204dbaac001425c73f394334f6f", 2413102),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "adi4",
+ "Adi 4.0 / Adibou 2 Demo",
+ AD_ENTRY1s("intro.stk", "d41d8cd98f00b204e9800998ecf8427e", 0),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NONE
+ },
+ kGameTypeAdi4,
+ kFeatures640,
+ 0, 0, 0
+ },
+ {
+ {
+ "ajworld",
+ "",
+ AD_ENTRY1s("intro.stk", "e453bea7b28a67c930764d945f64d898", 3913628),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "adibou1",
+ "ADIBOU 1 Environnement 4-7 ans",
+ AD_ENTRY1s("intro.stk", "6db110188fcb7c5208d9721b5282682a", 4805104),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeAdibou1,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ {
+ {
+ "adibou2",
+ "ADIBOU 2",
+ AD_ENTRY1s("intro.stk", "94ae7004348dc8bf99c23a9a6ef81827", 956162),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adibou2",
+ "Le Jardin Magique d'Adibou",
+ AD_ENTRY1s("intro.stk", "a8ff86f3cc40dfe5898e0a741217ef27", 956328),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adibou2",
+ "ADIBOU 2",
+ AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adibou2",
+ "ADIB\xD9 2",
+ AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adibou2",
+ "ADIBOU Version Decouverte",
+ AD_ENTRY1s("intro.stk", "558c14327b79ed39214b49d567a75e33", 8737856),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adibou2",
+ "ADIBOU 2.10 Environnement",
+ AD_ENTRY1s("intro.stk", "f2b797819aeedee557e904b0b5ccd82e", 8736454),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adibou2",
+ "ADIBOU 2.11 Environnement",
+ AD_ENTRY1s("intro.stk", "7b1f1f6f6477f54401e95d913f75e333", 8736904),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adibou2",
+ "ADIBOU 2.12 Environnement",
+ AD_ENTRY1s("intro.stk", "1e49c39a4a3ce6032a84b712539c2d63", 8738134),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adibou2",
+ "ADIBOU 2.13s Environnement",
+ AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ {
+ {
+ "adibou2",
+ "ADIBOO 2.14 Environnement",
+ AD_ENTRY1s("intro.stk", "ff63637e3cb7f0a457edf79457b1c6b3", 9333874),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, 0, 0, 0}
+};
+
+static const GOBGameDescription fallbackDescs[] = {
+ { //0
+ {
+ "gob1",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { //1
+ {
+ "gob1cd",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { //2
+ {
+ "gob2",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { //3
+ {
+ "gob2mac",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { //4
+ {
+ "gob2cd",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { //5
+ {
+ "bargon",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { //6
+ {
+ "gob3",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { //7
+ {
+ "gob3cd",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { //8
+ {
+ "woodruff",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { //9
+ {
+ "lostintime",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { //10
+ {
+ "lostintime",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { //11
+ {
+ "lostintime",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { //12
+ {
+ "urban",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeUrban,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { //13
+ {
+ "playtoons1",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { //14
+ {
+ "playtoons2",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { //15
+ {
+ "playtoons3",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { //16
+ {
+ "playtoons4",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { //17
+ {
+ "playtoons5",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { //18
+ {
+ "playtoons construction kit",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypePlaytoons,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { //19
+ {
+ "bambou",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeBambou,
+ kFeatures640,
+ 0, 0, 0
+ },
+ { //20
+ {
+ "fascination",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeFascination,
+ kFeaturesNone,
+ "disk0.stk", 0, 0
+ },
+ { //21
+ {
+ "geisha",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeGeisha,
+ kFeaturesNone,
+ "disk1.stk", "intro.tot", 0
+ },
+ { //22
+ {
+ "adi2",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeAdi2,
+ kFeatures640,
+ "adi2.stk", 0, 0
+ },
+ { //23
+ {
+ "adi4",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeAdi4,
+ kFeatures640,
+ "adif41.stk", 0, 0
+ },
+ { //24
+ {
+ "coktelplayer",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ kGameTypeUrban,
+ kFeaturesAdLib | kFeatures640 | kFeaturesSCNDemo,
+ "", "", 8
+ }
+};
+
+static const ADFileBasedFallback fileBased[] = {
+ { &fallbackDescs[ 0], { "intro.stk", "disk1.stk", "disk2.stk", "disk3.stk", "disk4.stk", 0 } },
+ { &fallbackDescs[ 1], { "intro.stk", "gob.lic", 0 } },
+ { &fallbackDescs[ 2], { "intro.stk", 0 } },
+ { &fallbackDescs[ 2], { "intro.stk", "disk2.stk", "disk3.stk", 0 } },
+ { &fallbackDescs[ 3], { "intro.stk", "disk2.stk", "disk3.stk", "musmac1.mid", 0 } },
+ { &fallbackDescs[ 4], { "intro.stk", "gobnew.lic", 0 } },
+ { &fallbackDescs[ 5], { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } },
+ { &fallbackDescs[ 6], { "intro.stk", "imd.itk", 0 } },
+ { &fallbackDescs[ 7], { "intro.stk", "mus_gob3.lic", 0 } },
+ { &fallbackDescs[ 8], { "intro.stk", "woodruff.itk", 0 } },
+ { &fallbackDescs[ 9], { "intro.stk", "commun1.itk", 0 } },
+ { &fallbackDescs[10], { "intro.stk", "commun1.itk", "musmac1.mid", 0 } },
+ { &fallbackDescs[11], { "intro.stk", "commun1.itk", "lost.lic", 0 } },
+ { &fallbackDescs[12], { "intro.stk", "cd1.itk", "objet1.itk", 0 } },
+ { &fallbackDescs[13], { "playtoon.stk", "archi.stk", 0 } },
+ { &fallbackDescs[14], { "playtoon.stk", "spirou.stk", 0 } },
+ { &fallbackDescs[15], { "playtoon.stk", "chato.stk", 0 } },
+ { &fallbackDescs[16], { "playtoon.stk", "manda.stk", 0 } },
+ { &fallbackDescs[17], { "playtoon.stk", "wakan.stk", 0 } },
+ { &fallbackDescs[18], { "playtoon.stk", "dan.itk" } },
+ { &fallbackDescs[19], { "intro.stk", "bambou.itk", 0 } },
+ { &fallbackDescs[20], { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } },
+ { &fallbackDescs[21], { "disk1.stk", "disk2.stk", "disk3.stk", 0 } },
+ { &fallbackDescs[22], { "adi2.stk", 0 } },
+ { &fallbackDescs[23], { "adif41.stk", "adim41.stk", 0 } },
+ { &fallbackDescs[24], { "coktelplayer.scn", 0 } },
+ { 0, { 0 } }
+};
+
+}
diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp
index ff6d558998..36b75dc2eb 100644
--- a/engines/gob/draw.cpp
+++ b/engines/gob/draw.cpp
@@ -914,7 +914,7 @@ void Draw::winDraw(int16 fct) {
int table[10];
SurfaceDescPtr tempSrf;
- if (_destSurface == 21) {
+ if (_destSurface == kBackSurface) {
if (_vm->_global->_curWinId) {
if (_fascinWin[_vm->_global->_curWinId].id == -1)
@@ -1032,7 +1032,7 @@ void Draw::winDraw(int16 fct) {
table[_fascinWin[i].id] = i;
}
- if ((_sourceSurface == 21) && (fct == 0)) {
+ if ((_sourceSurface == kBackSurface) && (fct == 0)) {
_vm->_video->drawSprite(*_spritesArray[_sourceSurface], *_spritesArray[_destSurface],
_spriteLeft, _spriteTop, _spriteLeft + _spriteRight - 1,
_spriteTop + _spriteBottom - 1, _destSpriteX, _destSpriteY, _transparency);
@@ -1267,11 +1267,11 @@ void Draw::winDraw(int16 fct) {
}
if (_renderFlags & 16) {
- if (_sourceSurface == 21) {
+ if (_sourceSurface == kBackSurface) {
_spriteLeft -= _backDeltaX;
_spriteTop -= _backDeltaY;
}
- if (_destSurface == 21) {
+ if (_destSurface == kBackSurface) {
_destSpriteX -= _backDeltaX;
_destSpriteY -= _backDeltaY;
}
@@ -1323,9 +1323,9 @@ void Draw::forceBlit(bool backwards) {
return;
if (_frontSurface == _backSurface)
return;
- if (_spritesArray[20] != _frontSurface)
+ if (_spritesArray[kFrontSurface] != _frontSurface)
return;
- if (_spritesArray[21] != _backSurface)
+ if (_spritesArray[kBackSurface] != _backSurface)
return;
if (!backwards) {
diff --git a/engines/gob/draw.h b/engines/gob/draw.h
index 8997c53362..fa3cbb84cc 100644
--- a/engines/gob/draw.h
+++ b/engines/gob/draw.h
@@ -45,7 +45,12 @@ namespace Gob {
class Draw {
public:
- static const int kFontCount = 8;
+ static const int kFontCount = 8;
+ static const int kFrontSurface = 20;
+ static const int kBackSurface = 21;
+ static const int kAnimSurface = 22;
+ static const int kCursorSurface = 23;
+ static const int kCaptureSurface = 30;
struct FontToSprite {
int8 sprite;
diff --git a/engines/gob/draw_fascin.cpp b/engines/gob/draw_fascin.cpp
index 9d30faa972..1e01db7dfb 100644
--- a/engines/gob/draw_fascin.cpp
+++ b/engines/gob/draw_fascin.cpp
@@ -53,12 +53,12 @@ void Draw_Fascination::spriteOperation(int16 operation) {
_destSurface -= 80;
if ((_renderFlags & RENDERFLAG_USEDELTAS) && !deltaVeto) {
- if ((_sourceSurface == 21) && (operation != DRAW_LOADSPRITE)) {
+ if ((_sourceSurface == kBackSurface) && (operation != DRAW_LOADSPRITE)) {
_spriteLeft += _backDeltaX;
_spriteTop += _backDeltaY;
}
- if (_destSurface == 21) {
+ if (_destSurface == kBackSurface) {
_destSpriteX += _backDeltaX;
_destSpriteY += _backDeltaY;
if ((operation == DRAW_DRAWLINE) ||
@@ -70,7 +70,7 @@ void Draw_Fascination::spriteOperation(int16 operation) {
}
if (_renderFlags & 0x20) {
- if (_destSurface == 21 || (operation == 0 && _sourceSurface == 21)) {
+ if (_destSurface == kBackSurface || (operation == 0 && _sourceSurface == kBackSurface)) {
winDraw(operation);
return;
}
@@ -86,7 +86,7 @@ void Draw_Fascination::spriteOperation(int16 operation) {
int16 destSurface = _destSurface;
int16 sourceSurface = _sourceSurface;
- if (_vm->_video->_splitSurf && ((_destSurface == 20) || (_destSurface == 21))) {
+ if (_vm->_video->_splitSurf && ((_destSurface == kFrontSurface) || (_destSurface == kBackSurface))) {
if ((_destSpriteY >= _vm->_video->_splitStart)) {
_destSpriteY -= _vm->_video->_splitStart;
if ((operation == DRAW_DRAWLINE) ||
@@ -340,12 +340,12 @@ void Draw_Fascination::spriteOperation(int16 operation) {
}
if ((_renderFlags & RENDERFLAG_USEDELTAS) && !deltaVeto) {
- if (_sourceSurface == 21) {
+ if (_sourceSurface == kBackSurface) {
_spriteLeft -= _backDeltaX;
_spriteTop -= _backDeltaY;
}
- if (_destSurface == 21) {
+ if (_destSurface == kBackSurface) {
_destSpriteX -= _backDeltaX;
_destSpriteY -= _backDeltaY;
}
diff --git a/engines/gob/draw_playtoons.cpp b/engines/gob/draw_playtoons.cpp
index 862cdd33eb..583d13986e 100644
--- a/engines/gob/draw_playtoons.cpp
+++ b/engines/gob/draw_playtoons.cpp
@@ -53,12 +53,12 @@ void Draw_Playtoons::spriteOperation(int16 operation) {
_destSurface -= 80;
if ((_renderFlags & RENDERFLAG_USEDELTAS) && !deltaVeto) {
- if ((_sourceSurface == 21) && (operation != DRAW_LOADSPRITE)) {
+ if ((_sourceSurface == kBackSurface) && (operation != DRAW_LOADSPRITE)) {
_spriteLeft += _backDeltaX;
_spriteTop += _backDeltaY;
}
- if (_destSurface == 21) {
+ if (_destSurface == kBackSurface) {
_destSpriteX += _backDeltaX;
_destSpriteY += _backDeltaY;
if ((operation == DRAW_DRAWLINE) ||
@@ -78,7 +78,7 @@ void Draw_Playtoons::spriteOperation(int16 operation) {
int16 destSurface = _destSurface;
int16 sourceSurface = _sourceSurface;
- if (_vm->_video->_splitSurf && ((_destSurface == 20) || (_destSurface == 21))) {
+ if (_vm->_video->_splitSurf && ((_destSurface == kFrontSurface) || (_destSurface == kBackSurface))) {
if ((_destSpriteY >= _vm->_video->_splitStart)) {
_destSpriteY -= _vm->_video->_splitStart;
if ((operation == DRAW_DRAWLINE) ||
@@ -409,12 +409,12 @@ void Draw_Playtoons::spriteOperation(int16 operation) {
}
if ((_renderFlags & RENDERFLAG_USEDELTAS) && !deltaVeto) {
- if (_sourceSurface == 21) {
+ if (_sourceSurface == kBackSurface) {
_spriteLeft -= _backDeltaX;
_spriteTop -= _backDeltaY;
}
- if (_destSurface == 21) {
+ if (_destSurface == kBackSurface) {
_destSpriteX -= _backDeltaX;
_destSpriteY -= _backDeltaY;
}
diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp
index 719945fd6f..1cec15ce04 100644
--- a/engines/gob/draw_v1.cpp
+++ b/engines/gob/draw_v1.cpp
@@ -184,7 +184,7 @@ void Draw_v1::printTotText(int16 id) {
_destSpriteY = destY;
_spriteRight = spriteRight;
_spriteBottom = spriteBottom;
- _destSurface = 21;
+ _destSurface = kBackSurface;
_backColor = *ptr++;
_transparency = 1;
@@ -326,12 +326,12 @@ void Draw_v1::spriteOperation(int16 operation) {
_destSurface -= 80;
if (_renderFlags & RENDERFLAG_USEDELTAS) {
- if (_sourceSurface == 21) {
+ if (_sourceSurface == kBackSurface) {
_spriteLeft += _backDeltaX;
_spriteTop += _backDeltaY;
}
- if (_destSurface == 21) {
+ if (_destSurface == kBackSurface) {
_destSpriteX += _backDeltaX;
_destSpriteY += _backDeltaY;
if ((operation == DRAW_DRAWLINE) ||
@@ -508,12 +508,12 @@ void Draw_v1::spriteOperation(int16 operation) {
}
if (_renderFlags & RENDERFLAG_USEDELTAS) {
- if (_sourceSurface == 21) {
+ if (_sourceSurface == kBackSurface) {
_spriteLeft -= _backDeltaX;
_spriteTop -= _backDeltaY;
}
- if (_destSurface == 21) {
+ if (_destSurface == kBackSurface) {
_destSpriteX -= _backDeltaX;
_destSpriteY -= _backDeltaY;
}
diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp
index 985f84aaef..5d001f4b59 100644
--- a/engines/gob/draw_v2.cpp
+++ b/engines/gob/draw_v2.cpp
@@ -51,30 +51,30 @@ void Draw_v2::initScreen() {
_scrollOffsetX = 0;
_scrollOffsetY = 0;
- initSpriteSurf(21, _vm->_video->_surfWidth, _vm->_video->_surfHeight, 0);
- _backSurface = _spritesArray[21];
+ initSpriteSurf(kBackSurface, _vm->_video->_surfWidth, _vm->_video->_surfHeight, 0);
+ _backSurface = _spritesArray[kBackSurface];
_vm->_video->clearSurf(*_backSurface);
- if (!_spritesArray[23]) {
- initSpriteSurf(23, 32, 16, 2);
- _cursorSpritesBack = _spritesArray[23];
+ if (!_spritesArray[kCursorSurface]) {
+ initSpriteSurf(kCursorSurface, 32, 16, 2);
+ _cursorSpritesBack = _spritesArray[kCursorSurface];
_cursorSprites = _cursorSpritesBack;
_scummvmCursor =
_vm->_video->initSurfDesc(_vm->_global->_videoMode, 16, 16, SCUMMVM_CURSOR);
}
- _spritesArray[20] = _frontSurface;
- _spritesArray[21] = _backSurface;
+ _spritesArray[kFrontSurface] = _frontSurface;
+ _spritesArray[kBackSurface ] = _backSurface;
_vm->_video->dirtyRectsAll();
}
void Draw_v2::closeScreen() {
- //freeSprite(23);
+ //freeSprite(kCursorSurface);
//_cursorSprites = 0;
//_cursorSpritesBack = 0;
//_scummvmCursor = 0;
- freeSprite(21);
+ freeSprite(kBackSurface);
}
void Draw_v2::blitCursor() {
@@ -273,7 +273,7 @@ void Draw_v2::printTotText(int16 id) {
_destSpriteY = destY;
_spriteRight = spriteRight;
_spriteBottom = spriteBottom;
- _destSurface = 21;
+ _destSurface = kBackSurface;
_backColor = *ptr++;
_transparency = 1;
@@ -629,12 +629,12 @@ void Draw_v2::spriteOperation(int16 operation) {
_destSurface -= 80;
if ((_renderFlags & RENDERFLAG_USEDELTAS) && !deltaVeto) {
- if ((_sourceSurface == 21) && (operation != DRAW_LOADSPRITE)) {
+ if ((_sourceSurface == kBackSurface) && (operation != DRAW_LOADSPRITE)) {
_spriteLeft += _backDeltaX;
_spriteTop += _backDeltaY;
}
- if (_destSurface == 21) {
+ if (_destSurface == kBackSurface) {
_destSpriteX += _backDeltaX;
_destSpriteY += _backDeltaY;
if ((operation == DRAW_DRAWLINE) ||
@@ -654,7 +654,7 @@ void Draw_v2::spriteOperation(int16 operation) {
int16 destSurface = _destSurface;
int16 sourceSurface = _sourceSurface;
- if (_vm->_video->_splitSurf && ((_destSurface == 20) || (_destSurface == 21))) {
+ if (_vm->_video->_splitSurf && ((_destSurface == kFrontSurface) || (_destSurface == kBackSurface))) {
if ((_destSpriteY >= _vm->_video->_splitStart)) {
_destSpriteY -= _vm->_video->_splitStart;
if ((operation == DRAW_DRAWLINE) ||
@@ -908,12 +908,12 @@ void Draw_v2::spriteOperation(int16 operation) {
}
if ((_renderFlags & RENDERFLAG_USEDELTAS) && !deltaVeto) {
- if (_sourceSurface == 21) {
+ if (_sourceSurface == kBackSurface) {
_spriteLeft -= _backDeltaX;
_spriteTop -= _backDeltaY;
}
- if (_destSurface == 21) {
+ if (_destSurface == kBackSurface) {
_destSpriteX -= _backDeltaX;
_destSpriteY -= _backDeltaY;
}
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index ddf095a5d1..1a8823b156 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -286,8 +286,8 @@ void Game::playTot(int16 skipPlay) {
_vm->_mult->initAll();
_vm->_mult->zeroMultData();
- _vm->_draw->_spritesArray[20] = _vm->_draw->_frontSurface;
- _vm->_draw->_spritesArray[21] = _vm->_draw->_backSurface;
+ _vm->_draw->_spritesArray[Draw::kFrontSurface] = _vm->_draw->_frontSurface;
+ _vm->_draw->_spritesArray[Draw::kBackSurface ] = _vm->_draw->_backSurface;
_vm->_draw->_cursorSpritesBack = _vm->_draw->_cursorSprites;
} else
_vm->_inter->initControlVars(0);
@@ -299,7 +299,7 @@ void Game::playTot(int16 skipPlay) {
break;
if (skipPlay == -2) {
- _vm->_vidPlayer->primaryClose();
+ _vm->_vidPlayer->closeVideo();
skipPlay = 0;
}
@@ -397,10 +397,10 @@ void Game::capturePush(int16 left, int16 top, int16 width, int16 height) {
left &= 0xFFF0;
right |= 0xF;
- _vm->_draw->initSpriteSurf(30 + _captureCount, right - left + 1, height, 0);
+ _vm->_draw->initSpriteSurf(Draw::kCaptureSurface + _captureCount, right - left + 1, height, 0);
- _vm->_draw->_sourceSurface = 21;
- _vm->_draw->_destSurface = 30 + _captureCount;
+ _vm->_draw->_sourceSurface = Draw::kBackSurface;
+ _vm->_draw->_destSurface = Draw::kCaptureSurface + _captureCount;
_vm->_draw->_spriteLeft = left;
_vm->_draw->_spriteRight = right - left + 1;
@@ -425,13 +425,13 @@ void Game::capturePop(char doDraw) {
_captureStack[_captureCount].height();
_vm->_draw->_transparency = 0;
- _vm->_draw->_sourceSurface = 30 + _captureCount;
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_sourceSurface = Draw::kCaptureSurface + _captureCount;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
_vm->_draw->_spriteLeft = _vm->_draw->_destSpriteX & 0xF;
_vm->_draw->_spriteTop = 0;
_vm->_draw->spriteOperation(0);
}
- _vm->_draw->freeSprite(30 + _captureCount);
+ _vm->_draw->freeSprite(Draw::kCaptureSurface + _captureCount);
}
void Game::freeSoundSlot(int16 slot) {
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index e3472e9fe1..f904c8c802 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -126,8 +126,13 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
_pauseStart = 0;
// Setup mixer
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ bool muteSFX = ConfMan.getBool("mute") || ConfMan.getBool("sfx_mute");
+ bool muteMusic = ConfMan.getBool("mute") || ConfMan.getBool("music_mute");
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType,
+ muteSFX ? 0 : ConfMan.getInt("sfx_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType,
+ muteMusic ? 0 : ConfMan.getInt("music_volume"));
_copyProtection = ConfMan.getBool("copy_protection");
@@ -345,8 +350,8 @@ void GobEngine::pauseGame() {
}
bool GobEngine::initGameParts() {
- _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL;
-
+ // just detect some devices some of which will be always there if the music is not disabled
+ _noMusic = MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB)) == MT_NULL ? true : false;
_saveLoad = 0;
_global = new Global(this);
diff --git a/engines/gob/hotspots.cpp b/engines/gob/hotspots.cpp
index abdf513393..396d9f0a22 100644
--- a/engines/gob/hotspots.cpp
+++ b/engines/gob/hotspots.cpp
@@ -2082,7 +2082,7 @@ void Hotspots::getTextCursorPos(const Font &font, const char *str,
}
void Hotspots::fillRect(uint16 x, uint16 y, uint16 width, uint16 height, uint16 color) const {
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
_vm->_draw->_destSpriteX = x;
_vm->_draw->_destSpriteY = y;
_vm->_draw->_spriteRight = width;
diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp
index 24a8e0a390..3da71a2ba6 100644
--- a/engines/gob/init.cpp
+++ b/engines/gob/init.cpp
@@ -174,9 +174,11 @@ void Init::initGame() {
_vm->_util->longDelay(200); // Letting everything settle
- if (_vm->_vidPlayer->primaryOpen("coktel.imd")) {
- _vm->_vidPlayer->primaryPlay();
- _vm->_vidPlayer->primaryClose();
+ VideoPlayer::Properties props;
+ int slot;
+ if ((slot = _vm->_vidPlayer->openVideo(true, "coktel.imd", props)) >= 0) {
+ _vm->_vidPlayer->play(slot, props);
+ _vm->_vidPlayer->closeVideo(slot);
}
_vm->_draw->closeScreen();
diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp
index da8ca103aa..5c56196641 100644
--- a/engines/gob/inter_bargon.cpp
+++ b/engines/gob/inter_bargon.cpp
@@ -72,17 +72,47 @@ void Inter_Bargon::setupOpcodesGob() {
}
void Inter_Bargon::oBargon_intro0(OpGobParams &params) {
- if (_vm->_vidPlayer->primaryOpen("scaa", 0, 160)) {
- _vm->_vidPlayer->primaryPlay(0, 92, 27, 0, 0, 0);
- _vm->_vidPlayer->primaryClose();
- }
+ VideoPlayer::Properties props;
+
+ props.x = 0;
+ props.y = 160;
+ props.startFrame = 0;
+ props.lastFrame = 92;
+ props.palCmd = 0;
+ props.palStart = 0;
+ props.palEnd = 0;
+
+ int slot;
+ if ((slot = _vm->_vidPlayer->openVideo(true, "scaa", props)) < 0)
+ return;
+
+ _vm->_vidPlayer->play(slot, props);
+ _vm->_vidPlayer->closeVideo(slot);
}
void Inter_Bargon::oBargon_intro1(OpGobParams &params) {
- if (_vm->_vidPlayer->primaryOpen("scaa", 0, 160)) {
- _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0, 0, 0, true, 23);
- _vm->_vidPlayer->primaryClose();
- }
+ VideoPlayer::Properties props;
+
+ props.x = 0;
+ props.y = 160;
+ props.palCmd = 0;
+ props.palStart = 0;
+ props.palEnd = 0;
+ props.fade = true;
+
+ int slot;
+ if ((slot = _vm->_vidPlayer->openVideo(true, "scaa", props)) < 0)
+ return;
+
+ _vm->_vidPlayer->play(slot, props);
+
+ props.startFrame = -1;
+ props.lastFrame = _vm->_vidPlayer->getFrameCount(slot) - 23;
+ props.fade = false;
+
+ _vm->_vidPlayer->play(slot, props);
+
+ _vm->_vidPlayer->closeVideo(slot);
}
void Inter_Bargon::oBargon_intro2(OpGobParams &params) {
@@ -178,45 +208,106 @@ void Inter_Bargon::oBargon_intro3(OpGobParams &params) {
}
void Inter_Bargon::oBargon_intro4(OpGobParams &params) {
- if (_vm->_vidPlayer->primaryOpen("scba", 191, 54)) {
- _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0, 0, 0, true);
- _vm->_vidPlayer->primaryClose();
- }
+ VideoPlayer::Properties props;
+
+ props.x = 191;
+ props.y = 54;
+ props.palCmd = 0;
+ props.palStart = 0;
+ props.palEnd = 0;
+ props.fade = true;
+
+ int slot;
+ if ((slot = _vm->_vidPlayer->openVideo(true, "scba", props)) < 0)
+ return;
+
+ _vm->_vidPlayer->play(slot, props);
+ _vm->_vidPlayer->closeVideo(slot);
}
void Inter_Bargon::oBargon_intro5(OpGobParams &params) {
- if (_vm->_vidPlayer->primaryOpen("scbb", 191, 54)) {
- _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0);
- _vm->_vidPlayer->primaryClose();
- }
+ VideoPlayer::Properties props;
+
+ props.x = 191;
+ props.y = 54;
+ props.palCmd = 0;
+ props.palStart = 0;
+ props.palEnd = 0;
+
+ int slot;
+ if ((slot = _vm->_vidPlayer->openVideo(true, "scbb", props)) < 0)
+ return;
+
+ _vm->_vidPlayer->play(slot, props);
+ _vm->_vidPlayer->closeVideo(slot);
}
void Inter_Bargon::oBargon_intro6(OpGobParams &params) {
- if (_vm->_vidPlayer->primaryOpen("scbc", 191, 54)) {
- _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0);
- _vm->_vidPlayer->primaryClose();
- }
+ VideoPlayer::Properties props;
+
+ props.x = 191;
+ props.y = 54;
+ props.palCmd = 0;
+ props.palStart = 0;
+ props.palEnd = 0;
+
+ int slot;
+ if ((slot = _vm->_vidPlayer->openVideo(true, "scbc", props)) < 0)
+ return;
+
+ _vm->_vidPlayer->play(slot, props);
+ _vm->_vidPlayer->closeVideo(slot);
}
void Inter_Bargon::oBargon_intro7(OpGobParams &params) {
- if (_vm->_vidPlayer->primaryOpen("scbf", 191, 54)) {
- _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0);
- _vm->_vidPlayer->primaryClose();
- }
+ VideoPlayer::Properties props;
+
+ props.x = 191;
+ props.y = 54;
+ props.palCmd = 0;
+ props.palStart = 0;
+ props.palEnd = 0;
+
+ int slot;
+ if ((slot = _vm->_vidPlayer->openVideo(true, "scbf", props)) < 0)
+ return;
+
+ _vm->_vidPlayer->play(slot, props);
+ _vm->_vidPlayer->closeVideo(slot);
}
void Inter_Bargon::oBargon_intro8(OpGobParams &params) {
- if (_vm->_vidPlayer->primaryOpen("scbc", 191, 54)) {
- _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0);
- _vm->_vidPlayer->primaryClose();
- }
+ VideoPlayer::Properties props;
+
+ props.x = 191;
+ props.y = 54;
+ props.palCmd = 0;
+ props.palStart = 0;
+ props.palEnd = 0;
+
+ int slot;
+ if ((slot = _vm->_vidPlayer->openVideo(true, "scbc", props)) < 0)
+ return;
+
+ _vm->_vidPlayer->play(slot, props);
+ _vm->_vidPlayer->closeVideo(slot);
}
void Inter_Bargon::oBargon_intro9(OpGobParams &params) {
- if (_vm->_vidPlayer->primaryOpen("scbd", 191, 54)) {
- _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0);
- _vm->_vidPlayer->primaryClose();
- }
+ VideoPlayer::Properties props;
+
+ props.x = 191;
+ props.y = 54;
+ props.palCmd = 0;
+ props.palStart = 0;
+ props.palEnd = 0;
+
+ int slot;
+ if ((slot = _vm->_vidPlayer->openVideo(true, "scbd", props)) < 0)
+ return;
+
+ _vm->_vidPlayer->play(slot, props);
+ _vm->_vidPlayer->closeVideo(slot);
}
} // End of namespace Gob
diff --git a/engines/gob/inter_fascin.cpp b/engines/gob/inter_fascin.cpp
index 5738197539..304f02f4fa 100644
--- a/engines/gob/inter_fascin.cpp
+++ b/engines/gob/inter_fascin.cpp
@@ -131,21 +131,41 @@ bool Inter_Fascination::oFascin_copySprite(OpFuncParams &params) {
void Inter_Fascination::oFascin_playTirb(OpGobParams &params) {
warning("funcPlayImd with parameter : 'tirb.imd'");
- if (_vm->_vidPlayer->primaryOpen("tirb", 150, 88, VideoPlayer::kFlagFrontSurface,
- VideoPlayer::kVideoTypePreIMD, 128, 80)) {
- _vm->_vidPlayer->primaryPlay();
- _vm->_vidPlayer->primaryClose();
- }
+ VideoPlayer::Properties vidProps;
+
+ vidProps.type = VideoPlayer::kVideoTypePreIMD;
+ vidProps.sprite = Draw::kFrontSurface;
+ vidProps.x = 150;
+ vidProps.y = 88;
+ vidProps.width = 128;
+ vidProps.height = 80;
+
+ int vidSlot = _vm->_vidPlayer->openVideo(true, "tirb", vidProps);
+ if (vidSlot < 0)
+ return;
+
+ _vm->_vidPlayer->play(vidSlot, vidProps);
+ _vm->_vidPlayer->closeVideo(vidSlot);
}
void Inter_Fascination::oFascin_playTira(OpGobParams &params) {
warning("funcPlayImd with parameter : 'tira.imd'");
- if (_vm->_vidPlayer->primaryOpen("tira", 88, 66, VideoPlayer::kFlagFrontSurface,
- VideoPlayer::kVideoTypePreIMD, 128, 80)) {
- _vm->_vidPlayer->primaryPlay();
- _vm->_vidPlayer->primaryClose();
- }
+ VideoPlayer::Properties vidProps;
+
+ vidProps.type = VideoPlayer::kVideoTypePreIMD;
+ vidProps.sprite = Draw::kFrontSurface;
+ vidProps.x = 88;
+ vidProps.y = 66;
+ vidProps.width = 128;
+ vidProps.height = 80;
+
+ int vidSlot = _vm->_vidPlayer->openVideo(true, "tira", vidProps);
+ if (vidSlot < 0)
+ return;
+
+ _vm->_vidPlayer->play(vidSlot, vidProps);
+ _vm->_vidPlayer->closeVideo(vidSlot);
}
void Inter_Fascination::oFascin_loadExtasy(OpGobParams &params) {
diff --git a/engines/gob/inter_playtoons.cpp b/engines/gob/inter_playtoons.cpp
index c9b962579b..befed4b1c2 100644
--- a/engines/gob/inter_playtoons.cpp
+++ b/engines/gob/inter_playtoons.cpp
@@ -107,7 +107,7 @@ bool Inter_Playtoons::oPlaytoons_printText(OpFuncParams &params) {
_vm->_draw->_backColor = _vm->_game->_script->readValExpr();
_vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
_vm->_draw->_fontIndex = _vm->_game->_script->readValExpr();
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
_vm->_draw->_textToPrint = buf;
_vm->_draw->_transparency = 0;
@@ -362,7 +362,6 @@ void Inter_Playtoons::oPlaytoons_getObjAnimSize() {
int16 objIndex;
uint16 readVar[4];
uint8 i;
- bool break_fl;
Mult::Mult_AnimData animData;
_vm->_game->_script->evalExpr(&objIndex);
@@ -375,7 +374,6 @@ void Inter_Playtoons::oPlaytoons_getObjAnimSize() {
return;
}
if (objIndex == -2) {
- break_fl = false;
warning("oPlaytoons_getObjAnimSize case -2 not implemented");
return;
}
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index 805893d8a7..11fe0c9c5e 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -328,7 +328,7 @@ void Inter_v1::o1_initCursor() {
(height != _vm->_draw->_cursorHeight) ||
(_vm->_draw->_cursorSprites->getWidth() != (width * count))) {
- _vm->_draw->freeSprite(23);
+ _vm->_draw->freeSprite(Draw::kCursorSurface);
_vm->_draw->_cursorSprites.reset();
_vm->_draw->_cursorSpritesBack.reset();
_vm->_draw->_scummvmCursor.reset();
@@ -344,9 +344,9 @@ void Inter_v1::o1_initCursor() {
if (count > 0x80)
count -= 0x80;
- _vm->_draw->initSpriteSurf(23, _vm->_draw->_cursorWidth * count,
+ _vm->_draw->initSpriteSurf(Draw::kCursorSurface, _vm->_draw->_cursorWidth * count,
_vm->_draw->_cursorHeight, 2);
- _vm->_draw->_cursorSpritesBack = _vm->_draw->_spritesArray[23];
+ _vm->_draw->_cursorSpritesBack = _vm->_draw->_spritesArray[Draw::kCursorSurface];
_vm->_draw->_cursorSprites = _vm->_draw->_cursorSpritesBack;
_vm->_draw->_scummvmCursor =
@@ -482,14 +482,14 @@ void Inter_v1::o1_initMult() {
if (_vm->_mult->_animSurf &&
((oldAnimWidth != _vm->_mult->_animWidth) ||
(oldAnimHeight != _vm->_mult->_animHeight))) {
- _vm->_draw->freeSprite(22);
+ _vm->_draw->freeSprite(Draw::kAnimSurface);
_vm->_mult->_animSurf.reset();
}
if (!_vm->_mult->_animSurf) {
- _vm->_draw->initSpriteSurf(22, _vm->_mult->_animWidth,
+ _vm->_draw->initSpriteSurf(Draw::kAnimSurface, _vm->_mult->_animWidth,
_vm->_mult->_animHeight, 0);
- _vm->_mult->_animSurf = _vm->_draw->_spritesArray[22];
+ _vm->_mult->_animSurf = _vm->_draw->_spritesArray[Draw::kAnimSurface];
}
_vm->_video->drawSprite(*_vm->_draw->_backSurface, *_vm->_mult->_animSurf,
@@ -813,6 +813,14 @@ bool Inter_v1::o1_if(OpFuncParams &params) {
byte cmd;
bool boolRes;
+ // WORKAROUND: Windows Gob1 OUTODDV reload goblin stuck bug present in original
+ if ((_vm->getGameType() == kGameTypeGob1) && (_vm->_game->_script->pos() == 11294) &&
+ !scumm_stricmp(_vm->_game->_curTotFile, "avt00.tot") && VAR(59) == 1) {
+ warning("Workaround for Win Gob1 OUTODDV Reload Goblin Stuck Bug...");
+ WRITE_VAR(285, 0);
+ WRITE_VAR(59, 0);
+ }
+
boolRes = _vm->_game->_script->evalBoolResult();
if (boolRes) {
if ((params.counter == params.cmdCount) && (params.retFlag == 2))
@@ -914,7 +922,7 @@ bool Inter_v1::o1_printText(OpFuncParams &params) {
_vm->_draw->_backColor = _vm->_game->_script->readValExpr();
_vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
_vm->_draw->_fontIndex = _vm->_game->_script->readValExpr();
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
_vm->_draw->_textToPrint = buf;
_vm->_draw->_transparency = 0;
@@ -1331,7 +1339,8 @@ bool Inter_v1::o1_goblinFunc(OpFuncParams &params) {
gobParams.retVarPtr.set(*_variables, 236);
cmd = _vm->_game->_script->readInt16();
- _vm->_game->_script->skip(2);
+ gobParams.paramCount = _vm->_game->_script->readInt16();
+
if ((cmd > 0) && (cmd < 17)) {
objDescSet = true;
gobParams.extraData = _vm->_game->_script->readInt16();
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 72764eec8d..0003332e47 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -360,24 +360,24 @@ void Inter_v2::o2_initMult() {
if (_vm->_mult->_animSurf &&
((oldAnimWidth != _vm->_mult->_animWidth) ||
(oldAnimHeight != _vm->_mult->_animHeight))) {
- _vm->_draw->freeSprite(22);
+ _vm->_draw->freeSprite(Draw::kAnimSurface);
_vm->_mult->_animSurf.reset();
}
_vm->_draw->adjustCoords(0,
&_vm->_mult->_animWidth, &_vm->_mult->_animHeight);
if (!_vm->_mult->_animSurf) {
- _vm->_draw->initSpriteSurf(22, _vm->_mult->_animWidth,
+ _vm->_draw->initSpriteSurf(Draw::kAnimSurface, _vm->_mult->_animWidth,
_vm->_mult->_animHeight, 0);
- _vm->_mult->_animSurf = _vm->_draw->_spritesArray[22];
+ _vm->_mult->_animSurf = _vm->_draw->_spritesArray[Draw::kAnimSurface];
if (_terminate)
return;
}
_vm->_draw->adjustCoords(1,
&_vm->_mult->_animWidth, &_vm->_mult->_animHeight);
- _vm->_draw->_sourceSurface = 21;
- _vm->_draw->_destSurface = 22;
+ _vm->_draw->_sourceSurface = Draw::kBackSurface;
+ _vm->_draw->_destSurface = Draw::kAnimSurface;
_vm->_draw->_spriteLeft = _vm->_mult->_animLeft;
_vm->_draw->_spriteTop = _vm->_mult->_animTop;
_vm->_draw->_spriteRight = _vm->_mult->_animWidth;
@@ -481,7 +481,7 @@ void Inter_v2::o2_loadMultObject() {
if ((((int32) *(obj.pPosX)) == -1234) && (((int32) *(obj.pPosY)) == -4321)) {
if (obj.videoSlot > 0)
- _vm->_vidPlayer->slotClose(obj.videoSlot - 1);
+ _vm->_vidPlayer->closeVideo(obj.videoSlot - 1);
obj.videoSlot = 0;
obj.lastLeft = -1;
@@ -959,50 +959,50 @@ void Inter_v2::o2_setScrollOffset() {
void Inter_v2::o2_playImd() {
char imd[128];
- int16 x, y;
- int16 startFrame;
- int16 lastFrame;
- int16 breakKey;
- int16 flags;
- int16 palStart;
- int16 palEnd;
- uint16 palCmd;
bool close;
_vm->_game->_script->evalExpr(0);
_vm->_game->_script->getResultStr()[8] = 0;
strncpy0(imd, _vm->_game->_script->getResultStr(), 127);
- x = _vm->_game->_script->readValExpr();
- y = _vm->_game->_script->readValExpr();
- startFrame = _vm->_game->_script->readValExpr();
- lastFrame = _vm->_game->_script->readValExpr();
- breakKey = _vm->_game->_script->readValExpr();
- flags = _vm->_game->_script->readValExpr();
- palStart = _vm->_game->_script->readValExpr();
- palEnd = _vm->_game->_script->readValExpr();
- palCmd = 1 << (flags & 0x3F);
+ VideoPlayer::Properties props;
- debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
- "paletteCmd %d (%d - %d), flags %X", _vm->_game->_script->getResultStr(), x, y,
- startFrame, lastFrame, palCmd, palStart, palEnd, flags);
+ props.x = _vm->_game->_script->readValExpr();
+ props.y = _vm->_game->_script->readValExpr();
+ props.startFrame = _vm->_game->_script->readValExpr();
+ props.lastFrame = _vm->_game->_script->readValExpr();
+ props.breakKey = _vm->_game->_script->readValExpr();
+ props.flags = _vm->_game->_script->readValExpr();
+ props.palStart = _vm->_game->_script->readValExpr();
+ props.palEnd = _vm->_game->_script->readValExpr();
+ props.palCmd = 1 << (props.flags & 0x3F);
- if ((imd[0] != 0) && !_vm->_vidPlayer->primaryOpen(imd, x, y, flags)) {
- WRITE_VAR(11, (uint32) -1);
- return;
+ debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
+ "paletteCmd %d (%d - %d), flags %X", imd,
+ props.x, props.y, props.startFrame, props.lastFrame,
+ props.palCmd, props.palStart, props.palEnd, props.flags);
+
+ int slot = 0;
+ if (imd[0] != 0) {
+ _vm->_vidPlayer->evaluateFlags(props);
+ if ((slot = _vm->_vidPlayer->openVideo(true, imd, props)) < 0) {
+ WRITE_VAR(11, (uint32) -1);
+ return;
+ }
}
- close = (lastFrame == -1);
- if (startFrame == -2) {
- startFrame = lastFrame = 0;
+ close = (props.lastFrame == -1);
+ if (props.startFrame == -2) {
+ props.startFrame = 0;
+ props.lastFrame = 0;
close = false;
}
- if (startFrame >= 0)
- _vm->_vidPlayer->primaryPlay(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
+ if (props.startFrame >= 0)
+ _vm->_vidPlayer->play(slot, props);
if (close)
- _vm->_vidPlayer->primaryClose();
+ _vm->_vidPlayer->closeVideo(slot);
}
void Inter_v2::o2_getImdInfo() {
@@ -1011,10 +1011,10 @@ void Inter_v2::o2_getImdInfo() {
int16 varWidth, varHeight;
_vm->_game->_script->evalExpr(0);
- varX = _vm->_game->_script->readVarIndex();
- varY = _vm->_game->_script->readVarIndex();
+ varX = _vm->_game->_script->readVarIndex();
+ varY = _vm->_game->_script->readVarIndex();
varFrames = _vm->_game->_script->readVarIndex();
- varWidth = _vm->_game->_script->readVarIndex();
+ varWidth = _vm->_game->_script->readVarIndex();
varHeight = _vm->_game->_script->readVarIndex();
// WORKAROUND: The nut rolling animation in the administration center
@@ -1106,7 +1106,7 @@ bool Inter_v2::o2_printText(OpFuncParams &params) {
_vm->_draw->_backColor = _vm->_game->_script->readValExpr();
_vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
_vm->_draw->_fontIndex = _vm->_game->_script->readValExpr();
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
_vm->_draw->_textToPrint = buf;
_vm->_draw->_transparency = 0;
diff --git a/engines/gob/inter_v3.cpp b/engines/gob/inter_v3.cpp
index beace1b7d8..10ed23619d 100644
--- a/engines/gob/inter_v3.cpp
+++ b/engines/gob/inter_v3.cpp
@@ -253,8 +253,8 @@ bool Inter_v3::o3_copySprite(OpFuncParams &params) {
o1_copySprite(params);
// For the close-up "fading" in the CD version
- if (_vm->_draw->_destSurface == 20)
- _vm->_video->sparseRetrace(20);
+ if (_vm->_draw->_destSurface == Draw::kFrontSurface)
+ _vm->_video->sparseRetrace(Draw::kFrontSurface);
return false;
}
diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp
index 1f6899d85c..d0824ffb58 100644
--- a/engines/gob/inter_v4.cpp
+++ b/engines/gob/inter_v4.cpp
@@ -142,14 +142,6 @@ void Inter_v4::o4_initScreen() {
void Inter_v4::o4_playVmdOrMusic() {
char fileName[128];
- int16 x, y;
- int16 startFrame;
- int16 lastFrame;
- int16 breakKey;
- int16 flags;
- int16 palStart;
- int16 palEnd;
- uint16 palCmd;
bool close;
_vm->_game->_script->evalExpr(0);
@@ -161,83 +153,92 @@ void Inter_v4::o4_playVmdOrMusic() {
(!scumm_stricmp(fileName, "noixroule")))
strcpy(fileName, "noixroul");
- x = _vm->_game->_script->readValExpr();
- y = _vm->_game->_script->readValExpr();
- startFrame = _vm->_game->_script->readValExpr();
- lastFrame = _vm->_game->_script->readValExpr();
- breakKey = _vm->_game->_script->readValExpr();
- flags = _vm->_game->_script->readValExpr();
- palStart = _vm->_game->_script->readValExpr();
- palEnd = _vm->_game->_script->readValExpr();
- palCmd = 1 << (flags & 0x3F);
+ VideoPlayer::Properties props;
+
+ props.x = _vm->_game->_script->readValExpr();
+ props.y = _vm->_game->_script->readValExpr();
+ props.startFrame = _vm->_game->_script->readValExpr();
+ props.lastFrame = _vm->_game->_script->readValExpr();
+ props.breakKey = _vm->_game->_script->readValExpr();
+ props.flags = _vm->_game->_script->readValExpr();
+ props.palStart = _vm->_game->_script->readValExpr();
+ props.palEnd = _vm->_game->_script->readValExpr();
+ props.palCmd = 1 << (props.flags & 0x3F);
debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
- "paletteCmd %d (%d - %d), flags %X", fileName, x, y, startFrame, lastFrame,
- palCmd, palStart, palEnd, flags);
+ "paletteCmd %d (%d - %d), flags %X", fileName,
+ props.x, props.y, props.startFrame, props.lastFrame,
+ props.palCmd, props.palStart, props.palEnd, props.flags);
close = false;
- if (lastFrame == -1) {
+ if (props.lastFrame == -1) {
close = true;
- } else if (lastFrame == -2) {
- } else if (lastFrame == -3) {
+ } else if (props.lastFrame == -2) {
+ } else if (props.lastFrame == -3) {
+
+ props.flags = VideoPlayer::kFlagOtherSurface;
+ props.sprite = -1;
- _vm->_mult->_objects[startFrame].pAnimData->animation = -startFrame - 1;
+ _vm->_mult->_objects[props.startFrame].pAnimData->animation = -props.startFrame - 1;
- if (_vm->_mult->_objects[startFrame].videoSlot > 0)
- _vm->_vidPlayer->slotClose(_vm->_mult->_objects[startFrame].videoSlot - 1);
+ if (_vm->_mult->_objects[props.startFrame].videoSlot > 0)
+ _vm->_vidPlayer->closeVideo(_vm->_mult->_objects[props.startFrame].videoSlot - 1);
- int slot = _vm->_vidPlayer->slotOpen(fileName);
+ int slot = _vm->_vidPlayer->openVideo(false, fileName, props);
- _vm->_mult->_objects[startFrame].videoSlot = slot + 1;
+ _vm->_mult->_objects[props.startFrame].videoSlot = slot + 1;
- if (x == -1) {
- *_vm->_mult->_objects[startFrame].pPosX = _vm->_vidPlayer->getDefaultX(slot);
- *_vm->_mult->_objects[startFrame].pPosY = _vm->_vidPlayer->getDefaultY(slot);
+ if (props.x == -1) {
+ *_vm->_mult->_objects[props.startFrame].pPosX = _vm->_vidPlayer->getDefaultX(slot);
+ *_vm->_mult->_objects[props.startFrame].pPosY = _vm->_vidPlayer->getDefaultY(slot);
} else {
- *_vm->_mult->_objects[startFrame].pPosX = x;
- *_vm->_mult->_objects[startFrame].pPosY = y;
+ *_vm->_mult->_objects[props.startFrame].pPosX = props.x;
+ *_vm->_mult->_objects[props.startFrame].pPosY = props.y;
}
return;
- } else if (lastFrame == -4) {
+ } else if (props.lastFrame == -4) {
warning("Woodruff Stub: Video/Music command -4: Play background video %s", fileName);
return;
- } else if (lastFrame == -5) {
+ } else if (props.lastFrame == -5) {
_vm->_sound->bgStop();
return;
- } else if (lastFrame == -6) {
+ } else if (props.lastFrame == -6) {
return;
- } else if (lastFrame == -7) {
+ } else if (props.lastFrame == -7) {
return;
- } else if (lastFrame == -8) {
+ } else if (props.lastFrame == -8) {
warning("Woodruff Stub: Video/Music command -8: Play background video %s", fileName);
return;
- } else if (lastFrame == -9) {
+ } else if (props.lastFrame == -9) {
_vm->_sound->bgStop();
_vm->_sound->bgSetPlayMode(BackgroundAtmosphere::kPlayModeRandom);
- _vm->_sound->bgPlay(fileName, "SND", SOUND_SND, palStart);
+ _vm->_sound->bgPlay(fileName, "SND", SOUND_SND, props.palStart);
return;
- } else if (lastFrame < 0) {
- warning("Unknown Video/Music command: %d, %s", lastFrame, fileName);
+ } else if (props.lastFrame < 0) {
+ warning("Unknown Video/Music command: %d, %s", props.lastFrame, fileName);
return;
}
- if (startFrame == -2) {
- startFrame = 0;
- lastFrame = -1;
+ if (props.startFrame == -2) {
+ props.startFrame = 0;
+ props.lastFrame = -1;
close = false;
}
- if ((fileName[0] != 0) && !_vm->_vidPlayer->primaryOpen(fileName, x, y, flags)) {
+ _vm->_vidPlayer->evaluateFlags(props);
+
+ int slot;
+ if ((fileName[0] != 0) && ((slot = _vm->_vidPlayer->openVideo(true, fileName, props)) < 0)) {
WRITE_VAR(11, (uint32) -1);
return;
}
- if (startFrame >= 0)
- _vm->_vidPlayer->primaryPlay(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
+ if (props.startFrame >= 0)
+ _vm->_vidPlayer->play(slot, props);
if (close)
- _vm->_vidPlayer->primaryClose();
+ _vm->_vidPlayer->closeVideo(slot);
}
} // End of namespace Gob
diff --git a/engines/gob/inter_v6.cpp b/engines/gob/inter_v6.cpp
index cbc831b5a1..73ef46bf31 100644
--- a/engines/gob/inter_v6.cpp
+++ b/engines/gob/inter_v6.cpp
@@ -102,88 +102,86 @@ void Inter_v6::o6_totSub() {
void Inter_v6::o6_playVmdOrMusic() {
char fileName[128];
- int16 x, y;
- int16 startFrame;
- int16 lastFrame;
- int16 breakKey;
- int16 flags;
- int16 palStart;
- int16 palEnd;
- uint16 palCmd;
bool close;
_vm->_game->_script->evalExpr(0);
strncpy0(fileName, _vm->_game->_script->getResultStr(), 127);
- x = _vm->_game->_script->readValExpr();
- y = _vm->_game->_script->readValExpr();
- startFrame = _vm->_game->_script->readValExpr();
- lastFrame = _vm->_game->_script->readValExpr();
- breakKey = _vm->_game->_script->readValExpr();
- flags = _vm->_game->_script->readValExpr();
- palStart = _vm->_game->_script->readValExpr();
- palEnd = _vm->_game->_script->readValExpr();
- palCmd = 1 << (flags & 0x3F);
+ VideoPlayer::Properties props;
+
+ props.x = _vm->_game->_script->readValExpr();
+ props.y = _vm->_game->_script->readValExpr();
+ props.startFrame = _vm->_game->_script->readValExpr();
+ props.lastFrame = _vm->_game->_script->readValExpr();
+ props.breakKey = _vm->_game->_script->readValExpr();
+ props.flags = _vm->_game->_script->readValExpr();
+ props.palStart = _vm->_game->_script->readValExpr();
+ props.palEnd = _vm->_game->_script->readValExpr();
+ props.palCmd = 1 << (props.flags & 0x3F);
+ props.forceSeek = true;
debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
- "paletteCmd %d (%d - %d), flags %X", fileName, x, y, startFrame, lastFrame,
- palCmd, palStart, palEnd, flags);
+ "paletteCmd %d (%d - %d), flags %X", fileName,
+ props.x, props.y, props.startFrame, props.lastFrame,
+ props.palCmd, props.palStart, props.palEnd, props.flags);
close = false;
- if (lastFrame == -1) {
+ if (props.lastFrame == -1) {
close = true;
- } else if (lastFrame == -5) {
+ } else if (props.lastFrame == -5) {
// warning("Urban/Playtoons Stub: Stop without delay");
_vm->_sound->bgStop();
return;
- } else if (lastFrame == -6) {
+ } else if (props.lastFrame == -6) {
// warning("Urban/Playtoons Stub: Video/Music command -6 (cache video)");
return;
- } else if (lastFrame == -7) {
+ } else if (props.lastFrame == -7) {
// warning("Urban/Playtoons Stub: Video/Music command -6 (flush cache)");
return;
- } else if ((lastFrame == -8) || (lastFrame == -9)) {
+ } else if ((props.lastFrame == -8) || (props.lastFrame == -9)) {
if (!strchr(fileName, '.'))
strcat(fileName, ".WA8");
probe16bitMusic(fileName);
- if (lastFrame == -9) {
+ if (props.lastFrame == -9) {
warning("Urban/Playtoons Stub: delayed stop not implemented");
}
_vm->_sound->bgStop();
_vm->_sound->bgPlay(fileName, SOUND_WAV);
return;
- } else if (lastFrame <= -10) {
- _vm->_vidPlayer->primaryClose();
- warning("Urban/Playtoons Stub: Video/Music command %d (close video?), %s", lastFrame, fileName);
- if (lastFrame <= -100)
- lastFrame += 100;
+ } else if (props.lastFrame <= -10) {
+ _vm->_vidPlayer->closeVideo();
+ warning("Urban/Playtoons Stub: Video/Music command %d (close video?), %s", props.lastFrame, fileName);
+ if (props.lastFrame <= -100)
+ props.lastFrame += 100;
- if (((-lastFrame) % 10 == 3) && (lastFrame <= -20))
+ if (((-props.lastFrame) % 10 == 3) && (props.lastFrame <= -20))
_vm->_sound->bgPlay(fileName, SOUND_WAV);
- } else if (lastFrame < 0) {
- warning("Urban/Playtoons Stub: Unknown Video/Music command: %d, %s", lastFrame, fileName);
+ } else if (props.lastFrame < 0) {
+ warning("Urban/Playtoons Stub: Unknown Video/Music command: %d, %s", props.lastFrame, fileName);
return;
}
- if (startFrame == -2) {
- startFrame = 0;
- lastFrame = -1;
+ if (props.startFrame == -2) {
+ props.startFrame = 0;
+ props.lastFrame = -1;
close = false;
}
- if ((fileName[0] != 0) && !_vm->_vidPlayer->primaryOpen(fileName, x, y, flags)) {
+ _vm->_vidPlayer->evaluateFlags(props);
+
+ int slot;
+ if ((fileName[0] != 0) && ((slot = _vm->_vidPlayer->openVideo(true, fileName, props)) < 0)) {
WRITE_VAR(11, (uint32) -1);
return;
}
- if (startFrame >= 0)
- _vm->_vidPlayer->primaryPlay(startFrame, lastFrame, breakKey,
- palCmd, palStart, palEnd, 0, -1, false, -1, true);
+ if (props.startFrame >= 0)
+ _vm->_vidPlayer->play(slot, props);
if (close)
- _vm->_vidPlayer->primaryClose();
+ _vm->_vidPlayer->closeVideo(slot);
}
void Inter_v6::o6_openItk() {
@@ -224,24 +222,30 @@ bool Inter_v6::o6_loadCursor(OpFuncParams &params) {
uint16 start = _vm->_game->_script->readUint16();
int8 index = _vm->_game->_script->readInt8();
- int vmdSlot = _vm->_vidPlayer->slotOpen(file);
+ VideoPlayer::Properties props;
+ props.sprite = -1;
+
+ int vmdSlot = _vm->_vidPlayer->openVideo(false, file, props);
if (vmdSlot == -1) {
warning("Can't open video \"%s\" as cursor", file);
return false;
}
- int16 framesCount = _vm->_vidPlayer->getFramesCount(vmdSlot);
+ int16 framesCount = _vm->_vidPlayer->getFrameCount(vmdSlot);
for (int i = 0; i < framesCount; i++) {
- _vm->_vidPlayer->slotPlay(vmdSlot);
- _vm->_vidPlayer->slotCopyFrame(vmdSlot, _vm->_draw->_cursorSprites->getVidMem(),
+ props.startFrame = i;
+ props.lastFrame = i;
+
+ _vm->_vidPlayer->play(vmdSlot, props);
+ _vm->_vidPlayer->copyFrame(vmdSlot, _vm->_draw->_cursorSprites->getVidMem(),
0, 0, _vm->_draw->_cursorWidth, _vm->_draw->_cursorWidth,
(start + i) * _vm->_draw->_cursorWidth, 0,
_vm->_draw->_cursorSprites->getWidth());
}
- _vm->_vidPlayer->slotClose(vmdSlot);
+ _vm->_vidPlayer->closeVideo(vmdSlot);
_vm->_draw->_cursorAnimLow[index] = start;
_vm->_draw->_cursorAnimHigh[index] = framesCount + start - 1;
diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp
index 327b3ed1bd..f744f14faf 100644
--- a/engines/gob/mult.cpp
+++ b/engines/gob/mult.cpp
@@ -146,7 +146,7 @@ void Mult::freeMult() {
_orderArray = 0;
_animSurf.reset();
- _vm->_draw->freeSprite(22);
+ _vm->_draw->freeSprite(Draw::kAnimSurface);
}
void Mult::checkFreeMult() {
@@ -238,7 +238,7 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape,
_orderArray = 0;
_animSurf.reset();
- _vm->_draw->freeSprite(22);
+ _vm->_draw->freeSprite(Draw::kAnimSurface);
_animDataAllocated = false;
}
@@ -452,7 +452,7 @@ void Mult::clearObjectVideos() {
for (int i = 0; i < _objCount; i++)
if (_objects[i].videoSlot > 0)
- _vm->_vidPlayer->slotClose(_objects[i].videoSlot - 1);
+ _vm->_vidPlayer->closeVideo(_objects[i].videoSlot - 1);
}
} // End of namespace Gob
diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp
index 1bb162c789..84869066e1 100644
--- a/engines/gob/mult_v1.cpp
+++ b/engines/gob/mult_v1.cpp
@@ -236,7 +236,7 @@ void Mult_v1::freeMultKeys() {
_animArrayData = 0;
_animSurf.reset();
- _vm->_draw->freeSprite(22);
+ _vm->_draw->freeSprite(Draw::kAnimSurface);
_animDataAllocated = false;
}
@@ -318,7 +318,7 @@ void Mult_v1::playMultInit() {
_animSurf = _vm->_video->initSurfDesc(_vm->_global->_videoMode,
320, 200, 0);
- _vm->_draw->_spritesArray[22] = _animSurf;
+ _vm->_draw->_spritesArray[Draw::kAnimSurface] = _animSurf;
_vm->_video->drawSprite(*_vm->_draw->_backSurface,
*_animSurf, 0, 0, 319, 199, 0, 0, 0);
@@ -579,8 +579,8 @@ void Mult_v1::animate() {
if ((pNeedRedraw[i] == 0) || (_objects[i].lastLeft == -1))
continue;
- _vm->_draw->_sourceSurface = 22;
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_sourceSurface = Draw::kAnimSurface;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
_vm->_draw->_spriteLeft = pDirtyLefts[i] - _animLeft;
_vm->_draw->_spriteTop = pDirtyTops[i] - _animTop;
_vm->_draw->_spriteRight = pDirtyRights[i] - pDirtyLefts[i] + 1;
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index 88b604023c..66488054e7 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -579,11 +579,11 @@ void Mult_v2::playMultInit() {
width = _animWidth;
height = _animHeight;
_vm->_draw->adjustCoords(0, &width, &height);
- _vm->_draw->initSpriteSurf(22, width, height, 0);
- _animSurf = _vm->_draw->_spritesArray[22];
+ _vm->_draw->initSpriteSurf(Draw::kAnimSurface, width, height, 0);
+ _animSurf = _vm->_draw->_spritesArray[Draw::kAnimSurface];
- _vm->_video->drawSprite(*_vm->_draw->_spritesArray[21],
- *_vm->_draw->_spritesArray[22], 0, 0,
+ _vm->_video->drawSprite(*_vm->_draw->_spritesArray[Draw::kBackSurface],
+ *_vm->_draw->_spritesArray[Draw::kAnimSurface], 0, 0,
_vm->_video->_surfWidth, _vm->_video->_surfHeight, 0, 0, 0);
for (_counter = 0; _counter < _objCount; _counter++)
@@ -633,14 +633,14 @@ void Mult_v2::drawStatics(bool &stop) {
READ_LE_UINT16(_multData->execPtr + layer * 2);
_vm->_draw->_destSpriteX = 0;
_vm->_draw->_destSpriteY = 0;
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
_vm->_draw->_transparency = 0;
_vm->_draw->spriteOperation(DRAW_LOADSPRITE);
_vm->_scenery->_curStatic = -1;
}
- _vm->_video->drawSprite(*_vm->_draw->_spritesArray[21],
- *_vm->_draw->_spritesArray[22], 0, 0,
+ _vm->_video->drawSprite(*_vm->_draw->_spritesArray[Draw::kBackSurface],
+ *_vm->_draw->_spritesArray[Draw::kAnimSurface], 0, 0,
_vm->_video->_surfWidth, _vm->_video->_surfHeight, 0, 0, 0);
}
}
@@ -710,7 +710,7 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) {
} else {
if (animObj.videoSlot > 0) {
_vm->_video->retrace();
- _vm->_vidPlayer->slotWaitEndFrame(animObj.videoSlot - 1, true);
+ _vm->_vidPlayer->waitEndFrame(animObj.videoSlot - 1, true);
}
}
@@ -736,8 +736,8 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) {
if (animData.animation < 0) {
if ((animObj.videoSlot > 0) &&
- (_vm->_vidPlayer->getCurrentFrame(animObj.videoSlot - 1) <
- _vm->_vidPlayer->getFramesCount(animObj.videoSlot - 1))) {
+ ((_vm->_vidPlayer->getCurrentFrame(animObj.videoSlot - 1) + 1) <
+ _vm->_vidPlayer->getFrameCount(animObj.videoSlot - 1))) {
animData.newCycle = 0;
return;
}
@@ -775,7 +775,7 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) {
animData.isStatic = 1;
animData.frame = 0;
if ((animData.animation < 0) && (animObj.videoSlot > 0)) {
- _vm->_vidPlayer->slotClose(animObj.videoSlot - 1);
+ _vm->_vidPlayer->closeVideo(animObj.videoSlot - 1);
animObj.videoSlot = 0;
}
@@ -788,7 +788,7 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) {
/*
if ((animData.animation < 0) && (animObj.videoSlot > 0)) {
if (_vm->_vidPlayer->getFlags(animObj.videoSlot - 1) & 0x1000) {
- _vm->_vidPlayer->slotClose(animObj.videoSlot - 1);
+ _vm->_vidPlayer->closeVideo(animObj.videoSlot - 1);
animObj.videoSlot = 0;
}
}
@@ -937,8 +937,8 @@ void Mult_v2::animate() {
if ((right <= 0) || (bottom <= 0))
continue;
- _vm->_draw->_sourceSurface = 22;
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_sourceSurface = Draw::kAnimSurface;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
_vm->_draw->_spriteLeft = maxleft - _animLeft;
_vm->_draw->_spriteTop = maxtop - _animTop;
_vm->_draw->_spriteRight = right;
@@ -1100,56 +1100,66 @@ void Mult_v2::animate() {
void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir,
int16 startFrame) {
- int16 x, y;
- int16 palStart, palEnd;
- int16 baseFrame, palFrame, lastFrame;
- uint16 flags;
+
+ VideoPlayer::Properties props;
if (_vm->_draw->_renderFlags & 0x100) {
- x = VAR(55);
- y = VAR(56);
- } else
- x = y = -1;
+ props.x = VAR(55);
+ props.y = VAR(56);
+ }
if (key.imdFile == -1) {
- _vm->_vidPlayer->primaryClose();
+ _vm->_vidPlayer->closeVideo();
return;
}
- flags = (key.flags >> 8) & 0xFF;
- if (flags & 0x20)
- flags = (flags & 0x9F) | 0x80;
+ props.flags = (key.flags >> 8) & 0xFF;
+ if (props.flags & 0x20)
+ props.flags = (props.flags & 0x9F) | 0x80;
- palStart = key.palStart;
- palEnd = key.palEnd;
- palFrame = key.palFrame;
- lastFrame = key.lastFrame;
+ props.palStart = key.palStart;
+ props.palEnd = key.palEnd;
+ props.palFrame = key.palFrame;
+ props.lastFrame = key.lastFrame;
- if ((palFrame != -1) && (lastFrame != -1))
- if ((lastFrame - palFrame) < startFrame)
+ if ((props.palFrame != -1) && (props.lastFrame != -1))
+ if ((props.lastFrame - props.palFrame) < props.startFrame)
if (!(key.flags & 0x4000)) {
- _vm->_vidPlayer->primaryClose();
+ _vm->_vidPlayer->closeVideo();
return;
}
- if (!_vm->_vidPlayer->primaryOpen(imdFile, x, y, flags))
+ _vm->_vidPlayer->evaluateFlags(props);
+
+ int slot;
+ if ((slot = _vm->_vidPlayer->openVideo(true, imdFile, props)) < 0)
return;
- if (palFrame == -1)
- palFrame = 0;
+ if (props.palFrame == -1)
+ props.palFrame = 0;
+
+ if (props.lastFrame == -1)
+ props.lastFrame = _vm->_vidPlayer->getFrameCount() - 1;
+
+ uint32 baseFrame = startFrame % (props.lastFrame - props.palFrame + 1);
+
+ props.endFrame = props.lastFrame;
+ props.startFrame = baseFrame + props.palFrame;
+ props.lastFrame = baseFrame + props.palFrame;
+
+ props.flags &= 0x7F;
- if (lastFrame == -1)
- lastFrame = _vm->_vidPlayer->getFramesCount() - 1;
+ debugC(2, kDebugVideo, "Playing mult video \"%s\" @ %d+%d, frame %d, "
+ "paletteCmd %d (%d - %d; %d), flags %X", imdFile,
+ props.x, props.y, props.startFrame,
+ props.palCmd, props.palStart, props.palEnd, props.endFrame, props.flags);
- baseFrame = startFrame % (lastFrame - palFrame + 1);
- _vm->_vidPlayer->primaryPlay(baseFrame + palFrame, baseFrame + palFrame, 0,
- flags & 0x7F, palStart, palEnd, palFrame, lastFrame);
+ _vm->_vidPlayer->play(slot, props);
}
void Mult_v2::advanceObjects(int16 index) {
int16 frame;
bool stop = false;
- bool hasImds = false;
frame = _multData->animKeysFrames[index];
if (frame == -1)
@@ -1254,7 +1264,6 @@ void Mult_v2::advanceObjects(int16 index) {
if ((dir != 1) && (--startFrame < 0))
startFrame = 0;
- hasImds = true;
playImd(imdFile, key, dir, startFrame);
}
}
diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp
index a6d6c06544..f9587dc0b3 100644
--- a/engines/gob/scenery.cpp
+++ b/engines/gob/scenery.cpp
@@ -261,10 +261,10 @@ void Scenery::renderStatic(int16 scenery, int16 layer) {
_vm->_draw->_spriteLeft = layerPtr->backResId;
if (_vm->_draw->_spriteLeft != -1) {
- _vm->_draw->_destSpriteX = 0;
- _vm->_draw->_destSpriteY = 0;
- _vm->_draw->_destSurface = 21;
- _vm->_draw->_transparency = 0;
+ _vm->_draw->_destSpriteX = 0;
+ _vm->_draw->_destSpriteY = 0;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
+ _vm->_draw->_transparency = 0;
_vm->_draw->spriteOperation(DRAW_LOADSPRITE);
}
@@ -295,7 +295,7 @@ void Scenery::renderStatic(int16 scenery, int16 layer) {
_vm->_draw->_sourceSurface =
_staticPictToSprite[scenery * 7 + pictIndex];
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
_vm->_draw->_spriteLeft = left;
_vm->_draw->_spriteTop = top;
_vm->_draw->_spriteRight = right - left + 1;
@@ -392,7 +392,7 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
_vm->_draw->_sourceSurface =
_staticPictToSprite[index * 7 + pictIndex];
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
_vm->_draw->_transparency = planePtr->transp ? 3 : 0;
_vm->_draw->spriteOperation(DRAW_BLITSURF);
}
@@ -616,26 +616,29 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
return;
}
- if (frame >= _vm->_vidPlayer->getFramesCount(obj.videoSlot - 1))
- frame = _vm->_vidPlayer->getFramesCount(obj.videoSlot - 1) - 1;
+ if (frame >= (int32)_vm->_vidPlayer->getFrameCount(obj.videoSlot - 1))
+ frame = _vm->_vidPlayer->getFrameCount(obj.videoSlot - 1) - 1;
- // Seek to frame
- if (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) < 256) {
- while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) <= frame)
- _vm->_vidPlayer->slotPlay(obj.videoSlot - 1);
- } else {
- int16 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1);
- uint8 frameWrap = curFrame / 256;
- frame = (frame + 1) % 256;
+ if (frame != (int32)_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1)) {
+ // Seek to frame
+
+ VideoPlayer::Properties props;
+
+ props.forceSeek = true;
+ props.waitEndFrame = false;
+ props.lastFrame = frame;
- while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) < (frameWrap * 256 + frame))
- _vm->_vidPlayer->slotPlay(obj.videoSlot - 1);
+ if ((int32)_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) < frame)
+ props.startFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) + 1;
+ else
+ props.startFrame = frame;
+
+ _vm->_vidPlayer->play(obj.videoSlot - 1, props);
}
- // Subtitle
- Graphics::CoktelVideo::State state = _vm->_vidPlayer->getState(obj.videoSlot - 1);
- if (state.flags & Graphics::CoktelVideo::kStateSpeech)
- _vm->_draw->printTotText(state.speechId);
+ int32 subtitle = _vm->_vidPlayer->getSubtitleIndex(obj.videoSlot - 1);
+ if (subtitle != -1)
+ _vm->_draw->printTotText(subtitle);
destX = 0;
destY = 0;
@@ -716,7 +719,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
_vm->_draw->_spriteLeft = _vm->_vidPlayer->getWidth(obj.videoSlot - 1) -
(destX + _vm->_draw->_spriteRight);
- _vm->_vidPlayer->slotCopyFrame(obj.videoSlot - 1, _vm->_draw->_backSurface->getVidMem(),
+ _vm->_vidPlayer->copyFrame(obj.videoSlot - 1, _vm->_draw->_backSurface->getVidMem(),
_vm->_draw->_spriteLeft, _vm->_draw->_spriteTop,
_vm->_draw->_spriteRight, _vm->_draw->_spriteBottom,
_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY,
@@ -726,13 +729,12 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
_vm->_draw->invalidateRect(_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY,
_vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1,
_vm->_draw->_destSpriteY + _vm->_draw->_spriteBottom - 1);
-
}
if (!(flags & 4)) {
- _animLeft = _toRedrawLeft = left;
- _animTop = _toRedrawTop = top;
- _animRight = _toRedrawRight = right;
+ _animLeft = _toRedrawLeft = left;
+ _animTop = _toRedrawTop = top;
+ _animRight = _toRedrawRight = right;
_animBottom = _toRedrawBottom = bottom;
}
@@ -878,7 +880,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
if (doDraw) {
_vm->_draw->_sourceSurface =
_animPictToSprite[animation * 7 + pictIndex];
- _vm->_draw->_destSurface = 21;
+ _vm->_draw->_destSurface = Draw::kBackSurface;
_vm->_draw->_spriteLeft = left;
_vm->_draw->_spriteTop = top;
diff --git a/engines/gob/totfile.cpp b/engines/gob/totfile.cpp
index 5cc723ba7d..178deeaf58 100644
--- a/engines/gob/totfile.cpp
+++ b/engines/gob/totfile.cpp
@@ -49,7 +49,7 @@ bool TOTFile::load(const Common::String &fileName) {
if (!_stream)
// Trying to open from video
- _stream = _vm->_vidPlayer->getExtraData(fileName.c_str());
+ _stream = _vm->_vidPlayer->getEmbeddedFile(fileName.c_str());
if (!_stream)
return false;
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index 125edd4307..9e49bfc092 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -29,7 +29,6 @@
#include "gob/global.h"
#include "gob/dataio.h"
#include "gob/video.h"
-#include "gob/draw.h"
#include "gob/game.h"
#include "gob/palanim.h"
#include "gob/inter.h"
@@ -38,767 +37,723 @@
namespace Gob {
-const char *VideoPlayer::_extensions[] = { "IMD", "IMD", "VMD", "RMD", "SMD" };
-
-VideoPlayer::Video::Video(GobEngine *vm) : _vm(vm), _stream(0), _video(0) {
-}
-
-VideoPlayer::Video::~Video() {
- close();
-}
-
-bool VideoPlayer::Video::open(const char *fileName, Type which, int16 width, int16 height) {
- close();
-
- int16 handle = _vm->_dataIO->openData(fileName);
-
- if (handle < 0) {
- warning("Couldn't open video \"%s\": No such file", fileName);
- return false;
- }
-
- _stream = _vm->_dataIO->openAsStream(handle, true);
-
- if (which == kVideoTypeIMD) {
- _video = new Graphics::Imd();
- } else if (which == kVideoTypePreIMD) {
- _video = new Graphics::PreImd(width, height);
- } else if (which == kVideoTypeVMD) {
- _video = new Graphics::Vmd(_vm->_video->_palLUT);
- } else if (which == kVideoTypeRMD) {
- _video = new Graphics::Vmd(_vm->_video->_palLUT);
- } else {
- warning("Couldn't open video \"%s\": Invalid video Type", fileName);
- close();
- return false;
- }
-
- if (!_video->load(*_stream)) {
- warning("While loading video \"%s\"", fileName);
- close();
- return false;
- }
-
- _fileName = fileName;
+VideoPlayer::Properties::Properties() : type(kVideoTypeTry), sprite(Draw::kFrontSurface),
+ x(-1), y(-1), width(-1), height(-1), flags(kFlagFrontSurface),
+ startFrame(-1), lastFrame(-1), endFrame(-1), forceSeek(false),
+ breakKey(kShortKeyEscape), palCmd(8), palStart(0), palEnd(255), palFrame(-1),
+ fade(false), waitEndFrame(true), canceled(false) {
- _defaultX = _video->getX();
- _defaultY = _video->getY();
-
- return true;
}
-void VideoPlayer::Video::close() {
- delete _video;
- delete _stream;
-
- _video = 0;
- _stream = 0;
- _fileName.clear();
- memset(&_state, 0, sizeof(Graphics::CoktelVideo::State));
- _defaultX = _defaultY = 0;
-}
-bool VideoPlayer::Video::isOpen() const {
- return (_video != 0);
+VideoPlayer::Video::Video() : decoder(0) {
}
-const char *VideoPlayer::Video::getFileName() const {
- return _fileName.c_str();
+bool VideoPlayer::Video::isEmpty() const {
+ return decoder == 0;
}
-Graphics::CoktelVideo *VideoPlayer::Video::getVideo() {
- return _video;
-}
+void VideoPlayer::Video::close() {
+ delete decoder;
-const Graphics::CoktelVideo *VideoPlayer::Video::getVideo() const {
- return _video;
+ decoder = 0;
+ fileName.clear();
+ surface.reset();
}
-uint32 VideoPlayer::Video::getFeatures() const {
- return _video->getFeatures();
-}
-Graphics::CoktelVideo::State VideoPlayer::Video::getState() const {
- return _state;
-}
+const char *VideoPlayer::_extensions[] = { "IMD", "IMD", "VMD", "RMD", "SMD" };
-int16 VideoPlayer::Video::getDefaultX() const {
- return _defaultX;
+VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm), _needBlit(false),
+ _noCursorSwitch(false), _woodruffCohCottWorkaround(false) {
}
-int16 VideoPlayer::Video::getDefaultY() const {
- return _defaultY;
+VideoPlayer::~VideoPlayer() {
+ for (int i = 0; i < kVideoSlotCount; i++)
+ _videoSlots[i].close();
+}
+
+void VideoPlayer::evaluateFlags(Properties &properties) {
+ if (properties.flags & kFlagFrontSurface) {
+ properties.sprite = Draw::kFrontSurface;
+ } else if (properties.flags & kFlagOtherSurface) {
+ properties.sprite = properties.x;
+ properties.x = 0;
+ } else if (properties.flags & kFlagScreenSurface) {
+ properties.sprite = 0;
+ } else if (properties.flags & kFlagNoVideo) {
+ properties.sprite = 0;
+ } else {
+ properties.sprite = Draw::kBackSurface;
+ }
}
-bool VideoPlayer::Video::hasExtraData(const char *fileName) const {
- if (!_video)
- return false;
+int VideoPlayer::openVideo(bool primary, const Common::String &file, Properties &properties) {
+ int slot = 0;
- return _video->hasExtraData(fileName);
-}
-
-Common::MemoryReadStream *VideoPlayer::Video::getExtraData(const char *fileName) {
- if (!_video)
- return 0;
+ Video *video = 0;
+ if (!primary) {
+ slot = getNextFreeSlot();
+ if (slot < 0) {
+ warning("VideoPlayer::openVideo(): Can't open video \"%s\": No free slot", file.c_str());
+ return -1;
+ }
- return _video->getExtraData(fileName);
-}
+ video = &_videoSlots[slot];
+ } else
+ video = &_videoSlots[0];
-Graphics::CoktelVideo::State VideoPlayer::Video::nextFrame() {
- if (_video)
- _state = _video->nextFrame();
+ // Different video already in the slot => close that video
+ if (!video->isEmpty() && (video->fileName.compareToIgnoreCase(file) != 0))
+ video->close();
- return _state;
-}
+ // No video => load the requested file
+ if (video->isEmpty()) {
+ // Open the video
+ if (!(video->decoder = openVideo(file, properties)))
+ return -1;
+ // Set the filename
+ video->fileName = file;
-VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm) {
- _primaryVideo = new Video(vm);
- _ownSurf = false;
- _backSurf = false;
- _needBlit = false;
- _noCursorSwitch = false;
- _woodruffCohCottWorkaround = false;
-}
+ // WORKAROUND: In some rare cases, the cursor should still be
+ // displayed while a video is playing.
+ _noCursorSwitch = false;
+ if (primary && (_vm->getGameType() == kGameTypeLostInTime)) {
+ if (!file.compareToIgnoreCase("PORTA03") ||
+ !file.compareToIgnoreCase("PORTA03A") ||
+ !file.compareToIgnoreCase("CALE1") ||
+ !file.compareToIgnoreCase("AMIL2") ||
+ !file.compareToIgnoreCase("AMIL3B") ||
+ !file.compareToIgnoreCase("DELB"))
+ _noCursorSwitch = true;
+ }
-VideoPlayer::~VideoPlayer() {
- delete _primaryVideo;
- for (uint i = 0; i < _videoSlots.size(); i++)
- delete _videoSlots[i];
-}
+ // WORKAROUND: In Woodruff, Coh Cott vanished in one video on her party.
+ // This is a bug in video, so we work around it.
+ _woodruffCohCottWorkaround = false;
+ if (primary && (_vm->getGameType() == kGameTypeWoodruff)) {
+ if (!file.compareToIgnoreCase("SQ32-03"))
+ _woodruffCohCottWorkaround = true;
+ }
-bool VideoPlayer::findFile(char *fileName, Type &which) {
- char *extStart = strrchr(fileName, '.');
- // There's no empty extension, Or the filename with its current extension is not found
- if ((extStart) && ((extStart == (fileName + strlen(fileName) - 1)) || (!_vm->_dataIO->existData(fileName)))) {
- *extStart = 0;
- extStart = 0;
- }
+ if (!(properties.flags & kFlagNoVideo) && (properties.sprite >= 0)) {
+ bool ownSurf = (properties.sprite != Draw::kFrontSurface) && (properties.sprite != Draw::kBackSurface);
+ bool screenSize = properties.flags & kFlagScreenSurface;
- if (extStart) {
- // The requested file already has an extension. Verifying.
+ if (ownSurf) {
+ _vm->_draw->_spritesArray[properties.sprite] =
+ _vm->_video->initSurfDesc(_vm->_global->_videoMode,
+ screenSize ? _vm->_width : video->decoder->getWidth(),
+ screenSize ? _vm->_height : video->decoder->getHeight(), 0);
+ }
- int i;
- for (i = 0; i < ARRAYSIZE(_extensions); i++) {
- if (!scumm_stricmp(extStart + 1, _extensions[i])) {
- if ((which != kVideoTypeTry) && (which == ((Type) i))) {
- warning("Attempted to open video \"%s\", "
- "but requested a different type", fileName);
- return false;
- }
- which = (Type) i;
- break;
+ if (!_vm->_draw->_spritesArray[properties.sprite]) {
+ properties.sprite = -1;
+ video->surface.reset();
+ video->decoder->setSurfaceMemory();
+ video->decoder->setXY(0, 0);
+ } else {
+ video->surface = _vm->_draw->_spritesArray[properties.sprite];
+ video->decoder->setSurfaceMemory(video->surface->getVidMem(),
+ video->surface->getWidth(), video->surface->getHeight(), 1);
+
+ if (!ownSurf || (ownSurf && screenSize)) {
+ if ((properties.x >= 0) || (properties.y >= 0))
+ video->decoder->setXY((properties.x < 0) ? 0xFFFF : properties.x,
+ (properties.y < 0) ? 0xFFFF : properties.y);
+ else
+ video->decoder->setXY();
+ } else
+ video->decoder->setXY(0, 0);
}
- }
- if (i >= ARRAYSIZE(_extensions))
- extStart = 0;
+ } else {
+ properties.sprite = -1;
+ video->surface.reset();
+ video->decoder->setSurfaceMemory();
+ video->decoder->setXY(0, 0);
+ }
}
- if (!extStart) {
- // No or unrecognized extension. Probing.
+ if (primary)
+ _needBlit = (properties.flags & kFlagUseBackSurfaceContent) && (properties.sprite == Draw::kFrontSurface);
- int len = strlen(fileName);
+ if (!video->decoder->hasSound())
+ video->decoder->setFrameRate(_vm->_util->getFrameRate());
- int i;
- for (i = 0; i < ARRAYSIZE(_extensions); i++) {
- if ((which == kVideoTypeTry) || (which == ((Type) i))) {
- fileName[len] = '.';
- fileName[len + 1] = 0;
- strcat(fileName, _extensions[i]);
+ WRITE_VAR(7, video->decoder->getFrameCount());
- if (_vm->_dataIO->existData(fileName)) {
- which = (Type) i;
- break;
- }
- }
- }
- if ((i >= ARRAYSIZE(_extensions)) || (which == kVideoTypeTry)) {
- fileName[len] = 0;
- warning("Couldn't open video \"%s\"", fileName);
- return false;
- }
+ return slot;
+}
- }
+bool VideoPlayer::closeVideo(int slot) {
+ Video *video = getVideoBySlot(slot);
+ if (!video)
+ return false;
+ video->close();
return true;
}
-bool VideoPlayer::primaryOpen(const char *videoFile, int16 x, int16 y,
- int32 flags, Type which, int16 width, int16 height) {
-
- char fileName[256];
-
- strncpy0(fileName, videoFile, 250);
-
- if (!findFile(fileName, which))
+bool VideoPlayer::play(int slot, Properties &properties) {
+ Video *video = getVideoBySlot(slot);
+ if (!video)
return false;
- if (scumm_strnicmp(_primaryVideo->getFileName(), fileName, strlen(fileName))) {
- if (!_primaryVideo->open(fileName, which, width, height))
- return false;
+ bool primary = slot == 0;
- // WORKAROUND: In some rare cases, the cursor should still be
- // displayed while a video is playing.
- _noCursorSwitch = false;
- if (_vm->getGameType() == kGameTypeLostInTime) {
- if (!scumm_stricmp(fileName, "PORTA03.IMD") ||
- !scumm_stricmp(fileName, "PORTA03A.IMD") ||
- !scumm_stricmp(fileName, "CALE1.IMD") ||
- !scumm_stricmp(fileName, "AMIL2.IMD") ||
- !scumm_stricmp(fileName, "AMIL3B.IMD") ||
- !scumm_stricmp(fileName, "DELB.IMD"))
- _noCursorSwitch = true;
- }
+ // NOTE: For testing (and comfort?) purposes, we enable aborting of all videos)
+ properties.breakKey = kShortKeyEscape;
- // WORKAROUND: In Woodruff, Coh Cott vanished in one video on her party.
- // This is a bug in video, so we work around it.
- _woodruffCohCottWorkaround = false;
- if (_vm->getGameType() == kGameTypeWoodruff) {
- if (!scumm_stricmp(fileName, "SQ32-03.VMD"))
- _woodruffCohCottWorkaround = true;
- }
+ if (properties.startFrame < 0)
+ properties.startFrame = video->decoder->getCurFrame() + 1;
+ if (properties.lastFrame < 0)
+ properties.lastFrame = video->decoder->getFrameCount() - 1;
+ if (properties.endFrame < 0)
+ properties.endFrame = properties.lastFrame;
+ if (properties.palFrame < 0)
+ properties.palFrame = properties.startFrame;
- _ownSurf = false;
+ properties.startFrame--;
+ properties.endFrame--;
+ properties.palFrame--;
- if (!(flags & kFlagNoVideo)) {
- SurfaceDescPtr surf;
+ if (primary) {
+ _vm->_draw->_showCursor = _noCursorSwitch ? 3 : 0;
- if (flags & kFlagOtherSurface) {
- _ownSurf = true;
- _backSurf = false;
+ if (properties.fade)
+ _vm->_palAnim->fade(0, -2, 0);
+ }
- surf = _vm->_video->initSurfDesc(_vm->_global->_videoMode,
- _primaryVideo->getVideo()->getWidth(),
- _primaryVideo->getVideo()->getHeight(), 0);
- _vm->_draw->_spritesArray[x] = surf;
+ bool backwards = properties.startFrame > properties.lastFrame;
- x = 0;
- } else if (flags & kFlagScreenSurface) {
- _ownSurf = true;
- _backSurf = false;
+ properties.canceled = false;
- surf = _vm->_video->initSurfDesc(_vm->_global->_videoMode,
- _vm->_width, _vm->_height, 0);
- _vm->_draw->_spritesArray[0] = surf;
- } else {
- _backSurf = ((flags & kFlagFrontSurface) == 0);
- surf = _vm->_draw->_spritesArray[_backSurf ? 21 : 20];
- }
+ while ((properties.startFrame != properties.lastFrame) &&
+ (properties.startFrame < (int32)(video->decoder->getFrameCount() - 1))) {
- _primaryVideo->getVideo()->setVideoMemory(surf->getVidMem(),
- surf->getWidth(), surf->getHeight());
+ playFrame(slot, properties);
+ if (properties.canceled)
+ break;
- } else
- _primaryVideo->getVideo()->setVideoMemory();
+ properties.startFrame += backwards ? -1 : 1;
- _needBlit = ((flags & kFlagUseBackSurfaceContent) != 0) && ((flags & kFlagFrontSurface) != 0);
+ evalBgShading(*video);
- _primaryVideo->getVideo()->enableSound(*_vm->_mixer);
- }
+ if (primary && properties.fade) {
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+ properties.fade = false;
+ }
- if (!_primaryVideo->isOpen())
- return false;
+ if (!_noCursorSwitch && properties.waitEndFrame)
+ waitEndFrame(slot);
+ }
- _primaryVideo->getVideo()->setFrameRate(_vm->_util->getFrameRate());
- _primaryVideo->getVideo()->setXY(x, y);
- WRITE_VAR(7, _primaryVideo->getVideo()->getFramesCount());
+ evalBgShading(*video);
return true;
}
-bool VideoPlayer::primaryPlay(int16 startFrame, int16 lastFrame, int16 breakKey,
- uint16 palCmd, int16 palStart, int16 palEnd,
- int16 palFrame, int16 endFrame, bool fade, int16 reverseTo, bool forceSeek) {
+void VideoPlayer::waitEndFrame(int slot, bool onlySound) {
+ Video *video = getVideoBySlot(slot);
+ if (!video)
+ return;
+
+ if (!onlySound || video->decoder->hasSound())
+ _vm->_util->delay(video->decoder->getTimeToNextFrame());
+}
- if (!_primaryVideo->isOpen())
+bool VideoPlayer::playFrame(int slot, Properties &properties) {
+ Video *video = getVideoBySlot(slot);
+ if (!video)
return false;
- Graphics::CoktelVideo &video = *(_primaryVideo->getVideo());
-
- breakKey = 27;
- if (startFrame < 0)
- startFrame = video.getCurrentFrame();
- if (lastFrame < 0)
- lastFrame = video.getFramesCount() - 1;
- if (palFrame < 0)
- palFrame = startFrame;
- if (endFrame < 0)
- endFrame = lastFrame;
- palCmd &= 0x3F;
-
- int16 realStartFrame = startFrame;
- if (video.getCurrentFrame() != startFrame) {
- if (!forceSeek && (video.getFeatures() & Graphics::CoktelVideo::kFeaturesSound))
- startFrame = video.getCurrentFrame();
- else
- video.seekFrame(startFrame);
- }
+ bool primary = slot == 0;
- _vm->_draw->_showCursor = _noCursorSwitch ? 3 : 0;
+ if (video->decoder->getCurFrame() != properties.startFrame) {
- if (fade)
- _vm->_palAnim->fade(0, -2, 0);
+ if (properties.startFrame != -1) {
+ // Seek into the middle of the video
- bool canceled = false;
+ if (video->decoder->hasSound()) {
+ // But there's sound
- while (startFrame <= lastFrame) {
- if (doPlay(startFrame, breakKey,
- palCmd, palStart, palEnd, palFrame, endFrame, startFrame < realStartFrame)) {
+ if (properties.forceSeek) {
+ // And we force seeking => Seek
- canceled = true;
- break;
- }
+ video->decoder->disableSound();
+ video->decoder->seek(properties.startFrame + 1, SEEK_SET, true);
+ }
- evalBgShading(video);
+ } else
+ // No sound => We can safely seek
+ video->decoder->seek(properties.startFrame + 1, SEEK_SET, true);
- if (fade) {
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
- fade = false;
+ } else {
+ // Seek to the start => We can safely seek
+
+ video->decoder->disableSound();
+ video->decoder->seek(0, SEEK_SET, true);
+ video->decoder->enableSound();
}
- if (!_noCursorSwitch)
- video.waitEndFrame();
- startFrame++;
}
- evalBgShading(video);
+ if (video->decoder->getCurFrame() > properties.startFrame)
+ // If the video is already beyond the wanted frame, skip
+ return true;
- if (reverseTo >= 0) {
- int16 toFrame = video.getFramesCount() - reverseTo;
- for (int i = video.getCurrentFrame(); i >= toFrame; i--) {
- video.seekFrame(i, SEEK_SET, true);
+ bool modifiedPal = false;
- bool b = doPlay(i, breakKey, 0, 0, 0, 0, 0);
- evalBgShading(video);
+ if (primary) {
+ // Pre-decoding palette and blitting, only for primary videos
- if (b) {
- _vm->_palAnim->fade(0, -2, 0);
- memset((char *)_vm->_draw->_vgaPalette, 0, 768);
- }
+ if ((properties.startFrame == properties.palFrame) ||
+ ((properties.startFrame == properties.endFrame) && (properties.palCmd == 8))) {
- if (!_noCursorSwitch)
- video.waitEndFrame();
- }
- }
+ modifiedPal = true;
+ _vm->_draw->_applyPal = true;
- evalBgShading(video);
+ if (properties.palCmd >= 4)
+ copyPalette(*video, properties.palStart, properties.palEnd);
+ }
- return canceled;
-}
+ if (modifiedPal && (properties.palCmd == 8) && (video->surface != _vm->_draw->_backSurface))
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
-void VideoPlayer::primaryClose() {
- _primaryVideo->close();
-}
+ if (_needBlit)
+ _vm->_draw->forceBlit();
+ }
-int VideoPlayer::slotOpen(const char *videoFile, Type which, int16 width, int16 height) {
- Video *video = new Video(_vm);
- char fileName[256];
+ Graphics::Surface *surface = video->decoder->decodeNextFrame();
- strncpy0(fileName, videoFile, 250);
+ WRITE_VAR(11, video->decoder->getCurFrame());
- if (!findFile(fileName, which)) {
- delete video;
- return -1;
- }
-
- if (!video->open(fileName, which, width, height)) {
- delete video;
- return -1;
+ uint32 ignoreBorder = 0;
+ if (_woodruffCohCottWorkaround && (properties.startFrame == 31)) {
+ // WORKAROUND: This frame mistakenly masks Coh Cott, making her vanish
+ // To prevent that, we'll never draw that part
+ ignoreBorder = 50;
}
- video->getVideo()->setVideoMemory();
- video->getVideo()->enableSound(*_vm->_mixer);
+ if (surface && primary) {
+ // Post-decoding palette and blitting, only for primary videos
- int slot = getNextFreeSlot();
+ if (_needBlit)
+ _vm->_draw->forceBlit(true);
- _videoSlots[slot] = video;
+ if (modifiedPal && (properties.palCmd == 16)) {
+ if (video->surface == _vm->_draw->_backSurface)
+ _vm->_draw->forceBlit();
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+ _vm->_draw->_noInvalidated = true;
+ _vm->_video->dirtyRectsAll();
+ }
- WRITE_VAR(7, video->getVideo()->getFramesCount());
+ if (video->decoder->hasPalette() && (properties.palCmd > 1)) {
+ copyPalette(*video, properties.palStart, properties.palEnd);
- return slot;
-}
+ if (video->surface != _vm->_draw->_backSurface)
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ else
+ _vm->_draw->_applyPal = true;
+ }
-int VideoPlayer::getNextFreeSlot() {
- uint slot;
+ const Common::List<Common::Rect> &dirtyRects = video->decoder->getDirtyRects();
- for (slot = 0; slot < _videoSlots.size(); slot++)
- if (!_videoSlots[slot])
- break;
+ if (modifiedPal && (properties.palCmd == 8) && (video->surface == _vm->_draw->_backSurface))
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
- if (slot == _videoSlots.size())
- _videoSlots.push_back(0);
+ if (video->surface == _vm->_draw->_backSurface) {
- return slot;
-}
-
-void VideoPlayer::slotPlay(int slot, int16 frame) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
- return;
+ for (Common::List<Common::Rect>::const_iterator rect = dirtyRects.begin(); rect != dirtyRects.end(); ++rect)
+ _vm->_draw->invalidateRect(rect->left + ignoreBorder, rect->top, rect->right - 1, rect->bottom - 1);
+ _vm->_draw->blitInvalidated();
- Graphics::CoktelVideo &video = *(_videoSlots[slot]->getVideo());
+ } else if (video->surface == _vm->_draw->_frontSurface) {
+ for (Common::List<Common::Rect>::const_iterator rect = dirtyRects.begin(); rect != dirtyRects.end(); ++rect)
+ _vm->_video->dirtyRectsAdd(rect->left + ignoreBorder, rect->top, rect->right - 1, rect->bottom - 1);
- if (frame < 0)
- frame = video.getCurrentFrame();
+ }
- if (frame >= video.getFramesCount())
- return;
+ if ((video->decoder->getCurFrame() - 1) == properties.startFrame)
+ // Only retrace if we're playing the frame we actually want to play
+ _vm->_video->retrace();
- if (video.getCurrentFrame() != frame)
- video.seekFrame(frame);
+ int32 subtitle = video->decoder->getSubtitleIndex();
+ if (subtitle != -1)
+ _vm->_draw->printTotText(subtitle);
- _videoSlots[slot]->nextFrame();
- WRITE_VAR(11, frame);
+ if (modifiedPal && ((properties.palCmd == 2) || (properties.palCmd == 4)))
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+ }
- evalBgShading(video);
-}
+ if (primary && properties.waitEndFrame)
+ checkAbort(*video, properties);
-void VideoPlayer::slotClose(int slot) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
- return;
+ if ((video->decoder->getCurFrame() - 1) < properties.startFrame)
+ // The video played a frame we actually didn't want, so we have to adjust
+ properties.startFrame--;
- delete _videoSlots[slot];
- _videoSlots[slot] = 0;
+ return true;
}
-void VideoPlayer::slotCopyFrame(int slot, byte *dest,
- uint16 left, uint16 top, uint16 width, uint16 height,
- uint16 x, uint16 y, uint16 pitch, int16 transp) {
-
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
- return;
+void VideoPlayer::checkAbort(Video &video, Properties &properties) {
+ _vm->_util->processInput();
- _videoSlots[slot]->getVideo()->copyCurrentFrame(dest,
- left, top, width, height, x, y, pitch, transp);
-}
+ if (_vm->shouldQuit()) {
+ video.decoder->disableSound();
-void VideoPlayer::slotCopyPalette(int slot, int16 palStart, int16 palEnd) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
+ properties.canceled = true;
return;
+ }
- copyPalette(*(_videoSlots[slot]->getVideo()), palStart, palEnd);
-}
+ if (properties.breakKey != 0) {
+ _vm->_util->getMouseState(&_vm->_global->_inter_mouseX,
+ &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons);
-void VideoPlayer::slotWaitEndFrame(int slot, bool onlySound) {
- Video *video = getVideoBySlot(slot);
+ _vm->_inter->storeKey(_vm->_util->checkKey());
+ if (VAR(0) == (unsigned) properties.breakKey) {
+ video.decoder->disableSound();
- if (video) {
- Graphics::CoktelVideo &cVideo = *video->getVideo();
+ // Seek to the last frame. Some scripts depend on that.
+ video.decoder->seek(properties.endFrame + 1, SEEK_SET, true);
- if (!onlySound || (cVideo.getFeatures() & Graphics::CoktelVideo::kFeaturesSound))
- cVideo.waitEndFrame();
+ properties.canceled = true;
+ }
}
}
bool VideoPlayer::slotIsOpen(int slot) const {
- if ((slot >= 0) && (((uint) slot) < _videoSlots.size()) && _videoSlots[slot])
- return true;
-
- return false;
-}
-
-void VideoPlayer::slotSetDoubleMode(int slot, bool doubleMode) {
- Video *video = getVideoBySlot(slot);
-
- if (video)
- video->getVideo()->setDoubleMode(doubleMode);
+ return getVideoBySlot(slot) != 0;
}
-const VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) const {
- if (slot < 0) {
- if (_primaryVideo->isOpen())
- return _primaryVideo;
- } else if (((uint) slot) < _videoSlots.size() && _videoSlots[slot])
- return _videoSlots[slot];
+Common::String VideoPlayer::getFileName(int slot) const {
+ const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return "";
- return 0;
+ return video->fileName;
}
-VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) {
- if (slot < 0) {
- if (_primaryVideo->isOpen())
- return _primaryVideo;
- } else if (((uint) slot) < _videoSlots.size() && _videoSlots[slot])
- return _videoSlots[slot];
+uint32 VideoPlayer::getFrameCount(int slot) const {
+ const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return 0;
- return 0;
+ return video->decoder->getFrameCount();
}
-const char *VideoPlayer::getFileName(int slot) const {
+uint32 VideoPlayer::getCurrentFrame(int slot) const {
const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return 0;
- if (video)
- return video->getFileName();
-
- return "";
+ return video->decoder->getCurFrame();
}
-uint16 VideoPlayer::getFlags(int slot) const {
+uint16 VideoPlayer::getWidth(int slot) const {
const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return 0;
- if (video)
- return video->getVideo()->getFlags();
-
- return 0;
+ return video->decoder->getWidth();
}
-int16 VideoPlayer::getFramesCount(int slot) const {
+uint16 VideoPlayer::getHeight(int slot) const {
const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return 0;
- if (video)
- return video->getVideo()->getFramesCount();
-
- return 0;
+ return video->decoder->getHeight();
}
-int16 VideoPlayer::getCurrentFrame(int slot) const {
+uint16 VideoPlayer::getDefaultX(int slot) const {
const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return 0;
- if (video)
- return video->getVideo()->getCurrentFrame();
-
- return 0;
+ return video->decoder->getDefaultX();
}
-int16 VideoPlayer::getWidth(int slot) const {
+uint16 VideoPlayer::getDefaultY(int slot) const {
const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return 0;
- if (video)
- return video->getVideo()->getWidth();
-
- return 0;
+ return video->decoder->getDefaultY();
}
-int16 VideoPlayer::getHeight(int slot) const {
+const Common::List<Common::Rect> *VideoPlayer::getDirtyRects(int slot) const {
const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return 0;
- if (video)
- return video->getVideo()->getHeight();
-
- return 0;
+ return &video->decoder->getDirtyRects();
}
-int16 VideoPlayer::getDefaultX(int slot) const {
+bool VideoPlayer::hasEmbeddedFile(const Common::String &fileName, int slot) const {
const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return false;
- if (video)
- return video->getDefaultX();
-
- return 0;
+ return video->decoder->hasEmbeddedFile(fileName);
}
-int16 VideoPlayer::getDefaultY(int slot) const {
+Common::MemoryReadStream *VideoPlayer::getEmbeddedFile(const Common::String &fileName, int slot) {
const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return 0;
- if (video)
- return video->getDefaultY();
-
- return 0;
+ return video->decoder->getEmbeddedFile(fileName);
}
-uint32 VideoPlayer::getFeatures(int slot) const {
+int32 VideoPlayer::getSubtitleIndex(int slot) const {
const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return -1;
- if (video)
- return video->getFeatures();
-
- return 0;
+ return video->decoder->getSubtitleIndex();
}
-Graphics::CoktelVideo::State VideoPlayer::getState(int slot) const {
- const Video *video = getVideoBySlot(slot);
- Graphics::CoktelVideo::State state;
+void VideoPlayer::writeVideoInfo(const Common::String &file, int16 varX, int16 varY,
+ int16 varFrames, int16 varWidth, int16 varHeight) {
- if (video)
- state = video->getState();
+ Properties properties;
- return state;
-}
+ int slot = openVideo(false, file, properties);
+ if (slot >= 0) {
+ Video &video = _videoSlots[slot];
-bool VideoPlayer::hasExtraData(const char *fileName, int slot) const {
- const Video *video = getVideoBySlot(slot);
+ int16 x = -1, y = -1, width = -1, height = -1;
- if (video)
- return video->hasExtraData(fileName);
+ x = video.decoder->getDefaultX();
+ y = video.decoder->getDefaultY();
+ width = video.decoder->getWidth();
+ height = video.decoder->getHeight();
- return false;
-}
+ if (VAR_OFFSET(varX) == 0xFFFFFFFF)
+ video.decoder->getFrameCoords(1, x, y, width, height);
-Common::MemoryReadStream *VideoPlayer::getExtraData(const char *fileName, int slot) {
- Video *video = getVideoBySlot(slot);
+ WRITE_VAR_OFFSET(varX , x);
+ WRITE_VAR_OFFSET(varY , y);
+ WRITE_VAR_OFFSET(varFrames, video.decoder->getFrameCount());
+ WRITE_VAR_OFFSET(varWidth , width);
+ WRITE_VAR_OFFSET(varHeight, height);
- if (video)
- return video->getExtraData(fileName);
+ closeVideo(slot);
- return 0;
+ } else {
+ WRITE_VAR_OFFSET(varX , (uint32) -1);
+ WRITE_VAR_OFFSET(varY , (uint32) -1);
+ WRITE_VAR_OFFSET(varFrames, (uint32) -1);
+ WRITE_VAR_OFFSET(varWidth , (uint32) -1);
+ WRITE_VAR_OFFSET(varHeight, (uint32) -1);
+ }
}
-void VideoPlayer::playFrame(int16 frame, int16 breakKey,
- uint16 palCmd, int16 palStart, int16 palEnd,
- int16 palFrame, int16 endFrame, bool noRetrace) {
+bool VideoPlayer::copyFrame(int slot, byte *dest,
+ uint16 left, uint16 top, uint16 width, uint16 height,
+ uint16 x, uint16 y, uint16 pitch, int16 transp) const {
- if (!_primaryVideo)
- return;
+ const Video *video = getVideoBySlot(slot);
+ if (!video)
+ return false;
- Video &video = *_primaryVideo;
- Graphics::CoktelVideo &cVideo = *video.getVideo();
+ const Graphics::Surface *surface = video->decoder->getSurface();
+ if (!surface)
+ return false;
- if (cVideo.getCurrentFrame() != frame)
- cVideo.seekFrame(frame);
- if (palFrame < 0)
- palFrame = 0;
- if (endFrame < 0)
- endFrame = cVideo.getFramesCount() - 1;
+ int32 w = MIN<int32>(width , surface->w);
+ int32 h = MIN<int32>(height, surface->h);
+ const byte *src = (byte*)surface->pixels + (top * surface->pitch) + left;
+ byte *dst = dest + (y * pitch) + x;
- bool modifiedPal = false;
+ if (transp < 0) {
+ // No transparency
- if ((frame == palFrame) || ((frame == endFrame) && (palCmd == 8))) {
- modifiedPal = true;
- _vm->_draw->_applyPal = true;
+ if ((x == 0) && (left == 0) && (pitch == surface->pitch) && (width == surface->w)) {
+ // Dimensions fit, we can copy everything at once
- if (palCmd >= 4)
- copyPalette(cVideo, palStart, palEnd);
- }
+ memcpy(dst, src, w * h);
+ return true;
+ }
- if (modifiedPal && (palCmd == 8) && !_backSurf)
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ // Copy row-by-row
+ while (h-- > 0) {
+ const byte *srcRow = src;
+ byte *dstRow = dst;
- if (_needBlit)
- _vm->_draw->forceBlit();
+ memcpy(dstRow, srcRow, w);
- Graphics::CoktelVideo::State state = video.nextFrame();
- WRITE_VAR(11, frame);
+ src += surface->pitch;
+ dst += pitch;
+ }
- if (_woodruffCohCottWorkaround && (frame == 32)) {
- // WORKAROUND: This frame mistakenly masks Coh Cott, making her vanish
- // To prevent that, we'll never draw that part
- state.left += 50;
+ return true;
}
- if (_needBlit)
- _vm->_draw->forceBlit(true);
+ // Copy pixel-by-pixel
+ while (h-- > 0) {
+ const byte *srcRow = src;
+ byte *dstRow = dst;
- if (modifiedPal && (palCmd == 16)) {
- if (_backSurf)
- _vm->_draw->forceBlit();
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
- _vm->_draw->_noInvalidated = true;
- _vm->_video->dirtyRectsAll();
+ for (int32 i = 0; i < w; i++, srcRow++, dstRow++)
+ if (*srcRow != transp)
+ *dstRow = *srcRow;
+
+ src += surface->pitch;
+ dst += pitch;
}
- if ((state.flags & Graphics::CoktelVideo::kStatePalette) && (palCmd > 1)) {
- copyPalette(cVideo, palStart, palEnd);
+ return true;
+}
- if (!_backSurf)
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
- else
- _vm->_draw->_applyPal = true;
- }
+const VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) const {
+ if ((slot < 0) || (slot >= kVideoSlotCount))
+ return 0;
- if (modifiedPal && (palCmd == 8) && _backSurf)
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ if (_videoSlots[slot].isEmpty())
+ return 0;
+ return &_videoSlots[slot];
+}
- if (!_ownSurf) {
- if (_backSurf) {
- _vm->_draw->invalidateRect(state.left, state.top, state.right, state.bottom);
- _vm->_draw->blitInvalidated();
- } else
- _vm->_video->dirtyRectsAdd(state.left, state.top, state.right, state.bottom);
+VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) {
+ if ((slot < 0) || (slot >= kVideoSlotCount))
+ return 0;
- if (!noRetrace)
- _vm->_video->retrace();
- }
+ if (_videoSlots[slot].isEmpty())
+ return 0;
- // Subtitle
- if (state.flags & Graphics::CoktelVideo::kStateSpeech)
- _vm->_draw->printTotText(state.speechId);
+ return &_videoSlots[slot];
+}
- if (modifiedPal && ((palCmd == 2) || (palCmd == 4)))
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+int VideoPlayer::getNextFreeSlot() {
+ // Starting with 1, since 0 is reserved for the "primary" video
+ for (int i = 1; i < kVideoSlotCount; i++)
+ if (_videoSlots[i].isEmpty())
+ return i;
+
+ return -1;
}
-bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
- uint16 palCmd, int16 palStart, int16 palEnd,
- int16 palFrame, int16 endFrame, bool noRetrace) {
+void VideoPlayer::evalBgShading(Video &video) {
+ if (video.decoder->isSoundPlaying())
+ _vm->_sound->bgShade();
+ else
+ _vm->_sound->bgUnshade();
+}
- playFrame(frame, breakKey, palCmd, palStart, palEnd, palFrame, endFrame, noRetrace);
+Common::String VideoPlayer::findFile(const Common::String &file, Properties &properties) {
- _vm->_util->processInput();
+ bool hasExtension = false;
- if (_vm->shouldQuit()) {
- _primaryVideo->getVideo()->disableSound();
- return true;
- }
+ Common::String base = file;
+ Common::String fileName = file;
- if (breakKey != 0) {
- _vm->_util->getMouseState(&_vm->_global->_inter_mouseX,
- &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons);
+ const char *posDot = strrchr(base.c_str(), '.');
+ if (posDot) {
+ hasExtension = true;
+ base = Common::String(base.c_str(), posDot);
+ posDot++;
+ }
- _vm->_inter->storeKey(_vm->_util->checkKey());
- if (VAR(0) == (unsigned) breakKey) {
- _primaryVideo->getVideo()->disableSound();
- // Seek to the last frame. Some scripts depend on that.
- _primaryVideo->getVideo()->seekFrame(endFrame, SEEK_SET, true);
- return true;
+ if (hasExtension) {
+ int i;
+ for (i = 0; i < ARRAYSIZE(_extensions); i++) {
+ if (!scumm_stricmp(posDot, _extensions[i])) {
+ if ((properties.type != kVideoTypeTry) && (properties.type == ((Type) i))) {
+ warning("Attempted to open video \"%s\", but requested a different type", fileName.c_str());
+ return "";
+ }
+ properties.type = (Type) i;
+ break;
+ }
}
+ if (i >= ARRAYSIZE(_extensions))
+ hasExtension = false;
}
- return false;
-}
+ if (!hasExtension) {
+ // No or unrecognized extension. Probing.
-void VideoPlayer::copyPalette(Graphics::CoktelVideo &video, int16 palStart, int16 palEnd) {
- if (!(video.getFeatures() & Graphics::CoktelVideo::kFeaturesPalette))
- return;
+ int i;
+ for (i = 0; i < ARRAYSIZE(_extensions); i++) {
+ if ((properties.type == kVideoTypeTry) || (properties.type == ((Type) i))) {
+ fileName = base + "." + _extensions[i];
- if (palStart < 0)
- palStart = 0;
- if (palEnd < 0)
- palEnd = 255;
+ if (_vm->_dataIO->existData(fileName.c_str())) {
+ properties.type = (Type) i;
+ break;
+ }
+ }
+ }
+ if ((i >= ARRAYSIZE(_extensions)) || (properties.type == kVideoTypeTry)) {
+ warning("Couldn't open video \"%s\"", file.c_str());
+ return "";
+ }
- memcpy(((char *)(_vm->_global->_pPaletteDesc->vgaPal)) + palStart * 3,
- video.getPalette() + palStart * 3,
- (palEnd - palStart + 1) * 3);
-}
+ }
-void VideoPlayer::writeVideoInfo(const char *videoFile, int16 varX, int16 varY,
- int16 varFrames, int16 varWidth, int16 varHeight) {
+ return fileName;
+}
- if (primaryOpen(videoFile)) {
- int16 x, y, width, height;
+Graphics::CoktelDecoder *VideoPlayer::openVideo(const Common::String &file, Properties &properties) {
+ Common::String fileName = findFile(file, properties);
+ if (fileName.empty())
+ return 0;
- x = _primaryVideo->getVideo()->getX();
- y = _primaryVideo->getVideo()->getY();
- width = _primaryVideo->getVideo()->getWidth();
- height = _primaryVideo->getVideo()->getHeight();
+ Common::SeekableReadStream *stream = _vm->_dataIO->getDataStream(fileName.c_str());
+ if (!stream)
+ return 0;
- if (VAR_OFFSET(varX) == 0xFFFFFFFF)
- _primaryVideo->getVideo()->getFrameCoords(1, x, y, width, height);
+ Graphics::CoktelDecoder *video = 0;
+ if (properties.type == kVideoTypeIMD)
+ video = new Graphics::IMDDecoder(_vm->_mixer, Audio::Mixer::kSFXSoundType);
+ else if (properties.type == kVideoTypePreIMD)
+ video = new Graphics::PreIMDDecoder(properties.width, properties.height, _vm->_mixer, Audio::Mixer::kSFXSoundType);
+ else if (properties.type == kVideoTypeVMD)
+ video = new Graphics::VMDDecoder(_vm->_mixer, Audio::Mixer::kSFXSoundType);
+ else if (properties.type == kVideoTypeRMD)
+ video = new Graphics::VMDDecoder(_vm->_mixer, Audio::Mixer::kSFXSoundType);
+ else
+ warning("Couldn't open video \"%s\": Invalid video Type", fileName.c_str());
- WRITE_VAR_OFFSET(varX, x);
- WRITE_VAR_OFFSET(varY, y);
- WRITE_VAR_OFFSET(varFrames, _primaryVideo->getVideo()->getFramesCount());
- WRITE_VAR_OFFSET(varWidth, width);
- WRITE_VAR_OFFSET(varHeight, height);
+ if (!video) {
+ delete stream;
+ return 0;
+ }
- primaryClose();
- } else {
- WRITE_VAR_OFFSET(varX, (uint32) -1);
- WRITE_VAR_OFFSET(varY, (uint32) -1);
- WRITE_VAR_OFFSET(varFrames, (uint32) -1);
- WRITE_VAR_OFFSET(varWidth, (uint32) -1);
- WRITE_VAR_OFFSET(varHeight, (uint32) -1);
+ if (!video->load(stream)) {
+ delete video;
+ return 0;
}
+
+ properties.width = video->getWidth();
+ properties.height = video->getHeight();
+
+ return video;
}
-void VideoPlayer::evalBgShading(Graphics::CoktelVideo &video) {
- if (video.isSoundPlaying())
- _vm->_sound->bgShade();
- else
- _vm->_sound->bgUnshade();
+void VideoPlayer::copyPalette(const Video &video, int16 palStart, int16 palEnd) {
+ if (!video.decoder->hasPalette())
+ return;
+
+ if (palStart < 0)
+ palStart = 0;
+ if (palEnd < 0)
+ palEnd = 255;
+
+ palStart = palStart * 3;
+ palEnd = (palEnd + 1) * 3;
+
+ for (int i = palStart; i <= palEnd; i++)
+ ((char *)(_vm->_global->_pPaletteDesc->vgaPal))[i] = video.decoder->getPalette()[i] >> 2;
}
} // End of namespace Gob
diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h
index 8ca8aebf44..d91d0a3845 100644
--- a/engines/gob/videoplayer.h
+++ b/engines/gob/videoplayer.h
@@ -27,11 +27,15 @@
#define GOB_VIDEOPLAYER_H
#include "common/array.h"
+#include "common/list.h"
+#include "common/rect.h"
#include "common/str.h"
-#include "graphics/video/coktelvideo/coktelvideo.h"
+#include "graphics/surface.h"
+#include "graphics/video/coktel_decoder.h"
#include "gob/util.h"
+#include "gob/draw.h"
namespace Gob {
@@ -41,132 +45,135 @@ class DataStream;
class VideoPlayer {
public:
enum Flags {
- kFlagNone = 0,
- kFlagUseBackSurfaceContent = 0x40,
- kFlagFrontSurface = 0x80,
- kFlagNoVideo = 0x100,
- kFlagOtherSurface = 0x800,
- kFlagScreenSurface = 0x400000
+ kFlagNone = 0x000000,
+ kFlagUseBackSurfaceContent = 0x000040, ///< Use the back surface as a video "base".
+ kFlagFrontSurface = 0x000080, ///< Draw directly into the front surface.
+ kFlagNoVideo = 0x000100, ///< Only sound.
+ kFlagOtherSurface = 0x000800, ///< Draw into a specific sprite.
+ kFlagScreenSurface = 0x400000 ///< Draw into a newly created sprite of screen dimensions.
};
+ /** Video format. */
enum Type {
- kVideoTypeTry = -1,
- kVideoTypeIMD = 0,
- kVideoTypePreIMD = 1,
- kVideoTypeVMD = 2,
- kVideoTypeRMD = 3
+ kVideoTypeTry = -1, ///< Try any format.
+ kVideoTypeIMD = 0,
+ kVideoTypePreIMD = 1, ///< Early IMD format found in Fascination.
+ kVideoTypeVMD = 2,
+ kVideoTypeRMD = 3 ///< VMD containing "reversed" video.
};
- VideoPlayer(GobEngine *vm);
- ~VideoPlayer();
+ struct Properties {
+ Type type; ///< Type of the video to open.
- bool primaryOpen(const char *videoFile, int16 x = -1, int16 y = -1,
- int32 flags = kFlagFrontSurface, Type which = kVideoTypeTry,
- int16 width = -1, int16 height = -1);
- bool primaryPlay(int16 startFrame = -1, int16 lastFrame = -1,
- int16 breakKey = kShortKeyEscape,
- uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255,
- int16 palFrame = -1, int16 endFrame = -1, bool fade = false,
- int16 reverseTo = -1, bool forceSeek = false);
- void primaryClose();
-
- void playFrame(int16 frame, int16 breakKey = kShortKeyEscape,
- uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255,
- int16 palFrame = -1 , int16 endFrame = -1, bool noRetrace = false);
-
- int slotOpen(const char *videoFile, Type which = kVideoTypeTry,
- int16 width = -1, int16 height = -1);
- void slotPlay(int slot, int16 frame = -1);
- void slotClose(int slot);
- void slotCopyFrame(int slot, byte *dest,
- uint16 left, uint16 top, uint16 width, uint16 height,
- uint16 x, uint16 y, uint16 pitch, int16 transp = -1);
- void slotCopyPalette(int slot, int16 palStart = -1, int16 palEnd = -1);
- void slotWaitEndFrame(int slot = -1, bool onlySound = false);
+ int sprite; ///< The sprite onto which to draw the video.
- void slotSetDoubleMode(int slot, bool doubleMode);
+ int32 x; ///< X coordinate of the video.
+ int32 y; ///< Y coordinate of the video.
+ int32 width; ///< Width of the video.
+ int32 height; ///< Height of the video.
- bool slotIsOpen(int slot) const;
+ uint32 flags; ///< Video flags.
- const char *getFileName(int slot = -1) const;
- uint16 getFlags(int slot = -1) const;
- int16 getFramesCount(int slot = -1) const;
- int16 getCurrentFrame(int slot = -1) const;
- int16 getWidth(int slot = -1) const;
- int16 getHeight(int slot = -1) const;
- int16 getDefaultX(int slot = -1) const;
- int16 getDefaultY(int slot = -1) const;
+ int32 startFrame; ///< Frame to start playback from.
+ int32 lastFrame; ///< Frame to stop playback at.
+ int32 endFrame; ///< Last frame of this playback cycle.
- Graphics::CoktelVideo::State getState(int slot = -1) const;
- uint32 getFeatures(int slot = -1) const;
+ bool forceSeek; ///< Force the seeking to the start frame.
- bool hasExtraData(const char *fileName, int slot = -1) const;
- Common::MemoryReadStream *getExtraData(const char *fileName, int slot = -1);
+ int16 breakKey; ///< Keycode of the break/abort key.
- void writeVideoInfo(const char *videoFile, int16 varX, int16 varY,
- int16 varFrames, int16 varWidth, int16 varHeight);
+ uint16 palCmd; ///< Palette command.
+ int16 palStart; ///< Palette entry to start with.
+ int16 palEnd; ///< Palette entry to end at.
+ int32 palFrame; ///< Frame to apply the palette command at.
-private:
- class Video {
- public:
- Video(GobEngine *vm);
- ~Video();
+ bool fade; ///< Fade in?
+
+ bool waitEndFrame; ///< Wait for the frame's time to run out?
+
+ bool canceled; ///< Was the video canceled?
+
+ Properties();
+ };
+
+ VideoPlayer(GobEngine *vm);
+ ~VideoPlayer();
+
+ void evaluateFlags(Properties &properties);
+
+ int openVideo(bool primary, const Common::String &file, Properties &properties);
+ bool closeVideo(int slot = 0);
+
+ bool play(int slot, Properties &properties);
+ void waitEndFrame(int slot, bool onlySound = false);
- bool open(const char *fileName, Type which, int16 width, int16 height);
- void close();
+ bool slotIsOpen(int slot = 0) const;
- bool isOpen() const;
+ Common::String getFileName(int slot = 0) const;
- const char *getFileName() const;
- Graphics::CoktelVideo *getVideo();
- const Graphics::CoktelVideo *getVideo() const;
+ uint32 getFrameCount (int slot = 0) const;
+ uint32 getCurrentFrame(int slot = 0) const;
+ uint16 getWidth (int slot = 0) const;
+ uint16 getHeight (int slot = 0) const;
+ uint16 getDefaultX (int slot = 0) const;
+ uint16 getDefaultY (int slot = 0) const;
- Graphics::CoktelVideo::State getState() const;
- uint32 getFeatures() const;
+ const Common::List<Common::Rect> *getDirtyRects(int slot = 0) const;
- int16 getDefaultX() const;
- int16 getDefaultY() const;
+ bool hasEmbeddedFile(const Common::String &fileName, int slot = 0) const;
+ Common::MemoryReadStream *getEmbeddedFile(const Common::String &fileName, int slot = 0);
- bool hasExtraData(const char *fileName) const;
- Common::MemoryReadStream *getExtraData(const char *fileName);
+ int32 getSubtitleIndex(int slot = 0) const;
- Graphics::CoktelVideo::State nextFrame();
+ void writeVideoInfo(const Common::String &file, int16 varX, int16 varY,
+ int16 varFrames, int16 varWidth, int16 varHeight);
+
+ bool copyFrame(int slot, byte *dest,
+ uint16 left, uint16 top, uint16 width, uint16 height,
+ uint16 x, uint16 y, uint16 pitch, int16 transp = -1) const;
+
+private:
+ struct Video {
+ Graphics::CoktelDecoder *decoder;
+ Common::String fileName;
+
+ SurfaceDescPtr surface;
- private:
- GobEngine *_vm;
+ Video();
- Common::String _fileName;
- DataStream *_stream;
- Graphics::CoktelVideo *_video;
- Graphics::CoktelVideo::State _state;
- int16 _defaultX, _defaultY;
+ bool isEmpty() const;
+ void close();
};
+ static const int kVideoSlotCount = 32;
+
static const char *_extensions[];
GobEngine *_vm;
- Common::Array<Video *> _videoSlots;
- Video *_primaryVideo;
- bool _ownSurf;
- bool _backSurf;
+ // _videoSlots[0] is reserved for the "primary" video
+ Video _videoSlots[kVideoSlotCount];
+
bool _needBlit;
- bool _noCursorSwitch;
+ bool _noCursorSwitch;
bool _woodruffCohCottWorkaround;
- bool findFile(char *fileName, Type &which);
-
- const Video *getVideoBySlot(int slot = -1) const;
- Video *getVideoBySlot(int slot = -1);
+ const Video *getVideoBySlot(int slot) const;
+ Video *getVideoBySlot(int slot);
int getNextFreeSlot();
- void copyPalette(Graphics::CoktelVideo &video, int16 palStart = -1, int16 palEnd = -1);
- bool doPlay(int16 frame, int16 breakKey,
- uint16 palCmd, int16 palStart, int16 palEnd,
- int16 palFrame, int16 endFrame, bool noRetrace = false);
- void evalBgShading(Graphics::CoktelVideo &video);
+ Common::String findFile(const Common::String &file, Properties &properties);
+
+ Graphics::CoktelDecoder *openVideo(const Common::String &file, Properties &properties);
+
+ bool playFrame(int slot, Properties &properties);
+
+ void checkAbort(Video &video, Properties &properties);
+ void evalBgShading(Video &video);
+
+ void copyPalette(const Video &video, int16 palStart, int16 palEnd);
};
} // End of namespace Gob
diff --git a/engines/groovie/cell.h b/engines/groovie/cell.h
index 39ee529beb..a5feab4017 100644
--- a/engines/groovie/cell.h
+++ b/engines/groovie/cell.h
@@ -26,11 +26,7 @@
#ifndef GROOVIE_CELL_H
#define GROOVIE_CELL_H
-#include "common/file.h"
-#include "common/util.h"
-
-#include "groovie/cell.h"
-#include "groovie/groovie.h"
+#include "common/textconsole.h"
#define BOARDSIZE 7
#define CELL_CLEAR 0
diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp
index 3f304c7859..2d0a2df245 100644
--- a/engines/groovie/cursor.cpp
+++ b/engines/groovie/cursor.cpp
@@ -403,18 +403,15 @@ GrvCursorMan_v2::GrvCursorMan_v2(OSystem *system) :
// Open the icons file
Common::File iconsFile;
- if (!iconsFile.open("icons.ph")) {
+ if (!iconsFile.open("icons.ph"))
error("Groovie::Cursor: Couldn't open icons.ph");
- return;
- }
// Verify the signature
- uint32 tmp32 = iconsFile.readUint32LE();
+ uint32 tmp32 = iconsFile.readUint32BE();
uint16 tmp16 = iconsFile.readUint16LE();
- if (tmp32 != 0x6e6f6369 || tmp16 != 1) {
- error("Groovie::Cursor: icons.ph signature failed: %04X %d", tmp32, tmp16);
- return;
- }
+ if (tmp32 != MKID_BE('icon') || tmp16 != 1)
+ error("Groovie::Cursor: icons.ph signature failed: %s %d", tag2str(tmp32), tmp16);
+
// Read the number of icons
uint16 nicons = iconsFile.readUint16LE();
diff --git a/engines/groovie/cursor.h b/engines/groovie/cursor.h
index 83aebb37d3..7a1f3ccc0e 100644
--- a/engines/groovie/cursor.h
+++ b/engines/groovie/cursor.h
@@ -26,9 +26,8 @@
#ifndef GROOVIE_CURSOR_H
#define GROOVIE_CURSOR_H
-#include "common/system.h"
#include "common/array.h"
-#include "common/file.h"
+#include "common/system.h"
namespace Common {
class MacResManager;
diff --git a/engines/groovie/debug.cpp b/engines/groovie/debug.cpp
index 41ebb2fbcd..7055965917 100644
--- a/engines/groovie/debug.cpp
+++ b/engines/groovie/debug.cpp
@@ -24,15 +24,17 @@
*/
#include "groovie/debug.h"
+#include "groovie/graphics.h"
#include "groovie/groovie.h"
#include "groovie/script.h"
#include "common/debug-channels.h"
+#include "common/system.h"
namespace Groovie {
Debugger::Debugger(GroovieEngine *vm) :
- _vm (vm), _script(_vm->_script), _syst(_vm->_system) {
+ _vm(vm), _script(_vm->_script) {
// Register the debugger comands
DCmd_Register("step", WRAP_METHOD(Debugger, cmd_step));
@@ -136,7 +138,7 @@ bool Debugger::cmd_playref(int argc, const char **argv) {
bool Debugger::cmd_dumppal(int argc, const char **argv) {
uint16 i;
byte palettedump[256 * 4];
- _syst->grabPalette(palettedump, 0, 256);
+ _vm->_system->grabPalette(palettedump, 0, 256);
for (i = 0; i < 256; i++) {
DebugPrintf("%3d: %3d,%3d,%3d,%3d\n", i, palettedump[(i * 4)], palettedump[(i * 4) + 1], palettedump[(i * 4) + 2], palettedump[(i * 4) + 3]);
diff --git a/engines/groovie/debug.h b/engines/groovie/debug.h
index dadba9482c..e21746a426 100644
--- a/engines/groovie/debug.h
+++ b/engines/groovie/debug.h
@@ -27,12 +27,11 @@
#define GROOVIE_DEBUG_H
#include "gui/debugger.h"
-#include "engines/engine.h"
namespace Groovie {
-class Script;
class GroovieEngine;
+class Script;
class Debugger : public GUI::Debugger {
public:
@@ -42,7 +41,6 @@ public:
private:
GroovieEngine *_vm;
Script *_script;
- OSystem *_syst;
int getNumber(const char *arg);
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 5b0fa4b3b1..b30c2361d2 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -23,12 +23,12 @@
*
*/
-#include "common/savefile.h"
-
#include "groovie/groovie.h"
#include "groovie/detection.h"
#include "groovie/saveload.h"
+#include "common/system.h"
+
namespace Groovie {
static const PlainGameDescriptor groovieGames[] = {
@@ -176,7 +176,11 @@ static const ADParams detectionParams = {
// Flags
kADFlagUseExtraAsHint,
// Additional GUI options (for every game}
- Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX
+ Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
diff --git a/engines/groovie/font.cpp b/engines/groovie/font.cpp
index ece8447735..dc1d7ae73a 100644
--- a/engines/groovie/font.cpp
+++ b/engines/groovie/font.cpp
@@ -23,106 +23,106 @@
*
*/
-#include "common/file.h"
-#include "graphics/surface.h"
-
#include "groovie/font.h"
namespace Groovie {
-Font::Font(OSystem *syst) :
- _syst(syst), _sphinxfnt(NULL) {
-
- Common::File fontfile;
- if (!fontfile.open("sphinx.fnt")) {
- error("Groovie::Font: Couldn't open sphinx.fnt");
- }
- uint16 fontfilesize = fontfile.size();
- _sphinxfnt = fontfile.readStream(fontfilesize);
- fontfile.close();
+T7GFont::T7GFont() : _maxHeight(0), _maxWidth(0), _glyphs(0) {
}
-Font::~Font() {
- delete _sphinxfnt;
+T7GFont::~T7GFont() {
+ delete[] _glyphs;
}
-void Font::printstring(const char *messagein) {
- uint16 totalwidth = 0, currxoffset, i;
+bool T7GFont::load(Common::SeekableReadStream &stream) {
+ // Read the mapping of characters to glyphs
+ if (stream.read(_mapChar2Glyph, 128) < 128) {
+ error("Groovie::T7GFont: Couldn't read the character to glyph map");
+ return false;
+ }
- char message[15];
- memset(message, 0, 15);
+ // Calculate the number of glyphs
+ byte numGlyphs = 0;
+ for (int i = 0; i < 128; i++)
+ if (_mapChar2Glyph[i] >= numGlyphs)
+ numGlyphs = _mapChar2Glyph[i] + 1;
+
+ // Read the glyph offsets
+ uint16 *glyphOffsets = new uint16[numGlyphs];
+ for (int i = 0; i < numGlyphs; i++)
+ glyphOffsets[i] = stream.readUint16LE();
+
+ if (stream.eos()) {
+ error("Groovie::T7GFont: Couldn't read the glyph offsets");
+ delete[] glyphOffsets;
+ return false;
+ }
- // Clear the top bar
- Common::Rect topbar(640, 80);
- Graphics::Surface *gamescreen;
- gamescreen = _syst->lockScreen();
- gamescreen->fillRect(topbar, 0);
- _syst->unlockScreen();
+ // Allocate the glyph data
+ delete[] _glyphs;
+ _glyphs = new Glyph[numGlyphs];
+
+ // Read the glyphs
+ _maxHeight = _maxWidth = 0;
+ for (int i = 0; (i < numGlyphs) && !stream.eos(); i++) {
+ // Verify we're at the expected stream position
+ if (stream.pos() != glyphOffsets[i]) {
+ error("Groovie::T7GFont: Glyph %d starts at %d but the current "
+ "offset is %d", i, glyphOffsets[i], stream.pos());
+ return false;
+ }
- for (i = 0; i < 14; i++) {
- char chartocopy = messagein[i];
- if (chartocopy <= 0x00 || chartocopy == 0x24) {
- break;
+ // Read the glyph information
+ Glyph *g = &_glyphs[i];
+ g->width = stream.readByte();
+ g->julia = stream.readByte();
+
+ // Read the pixels data into a dynamic array (we don't know its length)
+ Common::Array<byte> data;
+ data.reserve(300);
+ byte b = stream.readByte();
+ while (!stream.eos() && (b != 0xFF)) {
+ data.push_back(b);
+ b = stream.readByte();
}
- message[i] = chartocopy;
- }
- Common::rtrim(message);
- for (i = 0; i < strlen(message); i++) {
- totalwidth += letterwidth(message[i]);
- }
- currxoffset = (640 - totalwidth) / 2;
- char *currpos = message;
- while (*(currpos) != 0) {
- currxoffset += printletter(*(currpos++), currxoffset);
- }
-}
-uint16 Font::letteroffset(char letter) {
- uint16 offset;
- offset = letter;
- _sphinxfnt->seek(offset);
- offset = _sphinxfnt->readByte() * 2 + 128;
- _sphinxfnt->seek(offset);
- offset = _sphinxfnt->readUint16LE();
- return offset;
-}
+ // Verify the pixel data size
+ assert (data.size() % g->width == 0);
+ g->height = data.size() / g->width;
-uint8 Font::letterwidth(char letter) {
- uint16 offset = letteroffset(letter);
- _sphinxfnt->seek(offset);
- return _sphinxfnt->readByte();
-}
+ // Copy the pixel data into the definitive static array
+ g->pixels = new byte[data.size()];
+ memcpy(g->pixels, data.begin(), data.size());
-uint8 Font::letterheight(char letter) {
- uint16 offset, width, julia, data, counter = 0;
- offset = letteroffset(letter);
- _sphinxfnt->seek(offset);
- width = _sphinxfnt->readByte();
- julia = _sphinxfnt->readByte();
- data = _sphinxfnt->readByte();
- while (data != 0xFF) {
- data = _sphinxfnt->readByte();
- counter++;
+ // Update the max values
+ if (g->width > _maxWidth)
+ _maxWidth = g->width;
+ if (g->height > _maxHeight)
+ _maxHeight = g->height;
}
- if (counter % width != 0) assert("font file corrupt");
- return counter / width;
+
+ delete[] glyphOffsets;
+ return true;
}
+void T7GFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) const {
+ // We ignore the color, as the font is already colored
+ const Glyph *glyph = getGlyph(chr);
+ const byte *src = glyph->pixels;
+ byte *target = (byte *)dst->getBasePtr(x, y);
-uint8 Font::printletter(char letter, uint16 xoffset) {
- uint16 offset, width, height, julia;
- offset = letteroffset(letter);
- height = letterheight(letter);
- _sphinxfnt->seek(offset);
- width = _sphinxfnt->readByte();
- julia = _sphinxfnt->readByte();
+ for (int i = 0; i < glyph->height; i++) {
+ memcpy(target, src, glyph->width);
+ src += glyph->width;
+ target += dst->pitch;
+ }
+}
- byte *data = new byte[width * height];
- _sphinxfnt->read(data, width * height);
- _syst->copyRectToScreen(data, width, xoffset, 16, width, height);
- delete[] data;
+const T7GFont::Glyph *T7GFont::getGlyph(byte chr) const {
+ assert (chr < 128);
- return width;
+ byte numGlyph = _mapChar2Glyph[chr];
+ return &_glyphs[numGlyph];
}
} // End of Groovie namespace
diff --git a/engines/groovie/font.h b/engines/groovie/font.h
index 1a4a967fa6..71f8393d28 100644
--- a/engines/groovie/font.h
+++ b/engines/groovie/font.h
@@ -27,24 +27,38 @@
#define GROOVIE_FONT_H
#include "common/stream.h"
-#include "common/system.h"
+#include "graphics/font.h"
namespace Groovie {
-class Font {
+class T7GFont : public Graphics::Font {
public:
- Font(OSystem *syst);
- ~Font();
- void printstring(const char *messagein);
+ T7GFont();
+ ~T7GFont();
+
+ bool load(Common::SeekableReadStream &stream);
+
+ int getFontHeight() const { return _maxHeight; }
+ int getMaxCharWidth() const { return _maxWidth; }
+ int getCharWidth(byte chr) const { return getGlyph(chr)->width; }
+ void drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) const;
private:
- OSystem *_syst;
- Common::MemoryReadStream *_sphinxfnt;
+ int _maxHeight, _maxWidth;
+
+ struct Glyph {
+ Glyph() : pixels(0) {}
+ ~Glyph() { delete[] pixels; }
+
+ byte width;
+ byte height;
+ byte julia;
+ byte *pixels;
+ };
- uint16 letteroffset(char letter);
- uint8 letterwidth(char letter);
- uint8 letterheight(char letter);
- uint8 printletter(char letter, uint16 xoffset);
+ byte _mapChar2Glyph[128];
+ Glyph *_glyphs;
+ const Glyph *getGlyph(byte chr) const;
};
} // End of Groovie namespace
diff --git a/engines/groovie/graphics.cpp b/engines/groovie/graphics.cpp
index 1e54f0e79b..8546a13d40 100644
--- a/engines/groovie/graphics.cpp
+++ b/engines/groovie/graphics.cpp
@@ -23,8 +23,9 @@
*
*/
-#include "groovie/groovie.h"
#include "groovie/graphics.h"
+#include "groovie/groovie.h"
+#include "common/system.h"
namespace Groovie {
diff --git a/engines/groovie/graphics.h b/engines/groovie/graphics.h
index ea3261c85f..c9bade9538 100644
--- a/engines/groovie/graphics.h
+++ b/engines/groovie/graphics.h
@@ -26,6 +26,8 @@
#ifndef GROOVIE_GRAPHICS_H
#define GROOVIE_GRAPHICS_H
+#include "graphics/surface.h"
+
namespace Groovie {
class GroovieEngine;
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index ba18b37690..cdf5171ab9 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -23,27 +23,30 @@
*
*/
+#include "groovie/groovie.h"
+#include "groovie/cursor.h"
+#include "groovie/detection.h"
+#include "groovie/graphics.h"
+#include "groovie/music.h"
+#include "groovie/resource.h"
+#include "groovie/roq.h"
+#include "groovie/vdx.h"
+
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/events.h"
#include "common/macresman.h"
#include "engines/util.h"
-
+#include "graphics/fontman.h"
#include "sound/mixer.h"
-#include "groovie/groovie.h"
-#include "groovie/detection.h"
-#include "groovie/music.h"
-#include "groovie/roq.h"
-#include "groovie/vdx.h"
-
namespace Groovie {
GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) :
Engine(syst), _gameDescription(gd), _debugger(NULL), _script(NULL),
_resMan(NULL), _grvCursorMan(NULL), _videoPlayer(NULL), _musicPlayer(NULL),
- _graphicsMan(NULL), _macResFork(NULL), _waitingForInput(false) {
+ _graphicsMan(NULL), _macResFork(NULL), _waitingForInput(false), _font(NULL) {
// Adding the default directories
const Common::FSNode gameDataDir(ConfMan.get("path"));
@@ -104,12 +107,26 @@ Common::Error GroovieEngine::run() {
_graphicsMan = new GraphicsMan(this);
// Create the resource and cursor managers and the video player
+ // Prepare the font too
switch (_gameDescription->version) {
case kGroovieT7G:
- if (_gameDescription->desc.platform == Common::kPlatformMacintosh) {
+ if (getPlatform() == Common::kPlatformMacintosh) {
_macResFork = new Common::MacResManager();
if (!_macResFork->open(_gameDescription->desc.filesDescriptions[0].fileName))
error("Could not open %s as a resource fork", _gameDescription->desc.filesDescriptions[0].fileName);
+ // The Macintosh release used system fonts. We use GUI fonts.
+ _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
+ } else {
+ Common::File fontfile;
+ if (!fontfile.open("sphinx.fnt")) {
+ error("Couldn't open sphinx.fnt");
+ return Common::kNoGameDataFoundError;
+ } else if (!_sphinxFont.load(fontfile)) {
+ error("Error loading sphinx.fnt");
+ return Common::kUnknownError;
+ }
+ fontfile.close();
+ _font = &_sphinxFont;
}
_resMan = new ResMan_t7g(_macResFork);
@@ -124,7 +141,7 @@ Common::Error GroovieEngine::run() {
}
// Create the music player
- if (_gameDescription->desc.platform == Common::kPlatformMacintosh)
+ if (getPlatform() == Common::kPlatformMacintosh)
_musicPlayer = new MusicPlayerMac(this);
else
_musicPlayer = new MusicPlayerXMI(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample");
@@ -137,8 +154,8 @@ Common::Error GroovieEngine::run() {
if (_gameDescription->version == kGroovieT7G) {
// Run The 7th Guest's demo if requested
if (ConfMan.hasKey("demo_mode") && ConfMan.getBool("demo_mode"))
- filename = Common::String("demo.grv");
- else if (_gameDescription->desc.platform == Common::kPlatformMacintosh)
+ filename = "demo.grv";
+ else if (getPlatform() == Common::kPlatformMacintosh)
filename = "script.grv"; // Stored inside the executable's resource fork
} else if (_gameDescription->version == kGroovieV2) {
// Open the disk index
@@ -203,10 +220,8 @@ Common::Error GroovieEngine::run() {
_system->openCD(cd_num);
while (!shouldQuit()) {
- // Show the debugger if required
- if (_debugger->isAttached()) {
- _debugger->onFrame();
- }
+ // Give the debugger a chance to act
+ _debugger->onFrame();
// Handle input
Common::Event ev;
@@ -290,6 +305,10 @@ Common::Error GroovieEngine::run() {
return Common::kNoError;
}
+Common::Platform GroovieEngine::getPlatform() const {
+ return _gameDescription->desc.platform;
+}
+
bool GroovieEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsRTL) ||
diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h
index dae2df0595..8ae5f4157f 100644
--- a/engines/groovie/groovie.h
+++ b/engines/groovie/groovie.h
@@ -26,15 +26,11 @@
#ifndef GROOVIE_H
#define GROOVIE_H
-#include "engines/engine.h"
-#include "graphics/surface.h"
-
-#include "groovie/cursor.h"
#include "groovie/debug.h"
-#include "groovie/graphics.h"
-#include "groovie/player.h"
-#include "groovie/resource.h"
-#include "groovie/script.h"
+#include "groovie/font.h"
+
+#include "engines/engine.h"
+#include "graphics/pixelformat.h"
namespace Common {
class MacResManager;
@@ -57,7 +53,12 @@ namespace Common {
*/
namespace Groovie {
+class GraphicsMan;
+class GrvCursorMan;
class MusicPlayer;
+class ResMan;
+class Script;
+class VideoPlayer;
enum DebugLevels {
kGroovieDebugAll = 1 << 0,
@@ -81,6 +82,8 @@ public:
GroovieEngine(OSystem *syst, const GroovieGameDescription *gd);
~GroovieEngine();
+ Common::Platform getPlatform() const;
+
protected:
// Engine APIs
@@ -106,6 +109,7 @@ public:
VideoPlayer *_videoPlayer;
MusicPlayer *_musicPlayer;
GraphicsMan *_graphicsMan;
+ const Graphics::Font *_font;
Common::MacResManager *_macResFork;
@@ -113,6 +117,7 @@ private:
const GroovieGameDescription *_gameDescription;
Debugger *_debugger;
bool _waitingForInput;
+ T7GFont _sphinxFont;
};
} // End of namespace Groovie
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index f6670da716..6959a6a6f1 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -23,13 +23,14 @@
*
*/
-#include "groovie/lzss.h"
#include "groovie/music.h"
+#include "groovie/groovie.h"
#include "groovie/resource.h"
#include "common/config-manager.h"
#include "common/macresman.h"
#include "sound/audiocd.h"
+#include "sound/midiparser.h"
namespace Groovie {
@@ -110,6 +111,20 @@ void MusicPlayer::playCD(uint8 track) {
// Play the track starting at the requested offset (1000ms = 75 frames)
AudioCD.play(track - 1, 1, startms * 75 / 1000, 0);
+
+ // If the audio is not playing from the CD, play the "fallback" MIDI.
+ // The Mac version has no CD tracks, so it will always use the MIDI.
+ if (!AudioCD.isPlaying()) {
+ if (track == 2) {
+ // Intro MIDI fallback
+ if (_vm->getPlatform() == Common::kPlatformMacintosh)
+ playSong(70);
+ else
+ playSong((19 << 10) | 36); // XMI.GJD, file 36
+ } else if (track == 3) {
+ // TODO: Credits MIDI fallback
+ }
+ }
}
void MusicPlayer::startBackground() {
@@ -385,8 +400,8 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String &gtlName)
_midiParser = MidiParser::createParser_XMIDI();
// Create the driver
- MidiDriverType driver = detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- _driver = createMidi(driver);
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _driver = createMidi(dev);
this->open();
// Set the parser's driver
@@ -401,9 +416,9 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String &gtlName)
}
// Load the Global Timbre Library
- if (driver == MD_ADLIB) {
+ if (MidiDriver::getMusicType(dev) == MT_ADLIB) {
// MIDI through AdLib
- _musicType = MD_ADLIB;
+ _musicType = MT_ADLIB;
loadTimbres(gtlName + ".ad");
// Setup the percussion channel
@@ -411,9 +426,9 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String &gtlName)
if (_timbres[i].bank == 0x7F)
setTimbreAD(9, _timbres[i]);
}
- } else if ((driver == MD_MT32) || ConfMan.getBool("native_mt32")) {
+ } else if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")) {
// MT-32
- _musicType = MD_MT32;
+ _musicType = MT_MT32;
loadTimbres(gtlName + ".mt");
} else {
// GM
@@ -454,9 +469,9 @@ void MusicPlayerXMI::send(uint32 b) {
for (int i = 0; i < numTimbres; i++) {
if ((_timbres[i].bank == _chanBanks[chan]) &&
(_timbres[i].patch == patch)) {
- if (_musicType == MD_ADLIB) {
+ if (_musicType == MT_ADLIB) {
setTimbreAD(chan, _timbres[i]);
- } else if (_musicType == MD_MT32) {
+ } else if (_musicType == MT_MT32) {
setTimbreMT(chan, _timbres[i]);
}
return;
@@ -681,8 +696,8 @@ MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : MusicPlayerMidi(vm) {
_midiParser = MidiParser::createParser_SMF();
// Create the driver
- MidiDriverType driver = detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- _driver = createMidi(driver);
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _driver = createMidi(dev);
this->open();
// Set the parser's driver
@@ -702,20 +717,64 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) {
Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKID_BE('cmid'), fileref & 0x3FF);
if (file) {
- // TODO: A form of LZSS, not supported by the current Groovie decoder.
- // The offset/length uint16 is BE, but not sure the amount of length bits
- // nor whether the offset is absolute/relative.
- warning("TODO: Mac Compressed MIDI: cmid 0x%04x", fileref & 0x3FF);
+ // Found the resource, decompress it
+ Common::SeekableReadStream *tmp = decompressMidi(file);
delete file;
- return false;
+ file = tmp;
+ } else {
+ // Otherwise, it's uncompressed
+ file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF);
+ if (!file)
+ error("Groovie::Music: Couldn't find resource 0x%04X", fileref);
}
- // Otherwise, it's uncompressed
- file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF);
- if (!file)
- error("Groovie::Music: Couldn't find resource 0x%04X", fileref);
-
return loadParser(file, loop);
}
+Common::SeekableReadStream *MusicPlayerMac::decompressMidi(Common::SeekableReadStream *stream) {
+ // Initialize an output buffer of the given size
+ uint32 size = stream->readUint32BE();
+ byte *output = (byte *)malloc(size);
+
+ byte *current = output;
+ uint32 decompBytes = 0;
+ while ((decompBytes < size) && !stream->eos()) {
+ // 8 flags
+ byte flags = stream->readByte();
+
+ for (byte i = 0; (i < 8) && !stream->eos(); i++) {
+ if (flags & 1) {
+ // 1: Next byte is a literal
+ *(current++) = stream->readByte();
+ if (stream->eos())
+ continue;
+ decompBytes++;
+ } else {
+ // 0: It's a reference to part of the history
+ uint16 args = stream->readUint16BE();
+ if (stream->eos())
+ continue;
+
+ // Length = 4bit unsigned (3 minimal)
+ uint8 length = (args >> 12) + 3;
+
+ // Offset = 12bit signed (all values are negative)
+ int16 offset = (args & 0xFFF) | 0xF000;
+
+ // Copy from the past decompressed bytes
+ decompBytes += length;
+ while (length > 0) {
+ *(current) = *(current + offset);
+ current++;
+ length--;
+ }
+ }
+ flags = flags >> 1;
+ }
+ }
+
+ // Return the output buffer wrapped in a MemoryReadStream
+ return new Common::MemoryReadStream(output, size, DisposeAfterUse::YES);
+}
+
} // End of Groovie namespace
diff --git a/engines/groovie/music.h b/engines/groovie/music.h
index 6302c81dcc..5b5f5bd346 100644
--- a/engines/groovie/music.h
+++ b/engines/groovie/music.h
@@ -26,14 +26,16 @@
#ifndef GROOVIE_MUSIC_H
#define GROOVIE_MUSIC_H
-#include "groovie/groovie.h"
-
-#include "sound/mididrv.h"
-#include "sound/midiparser.h"
+#include "common/array.h"
#include "common/mutex.h"
+#include "sound/mididrv.h"
+
+class MidiParser;
namespace Groovie {
+class GroovieEngine;
+
class MusicPlayer {
public:
MusicPlayer(GroovieEngine *vm);
@@ -159,6 +161,9 @@ public:
protected:
bool load(uint32 fileref, bool loop);
+
+private:
+ Common::SeekableReadStream *decompressMidi(Common::SeekableReadStream *stream);
};
} // End of Groovie namespace
diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp
index 5bac190701..8badd90012 100644
--- a/engines/groovie/player.cpp
+++ b/engines/groovie/player.cpp
@@ -23,8 +23,8 @@
*
*/
-#include "groovie/groovie.h"
#include "groovie/player.h"
+#include "groovie/groovie.h"
namespace Groovie {
diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp
index 42de1a804d..32cc1735ef 100644
--- a/engines/groovie/resource.cpp
+++ b/engines/groovie/resource.cpp
@@ -26,8 +26,8 @@
#include "common/archive.h"
#include "common/macresman.h"
-#include "groovie/groovie.h"
#include "groovie/resource.h"
+#include "groovie/groovie.h"
namespace Groovie {
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index de91bb2067..11bacef8e8 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -26,8 +26,9 @@
// ROQ video player based on this specification by Dr. Tim Ferguson:
// http://www.csse.monash.edu.au/~timf/videocodec/idroq.txt
-#include "groovie/groovie.h"
#include "groovie/roq.h"
+#include "groovie/graphics.h"
+#include "groovie/groovie.h"
#include "graphics/jpeg.h"
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 15a0a473c0..9fd7fa7d63 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -23,18 +23,19 @@
*
*/
-#include "groovie/debug.h"
-#include "groovie/music.h"
#include "groovie/script.h"
-#include "groovie/groovie.h"
#include "groovie/cell.h"
+#include "groovie/cursor.h"
+#include "groovie/graphics.h"
+#include "groovie/groovie.h"
+#include "groovie/music.h"
+#include "groovie/player.h"
+#include "groovie/resource.h"
#include "groovie/saveload.h"
#include "common/archive.h"
#include "common/config-manager.h"
#include "common/debug-channels.h"
-#include "common/endian.h"
-#include "common/events.h"
#include "common/EventRecorder.h"
#include "common/macresman.h"
@@ -63,9 +64,8 @@ static void debugScript(int level, bool nl, const char *s, ...) {
}
Script::Script(GroovieEngine *vm, EngineVersion version) :
- _code(NULL), _savedCode(NULL), _stacktop(0),
- _debugger(NULL), _vm(vm),
- _videoFile(NULL), _videoRef(0), _font(NULL), _staufsMove(NULL) {
+ _code(NULL), _savedCode(NULL), _stacktop(0), _debugger(NULL), _vm(vm),
+ _videoFile(NULL), _videoRef(0), _staufsMove(NULL) {
// Initialize the opcode set depending on the engine version
switch (version) {
case kGroovieT7G:
@@ -86,11 +86,11 @@ Script::Script(GroovieEngine *vm, EngineVersion version) :
}
// Initialize the music type variable
- int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- if (midiDriver == MD_ADLIB) {
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ if (MidiDriver::getMusicType(dev) == MT_ADLIB) {
// MIDI through AdLib
setVariable(0x100, 0);
- } else if ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")) {
+ } else if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")) {
// MT-32
setVariable(0x100, 2);
} else {
@@ -112,7 +112,6 @@ Script::~Script() {
delete[] _code;
delete[] _savedCode;
- delete _font;
delete _videoFile;
}
@@ -429,6 +428,22 @@ void Script::savegame(uint slot) {
_saveNames[slot] = save;
}
+void Script::printString(Graphics::Surface *surface, const char *str) {
+ char message[15];
+ memset(message, 0, 15);
+
+ // Preprocess the string
+ for (int i = 0; i < 14; i++) {
+ if (str[i] <= 0x00 || str[i] == 0x24)
+ break;
+ message[i] = str[i];
+ }
+ Common::rtrim(message);
+
+ // Draw the string
+ _vm->_font->drawString(surface, message, 0, 16, 640, 0xE2, Graphics::kTextAlignCenter);
+}
+
// OPCODES
void Script::o_invalid() {
@@ -1249,11 +1264,16 @@ void Script::o_printstring() {
stringstorage[counter] = 0;
- // Load the font if required
- if (!_font) {
- _font = new Font(_vm->_system);
- }
- _font->printstring(stringstorage);
+ Common::Rect topbar(640, 80);
+ Graphics::Surface *gamescreen = _vm->_system->lockScreen();
+
+ // Clear the top bar
+ gamescreen->fillRect(topbar, 0);
+
+ // Draw the string
+ printString(gamescreen, stringstorage);
+
+ _vm->_system->unlockScreen();
}
void Script::o_hotspot_slot() {
@@ -1273,11 +1293,15 @@ void Script::o_hotspot_slot() {
return;
}
- // Load the font if required
- if (!_font) {
- _font = new Font(_vm->_system);
- }
- _font->printstring(_saveNames[slot].c_str());
+ Common::Rect topbar(640, 80);
+ Graphics::Surface *gamescreen = _vm->_system->lockScreen();
+
+ // Clear the top bar
+ gamescreen->fillRect(topbar, 0);
+
+ printString(gamescreen, _saveNames[slot].c_str());
+
+ _vm->_system->unlockScreen();
// Save the currently highlighted slot
_hotspotSlot = slot;
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index e4a6a288e6..cda87a8917 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -26,12 +26,16 @@
#ifndef GROOVIE_SCRIPT_H
#define GROOVIE_SCRIPT_H
-#include "common/file.h"
#include "common/random.h"
#include "common/rect.h"
-#include "groovie/font.h"
-#include "groovie/cell.h"
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace Graphics {
+struct Surface;
+}
namespace Groovie {
@@ -40,8 +44,9 @@ enum EngineVersion {
kGroovieV2
};
-class GroovieEngine;
class CellGame;
+class Debugger;
+class GroovieEngine;
class Script {
friend class Debugger;
@@ -112,7 +117,6 @@ private:
uint16 _hotspotSlot;
// Video
- Font *_font;
Common::SeekableReadStream *_videoFile;
uint32 _videoRef;
uint16 _bitflags;
@@ -140,6 +144,7 @@ private:
void loadgame(uint slot);
void savegame(uint slot);
bool playvideofromref(uint32 fileref);
+ void printString(Graphics::Surface *surface, const char *str);
// Opcodes
typedef void (Script::*OpcodeFunc)();
diff --git a/engines/groovie/vdx.cpp b/engines/groovie/vdx.cpp
index fb6377349f..61756cb218 100644
--- a/engines/groovie/vdx.cpp
+++ b/engines/groovie/vdx.cpp
@@ -23,9 +23,10 @@
*
*/
+#include "groovie/vdx.h"
+#include "groovie/graphics.h"
#include "groovie/groovie.h"
#include "groovie/lzss.h"
-#include "groovie/vdx.h"
#include "common/debug-channels.h"
#include "sound/mixer.h"
@@ -208,17 +209,14 @@ static const uint16 vdxBlockMapLookup[] = {
};
void VDXPlayer::getDelta(Common::ReadStream *in) {
- uint16 j, k, l;
- uint32 offset;
- uint8 currOpCode, param1, param2, param3;
+ uint16 k, l;
// Get the size of the local palette
- j = in->readUint16LE();
+ uint16 palSize = in->readUint16LE();
// Load the palette if it isn't empty
- if (j) {
+ if (palSize) {
uint16 palBitField[16];
- int flag = 1, palIndex;
// Load the bit field
for (l = 0; l < 16; l++) {
@@ -227,9 +225,9 @@ void VDXPlayer::getDelta(Common::ReadStream *in) {
// Load the actual palette
for (l = 0; l < 16; l++) {
- flag = 1 << 15;
- for (j = 0; j < 16; j++) {
- palIndex = (l * 16) + j;
+ int flag = 1 << 15;
+ for (uint16 j = 0; j < 16; j++) {
+ int palIndex = (l * 16) + j;
if (flag & palBitField[l]) {
for (k = 0; k < 3; k++) {
@@ -246,11 +244,12 @@ void VDXPlayer::getDelta(Common::ReadStream *in) {
setPalette(_palBuf);
}
}
- currOpCode = in->readByte();
- /* j now becomes the current block line we're dealing with */
- j = 0;
- offset = 0;
+ uint8 currOpCode = in->readByte();
+ uint8 param1, param2, param3;
+
+ uint16 currentLine = 0;
+ uint32 offset = 0;
while (!in->eos()) {
byte colours[16];
if (currOpCode < 0x60) {
@@ -276,8 +275,8 @@ void VDXPlayer::getDelta(Common::ReadStream *in) {
break;
case 0x61: /* Skip to the end of this line, next block is start of next */
/* Note this is used at the end of EVERY line */
- j++;
- offset = j * TILE_SIZE * 640;
+ currentLine++;
+ offset = currentLine * TILE_SIZE * 640;
break;
case 0x62:
case 0x63:
@@ -381,12 +380,15 @@ void VDXPlayer::getStill(Common::ReadStream *in) {
byte colours[16];
for (uint16 j = 0; j < numYTiles; j++) {
- for (uint16 i = 0; i < numXTiles; i++) { /* Tile number */
+ byte *currentTile = buf + j * TILE_SIZE * imageWidth;
+ for (uint16 i = numXTiles; i; i--) {
uint8 colour1 = in->readByte();
uint8 colour0 = in->readByte();
uint16 colourMap = in->readUint16LE();
expandColourMap(colours, colourMap, colour1, colour0);
- decodeBlockStill(buf + j * TILE_SIZE * imageWidth + i * TILE_SIZE, colours, 640, mask);
+ decodeBlockStill(currentTile, colours, 640, mask);
+
+ currentTile += TILE_SIZE;
}
}
@@ -424,20 +426,27 @@ void VDXPlayer::getStill(Common::ReadStream *in) {
}
void VDXPlayer::expandColourMap(byte *out, uint16 colourMap, uint8 colour1, uint8 colour0) {
- int flag = 1 << 15;
- for (int i = 0; i < 16; i++) {
+ // It's a bit faster to start from the end
+ out += 16;
+ for (int i = 16; i; i--) {
// Set the corresponding colour
- out[i] = (colourMap & flag) ? colour1 : colour0;
+ // The following is an optimized version of:
+ // *--out = (colourMap & 1) ? colour1 : colour0;
+ uint8 selector = -(colourMap & 1);
+ *--out = (selector & colour1) | (~selector & colour0);
- // Update the flag to test the next colour
- flag >>= 1;
+ // Update the flag map to test the next colour
+ colourMap >>= 1;
}
}
void VDXPlayer::decodeBlockStill(byte *buf, byte *colours, uint16 imageWidth, uint8 mask) {
- for (int y = 0; y < TILE_SIZE; y++) {
- for (int x = 0; x < TILE_SIZE; x++) {
- if (_flagOne) {
+ assert(TILE_SIZE == 4);
+
+ for (int y = TILE_SIZE; y; y--) {
+ if (_flagOne) {
+ // TODO: optimize with bit logic?
+ for (int x = 0; x < TILE_SIZE; x++) {
// 0xff pixels don't modify the buffer
if (*colours != 0xff) {
// Write the colour
@@ -445,25 +454,28 @@ void VDXPlayer::decodeBlockStill(byte *buf, byte *colours, uint16 imageWidth, ui
// Note: if the mask is 0, it paints the image
// else, it paints the image's mask using 0xff
}
- } else {
- *buf = *colours;
+
+ // Point to the next colour
+ colours++;
+
+ // Point to the next pixel
+ buf++;
}
- // Point to the next colour
- colours++;
+ // Point to the start of the next line
+ buf += imageWidth - TILE_SIZE;
+ } else {
+ *((uint32 *)buf) = *((uint32 *)colours);
+ colours += 4;
- // Point to the next pixel
- buf++;
+ // Point to the start of the next line
+ buf += imageWidth;
}
-
- // Point to the start of the next line
- buf += imageWidth - TILE_SIZE;
}
}
void VDXPlayer::decodeBlockDelta(uint32 offset, byte *colours, uint16 imageWidth) {
- byte *fgBuf = (byte *)_fg->getBasePtr(0, 0) + offset;
- //byte *bgBuf = (byte *)_bg->getBasePtr(0, 0) + offset;
+ assert(TILE_SIZE == 4);
byte *dest;
// TODO: Verify just the else block is required
@@ -474,27 +486,38 @@ void VDXPlayer::decodeBlockDelta(uint32 offset, byte *colours, uint16 imageWidth
dest = (byte *)_bg->getBasePtr(0, 0) + offset;
//}
- int32 off = _origX + _origY * imageWidth;
- for (int y = 0; y < TILE_SIZE; y++) {
- for (int x = 0; x < TILE_SIZE; x++) {
- if (_flagSeven) {
- if (fgBuf[off] != 0xff) {
+ // Move the pointers to the beginning of the current block
+ int32 blockOff = _origX + _origY * imageWidth;
+ dest += blockOff;
+ byte *fgBuf = 0;
+ if (_flagSeven) {
+ fgBuf = (byte *)_fg->getBasePtr(0, 0) + offset + blockOff;
+ //byte *bgBuf = (byte *)_bg->getBasePtr(0, 0) + offset + blockOff;
+ }
+
+ for (int y = TILE_SIZE; y; y--) {
+ if (_flagSeven) {
+ // Paint mask
+ for (int x = 0; x < TILE_SIZE; x++) {
+ // TODO: this can probably be optimized with bit logic
+ if (fgBuf[x] != 0xff) {
if (*colours == 0xff) {
- dest[off] = fgBuf[off];
+ dest[x] = fgBuf[x];
} else {
- dest[off] = *colours;
+ dest[x] = *colours;
}
}
- } else {
- // Paint directly
- dest[off] = *colours;
+ colours++;
}
- colours++;
- off++;
+ fgBuf += imageWidth;
+ } else {
+ // Paint directly
+ *((uint32 *)dest) = *((uint32 *)colours);
+ colours += 4;
}
- // Prepare the offset of the next line
- off += imageWidth - TILE_SIZE;
+ // Move to the next line
+ dest += imageWidth;
}
}
diff --git a/engines/groovie/vdx.h b/engines/groovie/vdx.h
index 207d2e0c18..0b29493108 100644
--- a/engines/groovie/vdx.h
+++ b/engines/groovie/vdx.h
@@ -28,6 +28,10 @@
#include "groovie/player.h"
+namespace Common {
+ class ReadStream;
+}
+
namespace Groovie {
class VDXPlayer : public VideoPlayer {
diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp
index d71f7b8b25..225b44b3f4 100644
--- a/engines/kyra/debugger.cpp
+++ b/engines/kyra/debugger.cpp
@@ -240,7 +240,7 @@ bool Debugger_LoK::cmd_enterRoom(int argc, const char **argv) {
while (!_vm->_screen->isMouseVisible())
_vm->_screen->showMouse();
- _detach_now = true;
+ detach();
return false;
}
@@ -327,7 +327,7 @@ bool Debugger_v2::cmd_enterScene(int argc, const char **argv) {
while (!_vm->screen_v2()->isMouseVisible())
_vm->screen_v2()->showMouse();
- _detach_now = true;
+ detach();
return false;
}
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 6e9359e7fc..135a9ae7b2 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -41,1172 +41,7 @@ struct KYRAGameDescription {
Kyra::GameFlags flags;
};
-namespace {
-
-#define FLAGS(x, y, z, a, b, c, d, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
-#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
-
-#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA1)
-#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, Kyra::GI_KYRA1)
-
-#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA2)
-#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, false, Kyra::GI_KYRA2)
-
-#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, true, true, Kyra::GI_KYRA3)
-#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, true, false, Kyra::GI_KYRA3)
-#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, true, false, Kyra::GI_KYRA3)
-
-#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_LOL)
-#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_LOL)
-#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, true, false, false, Kyra::GI_LOL)
-#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
-
-const KYRAGameDescription adGameDescs[] = {
- /* disable these targets until they get supported
- {
- {
- "kyra1",
- 0,
- AD_ENTRY1("DISK1.EXE", "c8641d0414d6c966d0a3dad79db07bf4"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_FLOPPY_CMP_FLAGS
- },
-
- {
- {
- "kyra1",
- 0,
- AD_ENTRY1("DISK1.EXE", "5d5cee4c3d0b68d586788b74243d254a"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_FLOPPY_CMP_FLAGS
- },
- */
-
- {
- {
- "kyra1",
- "Extracted",
- AD_ENTRY1("GEMCUT.EMC", "3c244298395520bb62b5edfe41688879"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_FLOPPY_FLAGS
- },
- {
- {
- "kyra1",
- "Extracted",
- AD_ENTRY1("GEMCUT.EMC", "796e44863dd22fa635b042df1bf16673"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_FLOPPY_FLAGS
- },
- {
- {
- "kyra1",
- "Extracted",
- AD_ENTRY1("GEMCUT.EMC", "abf8eb360e79a6c2a837751fbd4d3d24"),
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_FLOPPY_FLAGS
- },
- {
- {
- "kyra1",
- "Extracted",
- AD_ENTRY1("GEMCUT.EMC", "6018e1dfeaca7fe83f8d0b00eb0dd049"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_FLOPPY_FLAGS
- },
- { // from Arne.F
- {
- "kyra1",
- "Extracted",
- AD_ENTRY1("GEMCUT.EMC", "f0b276781f47c130f423ec9679fe9ed9"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_FLOPPY_FLAGS
- },
- { // from VooD
- {
- "kyra1",
- "Extracted",
- AD_ENTRY1("GEMCUT.EMC", "8909b41596913b3f5deaf3c9f1017b01"),
- Common::ES_ESP,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_FLOPPY_FLAGS
- },
- { // floppy 1.8 from clemmy
- {
- "kyra1",
- "Extracted",
- AD_ENTRY1("GEMCUT.EMC", "747861d2a9c643c59fdab570df5b9093"),
- Common::ES_ESP,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_FLOPPY_FLAGS
- },
- { // from gourry
- {
- "kyra1",
- "Extracted",
- AD_ENTRY1("GEMCUT.EMC", "ef08c8c237ee1473fd52578303fc36df"),
- Common::IT_ITA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_FLOPPY_FLAGS
- },
-
- {
- {
- "kyra1",
- 0,
- {
- { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 },
- { "GEMCUT.EMC", 0, "2a3f44e179f1e9f7643e90083c747571", -1 },
- { NULL, 0, NULL, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_AMIGA_FLAGS
- },
-
- {
- {
- "kyra1",
- 0,
- {
- { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 },
- { "GEMCUT.EMC", 0, "74f99e9ed99abf8d0429826d78485a2a", -1 },
- { NULL, 0, NULL, 0 }
- },
- Common::DE_DEU,
- Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_AMIGA_FLAGS
- },
-
- {
- {
- "kyra1",
- 0,
- {
- { "GEMCUT.EMC", 0, "796e44863dd22fa635b042df1bf16673", -1 },
- { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 },
- { NULL, 0, NULL, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_FLOPPY_FLAGS
- },
-
- { // FM-TOWNS version
- {
- "kyra1",
- 0,
- {
- { "EMC.PAK", 0, "a046bb0b422061aab8e4c4689400343a", -1 },
- { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 },
- { NULL, 0, NULL, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformFMTowns,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_TOWNS_FLAGS
- },
- {
- {
- "kyra1",
- 0,
- {
- { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 },
- { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 },
- { NULL, 0, NULL, 0 }
- },
- Common::JA_JPN,
- Common::kPlatformFMTowns,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_TOWNS_SJIS_FLAGS
- },
-
- // PC-9801 floppy + CD / PC-9821 floppy version are all using the same data files,
- // thus we will mark it as non CD game.
- {
- {
- "kyra1",
- "",
- {
- { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 },
- { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 },
- { NULL, 0, NULL, 0 }
- },
- Common::JA_JPN,
- Common::kPlatformPC98,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA1_TOWNS_SJIS_FLAGS
- },
-
- {
- {
- "kyra1",
- "CD",
- AD_ENTRY1("GEMCUT.PAK", "fac399fe62f98671e56a005c5e94e39f"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA1_CD_FLAGS
- },
- {
- {
- "kyra1",
- "CD",
- AD_ENTRY1("GEMCUT.PAK", "230f54e6afc007ab4117159181a1c722"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA1_CD_FLAGS
- },
- {
- {
- "kyra1",
- "CD",
- AD_ENTRY1("GEMCUT.PAK", "b037c41768b652a040360ffa3556fd2a"),
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA1_CD_FLAGS
- },
-
- { // italian fan translation see fr#1727941 "KYRA: add Italian CD Version to kyra.dat"
- {
- "kyra1",
- "CD",
- AD_ENTRY1("GEMCUT.PAK", "d8327fc4b7a72b23c900fa13aef4093a"),
- Common::IT_ITA,
- Common::kPlatformPC,
- ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA1_CD_FLAGS
- },
-
- { // Kyra 1 Mac CD as mentioned in fr #2766454 "KYRA1: Add support for Macintosh CD" by nnooiissee
- {
- "kyra1",
- "CD",
- {
- { "GEMCUT.PAK", 0, "d3d4b281cd357230aabcec46843d04bd", -1 },
- { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 },
- { NULL, 0, NULL, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA1_CD_FLAGS
- },
- {
- {
- "kyra1",
- "CD",
- {
- { "GEMCUT.PAK", 0, "4a0cb720e824295bcbccbd1407652110", -1 },
- { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 },
- { NULL, 0, NULL, 0 }
- },
- Common::DE_DEU,
- Common::kPlatformMacintosh,
- ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA1_CD_FLAGS
- },
- {
- {
- "kyra1",
- "CD",
- {
- { "GEMCUT.PAK", 0, "b71ee090aa12e80ed2ba068826d92bed", -1 },
- { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 },
- { NULL, 0, NULL, 0 }
- },
- Common::FR_FRA,
- Common::kPlatformMacintosh,
- ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA1_CD_FLAGS
- },
-
- {
- {
- "kyra1",
- "Demo",
- AD_ENTRY1("DEMO1.WSA", "fb722947d94897512b13b50cc84fd648"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DEMO,
- Common::GUIO_NOSPEECH
- },
- KYRA1_DEMO_FLAGS
- },
-
- { // Special Kyrandia 1 CD demo
- {
- "kyra1",
- "Demo/CD",
- AD_ENTRY1("INTRO.VRM", "e3045fb69b8c29db84b8fda3ccbdac54"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DEMO | ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA1_DEMO_CD_FLAGS
- },
-
- { // Floppy version
- {
- "kyra2",
- 0,
- AD_ENTRY1("WESTWOOD.001", "3f52dda68c4f7696c8309038be9f4151"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA2_FLOPPY_CMP_FLAGS
- },
-
- { // Floppy version
- {
- "kyra2",
- 0,
- AD_ENTRY1("WESTWOOD.001", "d787b9559afddfe058b84c0b3a787224"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA2_FLOPPY_CMP_FLAGS
- },
-
- { // Floppy version extracted
- {
- "kyra2",
- "Extracted",
- AD_ENTRY1("FATE.PAK", "1ba18be685ad8e5a0ab5d46a0ce4d345"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA2_FLOPPY_FLAGS
- },
-
- { // Floppy version extracted
- {
- "kyra2",
- "Extracted",
- AD_ENTRY1("FATE.PAK", "262fb69dd8e52e596c7aefc6456f7c1b"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA2_FLOPPY_FLAGS
- },
-
- { // Floppy version extracted
- {
- "kyra2",
- "Extracted",
- AD_ENTRY1("FATE.PAK", "f7de11506b4c8fdf64bc763206c3e4e7"),
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA2_FLOPPY_FLAGS
- },
-
- { // Floppy version extracted
- {
- "kyra2",
- "Extracted",
- AD_ENTRY1("FATE.PAK", "e0a70c31b022cb4bb3061890020fc27c"),
- Common::IT_ITA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA2_FLOPPY_FLAGS
- },
-
- { // CD version
- {
- "kyra2",
- "CD",
- AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA2_CD_FLAGS
- },
- {
- {
- "kyra2",
- "CD",
- AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA2_CD_FLAGS
- },
- {
- {
- "kyra2",
- "CD",
- AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"),
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA2_CD_FLAGS
- },
-
- // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3"
- { // CD version
- {
- "kyra2",
- "CD",
- AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"),
- Common::IT_ITA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
- },
- {
- {
- "kyra2",
- "CD",
- AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
- },
- {
- {
- "kyra2",
- "CD",
- AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"),
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
- },
-
- {
- {
- "kyra2",
- "CD",
- AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"),
- Common::IT_ITA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
- },
-
- {
- {
- "kyra2",
- "CD",
- AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
- },
-
- {
- {
- "kyra2",
- "CD",
- AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"),
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
- },
-
- { // Interactive Demo
- {
- "kyra2",
- "CD/Demo",
- AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO,
- Common::GUIO_NONE
- },
- KYRA2_CD_DEMO_FLAGS
- },
-
- { // Interactive Demo
- {
- "kyra2",
- "CD/Demo",
- AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO,
- Common::GUIO_NONE
- },
- KYRA2_CD_DEMO_FLAGS
- },
-
- { // Interactive Demo
- {
- "kyra2",
- "CD/Demo",
- AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"),
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO,
- Common::GUIO_NONE
- },
- KYRA2_CD_DEMO_FLAGS
- },
-
- { // Non-Interactive Demos
- {
- "kyra2",
- "Demo",
- AD_ENTRY1("VOC.PAK", "ecb3561b63749158172bf21528cf5f45"),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- KYRA2_DEMO_FLAGS
- },
-
- { // FM-TOWNS
- {
- "kyra2",
- 0,
- AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"),
- Common::EN_ANY,
- Common::kPlatformFMTowns,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA2_TOWNS_FLAGS
- },
- {
- {
- "kyra2",
- 0,
- AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"),
- Common::JA_JPN,
- Common::kPlatformFMTowns,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- KYRA2_TOWNS_SJIS_FLAGS
- },
- { // PC-9821
- {
- "kyra2",
- "CD",
- AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"),
- Common::EN_ANY,
- Common::kPlatformPC98,
- ADGF_CD,
- Common::GUIO_NOSPEECH
- },
- KYRA2_TOWNS_FLAGS
- },
- {
- {
- "kyra2",
- "CD",
- AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"),
- Common::JA_JPN,
- Common::kPlatformPC98,
- ADGF_CD,
- Common::GUIO_NOSPEECH
- },
- KYRA2_TOWNS_SJIS_FLAGS
- },
-
- // Kyra3
-
- // non installed version
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
- { "WESTWOOD.001", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_FLAGS
- },
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
- { "WESTWOOD.001", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_FLAGS
- },
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
- { "WESTWOOD.001", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_FLAGS
- },
-
- // installed version
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_INS_FLAGS
- },
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_INS_FLAGS
- },
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_INS_FLAGS
- },
-
- // Mac version
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_INS_FLAGS
- },
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::DE_DEU,
- Common::kPlatformMacintosh,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_INS_FLAGS
- },
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::FR_FRA,
- Common::kPlatformMacintosh,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_INS_FLAGS
- },
-
- // Spanish fan translation, see fr#1994040 "KYRA3: Add support for Spanish fan translation"
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::ES_ESP,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY)
- },
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY)
- },
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY)
- },
-
- // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3"
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA)
- },
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA)
- },
- {
- {
- "kyra3",
- 0,
- {
- { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 },
- { "AUD.PAK", 0, 0, -1 },
- { 0, 0, 0, 0 }
- },
- Common::IT_ITA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- Common::GUIO_NOMIDI
- },
- KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA)
- },
-
-#ifdef ENABLE_LOL
- // Lands of Lore CD
- {
- {
- "lol",
- "CD",
- {
- { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 },
- { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
- { 0, 0, 0, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- LOL_CD_FLAGS
- },
-
- {
- {
- "lol",
- "CD",
- {
- { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 },
- { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
- { 0, 0, 0, 0 }
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- LOL_CD_FLAGS
- },
-
- {
- {
- "lol",
- "CD",
- {
- { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 },
- { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
- { 0, 0, 0, 0 }
- },
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- LOL_CD_FLAGS
- },
-
- {
- {
- "lol",
- "CD",
- {
- { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 },
- { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
- { 0, 0, 0, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- LOL_CD_FLAGS
- },
-
- {
- {
- "lol",
- "CD",
- {
- { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 },
- { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
- { 0, 0, 0, 0 }
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- LOL_CD_FLAGS
- },
-
- {
- {
- "lol",
- "CD",
- {
- { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 },
- { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
- { 0, 0, 0, 0 }
- },
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE | ADGF_CD,
- Common::GUIO_NONE
- },
- LOL_CD_FLAGS
- },
-
- {
- {
- "lol",
- 0,
- {
- { "WESTWOOD.1", 0, "c656aa9a2b4032d341e3dc8e3525b917", -1 },
- { 0, 0, 0, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- LOL_FLOPPY_CMP_FLAGS
- },
-
- {
- {
- "lol",
- 0,
- {
- { "WESTWOOD.1", 0, "3c61cb7de5b2ec452f5851f5075207ee", -1 },
- { 0, 0, 0, 0 }
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- LOL_FLOPPY_CMP_FLAGS
- },
-
- {
- {
- "lol",
- "Extracted",
- {
- { "GENERAL.PAK", 0, "2aaa30e120c08af87196820e9dd4bf73", -1 },
- { "CHAPTER7.PAK", 0, "eb92bf7ebb4e890add1233a6b0c810ff", -1 },
- { 0, 0, 0, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- LOL_FLOPPY_FLAGS
- },
-
- {
- {
- "lol",
- "Extracted",
- {
- { "GENERAL.PAK", 0, "996e66e81054d36249907a1d8158da3d", -1 },
- { "CHAPTER7.PAK", 0, "cabee57f00d6d84b65a732b6868a4959", -1 },
- { 0, 0, 0, 0 }
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- LOL_FLOPPY_FLAGS
- },
-
- {
- {
- "lol",
- 0,
- {
- { "GENERAL.PAK", 0, "3fe6539b9b09084c0984eaf7170464e9", -1 },
- { "MUS.PAK", 0, "008dc69d8cbcdb6bae30e270fab26e76", -1 },
- { 0, 0, 0, 0 }
- },
- Common::JA_JPN,
- Common::kPlatformPC98,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH
- },
- LOL_PC98_SJIS_FLAGS
- },
-
- {
- {
- "lol",
- "Demo",
- {
- { "INTRO.PAK", 0, "4bc22a3b57f19a49212c5de58ab014d6", -1 },
- { "INTROVOC.PAK", 0, "7e578e4f1da31c1f294e14a8e8f3cc44", -1 },
- { 0, 0, 0, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- LOL_DEMO_FLAGS
- },
-
- {
- {
- "lol",
- "Demo",
- {
- { "GENERAL.PAK", 0, "e94863d86c4597a2d581d05481c152ba", -1 },
- { 0, 0, 0, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DEMO,
- Common::GUIO_NOSPEECH
- },
- LOL_KYRA2_DEMO_FLAGS
- },
-#endif // ENABLE_LOL
-
- { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0) }
-};
-
-const PlainGameDescriptor gameList[] = {
- { "kyra1", "The Legend of Kyrandia" },
- { "kyra2", "The Legend of Kyrandia: The Hand of Fate" },
- { "kyra3", "The Legend of Kyrandia: Malcolm's Revenge" },
-#ifdef ENABLE_LOL
- { "lol", "Lands of Lore: The Throne of Chaos" },
-#endif // ENABLE_LOL
- { 0, 0 }
-};
+#include "kyra/detection_tables.h"
const ADParams detectionParams = {
// Pointer to ADGameDescription or its superset structure
@@ -1226,11 +61,13 @@ const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
-} // End of anonymous namespace
-
class KyraMetaEngine : public AdvancedMetaEngine {
public:
KyraMetaEngine() : AdvancedMetaEngine(detectionParams) {}
@@ -1268,7 +105,8 @@ bool Kyra::KyraEngine_v1::hasFeature(EngineFeature f) const {
return
(f == kSupportsRTL) ||
(f == kSupportsLoadingDuringRuntime) ||
- (f == kSupportsSavingDuringRuntime);
+ (f == kSupportsSavingDuringRuntime) ||
+ (f == kSupportsSubtitleOptions);
}
bool KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h
new file mode 100644
index 0000000000..8eabb15264
--- /dev/null
+++ b/engines/kyra/detection_tables.h
@@ -0,0 +1,1209 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+namespace {
+
+#define FLAGS(x, y, z, a, b, c, d, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
+#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
+
+#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA1)
+#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, Kyra::GI_KYRA1)
+
+#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA2)
+#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, false, Kyra::GI_KYRA2)
+
+#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, true, true, Kyra::GI_KYRA3)
+#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, true, false, Kyra::GI_KYRA3)
+#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, true, false, Kyra::GI_KYRA3)
+
+#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_LOL)
+#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, true, false, false, Kyra::GI_LOL)
+#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
+
+const KYRAGameDescription adGameDescs[] = {
+ /* disable these targets until they get supported
+ {
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("DISK1.EXE", "c8641d0414d6c966d0a3dad79db07bf4"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_FLOPPY_CMP_FLAGS
+ },
+
+ {
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("DISK1.EXE", "5d5cee4c3d0b68d586788b74243d254a"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_FLOPPY_CMP_FLAGS
+ },
+ */
+
+ {
+ {
+ "kyra1",
+ "Extracted",
+ AD_ENTRY1("GEMCUT.EMC", "3c244298395520bb62b5edfe41688879"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ "Extracted",
+ AD_ENTRY1("GEMCUT.EMC", "796e44863dd22fa635b042df1bf16673"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ "Extracted",
+ AD_ENTRY1("GEMCUT.EMC", "abf8eb360e79a6c2a837751fbd4d3d24"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ "Extracted",
+ AD_ENTRY1("GEMCUT.EMC", "6018e1dfeaca7fe83f8d0b00eb0dd049"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ { // from Arne.F
+ {
+ "kyra1",
+ "Extracted",
+ AD_ENTRY1("GEMCUT.EMC", "f0b276781f47c130f423ec9679fe9ed9"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ { // from VooD
+ {
+ "kyra1",
+ "Extracted",
+ AD_ENTRY1("GEMCUT.EMC", "8909b41596913b3f5deaf3c9f1017b01"),
+ Common::ES_ESP,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ { // floppy 1.8 from clemmy
+ {
+ "kyra1",
+ "Extracted",
+ AD_ENTRY1("GEMCUT.EMC", "747861d2a9c643c59fdab570df5b9093"),
+ Common::ES_ESP,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ { // from gourry
+ {
+ "kyra1",
+ "Extracted",
+ AD_ENTRY1("GEMCUT.EMC", "ef08c8c237ee1473fd52578303fc36df"),
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+
+ {
+ {
+ "kyra1",
+ 0,
+ {
+ { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 },
+ { "GEMCUT.EMC", 0, "2a3f44e179f1e9f7643e90083c747571", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH
+ },
+ KYRA1_AMIGA_FLAGS
+ },
+
+ {
+ {
+ "kyra1",
+ 0,
+ {
+ { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 },
+ { "GEMCUT.EMC", 0, "74f99e9ed99abf8d0429826d78485a2a", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH
+ },
+ KYRA1_AMIGA_FLAGS
+ },
+
+ {
+ {
+ "kyra1",
+ 0,
+ {
+ { "GEMCUT.EMC", 0, "796e44863dd22fa635b042df1bf16673", -1 },
+ { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIGM
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+
+ { // FM-TOWNS version
+ {
+ "kyra1",
+ 0,
+ {
+ { "EMC.PAK", 0, "a046bb0b422061aab8e4c4689400343a", -1 },
+ { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformFMTowns,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS
+ },
+ KYRA1_TOWNS_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ 0,
+ {
+ { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 },
+ { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::JA_JPN,
+ Common::kPlatformFMTowns,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS
+ },
+ KYRA1_TOWNS_SJIS_FLAGS
+ },
+
+ // PC-9801 floppy + CD / PC-9821 floppy version are all using the same data files,
+ // thus we will mark it as non CD game.
+ {
+ {
+ "kyra1",
+ "",
+ {
+ { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 },
+ { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::JA_JPN,
+ Common::kPlatformPC98,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98
+ },
+ KYRA1_TOWNS_SJIS_FLAGS
+ },
+
+ {
+ {
+ "kyra1",
+ "CD",
+ AD_ENTRY1("GEMCUT.PAK", "fac399fe62f98671e56a005c5e94e39f"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_CD_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ "CD",
+ AD_ENTRY1("GEMCUT.PAK", "230f54e6afc007ab4117159181a1c722"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_CD_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ "CD",
+ AD_ENTRY1("GEMCUT.PAK", "b037c41768b652a040360ffa3556fd2a"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_CD_FLAGS
+ },
+
+ { // italian fan translation see fr#1727941 "KYRA: add Italian CD Version to kyra.dat"
+ {
+ "kyra1",
+ "CD",
+ AD_ENTRY1("GEMCUT.PAK", "d8327fc4b7a72b23c900fa13aef4093a"),
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_CD_FLAGS
+ },
+
+ { // Kyra 1 Mac CD as mentioned in fr #2766454 "KYRA1: Add support for Macintosh CD" by nnooiissee
+ {
+ "kyra1",
+ "CD",
+ {
+ { "GEMCUT.PAK", 0, "d3d4b281cd357230aabcec46843d04bd", -1 },
+ { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_CD,
+ Common::GUIO_NONE
+ },
+ KYRA1_CD_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ "CD",
+ {
+ { "GEMCUT.PAK", 0, "4a0cb720e824295bcbccbd1407652110", -1 },
+ { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformMacintosh,
+ ADGF_CD,
+ Common::GUIO_NONE
+ },
+ KYRA1_CD_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ "CD",
+ {
+ { "GEMCUT.PAK", 0, "b71ee090aa12e80ed2ba068826d92bed", -1 },
+ { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::FR_FRA,
+ Common::kPlatformMacintosh,
+ ADGF_CD,
+ Common::GUIO_NONE
+ },
+ KYRA1_CD_FLAGS
+ },
+
+ {
+ {
+ "kyra1",
+ "Demo",
+ AD_ENTRY1("DEMO1.WSA", "fb722947d94897512b13b50cc84fd648"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DEMO,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_DEMO_FLAGS
+ },
+
+ { // Special Kyrandia 1 CD demo
+ {
+ "kyra1",
+ "Demo/CD",
+ AD_ENTRY1("INTRO.VRM", "e3045fb69b8c29db84b8fda3ccbdac54"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DEMO | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_DEMO_CD_FLAGS
+ },
+
+ { // Floppy version
+ {
+ "kyra2",
+ 0,
+ AD_ENTRY1("WESTWOOD.001", "3f52dda68c4f7696c8309038be9f4151"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_FLOPPY_CMP_FLAGS
+ },
+
+ { // Floppy version
+ {
+ "kyra2",
+ 0,
+ AD_ENTRY1("WESTWOOD.001", "d787b9559afddfe058b84c0b3a787224"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_FLOPPY_CMP_FLAGS
+ },
+
+ { // Floppy version extracted
+ {
+ "kyra2",
+ "Extracted",
+ AD_ENTRY1("FATE.PAK", "1ba18be685ad8e5a0ab5d46a0ce4d345"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_FLOPPY_FLAGS
+ },
+
+ { // Floppy version extracted
+ {
+ "kyra2",
+ "Extracted",
+ AD_ENTRY1("FATE.PAK", "262fb69dd8e52e596c7aefc6456f7c1b"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_FLOPPY_FLAGS
+ },
+
+ { // Floppy version extracted
+ {
+ "kyra2",
+ "Extracted",
+ AD_ENTRY1("FATE.PAK", "f7de11506b4c8fdf64bc763206c3e4e7"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_FLOPPY_FLAGS
+ },
+
+ { // Floppy version extracted
+ {
+ "kyra2",
+ "Extracted",
+ AD_ENTRY1("FATE.PAK", "e0a70c31b022cb4bb3061890020fc27c"),
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_FLOPPY_FLAGS
+ },
+
+ { // CD version
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_FLAGS
+ },
+ {
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_FLAGS
+ },
+ {
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_FLAGS
+ },
+
+ // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3"
+ { // CD version
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"),
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
+ },
+ {
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
+ },
+ {
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
+ },
+
+ {
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"),
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
+ },
+
+ {
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
+ },
+
+ {
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
+ },
+
+ { // Interactive Demo
+ {
+ "kyra2",
+ "CD/Demo",
+ AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_DEMO_FLAGS
+ },
+
+ { // Interactive Demo
+ {
+ "kyra2",
+ "CD/Demo",
+ AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_DEMO_FLAGS
+ },
+
+ { // Interactive Demo
+ {
+ "kyra2",
+ "CD/Demo",
+ AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_CD_DEMO_FLAGS
+ },
+
+ { // Non-Interactive Demos
+ {
+ "kyra2",
+ "Demo",
+ AD_ENTRY1("VOC.PAK", "ecb3561b63749158172bf21528cf5f45"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DEMO,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_DEMO_FLAGS
+ },
+
+ { // FM-TOWNS
+ {
+ "kyra2",
+ 0,
+ AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"),
+ Common::EN_ANY,
+ Common::kPlatformFMTowns,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS
+ },
+ KYRA2_TOWNS_FLAGS
+ },
+ {
+ {
+ "kyra2",
+ 0,
+ AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"),
+ Common::JA_JPN,
+ Common::kPlatformFMTowns,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS
+ },
+ KYRA2_TOWNS_SJIS_FLAGS
+ },
+ { // PC-9821
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"),
+ Common::EN_ANY,
+ Common::kPlatformPC98,
+ ADGF_CD,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98
+ },
+ KYRA2_TOWNS_FLAGS
+ },
+ {
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"),
+ Common::JA_JPN,
+ Common::kPlatformPC98,
+ ADGF_CD,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98
+ },
+ KYRA2_TOWNS_SJIS_FLAGS
+ },
+
+ // Kyra3
+
+ // non installed version
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "WESTWOOD.001", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_FLAGS
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "WESTWOOD.001", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_FLAGS
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "WESTWOOD.001", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_FLAGS
+ },
+
+ // installed version
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_INS_FLAGS
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_INS_FLAGS
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_INS_FLAGS
+ },
+
+ // Mac version
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_INS_FLAGS
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformMacintosh,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_INS_FLAGS
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::FR_FRA,
+ Common::kPlatformMacintosh,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_INS_FLAGS
+ },
+
+ // Spanish fan translation, see fr#1994040 "KYRA3: Add support for Spanish fan translation"
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::ES_ESP,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY)
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY)
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY)
+ },
+
+ // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3"
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA)
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA)
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ Common::GUIO_NOMIDI
+ },
+ KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA)
+ },
+
+#ifdef ENABLE_LOL
+ // Lands of Lore CD
+ {
+ {
+ "lol",
+ "CD",
+ {
+ { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 },
+ { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_CD_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ "CD",
+ {
+ { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 },
+ { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_CD_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ "CD",
+ {
+ { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 },
+ { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_CD_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ "CD",
+ {
+ { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 },
+ { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_CD_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ "CD",
+ {
+ { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 },
+ { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_CD_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ "CD",
+ {
+ { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 },
+ { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_CD_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ 0,
+ {
+ { "WESTWOOD.1", 0, "c656aa9a2b4032d341e3dc8e3525b917", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_FLOPPY_CMP_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ 0,
+ {
+ { "WESTWOOD.1", 0, "3c61cb7de5b2ec452f5851f5075207ee", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_FLOPPY_CMP_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ "Extracted",
+ {
+ { "GENERAL.PAK", 0, "2aaa30e120c08af87196820e9dd4bf73", -1 },
+ { "CHAPTER7.PAK", 0, "eb92bf7ebb4e890add1233a6b0c810ff", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_FLOPPY_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ "Extracted",
+ {
+ { "GENERAL.PAK", 0, "0f1fabc1f67b772a30d8e05ece720ac5", -1 },
+ { "CHAPTER7.PAK", 0, "482308aba1c40ee32449b91b0c63b990", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_FLOPPY_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ "Extracted",
+ {
+ { "GENERAL.PAK", 0, "996e66e81054d36249907a1d8158da3d", -1 },
+ { "CHAPTER7.PAK", 0, "cabee57f00d6d84b65a732b6868a4959", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_FLOPPY_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ 0,
+ {
+ { "GENERAL.PAK", 0, "3fe6539b9b09084c0984eaf7170464e9", -1 },
+ { "MUS.PAK", 0, "008dc69d8cbcdb6bae30e270fab26e76", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::JA_JPN,
+ Common::kPlatformPC98,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98
+ },
+ LOL_PC98_SJIS_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ "Demo",
+ {
+ { "INTRO.PAK", 0, "4bc22a3b57f19a49212c5de58ab014d6", -1 },
+ { "INTROVOC.PAK", 0, "7e578e4f1da31c1f294e14a8e8f3cc44", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DEMO,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_DEMO_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ "Demo",
+ {
+ { "GENERAL.PAK", 0, "e94863d86c4597a2d581d05481c152ba", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DEMO,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_KYRA2_DEMO_FLAGS
+ },
+#endif // ENABLE_LOL
+
+ { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0) }
+};
+
+const PlainGameDescriptor gameList[] = {
+ { "kyra1", "The Legend of Kyrandia" },
+ { "kyra2", "The Legend of Kyrandia: The Hand of Fate" },
+ { "kyra3", "The Legend of Kyrandia: Malcolm's Revenge" },
+#ifdef ENABLE_LOL
+ { "lol", "Lands of Lore: The Throne of Chaos" },
+#endif // ENABLE_LOL
+ { 0, 0 }
+};
+
+} // End of anonymous namespace
diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp
index c8b7e8ec4f..9a1d750391 100644
--- a/engines/kyra/gui_lok.cpp
+++ b/engines/kyra/gui_lok.cpp
@@ -579,7 +579,7 @@ void GUI_LoK::setupSavegames(Menu &menu, int num) {
for (int i = startSlot; i < num; ++i)
menu.item[i].enabled = 0;
- KyraEngine_v1::SaveHeader header;
+ KyraEngine_LoK::SaveHeader header;
for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); i++) {
if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header))) {
Common::strlcpy(savenames[i], header.description.c_str(), ARRAYSIZE(savenames[0]));
diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp
index ded1326110..2c86073892 100644
--- a/engines/kyra/gui_lol.cpp
+++ b/engines/kyra/gui_lol.cpp
@@ -2611,7 +2611,7 @@ void GUI_LoL::updateSavegameList() {
if (_savegameListSize) {
Common::sort(_saveSlots.begin(), _saveSlots.end(), Common::Greater<int>());
- KyraEngine_v1::SaveHeader header;
+ LoLEngine::SaveHeader header;
Common::InSaveFile *in;
_savegameList = new char *[_savegameListSize];
@@ -2658,7 +2658,7 @@ int GUI_LoL::getInput() {
if (_currentMenu == &_savenameMenu) {
_vm->updateInput();
- for (Common::List<KyraEngine_v1::Event>::const_iterator evt = _vm->_eventList.begin(); evt != _vm->_eventList.end(); ++evt) {
+ for (Common::List<LoLEngine::Event>::const_iterator evt = _vm->_eventList.begin(); evt != _vm->_eventList.end(); ++evt) {
if (evt->event.type == Common::EVENT_KEYDOWN)
_keyPressed = evt->event.kbd;
}
diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp
index de19228d16..fe4b54d09b 100644
--- a/engines/kyra/gui_v2.cpp
+++ b/engines/kyra/gui_v2.cpp
@@ -452,7 +452,7 @@ void GUI_v2::setupSavegameNames(Menu &menu, int num) {
if (_isSaveMenu && _savegameOffset == 0)
startSlot = 1;
- KyraEngine_v1::SaveHeader header;
+ KyraEngine_v2::SaveHeader header;
Common::InSaveFile *in;
for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); ++i) {
if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header)) != 0) {
diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp
index 2716f0b285..0fafaa15ce 100644
--- a/engines/kyra/kyra_hof.cpp
+++ b/engines/kyra/kyra_hof.cpp
@@ -679,7 +679,7 @@ void KyraEngine_HoF::updateWithText() {
restorePage3();
drawAnimObjects();
- if (textEnabled() && _chatText) {
+ if (_chatTextEnabled && _chatText) {
int pageBackUp = _screen->_curPage;
_screen->_curPage = 2;
objectChatPrintText(_chatText, _chatObject);
@@ -1996,9 +1996,10 @@ void KyraEngine_HoF::writeSettings() {
}
void KyraEngine_HoF::readSettings() {
+ KyraEngine_v2::readSettings();
+
int talkspeed = ConfMan.getInt("talkspeed");
_configTextspeed = (talkspeed*95)/255 + 2;
- KyraEngine_v1::readSettings();
}
} // End of namespace Kyra
diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp
index cf61b58326..159230e928 100644
--- a/engines/kyra/kyra_lok.cpp
+++ b/engines/kyra/kyra_lok.cpp
@@ -234,6 +234,7 @@ Common::Error KyraEngine_LoK::init() {
_talkingCharNum = -1;
_charSayUnk3 = -1;
+ _disabledTalkAnimObject = _enabledTalkAnimObject = 0;
memset(_currSentenceColor, 0, 3);
_startSentencePalIndex = -1;
_fadeText = false;
diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h
index c0c9bf06c4..50f36d7b71 100644
--- a/engines/kyra/kyra_lok.h
+++ b/engines/kyra/kyra_lok.h
@@ -132,7 +132,7 @@ public:
int _paletteChanged;
int16 _northExitHeight;
- typedef void (KyraEngine_LoK::*IntroProc)();
+ typedef bool (KyraEngine_LoK::*IntroProc)();
// static data access
const char * const *seqWSATable() { return _seq_WSATable; }
@@ -157,11 +157,12 @@ protected:
// -> intro
void seq_intro();
- void seq_introLogos();
- void seq_introStory();
- void seq_introMalcolmTree();
- void seq_introKallakWriting();
- void seq_introKallakMalcolm();
+ bool seq_introPublisherLogos();
+ bool seq_introLogos();
+ bool seq_introStory();
+ bool seq_introMalcolmTree();
+ bool seq_introKallakWriting();
+ bool seq_introKallakMalcolm();
// -> ingame animations
void seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly);
@@ -318,7 +319,7 @@ protected:
// chat
// -> process
void characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration);
- void waitForChatToFinish(int vocFile, int16 chatDuration, const char *str, uint8 charNum);
+ void waitForChatToFinish(int vocFile, int16 chatDuration, const char *str, uint8 charNum, const bool printText);
// -> initialization
int initCharacterChat(int8 charNum);
@@ -373,20 +374,24 @@ protected:
//void setTimer19();
void setupTimers();
void timerUpdateHeadAnims(int timerNum);
- void timerSetFlags1(int timerNum);
- void timerSetFlags2(int timerNum);
- void timerSetFlags3(int timerNum);
- void timerCheckAnimFlag1(int timerNum);
- void timerCheckAnimFlag2(int timerNum);
+ void timerTulipCreator(int timerNum);
+ void timerRubyCreator(int timerNum);
+ void timerAsInvisibleTimeout(int timerNum);
+ void timerAsWillowispTimeout(int timerNum);
void checkAmuletAnimFlags();
void timerRedrawAmulet(int timerNum);
+ void timerLavenderRoseCreator(int timerNum);
+ void timerAcornCreator(int timerNum);
+ void timerBlueberryCreator(int timerNum);
void timerFadeText(int timerNum);
- void updateAnimFlag1(int timerNum);
- void updateAnimFlag2(int timerNum);
+ void timerWillowispFrameTimer(int timerNum);
+ void timerInvisibleFrameTimer(int timerNum);
void drawAmulet();
void setTextFadeTimerCountdown(int16 countdown);
void setWalkspeed(uint8 newSpeed);
+ void setItemCreationFlags(int offset, int count);
+
int buttonInventoryCallback(Button *caller);
int buttonAmuletCallback(Button *caller);
@@ -472,6 +477,8 @@ protected:
int8 _charSayUnk2;
int8 _charSayUnk3;
int8 _currHeadShape;
+ int8 _disabledTalkAnimObject;
+ int8 _enabledTalkAnimObject;
uint8 _currSentenceColor[3];
int8 _startSentencePalIndex;
bool _fadeText;
diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp
index cf90c73dbd..2169e5283f 100644
--- a/engines/kyra/kyra_mr.cpp
+++ b/engines/kyra/kyra_mr.cpp
@@ -369,9 +369,7 @@ void KyraEngine_MR::playVQA(const char *name) {
VQAMovie vqa(this, _system);
char filename[20];
- int size = 0; // TODO: Movie size is 0, 1 or 2.
-
- snprintf(filename, sizeof(filename), "%s%d.VQA", name, size);
+ snprintf(filename, sizeof(filename), "%s%d.VQA", name, _configVQAQuality);
if (vqa.open(filename)) {
for (int i = 0; i < 4; ++i) {
@@ -1129,7 +1127,7 @@ void KyraEngine_MR::updateWithText() {
restorePage3();
drawAnimObjects();
- if (textEnabled() && _chatText) {
+ if (_chatTextEnabled && _chatText) {
int curPage = _screen->_curPage;
_screen->_curPage = 2;
objectChatPrintText(_chatText, _chatObject);
@@ -1460,6 +1458,8 @@ void KyraEngine_MR::registerDefaultSettings() {
ConfMan.registerDefault("studio_audience", true);
ConfMan.registerDefault("skip_support", true);
ConfMan.registerDefault("helium_mode", false);
+ // 0 - best, 1 - mid, 2 - low
+ ConfMan.registerDefault("video_quality", 0);
}
void KyraEngine_MR::writeSettings() {
@@ -1490,11 +1490,12 @@ void KyraEngine_MR::writeSettings() {
}
void KyraEngine_MR::readSettings() {
- KyraEngine_v1::readSettings();
+ KyraEngine_v2::readSettings();
_configStudio = ConfMan.getBool("studio_audience");
_configSkip = ConfMan.getBool("skip_support");
_configHelium = ConfMan.getBool("helium_mode");
+ _configVQAQuality = CLIP(ConfMan.getInt("video_quality"), 0, 2);
}
} // End of namespace Kyra
diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h
index 773b0a1699..36b937f2a8 100644
--- a/engines/kyra/kyra_mr.h
+++ b/engines/kyra/kyra_mr.h
@@ -73,6 +73,7 @@ private:
bool _configStudio;
bool _configSkip;
bool _configHelium;
+ int _configVQAQuality;
void registerDefaultSettings();
void writeSettings();
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index 00b32425c2..1c27716a67 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -100,13 +100,14 @@ void KyraEngine_v1::pauseEngineIntern(bool pause) {
Common::Error KyraEngine_v1::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"));
+ syncSoundSettings();
if (!_flags.useDigSound) {
- // We prefer AdLib over MIDI, since generally AdLib is better supported
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_MIDI | MDT_ADLIB);
+ // We prefer AdLib over MIDI in Kyra 1, since it offers MT-32 support only, most users don't have a real
+ // MT-32/LAPC1/CM32L/CM64 device and AdLib sounds better than our incomplete MT-32 emulator and also better than
+ // MT-32/GM mapping. For Kyra 2 and LoL which have real GM tracks which sound better than AdLib tracks we prefer GM
+ // since most users have a GM compatible device.
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB | ((_flags.gameID == GI_KYRA2 || _flags.gameID == GI_LOL) ? MDT_PREFER_GM : 0));
if (_flags.platform == Common::kPlatformFMTowns) {
if (_flags.gameID == GI_KYRA1)
@@ -120,24 +121,24 @@ Common::Error KyraEngine_v1::init() {
_sound = new SoundTownsPC98_v2(this, _mixer);
} else if (_flags.platform == Common::kPlatformAmiga) {
_sound = new SoundAmiga(this, _mixer);
- } else if (midiDriver == MD_ADLIB) {
+ } else if (MidiDriver::getMusicType(dev) == MT_ADLIB) {
_sound = new SoundAdLibPC(this, _mixer);
} else {
Sound::kType type;
- if (midiDriver == MD_PCSPK)
+ if (MidiDriver::getMusicType(dev) == MT_PCSPK)
type = Sound::kPCSpkr;
- else if (midiDriver == MD_MT32 || ConfMan.getBool("native_mt32"))
+ else if (MidiDriver::getMusicType(dev) == MT_MT32 || ConfMan.getBool("native_mt32"))
type = Sound::kMidiMT32;
else
type = Sound::kMidiGM;
MidiDriver *driver = 0;
- if (midiDriver == MD_PCSPK) {
+ if (MidiDriver::getMusicType(dev) == MT_PCSPK) {
driver = new MidiDriver_PCSpeaker(_mixer);
} else {
- driver = MidiDriver::createMidi(midiDriver);
+ driver = MidiDriver::createMidi(dev);
if (type == Sound::kMidiMT32)
driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
}
@@ -256,7 +257,7 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag)
int keys = 0;
int8 mouseWheel = 0;
- while (_eventList.size()) {
+ while (!_eventList.empty()) {
Common::Event event = *_eventList.begin();
bool breakLoop = false;
@@ -280,6 +281,7 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag)
if (event.kbd.keycode == Common::KEYCODE_d) {
if (_debugger)
_debugger->attach();
+ breakLoop = true;
} else if (event.kbd.keycode == Common::KEYCODE_q) {
quitGame();
}
@@ -333,7 +335,7 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag)
break;
}
- if (_debugger && _debugger->isAttached())
+ if (_debugger)
_debugger->onFrame();
if (breakLoop)
@@ -623,6 +625,10 @@ uint8 KyraEngine_v1::getVolume(kVolumeEntry vol) {
void KyraEngine_v1::syncSoundSettings() {
Engine::syncSoundSettings();
+ // We need to use this here to allow the subtitle options to be changed
+ // through the GMM's options dialog.
+ readSettings();
+
if (_sound)
_sound->updateVolumeSettings();
}
diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp
index 34284a8e20..53c57c21cd 100644
--- a/engines/kyra/kyra_v2.cpp
+++ b/engines/kyra/kyra_v2.cpp
@@ -63,6 +63,7 @@ KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags, const Engi
_chatVocLow = -1;
_chatText = 0;
_chatObject = -1;
+ _chatTextEnabled = false;
memset(_hiddenItems, -1, sizeof(_hiddenItems));
diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h
index 6aaa8c3687..6414040344 100644
--- a/engines/kyra/kyra_v2.h
+++ b/engines/kyra/kyra_v2.h
@@ -350,6 +350,7 @@ protected:
int _chatObject;
uint32 _chatEndTime;
int _chatVocHigh, _chatVocLow;
+ bool _chatTextEnabled;
EMCData _chatScriptData;
EMCState _chatScriptState;
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 5a066e5d0c..03d52ec4ac 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -810,8 +810,8 @@ void LoLEngine::startup() {
pal.fill(0, 1, 0x3F);
pal.fill(2, 126, 0x3F);
pal.fill(192, 4, 0x3F);
- _screen->generateOverlay(pal, _screen->_paletteOverlay1, 1, 96);
- _screen->generateOverlay(pal, _screen->_paletteOverlay2, 144, 65);
+ _screen->generateOverlay(pal, _screen->_paletteOverlay1, 1, 96, 254);
+ _screen->generateOverlay(pal, _screen->_paletteOverlay2, 144, 65, 254);
_screen->copyPalette(0, 1);
}
@@ -4291,7 +4291,7 @@ void LoLEngine::drawMapPage(int pageNum) {
if (!_defaultLegendData[ii].enable)
continue;
_screen->copyBlockAndApplyOverlay(_screen->_curPage, 235, (tY << 3) + 21 + yOffset, _screen->_curPage, 235 + xOffset, (tY << 3) + 21 + yOffset, 7, 6, 0, _mapOverlay);
- _screen->drawShape(_screen->_curPage, _automapShapes[_defaultLegendData[ii].shapeIndex << 2], 232 + xOffset, (tY << 3) + 18 + yOffset + _defaultLegendData[ii].x, 0, 0);
+ _screen->drawShape(_screen->_curPage, _automapShapes[_defaultLegendData[ii].shapeIndex << 2], 232 + xOffset, (tY << 3) + 18 + yOffset + _defaultLegendData[ii].y, 0, 0);
printMapText(_defaultLegendData[ii].stringId, 244 + xOffset, (tY << 3) + 22 + yOffset);
tY++;
}
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index b5a657ac15..57c127a94f 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -256,7 +256,7 @@ struct LevelTempData {
struct MapLegendData {
uint8 shapeIndex;
bool enable;
- int8 x;
+ int8 y;
uint16 stringId;
};
diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk
index b9006431d7..4708041cf7 100644
--- a/engines/kyra/module.mk
+++ b/engines/kyra/module.mk
@@ -84,6 +84,7 @@ MODULE_OBJS += \
sequences_lol.o \
sound_lol.o \
sprites_lol.o \
+ staticres_lol.o \
text_lol.o \
timer_lol.o
endif
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 7983be9a68..d572c1ac54 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -209,6 +209,7 @@ enum KyraResources {
k1CreditsStrings,
+ k1TownsMusicFadeTable,
k1TownsSFXwdTable,
k1TownsSFXbtTable,
k1TownsCDATable,
diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp
index 959d89f0ad..56e1c73d0a 100644
--- a/engines/kyra/saveload.cpp
+++ b/engines/kyra/saveload.cpp
@@ -122,7 +122,7 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
header.thumbnail = 0;
}
} else {
- Graphics::skipThumbnailHeader(*in);
+ Graphics::skipThumbnail(*in);
}
}
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
index ddc6e41bec..bf3320486a 100644
--- a/engines/kyra/scene_lol.cpp
+++ b/engines/kyra/scene_lol.cpp
@@ -468,7 +468,7 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight
for (int i = 0; i < 7; i++) {
weight = 100 - (i * _lastSpecialColorWeight);
weight = (weight > 0) ? (weight * 255) / 100 : 0;
- _screen->generateLevelOverlay(tpal, _screen->getLevelOverlay(i), _lastSpecialColor, weight);
+ _screen->generateOverlay(tpal, _screen->getLevelOverlay(i), _lastSpecialColor, weight);
int l = _flags.use16ColorMode ? 256 : 128;
uint8 *levelOverlay = _screen->getLevelOverlay(i);
diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp
index 875200895a..bd0a1fe544 100644
--- a/engines/kyra/scene_mr.cpp
+++ b/engines/kyra/scene_mr.cpp
@@ -79,11 +79,9 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
musicUpdate(0);
uint32 waitUntilTimer = 0;
- bool newSoundFile = false;
if (_lastMusicCommand != _sceneList[sceneId].sound) {
fadeOutMusic(60);
waitUntilTimer = _system->getMillis() + 60 * _tickLength;
- newSoundFile = true;
}
_chatAltFlag = false;
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 7f3959d5fe..ade9886c2e 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -611,14 +611,6 @@ void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upF
_vm->delay((delayAcc >> 8) * 1000 / 60);
delayAcc &= 0xFF;
}
-
- if (_vm->shouldQuit()) {
- setScreenPalette(pal);
- if (upFunc && upFunc->isValid())
- (*upFunc)();
- else
- _system->updateScreen();
- }
}
void Screen::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) {
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index e350d2c977..be3dbe5b21 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -183,68 +183,6 @@ void Screen_LoL::generateGrayOverlay(const Palette &srcPal, uint8 *grayOverlay,
grayOverlay[i] = findLeastDifferentColor(tmpPal.getData() + 3 * i, srcPal, 0, lastColor, skipSpecialColors);
}
-uint8 *Screen_LoL::generateLevelOverlay(const Palette &srcPal, uint8 *ovl, int opColor, int weight) {
- if (!ovl)
- return ovl;
-
- if (weight > 255)
- weight = 255;
-
- const uint8 *srt = srcPal.getData();
-
- uint16 r = srt[opColor * 3];
- uint16 g = srt[opColor * 3 + 1];
- uint16 b = srt[opColor * 3 + 2];
-
- uint8 *d = ovl;
- *d++ = 0;
-
- for (int i = 1; i != 256; i++) {
- uint16 a = srt[i * 3];
- uint8 dr = a - ((((a - r) * (weight >> 1)) << 1) >> 8);
- a = srt[i * 3 + 1];
- uint8 dg = a - ((((a - g) * (weight >> 1)) << 1) >> 8);
- a = srt[i * 3 + 2];
- uint8 db = a - ((((a - b) * (weight >> 1)) << 1) >> 8);
-
- int l = opColor;
- int m = _use16ColorMode ? 0xffff : 0x7fff;
- int ii = _use16ColorMode ? 255 : 127;
- int x = 1;
- const uint8 *s = srt + 3;
-
- do {
- if (!_use16ColorMode && i == x) {
- s += 3;
- } else {
- int t = *s++ - dr;
- int c = t * t;
- t = *s++ - dg;
- c += (t * t);
- t = *s++ - db;
- c += (t * t);
-
- if (!c) {
- l = x;
- break;
- }
-
- if (c <= m) {
- if (!_use16ColorMode || (x == opColor || i != x)) {
- m = c;
- l = x;
- }
- }
- }
- x++;
- } while (--ii);
-
- *d++ = l & 0xff;
- }
-
- return ovl;
-}
-
void Screen_LoL::createTransparencyTablesIntern(const uint8 *ovl, int a, const uint8 *fxPal1, const uint8 *fxPal2, uint8 *outTable1, uint8 *outTable2, int b) {
Palette screenPal(256);
screenPal.copy(fxPal2, 0, 256);
diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h
index cdd18f98f6..52e66df1ec 100644
--- a/engines/kyra/screen_lol.h
+++ b/engines/kyra/screen_lol.h
@@ -79,7 +79,6 @@ public:
Palette **generateFadeTable(Palette **dst, Palette *src1, Palette *src2, int numTabs);
void generateGrayOverlay(const Palette &Pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors);
- uint8 *generateLevelOverlay(const Palette &Pal, uint8 *ovl, int opColor, int weight);
uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; }
void createTransparencyTablesIntern(const uint8 *ovl, int a, const uint8 *fxPal1, const uint8 *fxPal2, uint8 *outTable1, uint8 *outTable2, int b);
diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp
index 919b9086f3..3907f844cb 100644
--- a/engines/kyra/screen_v2.cpp
+++ b/engines/kyra/screen_v2.cpp
@@ -38,38 +38,67 @@ Screen_v2::~Screen_v2() {
delete[] _wsaFrameAnimBuffer;
}
-uint8 *Screen_v2::generateOverlay(const Palette &pal, uint8 *buffer, int startColor, uint16 factor) {
+uint8 *Screen_v2::generateOverlay(const Palette &pal, uint8 *buffer, int opColor, uint weight, int maxColor) {
if (!buffer)
return buffer;
- factor = MIN<uint16>(255, factor);
- factor >>= 1;
- factor &= 0xFF;
+ weight = MIN<uint>(weight, 255) >> 1;
- const byte col1 = pal[startColor * 3 + 0];
- const byte col2 = pal[startColor * 3 + 1];
- const byte col3 = pal[startColor * 3 + 2];
+ const byte opR = pal[opColor * 3 + 0];
+ const byte opG = pal[opColor * 3 + 1];
+ const byte opB = pal[opColor * 3 + 2];
uint8 *dst = buffer;
*dst++ = 0;
- for (int i = 1; i != 255; ++i) {
- uint8 processedPalette[3];
- byte col;
+ int maxIndex = maxColor;
+ if (maxIndex == -1) {
+ if (_vm->gameFlags().gameID == GI_LOL) {
+ if (_use16ColorMode)
+ maxIndex = 255;
+ else
+ maxIndex = 127;
+ } else {
+ maxIndex = 255;
+ }
+ }
+
+ for (int i = 1; i != 256; ++i) {
+ const byte curR = pal[i * 3 + 0] - ((((pal[i * 3 + 0] - opR) * weight) >> 7) & 0x7F);
+ const byte curG = pal[i * 3 + 1] - ((((pal[i * 3 + 1] - opG) * weight) >> 7) & 0x7F);
+ const byte curB = pal[i * 3 + 2] - ((((pal[i * 3 + 2] - opB) * weight) >> 7) & 0x7F);
+
+ uint16 idxSum = _use16ColorMode ? 0xFFFF : 0x7FFF;
+ byte index = opColor;
+
+ for (int curIdx = 1; curIdx <= maxIndex; ++curIdx) {
+ if (!_use16ColorMode && i == curIdx)
+ continue;
- col = pal[i * 3 + 0];
- col -= ((((col - col1) * factor) << 1) >> 8) & 0xFF;
- processedPalette[0] = col;
+ int diff = 0;
+ uint16 sum = 0;
- col = pal[i * 3 + 1];
- col -= ((((col - col2) * factor) << 1) >> 8) & 0xFF;
- processedPalette[1] = col;
+ diff = pal[curIdx * 3 + 0] - curR;
+ sum += diff * diff;
+ diff = pal[curIdx * 3 + 1] - curG;
+ sum += diff * diff;
+ diff = pal[curIdx * 3 + 2] - curB;
+ sum += diff * diff;
- col = pal[i * 3 + 2];
- col -= ((((col - col3) * factor) << 1) >> 8) & 0xFF;
- processedPalette[2] = col;
+ if (!sum) {
+ index = curIdx;
+ break;
+ }
+
+ if (sum <= idxSum) {
+ if (!_use16ColorMode || (curIdx == opColor || curIdx != i)) {
+ idxSum = sum;
+ index = curIdx;
+ }
+ }
+ }
- *dst++ = findLeastDifferentColor(processedPalette, pal, 1, 255) + 1;
+ *dst++ = index;
}
return buffer;
diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h
index 7be68e7b6d..92aeb3525d 100644
--- a/engines/kyra/screen_v2.h
+++ b/engines/kyra/screen_v2.h
@@ -40,7 +40,7 @@ public:
void checkedPageUpdate(int srcPage, int dstPage);
// palette handling
- uint8 *generateOverlay(const Palette &pal, uint8 *buffer, int color, uint16 factor);
+ uint8 *generateOverlay(const Palette &pal, uint8 *buffer, int color, uint weight, int maxColor = -1);
void applyOverlay(int x, int y, int w, int h, int pageNum, const uint8 *overlay);
int findLeastDifferentColor(const uint8 *paletteEntry, const Palette &pal, uint8 firstColor, uint16 numColors, bool skipSpecialColors = false);
diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp
index 4ec6e7f349..20bc8abec5 100644
--- a/engines/kyra/script_tim.cpp
+++ b/engines/kyra/script_tim.cpp
@@ -159,7 +159,7 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpc
_tim->opcodes = opcodes;
IFFParser iff(*stream);
- Common::Functor1Mem< Common::IFFChunk &, bool, TIMInterpreter > c(this, &TIMInterpreter::callback);
+ Common::Functor1Mem<Common::IFFChunk &, bool, TIMInterpreter> c(this, &TIMInterpreter::callback);
iff.parse(c);
if (!_tim->avtl)
@@ -170,7 +170,7 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpc
delete stream;
- int num = (_avtlChunkSize < TIM::kCountFuncs) ? _avtlChunkSize : (int)TIM::kCountFuncs;
+ const int num = (_avtlChunkSize < TIM::kCountFuncs) ? _avtlChunkSize : (int)TIM::kCountFuncs;
for (int i = 0; i < num; ++i)
_tim->func[i].avtl = _tim->avtl + _tim->avtl[i];
diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp
index 78e8ded9f7..c4bdc29f57 100644
--- a/engines/kyra/sequences_lok.cpp
+++ b/engines/kyra/sequences_lok.cpp
@@ -93,6 +93,7 @@ void KyraEngine_LoK::seq_intro() {
_res->loadPakFile("INTRO.VRM");
static const IntroProc introProcTable[] = {
+ &KyraEngine_LoK::seq_introPublisherLogos,
&KyraEngine_LoK::seq_introLogos,
&KyraEngine_LoK::seq_introStory,
&KyraEngine_LoK::seq_introMalcolmTree,
@@ -114,8 +115,13 @@ void KyraEngine_LoK::seq_intro() {
snd_playTheme(0, 2);
_text->setTalkCoords(144);
- for (int i = 0; i < ARRAYSIZE(introProcTable) && !seq_skipSequence(); ++i)
- (this->*introProcTable[i])();
+ for (int i = 0; i < ARRAYSIZE(introProcTable) && !seq_skipSequence(); ++i) {
+ if ((this->*introProcTable[i])() && !shouldQuit()) {
+ resetSkipFlag();
+ _screen->fadeToBlack();
+ _screen->clearPage(0);
+ }
+ }
_text->setTalkCoords(136);
delay(30 * _tickLength);
@@ -127,18 +133,32 @@ void KyraEngine_LoK::seq_intro() {
_res->unloadPakFile("INTRO.VRM");
}
-void KyraEngine_LoK::seq_introLogos() {
+bool KyraEngine_LoK::seq_introPublisherLogos() {
if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
_screen->loadBitmap("LOGO.CPS", 3, 3, &_screen->getPalette(0));
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
_screen->updateScreen();
_screen->fadeFromBlack();
delay(90 * _tickLength);
- _screen->fadeToBlack();
- if (!_abortIntroFlag)
+ if (!_abortIntroFlag) {
+ _screen->fadeToBlack();
snd_playWanderScoreViaMap(_flags.platform == Common::kPlatformFMTowns ? 57 : 2, 0);
+ }
+ } else if (_flags.platform == Common::kPlatformMacintosh && _res->exists("MP_GOLD.CPS")) {
+ _screen->loadPalette("MP_GOLD.COL", _screen->getPalette(0));
+ _screen->loadBitmap("MP_GOLD.CPS", 3, 3, 0);
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
+ _screen->updateScreen();
+ _screen->fadeFromBlack();
+ delay(120 * _tickLength);
+ if (!_abortIntroFlag)
+ _screen->fadeToBlack();
}
+ return _abortIntroFlag;
+}
+
+bool KyraEngine_LoK::seq_introLogos() {
_screen->clearPage(0);
if (_flags.platform == Common::kPlatformAmiga) {
@@ -159,11 +179,8 @@ void KyraEngine_LoK::seq_introLogos() {
_screen->updateScreen();
_screen->fadeFromBlack();
- if (_seq->playSequence(_seq_WestwoodLogo, skipFlag()) || shouldQuit()) {
- _screen->fadeToBlack();
- _screen->clearPage(0);
- return;
- }
+ if (_seq->playSequence(_seq_WestwoodLogo, skipFlag()) || shouldQuit())
+ return true;
delay(60 * _tickLength);
@@ -174,16 +191,14 @@ void KyraEngine_LoK::seq_introLogos() {
Screen::FontId of = _screen->setFont(Screen::FID_8_FNT);
- if ((_seq->playSequence(_seq_KyrandiaLogo, skipFlag()) && !seq_skipSequence()) || shouldQuit()) {
- _screen->fadeToBlack();
- _screen->clearPage(0);
- return;
- }
+ if (_seq->playSequence(_seq_KyrandiaLogo, skipFlag()) || shouldQuit())
+ return true;
+
_screen->setFont(of);
_screen->fillRect(0, 179, 319, 199, 0);
if (shouldQuit())
- return;
+ return false;
if (_flags.platform == Common::kPlatformAmiga) {
_screen->copyPalette(0, 2);
@@ -225,20 +240,20 @@ void KyraEngine_LoK::seq_introLogos() {
} while (!doneFlag && !shouldQuit() && !_abortIntroFlag);
}
- if (shouldQuit())
- return;
+ if (_abortIntroFlag || shouldQuit())
+ return true;
- _seq->playSequence(_seq_Forest, true);
+ return _seq->playSequence(_seq_Forest, true);
}
-void KyraEngine_LoK::seq_introStory() {
+bool KyraEngine_LoK::seq_introStory() {
_screen->clearPage(3);
_screen->clearPage(0);
// HACK: The Italian fan translation uses an special text screen here
// so we show it even when text is disabled
if (!textEnabled() && speechEnabled() && _flags.lang != Common::IT_ITA)
- return;
+ return false;
if ((_flags.lang == Common::EN_ANY && !_flags.isTalkie && _flags.platform == Common::kPlatformPC) || _flags.platform == Common::kPlatformAmiga)
_screen->loadBitmap("TEXT.CPS", 3, 3, &_screen->getPalette(0));
@@ -292,25 +307,30 @@ void KyraEngine_LoK::seq_introStory() {
_screen->updateScreen();
delay(360 * _tickLength);
+
+ return _abortIntroFlag;
}
-void KyraEngine_LoK::seq_introMalcolmTree() {
+bool KyraEngine_LoK::seq_introMalcolmTree() {
_screen->_curPage = 0;
_screen->clearPage(3);
- _seq->playSequence(_seq_MalcolmTree, true);
+ return _seq->playSequence(_seq_MalcolmTree, true);
}
-void KyraEngine_LoK::seq_introKallakWriting() {
+bool KyraEngine_LoK::seq_introKallakWriting() {
_seq->makeHandShapes();
_screen->setAnimBlockPtr(5060);
_screen->_charWidth = -2;
_screen->clearPage(3);
- _seq->playSequence(_seq_KallakWriting, true);
+ const bool skipped = _seq->playSequence(_seq_KallakWriting, true);
+ _seq->freeHandShapes();
+
+ return skipped;
}
-void KyraEngine_LoK::seq_introKallakMalcolm() {
+bool KyraEngine_LoK::seq_introKallakMalcolm() {
_screen->clearPage(3);
- _seq->playSequence(_seq_KallakMalcolm, true);
+ return _seq->playSequence(_seq_KallakMalcolm, true);
}
void KyraEngine_LoK::seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly) {
diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h
index f4aab4db29..f8738bc791 100644
--- a/engines/kyra/sound_intern.h
+++ b/engines/kyra/sound_intern.h
@@ -31,7 +31,9 @@
#include "common/mutex.h"
-#include "sound/softsynth/ym2612.h"
+#include "sound/softsynth/fmtowns_pc98/towns_pc98_driver.h"
+#include "sound/softsynth/fmtowns_pc98/towns_euphony.h"
+
#include "sound/softsynth/emumidi.h"
#include "sound/midiparser.h"
@@ -99,10 +101,7 @@ private:
Common::Mutex _mutex;
};
-class Towns_EuphonyDriver;
-class TownsPC98_OpnDriver;
-
-class SoundTowns : public MidiDriver, public Sound {
+class SoundTowns : public Sound {
public:
SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer);
~SoundTowns();
@@ -119,43 +118,35 @@ public:
void haltTrack();
void playSoundEffect(uint8);
+ void stopAllSoundEffects();
void beginFadeOut();
- //MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
- void metaEvent(byte type, byte *data, uint16 length) {}
-
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo();
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- static float calculatePhaseStep(int8 semiTone, int8 semiToneRootkey,
- uint32 sampleRate, uint32 outputRate, int32 pitchWheel);
+ void updateVolumeSettings();
private:
bool loadInstruments();
void playEuphonyTrack(uint32 offset, int loop);
- static void onTimer(void *data);
+ void fadeOutSoundEffects();
int _lastTrack;
Audio::AudioStream *_currentSFX;
Audio::SoundHandle _sfxHandle;
+ uint8 *_musicTrackData;
+
uint _sfxFileIndex;
uint8 *_sfxFileData;
+ uint8 _sfxChannel;
- Towns_EuphonyDriver * _driver;
- MidiParser * _parser;
-
+ TownsEuphonyDriver *_driver;
+
Common::Mutex _mutex;
+ bool _cdaPlaying;
+
+ const uint8 *_musicFadeTable;
const uint8 *_sfxBTTable;
const uint8 *_sfxWDTable;
};
@@ -180,11 +171,13 @@ public:
int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx) { return -1; }
void playSoundEffect(uint8);
+ void updateVolumeSettings();
+
protected:
int _lastTrack;
uint8 *_musicTrackData;
uint8 *_sfxTrackData;
- TownsPC98_OpnDriver *_driver;
+ TownsPC98_AudioDriver *_driver;
};
class SoundTownsPC98_v2 : public Sound {
@@ -207,6 +200,8 @@ public:
int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx);
void playSoundEffect(uint8 track);
+ void updateVolumeSettings();
+
protected:
Audio::AudioStream *_currentSFX;
int _lastTrack;
@@ -214,7 +209,7 @@ protected:
uint8 *_musicTrackData;
uint8 *_sfxTrackData;
- TownsPC98_OpnDriver *_driver;
+ TownsPC98_AudioDriver *_driver;
};
// PC Speaker MIDI driver
diff --git a/engines/kyra/sound_lok.cpp b/engines/kyra/sound_lok.cpp
index 1d0b334a09..40daa0b5bd 100644
--- a/engines/kyra/sound_lok.cpp
+++ b/engines/kyra/sound_lok.cpp
@@ -49,16 +49,14 @@ void KyraEngine_LoK::snd_playWanderScoreViaMap(int command, int restart) {
_lastMusicCommand = -1;
if (_flags.platform == Common::kPlatformFMTowns) {
- if (command == 1) {
- _sound->beginFadeOut();
- } else if (command >= 35 && command <= 38) {
+ if (command >= 35 && command <= 38) {
snd_playSoundEffect(command - 20);
} else if (command >= 2) {
if (_lastMusicCommand != command)
// the original does -2 here we handle this inside _sound->playTrack()
_sound->playTrack(command);
} else {
- _sound->haltTrack();
+ _sound->beginFadeOut();
}
_lastMusicCommand = command;
} else if (_flags.platform == Common::kPlatformPC98) {
diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp
index 1bcb77c89d..c233987120 100644
--- a/engines/kyra/sound_lol.cpp
+++ b/engines/kyra/sound_lol.cpp
@@ -225,7 +225,7 @@ void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
for (int i = 3; i > 0; i--) {
int dir = calcMonsterDirection(cbl & 0x1f, cbl >> 5, block & 0x1f, block >> 5);
- cbl += blockShiftTable[dir];
+ cbl = (cbl + blockShiftTable[dir]) & 0x3ff;
if (cbl != block) {
if (testWallFlag(cbl, 0, 1))
_environmentSfxVol >>= 1;
diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp
index 7eb151a64d..026c72de26 100644
--- a/engines/kyra/sound_midi.cpp
+++ b/engines/kyra/sound_midi.cpp
@@ -573,8 +573,12 @@ void SoundMidiPC::updateVolumeSettings() {
if (!_output)
return;
- int newMusVol = ConfMan.getInt("music_volume");
- _sfxVolume = ConfMan.getInt("sfx_volume");
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ const int newMusVol = (mute ? 0 : ConfMan.getInt("music_volume"));
+ _sfxVolume = (mute ? 0 : ConfMan.getInt("sfx_volume"));
_output->setSourceVolume(0, newMusVol, newMusVol != _musicVolume);
_musicVolume = newMusVol;
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index b0d3f994f2..750c6edfc2 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -23,7 +23,9 @@
*
*/
+#include "common/config-manager.h"
#include "common/system.h"
+
#include "kyra/resource.h"
#include "kyra/sound_intern.h"
#include "kyra/screen.h"
@@ -34,3765 +36,41 @@
#include "common/util.h"
-#define EUPHONY_FADEOUT_TICKS 600
-
namespace Kyra {
-enum EnvelopeState { s_ready, s_attacking, s_decaying, s_sustaining, s_releasing };
-
-class Towns_EuphonyChannel : public MidiChannel {
-public:
- Towns_EuphonyChannel() {}
- virtual ~Towns_EuphonyChannel() {}
-
- virtual void nextTick(int32 *outbuf, int buflen) = 0;
- virtual void rate(uint16 r) = 0;
-
-protected:
- uint16 _rate;
-};
-
-class Towns_EuphonyFmChannel : public Towns_EuphonyChannel {
-public:
- Towns_EuphonyFmChannel();
- virtual ~Towns_EuphonyFmChannel();
-
- void nextTick(int32 *outbuf, int buflen);
- void rate(uint16 r);
-
- // MidiChannel interface
- MidiDriver *device() { return 0; }
- byte getNumber() { return 0; }
- void release() { }
- void send(uint32) { }
- void noteOff(byte note);
- void noteOn(byte note, byte onVelo);
- void programChange(byte) {}
- void pitchBend(int16 value);
- void controlChange(byte control, byte value);
- void pitchBendFactor(byte) { }
- void sysEx_customInstrument(uint32 unused, const byte *instr);
-
-protected:
- Voice2612 *_voice;
-};
-
-class Towns_EuphonyPcmChannel : public Towns_EuphonyChannel {
-public:
- void nextTick(int32 *outbuf, int buflen);
- void rate(uint16 r);
-
- Towns_EuphonyPcmChannel();
- virtual ~Towns_EuphonyPcmChannel();
-
- // MidiChannel interface
- MidiDriver *device() { return 0; }
- byte getNumber() { return 0; }
- void release() { }
- void send(uint32 b) { }
- void noteOff(byte note);
- void noteOn(byte note, byte onVelo);
- void programChange(byte program) {}
- void pitchBend(int16 value);
- void controlChange(byte control, byte value);
- void pitchBendFactor(byte value) { }
- void sysEx_customInstrument(uint32 type, const byte *instr);
-
-protected:
- void velocity(int velo);
- void panPosition(int8 pan);
- void evpNextTick();
-
- int _ctrl7_volume;
- int16 _velocity;
- int16 _note;
- int32 _frequencyOffs;
- float _phase;
- int8 _current;
-
- struct Voice {
- char name[9];
- uint16 split[8];
- uint32 id[8];
- struct Snd {
- char name[9];
- int32 id;
- int32 numSamples;
- int32 loopStart;
- int32 loopLength;
- int32 samplingRate;
- int32 keyOffset;
- int32 keyNote;
- const int8 *_samples;
- } *_snd[8];
- struct Env {
- EnvelopeState state;
- int32 currentLevel;
- int32 rate;
- int32 tickCount;
- int32 totalLevel;
- int32 attackRate;
- int32 decayRate;
- int32 sustainLevel;
- int32 sustainRate;
- int32 releaseLevel;
- int32 releaseRate;
- int32 rootKeyOffset;
- int32 size;
- } *_env[8];
- } *_voice;
-};
-
-class Towns_EuphonyTrackQueue {
-public:
- Towns_EuphonyTrackQueue(Towns_EuphonyDriver *driver, Towns_EuphonyTrackQueue *last);
- ~Towns_EuphonyTrackQueue() {}
-
- Towns_EuphonyTrackQueue *release();
- void initDriver();
- void loadDataToCurrentPosition(uint8 *trackdata, uint32 size, bool loop = 0);
- void loadDataToEndOfQueue(uint8 *trackdata, uint32 size, bool loop = 0);
- void setPlayBackStatus(bool playing);
- bool isPlaying() const {return _playing; }
- uint8 *trackData() {return _trackData; }
-
- bool _loop;
- Towns_EuphonyTrackQueue *_next;
-
-private:
- uint8 *_trackData;
- uint8 *_used;
- uint8 *_fchan;
- uint8 *_wchan;
- bool _playing;
- Towns_EuphonyDriver *_driver;
- Towns_EuphonyTrackQueue *_last;
-};
-
-class Towns_EuphonyParser : public MidiParser {
-public:
- Towns_EuphonyParser(Towns_EuphonyTrackQueue * queue);
- bool loadMusic (byte *data, uint32 size);
- int32 calculateTempo(int16 val);
-
-protected:
- void parseNextEvent (EventInfo &info);
- void resetTracking();
- void setup();
-
- byte *_enable;
- byte *_mode;
- byte *_channel;
- byte *_adjVelo;
- int8 *_adjNote;
-
- uint8 _firstBaseTickStep;
- uint8 _nextBaseTickStep;
- uint32 _initialTempo;
- uint32 _baseTick;
-
- byte _tempo[3];
- Towns_EuphonyTrackQueue *_queue;
-};
-
-class Towns_EuphonyDriver : public MidiDriver_Emulated {
-public:
- Towns_EuphonyDriver(Audio::Mixer *mixer);
- virtual ~Towns_EuphonyDriver();
-
- int open();
- void close();
- void send(uint32 b);
- void send(byte channel, uint32 b);
- uint32 property(int prop, uint32 param) { return 0; }
-
- void setPitchBendRange(byte channel, uint range) { }
- void loadFmInstruments(const byte *instr);
- void loadWaveInstruments(const byte *instr);
-
- Towns_EuphonyTrackQueue *queue() { return _queue; }
-
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- void assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber);
- void assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber);
- void removeChannel(uint8 midiChannelNumber);
-
- void setVolume(int val = -1) { if (val >= 0) _volume = val; }
- int getVolume(int val = -1) { return _volume; }
-
- // AudioStream API
- bool isStereo() const { return true; }
- int getRate() const { return _mixer->getOutputRate(); }
-
- void fading(bool status = true);
-
-protected:
- void nextTick(int16 *buf1, int buflen);
- void rate(uint16 r);
-
- void generateSamples(int16 *buf, int len);
-
- Towns_EuphonyFmChannel *_fChannel[6];
- Towns_EuphonyPcmChannel *_wChannel[8];
- Towns_EuphonyChannel *_channel[16];
- Towns_EuphonyTrackQueue *_queue;
-
- int _volume;
- bool _fading;
- int16 _fadestate;
-
- uint8 *_fmInstruments;
- uint8 *_waveInstruments;
- int8 * _waveSounds[10];
-};
-
-Towns_EuphonyFmChannel::Towns_EuphonyFmChannel() {
- _voice = new Voice2612;
-}
-
-Towns_EuphonyFmChannel::~Towns_EuphonyFmChannel() {
- delete _voice;
-}
-
-void Towns_EuphonyFmChannel::noteOn(byte note, byte onVelo) {
- _voice->noteOn(note, onVelo);
-}
-
-void Towns_EuphonyFmChannel::noteOff(byte note) {
- _voice->noteOff(note);
-}
-
-void Towns_EuphonyFmChannel::controlChange(byte control, byte value) {
- if (control == 121) {
- // Reset controller
- delete _voice;
- _voice = new Voice2612;
- } else if (control == 10) {
- // pan position
- } else {
- _voice->setControlParameter(control, value);
- }
-}
-
-void Towns_EuphonyFmChannel::sysEx_customInstrument(uint32, const byte *fmInst) {
- _voice->_rate = _rate;
- _voice->setInstrument(fmInst);
-}
-
-void Towns_EuphonyFmChannel::pitchBend(int16 value) {
- _voice->pitchBend(value);
-}
-
-void Towns_EuphonyFmChannel::nextTick(int32 *outbuf, int buflen) {
- _voice->nextTick((int *)outbuf, buflen);
-}
-
-void Towns_EuphonyFmChannel::rate(uint16 r) {
- _rate = r;
- _voice->_rate = r;
-}
-
-Towns_EuphonyPcmChannel::Towns_EuphonyPcmChannel() {
- _voice = new Voice;
- for (uint8 i = 0; i < 8; i++) {
- _voice->_env[i] = new Voice::Env;
- _voice->_snd[i] = 0;
- }
-
- _ctrl7_volume = 127;
- velocity(0);
- _frequencyOffs = 0x2000;
- _current = -1;
-}
-
-Towns_EuphonyPcmChannel::~Towns_EuphonyPcmChannel() {
- for (uint8 i = 0; i < 8; i++) {
- if (_voice->_snd[i])
- delete _voice->_snd[i];
- delete _voice->_env[i];
- }
- delete _voice;
-}
-
-void Towns_EuphonyPcmChannel::noteOn(byte note, byte onVelo) {
- _note = note;
- velocity(onVelo);
- _phase = 0;
-
- for (_current = 0; _current < 7; _current++) {
- if (note <= _voice->split[_current])
- break;
- }
-
- _voice->_env[_current]->state = s_attacking;
- _voice->_env[_current]->currentLevel = 0;
- _voice->_env[_current]->rate = _rate;
- _voice->_env[_current]->tickCount = 0;
-}
-
-void Towns_EuphonyPcmChannel::noteOff(byte note) {
- if (_current == -1)
- return;
- if (_voice->_env[_current]->state == s_ready)
- return;
-
- _voice->_env[_current]->state = s_releasing;
- _voice->_env[_current]->releaseLevel = _voice->_env[_current]->currentLevel;
- _voice->_env[_current]->tickCount = 0;
-}
-
-void Towns_EuphonyPcmChannel::controlChange(byte control, byte value) {
- switch (control) {
- case 0x07:
- // volume
- _ctrl7_volume = value;
- break;
- case 0x0A:
- // pan position
- break;
- case 0x79:
- // Reset controller
- for (uint8 i = 0; i < 8; i++) {
- if (_voice->_snd[i])
- delete _voice->_snd[i];
- delete _voice->_env[i];
- }
- delete _voice;
- _voice = new Voice;
- for (uint8 i = 0; i < 8; i++) {
- _voice->_env[i] = new Voice::Env;
- _voice->_snd[i] = 0;
- }
- break;
- case 0x7B:
- noteOff(_note);
- break;
- default:
- break;
- }
-}
-
-void Towns_EuphonyPcmChannel::sysEx_customInstrument(uint32 type, const byte *fmInst) {
- if (type == 0x80) {
- for (uint8 i = 0; i < 8; i++) {
- const byte * const *pos = (const byte * const *)fmInst;
- for (uint8 ii = 0; ii < 10; ii++) {
- if (_voice->id[i] == *(pos[ii] + 8)) {
- if (!_voice->_snd[i])
- _voice->_snd[i] = new Voice::Snd;
- memset(_voice->_snd[i]->name, 0, 9);
- memcpy(_voice->_snd[i]->name, (const char *)pos[ii], 8);
- _voice->_snd[i]->id = READ_LE_UINT32(pos[ii] + 8);
- _voice->_snd[i]->numSamples = READ_LE_UINT32(pos[ii] + 12);
- _voice->_snd[i]->loopStart = READ_LE_UINT32(pos[ii] + 16);
- _voice->_snd[i]->loopLength = READ_LE_UINT32(pos[ii] + 20);
- _voice->_snd[i]->samplingRate = READ_LE_UINT16(pos[ii] + 24);
- _voice->_snd[i]->keyOffset = READ_LE_UINT16(pos[ii] + 26);
- _voice->_snd[i]->keyNote = *(const uint8 *)(pos[ii] + 28);
- _voice->_snd[i]->_samples = (const int8 *)(pos[ii] + 32);
- }
- }
- }
- } else {
- memset(_voice->name, 0, 9);
- memcpy(_voice->name, (const char *)fmInst, 8);
-
- for (uint8 i = 0; i < 8; i++) {
- _voice->split[i] = READ_LE_UINT16(fmInst + 16 + 2 * i);
- _voice->id[i] = READ_LE_UINT32(fmInst + 32 + 4 * i);
- _voice->_snd[i] = 0;
- _voice->_env[i]->state = s_ready;
- _voice->_env[i]->currentLevel = 0;
- _voice->_env[i]->totalLevel = *(fmInst + 64 + 8 * i);
- _voice->_env[i]->attackRate = *(fmInst + 65 + 8 * i) * 10;
- _voice->_env[i]->decayRate = *(fmInst + 66 + 8 * i) * 10;
- _voice->_env[i]->sustainLevel = *(fmInst + 67 + 8 * i);
- _voice->_env[i]->sustainRate = *(fmInst + 68 + 8 * i) * 20;
- _voice->_env[i]->releaseRate = *(fmInst + 69 + 8 * i) * 10;
- _voice->_env[i]->rootKeyOffset = *(fmInst + 70 + 8 * i);
- }
- }
-}
-
-void Towns_EuphonyPcmChannel::pitchBend(int16 value) {
- _frequencyOffs = value;
-}
-
-void Towns_EuphonyPcmChannel::nextTick(int32 *outbuf, int buflen) {
- if (_current == -1 || !_voice->_snd[_current] || !_voice->_env[_current]->state || !_velocity) {
- velocity(0);
- _current = -1;
- return;
- }
-
- 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;
- int32 numsamples = _voice->_snd[_current]->numSamples;
- const int8 * samples = _voice->_snd[_current]->_samples;
-
- for (int i = 0; i < buflen; i++) {
- if (looplength > 0) {
- while (_phase >= numsamples)
- _phase -= looplength;
- } else {
- if (_phase >= numsamples) {
- velocity(0);
- _current = -1;
- break;
- }
- }
-
- int32 output;
-
- int32 phase0 = int32(_phase);
- int32 phase1 = int32(_phase + 1);
- if (phase1 >= numsamples)
- phase1 -= looplength;
- float weight0 = _phase - phase0;
- float weight1 = phase1 - _phase;
- output = int32(samples[phase0] * weight0 + samples[phase1] * weight1);
-
- output *= _velocity;
- output <<= 1;
-
- evpNextTick();
- output *= _voice->_env[_current]->currentLevel;
- output >>= 7;
- output *= _ctrl7_volume;
- output >>= 7;
-
- output *= 185;
- output >>= 8;
- outbuf[i] += output;
- _phase += phaseStep;
- }
-}
-
-void Towns_EuphonyPcmChannel::evpNextTick() {
- switch (_voice->_env[_current]->state) {
- case s_ready:
- _voice->_env[_current]->currentLevel = 0;
- return;
-
- case s_attacking:
- if (_voice->_env[_current]->attackRate == 0)
- _voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel;
- else if (_voice->_env[_current]->attackRate >= 1270)
- _voice->_env[_current]->currentLevel = 0;
- else
- _voice->_env[_current]->currentLevel = (_voice->_env[_current]->totalLevel *
- _voice->_env[_current]->tickCount++ * 1000) /
- (_voice->_env[_current]->attackRate * _voice->_env[_current]->rate);
-
- if (_voice->_env[_current]->currentLevel >= _voice->_env[_current]->totalLevel) {
- _voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel;
- _voice->_env[_current]->state = s_decaying;
- _voice->_env[_current]->tickCount = 0;
- }
- break;
-
- case s_decaying:
- if (_voice->_env[_current]->decayRate == 0) {
- _voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel;
- } else if (_voice->_env[_current]->decayRate >= 1270) {
- _voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel;
- } else {
- _voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel;
- _voice->_env[_current]->currentLevel -= ((_voice->_env[_current]->totalLevel -
- _voice->_env[_current]->sustainLevel) * _voice->_env[_current]->tickCount++ * 1000) /
- (_voice->_env[_current]->decayRate * _voice->_env[_current]->rate);
- }
-
- if (_voice->_env[_current]->currentLevel <= _voice->_env[_current]->sustainLevel) {
- _voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel;
- _voice->_env[_current]->state = s_sustaining;
- _voice->_env[_current]->tickCount = 0;
- }
- break;
-
- case s_sustaining:
- if (_voice->_env[_current]->sustainRate == 0) {
- _voice->_env[_current]->currentLevel = 0;
- } else if (_voice->_env[_current]->sustainRate >= 2540) {
- _voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel;
- } else {
- _voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel;
- _voice->_env[_current]->currentLevel -= (_voice->_env[_current]->sustainLevel *
- _voice->_env[_current]->tickCount++ * 1000) / (_voice->_env[_current]->sustainRate *
- _voice->_env[_current]->rate);
- }
-
- if (_voice->_env[_current]->currentLevel <= 0) {
- _voice->_env[_current]->currentLevel = 0;
- _voice->_env[_current]->state = s_ready;
- _voice->_env[_current]->tickCount = 0;
- }
- break;
-
- case s_releasing:
- if (_voice->_env[_current]->releaseRate == 0) {
- _voice->_env[_current]->currentLevel = 0;
- } else if (_voice->_env[_current]->releaseRate >= 1270) {
- _voice->_env[_current]->currentLevel = _voice->_env[_current]->releaseLevel;
- } else {
- _voice->_env[_current]->currentLevel = _voice->_env[_current]->releaseLevel;
- _voice->_env[_current]->currentLevel -= (_voice->_env[_current]->releaseLevel *
- _voice->_env[_current]->tickCount++ * 1000) / (_voice->_env[_current]->releaseRate *
- _voice->_env[_current]->rate);
- }
-
- if (_voice->_env[_current]->currentLevel <= 0) {
- _voice->_env[_current]->currentLevel = 0;
- _voice->_env[_current]->state = s_ready;
- }
- break;
-
- default:
- break;
- }
-}
-
-void Towns_EuphonyPcmChannel::rate(uint16 r) {
- _rate = r;
-}
-
-void Towns_EuphonyPcmChannel::velocity(int velo) {
- _velocity = velo;
-}
-
-Towns_EuphonyDriver::Towns_EuphonyDriver(Audio::Mixer *mixer)
- : MidiDriver_Emulated(mixer) {
- _volume = 255;
- _fadestate = EUPHONY_FADEOUT_TICKS;
- _queue = 0;
-
- MidiDriver_YM2612::createLookupTables();
-
- for (uint8 i = 0; i < 6; i++)
- _channel[i] = _fChannel[i] = new Towns_EuphonyFmChannel;
- for (uint8 i = 0; i < 8; i++)
- _channel[i + 6] = _wChannel[i] = new Towns_EuphonyPcmChannel;
- _channel[14] = _channel[15] = 0;
-
- _fmInstruments = _waveInstruments = 0;
- memset(_waveSounds, 0, sizeof(uint8 *)* 10);
-
- rate(getRate());
- fading(0);
-
- _queue = new Towns_EuphonyTrackQueue(this, 0);
-}
-
-Towns_EuphonyDriver::~Towns_EuphonyDriver() {
- for (int i = 0; i < 6; i++)
- delete _fChannel[i];
- for (int i = 0; i < 8; i++)
- delete _wChannel[i];
-
- MidiDriver_YM2612::removeLookupTables();
-
- if (_fmInstruments) {
- delete[] _fmInstruments;
- _fmInstruments = 0;
- }
-
- if (_waveInstruments) {
- delete[] _waveInstruments;
- _waveInstruments = 0;
- }
-
- for (int i = 0; i < 10; i++) {
- if (_waveSounds[i]) {
- delete[] _waveSounds[i];
- _waveSounds[i] = 0;
- }
- }
-
- if (_queue) {
- _queue->release();
- delete _queue;
- _queue = 0;
- }
-}
-
-int Towns_EuphonyDriver::open() {
- if (_isOpen)
- return MERR_ALREADY_OPEN;
- MidiDriver_Emulated::open();
-
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle,
- this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
- return 0;
-}
-
-void Towns_EuphonyDriver::close() {
- if (!_isOpen)
- return;
- _isOpen = false;
- _mixer->stopHandle(_mixerSoundHandle);
-}
-
-void Towns_EuphonyDriver::send(uint32 b) {
- send(b & 0xF, b & 0xFFFFFFF0);
-}
-
-void Towns_EuphonyDriver::send(byte chan, uint32 b) {
- byte param2 = (byte) ((b >> 16) & 0xFF);
- byte param1 = (byte) ((b >> 8) & 0xFF);
- byte cmd = (byte) (b & 0xF0);
- if (chan > ARRAYSIZE(_channel))
- return;
-
- switch (cmd) {
- case 0x80:// Note Off
- if (_channel[chan])
- _channel[chan]->noteOff(param1);
- break;
- case 0x90: // Note On
- if (_channel[chan])
- _channel[chan]->noteOn(param1, param2);
- break;
- case 0xA0: // Aftertouch
- break; // Not supported.
- case 0xB0: // Control Change
- if (param1 == 0x79) {
- fading(0);
- for (int i = 0; i < 15; i++) {
- if (_channel[i]) {
- _channel[i]->controlChange(param1, param2);
- _channel[i]->programChange(0);
- }
- }
- } else if (param1 == 0x7B) {
- for (int i = 0; i < 15; i++) {
- if (_channel[i])
- _channel[i]->controlChange(param1, param2);
- }
- } else {
- if (_channel[chan])
- _channel[chan]->controlChange(param1, param2);
- }
- break;
- case 0xC0: // Program Change
- for (int i = 0; i < 6; i++) {
- if (_channel[chan] == _fChannel[i]) {
- _channel[chan]->sysEx_customInstrument(0, _fmInstruments + param1 * 0x30);
- break;
- }
- }
- for (int i = 0; i < 8; i++) {
- if (_channel[chan] == _wChannel[i]) {
- _channel[chan]->sysEx_customInstrument(0, _waveInstruments + param1 * 0x80);
- _channel[chan]->sysEx_customInstrument(0x80, (const byte *)_waveSounds);
- break;
- }
- }
- break;
- case 0xD0: // Channel Pressure
- break; // Not supported.
- case 0xE0: // Pitch Bend
- if (_channel[chan])
- _channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000);
- break;
- default:
- warning("Towns_EuphonyDriver: Unknown send() command 0x%02X", cmd);
- }
-}
-
-void Towns_EuphonyDriver::loadFmInstruments(const byte *instr) {
- delete[] _fmInstruments;
- _fmInstruments = new uint8[0x1800];
- memcpy(_fmInstruments, instr, 0x1800);
-}
-
-void Towns_EuphonyDriver::loadWaveInstruments(const byte *instr) {
- delete[] _waveInstruments;
- _waveInstruments = new uint8[0x1000];
- memcpy(_waveInstruments, instr, 0x1000);
-
- const uint8 *pos = (const uint8 *)(instr + 0x1000);
-
- for (uint8 i = 0; i < 10; i++) {
- delete[] _waveSounds[i];
- uint32 numsamples = READ_LE_UINT32(pos + 0x0C);
- _waveSounds[i] = new int8[numsamples + 0x20];
- memcpy(_waveSounds[i], pos, 0x20);
- pos += 0x20;
- for (uint32 ii = 0; ii < numsamples; ii++) {
- uint8 s = *(pos + ii);
- s = (s < 0x80) ? 0x80 - s : s;
- _waveSounds[i][ii + 0x20] = s ^ 0x80;
- }
- pos += numsamples;
- }
-}
-
-
-void Towns_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) {
- _channel[midiChannelNumber] = _fChannel[fmChannelNumber];
-}
-
-void Towns_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) {
- _channel[midiChannelNumber] = _wChannel[waveChannelNumber];
-}
-
-void Towns_EuphonyDriver::removeChannel(uint8 midiChannelNumber) {
- _channel[midiChannelNumber] = 0;
-}
-
-void Towns_EuphonyDriver::generateSamples(int16 *data, int len) {
- memset(data, 0, 2 * sizeof(int16) * len);
- nextTick(data, len);
-}
-
-void Towns_EuphonyDriver::nextTick(int16 *buf1, int buflen) {
- int32 *buf0 = (int32 *)buf1;
-
- for (int i = 0; i < ARRAYSIZE(_channel); i++) {
- if (_channel[i])
- _channel[i]->nextTick(buf0, buflen);
- }
-
- for (int i = 0; i < buflen; ++i) {
- int s = int( float(buf0[i] * _volume) * float((float)_fadestate / EUPHONY_FADEOUT_TICKS) );
- buf1[i*2] = buf1[i*2+1] = (s >> 9) & 0xffff;
- }
-
- if (_fading) {
- if (_fadestate) {
- _fadestate--;
- } else {
- _fading = false;
- _queue->setPlayBackStatus(false);
- }
- }
-}
-
-void Towns_EuphonyDriver::rate(uint16 r) {
- for (uint8 i = 0; i < 16; i++) {
- if (_channel[i])
- _channel[i]->rate(r);
- }
-}
-
-void Towns_EuphonyDriver::fading(bool status) {
- _fading = status;
- if (!_fading)
- _fadestate = EUPHONY_FADEOUT_TICKS;
-}
-
-Towns_EuphonyParser::Towns_EuphonyParser(Towns_EuphonyTrackQueue * queue) : MidiParser(),
- _firstBaseTickStep(0x33), _nextBaseTickStep(0x33) {
- _initialTempo = calculateTempo(0x5a);
- _queue = queue;
-}
-
-void Towns_EuphonyParser::parseNextEvent(EventInfo &info) {
- byte *pos = _position._play_pos;
-
- if (_queue->_next) {
- if (info.ext.type == 0x2F) {
- unloadMusic();
- memset(&info, 0, sizeof(EventInfo));
- pos = _position._play_pos = _tracks[0] = _queue->trackData() + 0x806;
- } else if (_active_track == 255) {
- _queue = _queue->_next;
- setup();
- setTrack(0);
- _queue->setPlayBackStatus(true);
- return;
- } else if (!_queue->isPlaying()) {
- unloadMusic();
- _queue = _queue->_next;
- setup();
- setTrack(0);
- _queue->setPlayBackStatus(true);
- return;
- }
- }
-
- bool loop = true;
- while (loop) {
- byte cmd = *pos;
- byte evt = (cmd & 0xF0);
-
- if (evt == 0x90) {
- byte chan = pos[1];
-
- if (_enable[chan]) {
- uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick;
- info.start = pos + 6;
- uint32 last = _position._last_event_tick;
- info.delta = (tick < last) ? 0 : (tick - last);
-
- info.event = 0x90 | _channel[chan];
- info.length = pos[7] | (pos[8] << 4) | (pos[9] << 8) | (pos[10] << 12);
-
- int8 note = (int8) pos[4];
- if (_adjNote[chan]) {
- note = (note & 0x7f) & _adjNote[chan];
- if (note > 0x7c)
- note -= 0x0c;
- else if (note < 0)
- note += 0x0c;
- }
- info.basic.param1 = (byte) note;
-
- uint8 onVelo = (pos[5] & 0x7f) + _adjVelo[chan];
- if (onVelo > 0x7f)
- onVelo = 0x7f;
- if (onVelo < 1)
- onVelo = 1;
- info.basic.param2 = onVelo;
-
- pos += 12;
- loop = false;
- } else {
- pos += 6;
- }
- } else if (evt == 0xB0 || evt == 0xC0 || evt == 0xe0) {
- byte chan = pos[1];
-
- if (_enable[chan]) {
- info.start = pos;
- uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick;
- uint32 last = _position._last_event_tick;
- info.delta = (tick < last) ? 0 : (tick - last);
- info.event = evt | _channel[chan];
- info.length = 0;
- info.basic.param1 = pos[4];
- info.basic.param2 = pos[5];
- pos += 6;
- loop = false;
- } else {
- pos += 6;
- }
- } else if (cmd == 0xF2) {
- static const uint16 tickTable[] = { 0x180, 0xC0, 0x80, 0x60, 0x40, 0x30, 0x20, 0x18 };
- _baseTick += tickTable[_nextBaseTickStep >> 4] * ((_nextBaseTickStep & 0x0f) + 1);
- _nextBaseTickStep = pos[1];
- pos += 6;
- } else if (cmd == 0xF8) {
- int32 tempo = calculateTempo(pos[4] | (pos[5] << 7));
- info.event = 0xff;
- info.length = 3;
- info.ext.type = 0x51;
- _tempo[0] = (tempo >> 16) & 0xff;
- _tempo[1] = (tempo >> 8) & 0xff;
- _tempo[2] = tempo & 0xff;
- info.ext.data = (byte *)_tempo;
- pos += 6;
- loop = false;
- } else if (cmd == 0xFD || cmd == 0xFE) {
- // End of track.
- if (_autoLoop) {
- unloadMusic();
- _queue->setPlayBackStatus(true);
- pos = info.start = _tracks[0];
- } else {
- info.start = pos;
- }
-
- uint32 last = _position._last_event_tick;
- uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick;
- info.delta = (tick < last) ? 0 : (tick - last);
- info.event = 0xFF;
- info.ext.type = 0x2F;
- info.ext.data = pos;
- loop = false;
- } else {
- warning("Unknown Euphony music event 0x%02X", (int)cmd);
- memset(&info, 0, sizeof(info));
- pos = 0;
- loop = false;
- }
- }
- _position._play_pos = pos;
-}
-
-bool Towns_EuphonyParser::loadMusic(byte *data, uint32 size) {
- bool loop = _autoLoop;
-
- if (_queue->isPlaying() && !_queue->_loop) {
- _queue->loadDataToEndOfQueue(data, size, loop);
- } else {
- unloadMusic();
- _queue = _queue->release();
- _queue->loadDataToCurrentPosition(data, size, loop);
- setup();
- setTrack(0);
- _queue->setPlayBackStatus(true);
- }
- return true;
-}
-
-int32 Towns_EuphonyParser::calculateTempo(int16 val) {
- int32 tempo = val;
-
- if (tempo < 0)
- tempo = 0;
- if (tempo > 0x1F4)
- tempo = 0x1F4;
-
- tempo = 0x4C4B4 / (tempo + 0x1E);
- while (tempo < 0x451)
- tempo <<= 1;
- tempo <<= 8;
-
- return tempo;
-}
-
-void Towns_EuphonyParser::resetTracking() {
- MidiParser::resetTracking();
-
- _nextBaseTickStep = _firstBaseTickStep;
- _baseTick = 0;
- setTempo(_initialTempo);
- _queue->setPlayBackStatus(false);
-}
-
-void Towns_EuphonyParser::setup() {
- uint8 *data = _queue->trackData();
- if (!data)
- return;
- _queue->initDriver();
-
- _enable = data + 0x354;
- _mode = data + 0x374;
- _channel = data + 0x394;
- _adjVelo = data + 0x3B4;
- _adjNote = (int8 *)data + 0x3D4;
-
- _nextBaseTickStep = _firstBaseTickStep = data[0x804];
- _initialTempo = calculateTempo((data[0x805] > 0xfc) ? 0x5a : data[0x805]);
-
- property(MidiParser::mpAutoLoop, _queue->_loop);
-
- _num_tracks = 1;
- _ppqn = 120;
- _tracks[0] = data + 0x806;
-}
-
-Towns_EuphonyTrackQueue::Towns_EuphonyTrackQueue(Towns_EuphonyDriver * driver, Towns_EuphonyTrackQueue * last) {
- _trackData = 0;
- _next = 0;
- _driver = driver;
- _last = last;
- _used = _fchan = _wchan = 0;
- _playing = _loop = false;
-}
-
-void Towns_EuphonyTrackQueue::setPlayBackStatus(bool playing) {
- Towns_EuphonyTrackQueue *i = this;
- do {
- i->_playing = playing;
- i = i->_next;
- } while (i);
-}
-
-void Towns_EuphonyTrackQueue::loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop) {
- delete[] _trackData;
- _trackData = new uint8[0xC58A];
- memset(_trackData, 0, 0xC58A);
- Screen::decodeFrame4(trackdata, _trackData, size);
-
- _used = _trackData + 0x374;
- _fchan = _trackData + 0x6d4;
- _wchan = _trackData + 0x6dA;
- _loop = loop;
- _playing = false;
-}
-
-void Towns_EuphonyTrackQueue::loadDataToEndOfQueue(uint8 * trackdata, uint32 size, bool loop) {
- if (!_trackData) {
- loadDataToCurrentPosition(trackdata, size, loop);
- return;
- }
-
- Towns_EuphonyTrackQueue *i = this;
- while (i->_next)
- i = i->_next;
-
- i = i->_next = new Towns_EuphonyTrackQueue(_driver, i);
- i->_trackData = new uint8[0xC58A];
- memset(i->_trackData, 0, 0xC58A);
- Screen::decodeFrame4(trackdata, i->_trackData, size);
-
- i->_used = i->_trackData + 0x374;
- i->_fchan = i->_trackData + 0x6d4;
- i->_wchan = i->_trackData + 0x6dA;
- i->_loop = loop;
- i->_playing = _playing;
-}
-
-Towns_EuphonyTrackQueue *Towns_EuphonyTrackQueue::release() {
- Towns_EuphonyTrackQueue *i = this;
- while (i->_next)
- i = i->_next;
-
- Towns_EuphonyTrackQueue *res = i;
-
- while (i) {
- i->_playing = false;
- i->_used = i->_fchan = i->_wchan = 0;
- delete[] i->_trackData;
- i->_trackData = 0;
- i = i->_last;
- if (i) {
- res = i;
- delete i->_next;
- i->_next = 0;
- }
- }
-
- delete[] res->_trackData;
- res->_trackData = 0;
-
- return res;
-}
-
-void Towns_EuphonyTrackQueue::initDriver() {
- for (uint8 i = 0; i < 6; i++) {
- if (_used[_fchan[i]])
- _driver->assignFmChannel(_fchan[i], i);
- }
-
- for (uint8 i = 0; i < 8; i++) {
- if (_used[_wchan[i]])
- _driver->assignWaveChannel(_wchan[i], i);
- }
-
- for (uint8 i = 0; i < 16; i++) {
- if (!_used[i])
- _driver->removeChannel(i);
- }
- _driver->send(0x79B0);
-}
-
-class TownsPC98_OpnOperator {
-public:
- 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() {}
-
- void keyOn();
- void keyOff();
- void frequency(int freq);
- void updatePhaseIncrement();
- void recalculateRates();
- 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]; }
- void multiple(uint32 value) { _multiple = value ? (value << 1) : 1; }
- void attackRate(uint32 value) { _specifiedAttackRate = value; }
- bool scaleRate(uint8 value);
- void decayRate(uint32 value) { _specifiedDecayRate = value; recalculateRates(); }
- void sustainRate(uint32 value) { _specifiedSustainRate = value; recalculateRates(); }
- void sustainLevel(uint32 value) { _sustainLevel = (value == 0x0f) ? 0x3e0 : value << 5; }
- void releaseRate(uint32 value) { _specifiedReleaseRate = value; recalculateRates(); }
- void totalLevel(uint32 value) { _totalLevel = value << 3; }
- void reset();
-
-protected:
- EnvelopeState _state;
- bool _playing;
- uint32 _feedbackLevel;
- uint32 _multiple;
- uint32 _totalLevel;
- uint8 _keyScale1;
- uint8 _keyScale2;
- uint32 _specifiedAttackRate;
- uint32 _specifiedDecayRate;
- uint32 _specifiedSustainRate;
- uint32 _specifiedReleaseRate;
- uint32 _tickCount;
- uint32 _sustainLevel;
-
- uint32 _frequency;
- uint8 _kcode;
- uint32 _phase;
- uint32 _phaseIncrement;
- const int32 *_detn;
-
- const uint8 *_rateTbl;
- const uint8 *_rshiftTbl;
- const uint8 *_adTbl;
- const uint32 *_fTbl;
- const uint32 *_sinTbl;
- const int32 *_tLvlTbl;
- const int32 *_detnTbl;
-
- const uint32 _tickLength;
- uint32 _timer;
- int32 _currentLevel;
-
- struct EvpState {
- uint8 rate;
- uint8 shift;
- } fs_a, fs_d, fs_s, fs_r;
-};
-
-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(timerbase * 2),
- _specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0),
- _phase(0), _state(s_ready), _playing(false), _timer(0), _keyScale1(0), _keyScale2(0), _currentLevel(1023),
- _tickCount(0) {
-
- fs_a.rate = fs_a.shift = fs_d.rate = fs_d.shift = fs_s.rate = fs_s.shift = fs_r.rate = fs_r.shift = 0;
-
- 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;
-}
-
-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);
-}
-
-void TownsPC98_OpnOperator::updatePhaseIncrement() {
- _phaseIncrement = ((_frequency + _detn[_kcode]) * _multiple) >> 1;
- uint8 keyscale = _kcode >> _keyScale1;
- if (_keyScale2 != keyscale) {
- _keyScale2 = keyscale;
- recalculateRates();
- }
-}
-
-void TownsPC98_OpnOperator::recalculateRates() {
- int k = _keyScale2;
- int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0;
- fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136;
- fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0;
-
- r = _specifiedDecayRate ? (_specifiedDecayRate << 1) + 0x20 : 0;
- fs_d.rate = _rateTbl[r + k];
- fs_d.shift = _rshiftTbl[r + k];
-
- r = _specifiedSustainRate ? (_specifiedSustainRate << 1) + 0x20 : 0;
- fs_s.rate = _rateTbl[r + k];
- fs_s.shift = _rshiftTbl[r + k];
-
- r = (_specifiedReleaseRate << 2) + 0x22;
- fs_r.rate = _rateTbl[r + k];
- fs_r.shift = _rshiftTbl[r + k];
-}
-
-void TownsPC98_OpnOperator::generateOutput(int32 phasebuf, int32 *feed, int32 &out) {
- if (_state == s_ready)
- return;
-
- _timer += _tickLength;
- while (_timer > 0x5B8D80) {
- _timer -= 0x5B8D80;
- ++_tickCount;
-
- int32 levelIncrement = 0;
- uint32 targetTime = 0;
- int32 targetLevel = 0;
- EnvelopeState nextState = s_ready;
-
- switch (_state) {
- case s_ready:
- return;
- case s_attacking:
- targetLevel = 0;
- nextState = s_decaying;
- if ((_specifiedAttackRate << 1) + _keyScale2 < 64) {
- targetTime = (1 << fs_a.shift) - 1;
- levelIncrement = (~_currentLevel * _adTbl[fs_a.rate + ((_tickCount >> fs_a.shift) & 7)]) >> 4;
- break;
- } else {
- _currentLevel = targetLevel;
- _state = nextState;
- }
- // Fall through
- case s_decaying:
- targetTime = (1 << fs_d.shift) - 1;
- 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;
- 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;
- nextState = s_ready;
- targetLevel = 1023;
- levelIncrement = _adTbl[fs_r.rate + ((_tickCount >> fs_r.shift) & 7)];
- break;
- }
-
- if (!(_tickCount & targetTime)) {
- _currentLevel += levelIncrement;
- if ((_state == s_attacking && _currentLevel <= targetLevel) || (_state != s_attacking && _currentLevel >= targetLevel)) {
- if (_state != s_decaying)
- _currentLevel = targetLevel;
- _state = nextState;
- }
- }
- }
-
- uint32 lvlout = _totalLevel + (uint32) _currentLevel;
-
-
- int32 outp = 0;
- int32 *i = &outp, *o = &outp;
- int phaseShift = 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)
- + phaseShift)) >> 16) & 0x3ff];
- *i = ((index < 6656) ? _tLvlTbl[index] : 0);
- } else {
- *i = 0;
- }
-
- _phase += _phaseIncrement;
- out += *o;
-}
-
-void TownsPC98_OpnOperator::reset(){
- keyOff();
- _timer = 0;
- _keyScale2 = 0;
- _currentLevel = 1023;
-
- frequency(0);
- detune(0);
- scaleRate(0);
- multiple(0);
- updatePhaseIncrement();
- attackRate(0);
- decayRate(0);
- releaseRate(0);
- sustainRate(0);
- feedbackLevel(0);
- totalLevel(127);
-}
-
-bool TownsPC98_OpnOperator::scaleRate(uint8 value) {
- value = 3 - value;
- if (_keyScale1 != value) {
- _keyScale1 = value;
- return true;
- }
-
- int k = _keyScale2;
- int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0;
- fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136;
- fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0;
- return false;
-}
-
-class TownsPC98_OpnDriver;
-class TownsPC98_OpnChannel {
-public:
- TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num,
- uint8 key, uint8 prt, uint8 id);
- virtual ~TownsPC98_OpnChannel();
- virtual void init();
-
- typedef enum channelState {
- CHS_RECALCFREQ = 0x01,
- CHS_KEYOFF = 0x02,
- 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();
- virtual bool processControlEvent(uint8 cmd);
-
- virtual void keyOn();
- void keyOff();
-
- void setOutputLevel();
- virtual void fadeStep();
- void reset();
-
- 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);
- bool control_f2_setKeyOffTime(uint8 para);
- bool control_f3_setFreqLSB(uint8 para);
- bool control_f4_setOutputLevel(uint8 para);
- bool control_f5_setTempo(uint8 para);
- bool control_f6_repeatSection(uint8 para);
- bool control_f7_setupVibrato(uint8 para);
- bool control_f8_toggleVibrato(uint8 para);
- bool control_fa_writeReg(uint8 para);
- virtual bool control_fb_incOutLevel(uint8 para);
- virtual bool control_fc_decOutLevel(uint8 para);
- bool control_fd_jump(uint8 para);
- virtual bool control_ff_endOfTrack(uint8 para);
-
- uint8 _ticksLeft;
- uint8 _algorithm;
- uint8 _instr;
- uint8 _totalLevel;
- uint8 _frqBlockMSB;
- int8 _frqLSB;
- uint8 _keyOffTime;
- bool _hold;
- uint8 *_dataPtr;
- uint8 _vbrInitDelayHi;
- uint8 _vbrInitDelayLo;
- int16 _vbrModInitVal;
- uint8 _vbrDuration;
- uint8 _vbrCurDelay;
- int16 _vbrModCurVal;
- uint8 _vbrDurLeft;
- uint16 _frequency;
- uint8 _block;
- uint8 _regOffset;
- uint8 _flags;
- uint8 _ssgTl;
- uint8 _ssgStep;
- uint8 _ssgTicksLeft;
- uint8 _ssgTargetLvl;
- uint8 _ssgStartLvl;
-
- const uint8 _chanNum;
- const uint8 _keyNum;
- const uint8 _part;
-
- TownsPC98_OpnDriver *_drv;
-
- typedef bool (TownsPC98_OpnChannel::*ControlEventFunc)(uint8 para);
- const ControlEventFunc *controlEvents;
-};
-
-class TownsPC98_OpnChannelSSG : public TownsPC98_OpnChannel {
-public:
- TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs,
- uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id);
- virtual ~TownsPC98_OpnChannelSSG() {}
- void init();
-
- virtual void loadData(uint8 *data);
- void processEvents();
- void processFrequency();
- bool processControlEvent(uint8 cmd);
-
- void keyOn();
- 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:
- 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();
-
- 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() const { return _chanEnable; }
-private:
- void updatesRegs();
-
- uint8 _updateRequestBuf[64];
- 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 **_reg;
-
- bool _ready;
-};
-
-class TownsPC98_OpnPercussionSource {
-public:
- TownsPC98_OpnPercussionSource(const uint32 timerbase);
- ~TownsPC98_OpnPercussionSource() { delete[] _reg; }
-
- 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 **_reg;
-
- bool _ready;
-};
-
-class TownsPC98_OpnCore : public Audio::AudioStream {
-public:
- enum OpnType {
- OD_TOWNS,
- OD_TYPE26,
- OD_TYPE86
- };
-
- TownsPC98_OpnCore(Audio::Mixer *mixer, OpnType type);
- virtual ~TownsPC98_OpnCore();
-
- virtual bool init();
- virtual void reset();
-
- void writeReg(uint8 part, uint8 regAddress, uint8 value);
-
- // AudioStream interface
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return true; }
- bool endOfData() const { return false; }
- int getRate() const { return _mixer->getOutputRate(); }
-
-protected:
- void generateTables();
-
- void toggleRegProtection(bool prot) { _regProtectionFlag = prot; }
- uint8 readSSGStatus() { return _ssg->chanEnable(); }
-
- virtual void timerCallbackA() = 0;
- virtual void timerCallbackB() = 0;
-
- const int _numChan;
- const int _numSSG;
- const bool _hasPercussion;
-
- Common::Mutex _mutex;
-private:
- void nextTick(int32 *buffer, uint32 bufferSize);
- void generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed);
-
- struct ChanInternal {
- ChanInternal() {
- memset(this, 0, sizeof(ChanInternal));
- }
-
- ~ChanInternal() {
- for (uint i = 0; i < ARRAYSIZE(opr); ++i)
- delete opr[i];
- }
-
- uint16 frqTemp;
- bool enableLeft;
- bool enableRight;
- bool updateEnvelopeParameters;
- int32 feedbuf[3];
- uint8 algorithm;
- TownsPC98_OpnOperator *opr[4];
- };
-
- TownsPC98_OpnSquareSineSource *_ssg;
- TownsPC98_OpnPercussionSource *_prc;
- ChanInternal *_chanInternal;
-
- uint8 *_oprRates;
- uint8 *_oprRateshift;
- uint8 *_oprAttackDecay;
- uint32 *_oprFrq;
- uint32 *_oprSinTbl;
- int32 *_oprLevelOut;
- int32 *_oprDetune;
-
- 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);
-
- TownsPC98_OpnChannel **_channels;
- TownsPC98_OpnChannelSSG **_ssgChannels;
- TownsPC98_OpnSfxChannel **_sfxChannels;
- TownsPC98_OpnChannelPCM *_rhythmChannel;
-
- 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 _updateChannelsFlag;
- uint8 _updateSSGFlag;
- uint8 _updateRhythmFlag;
- uint8 _updateSfxFlag;
- uint8 _finishedChannelsFlag;
- uint8 _finishedSSGFlag;
- uint8 _finishedRhythmFlag;
- uint8 _finishedSfxFlag;
-
- bool _musicPlaying;
- bool _sfxPlaying;
- uint8 _fading;
- uint8 _looping;
- uint32 _musicTickCounter;
-
- int _sfxOffs;
- uint8 *_sfxData;
- uint16 _sfxOffsets[2];
-
- static const uint8 _drvTables[];
-
- bool _ready;
-};
-
-TownsPC98_OpnChannel::TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num,
- uint8 key, uint8 prt, uint8 id) : _drv(driver), _regOffset(regOffs), _flags(flgs), _chanNum(num), _keyNum(key),
- _part(prt), _idFlag(id), controlEvents(0) {
-
- _ticksLeft = _algorithm = _instr = _totalLevel = _frqBlockMSB = _keyOffTime = 0;
- _ssgStartLvl = _ssgTl = _ssgStep = _ssgTicksLeft = _ssgTargetLvl = _block = 0;
- _vbrInitDelayHi = _vbrInitDelayLo = _vbrDuration = _vbrCurDelay = _vbrDurLeft = 0;
- _frqLSB = 0;
- _hold = false;
- _dataPtr = 0;
- _vbrModInitVal = _vbrModCurVal = 0;
- _frequency = 0;
-}
-
-TownsPC98_OpnChannel::~TownsPC98_OpnChannel() {
-}
-
-void TownsPC98_OpnChannel::init() {
- #define Control(x) &TownsPC98_OpnChannel::control_##x
- static const ControlEventFunc ctrlEvents[] = {
- Control(f0_setPatch),
- Control(f1_presetOutputLevel),
- Control(f2_setKeyOffTime),
- Control(f3_setFreqLSB),
- Control(f4_setOutputLevel),
- Control(f5_setTempo),
- Control(f6_repeatSection),
- Control(f7_setupVibrato),
- Control(f8_toggleVibrato),
- Control(dummy),
- Control(fa_writeReg),
- Control(fb_incOutLevel),
- Control(fc_decOutLevel),
- Control(fd_jump),
- Control(dummy),
- Control(ff_endOfTrack)
- };
- #undef Control
-
- controlEvents = ctrlEvents;
-}
-
-void TownsPC98_OpnChannel::keyOff() {
- // all operators off
- uint8 value = _keyNum & 0x0f;
- 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;
- if (_part)
- value |= 4;
- uint8 regAddress = 0x28;
- _drv->writeReg(0, regAddress, value);
-}
-
-void TownsPC98_OpnChannel::loadData(uint8 *data) {
- _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
- _ticksLeft = 1;
- _dataPtr = data;
- _totalLevel = 0x7F;
-
- uint8 *src_b = _dataPtr;
- int loop = 1;
- uint8 cmd = 0;
- while (loop) {
- if (loop == 1) {
- cmd = *src_b++;
- if (cmd < 0xf0) {
- src_b++;
- loop = 1;
- } else {
- if (cmd == 0xff) {
- loop = *src_b ? 2 : 0;
- if (READ_LE_UINT16(src_b))
- _drv->_looping |= _idFlag;
- } else if (cmd == 0xf6) {
- loop = 3;
- } else {
- loop = 2;
- }
- }
- } else if (loop == 2) {
- src_b += _drv->_opnFxCmdLen[cmd - 240];
- loop = 1;
- } else if (loop == 3) {
- src_b[0] = src_b[1];
- src_b += 4;
- loop = 1;
- }
- }
-}
-
-void TownsPC98_OpnChannel::processEvents() {
- if (_flags & CHS_EOT)
- return;
-
- if (!_hold && _ticksLeft == _keyOffTime)
- keyOff();
-
- if (--_ticksLeft)
- return;
-
- if (!_hold)
- keyOff();
-
- 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) {
- keyOff();
- _hold = false;
- } else {
- keyOn();
-
- if (_hold == false || cmd != _frqBlockMSB)
- _flags |= CHS_RECALCFREQ;
-
- _hold = (para & 0x80) ? true : false;
- _frqBlockMSB = cmd;
- }
-
- _ticksLeft = para & 0x7f;
-}
-
-void TownsPC98_OpnChannel::processFrequency() {
- if (_flags & CHS_RECALCFREQ) {
-
- _frequency = (((const uint16 *)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f] + _frqLSB) | (((_frqBlockMSB & 0x70) >> 1) << 8);
-
- _drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8));
- _drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff));
-
- setupVibrato();
- }
-
- if (!(_flags & CHS_VBROFF)) {
- if (!processVibrato())
- return;
-
- _drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8));
- _drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff));
- }
-}
-
-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) {
- uint8 para = *_dataPtr++;
- return (this->*controlEvents[cmd & 0x0f])(para);
-}
-
-void TownsPC98_OpnChannel::setOutputLevel() {
- uint8 outopr = _drv->_opnCarrier[_algorithm];
- uint8 reg = 0x40 + _regOffset;
-
- for (int i = 0; i < 4; i++) {
- if (outopr & 1)
- _drv->writeReg(_part, reg, _totalLevel);
- outopr >>= 1;
- reg += 4;
- }
-}
-
-void TownsPC98_OpnChannel::fadeStep() {
- _totalLevel += 3;
- if (_totalLevel > 0x7f)
- _totalLevel = 0x7f;
- setOutputLevel();
-}
-
-void TownsPC98_OpnChannel::reset() {
- _hold = false;
- _keyOffTime = 0;
- _ticksLeft = 1;
-
- _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
-
- _totalLevel = 0;
- _algorithm = 0;
- _flags = CHS_EOT;
- _algorithm = 0;
-
- _block = 0;
- _frequency = 0;
- _frqBlockMSB = 0;
- _frqLSB = 0;
-
- _ssgTl = 0;
- _ssgStartLvl = 0;
- _ssgTargetLvl = 0;
- _ssgStep = 0;
- _ssgTicksLeft = 0;
-
- _vbrInitDelayHi = 0;
- _vbrInitDelayLo = 0;
- _vbrModInitVal = 0;
- _vbrDuration = 0;
- _vbrCurDelay = 0;
- _vbrModCurVal = 0;
- _vbrDurLeft = 0;
-}
-
-bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) {
- _instr = para;
- uint8 reg = _regOffset + 0x80;
-
- for (int i = 0; i < 4; i++) {
- // set release rate for each operator
- _drv->writeReg(_part, reg, 0x0f);
- reg += 4;
- }
-
- const uint8 *tptr = _drv->_patches + ((uint32)_instr << 5);
- reg = _regOffset + 0x30;
-
- // write registers 0x30 to 0x8f
- for (int i = 0; i < 6; i++) {
- _drv->writeReg(_part, reg, tptr[0]);
- reg += 4;
- _drv->writeReg(_part, reg, tptr[2]);
- reg += 4;
- _drv->writeReg(_part, reg, tptr[1]);
- reg += 4;
- _drv->writeReg(_part, reg, tptr[3]);
- reg += 4;
- tptr += 4;
- }
-
- reg = _regOffset + 0xB0;
- _algorithm = tptr[0] & 7;
- // set feedback and algorithm
- _drv->writeReg(_part, reg, tptr[0]);
-
- setOutputLevel();
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_f1_presetOutputLevel(uint8 para) {
- if (_drv->_fading)
- return true;
-
- _totalLevel = _drv->_opnLvlPresets[para];
- setOutputLevel();
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_f2_setKeyOffTime(uint8 para) {
- _keyOffTime = para;
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_f3_setFreqLSB(uint8 para) {
- _frqLSB = (int8) para;
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_f4_setOutputLevel(uint8 para) {
- if (_drv->_fading)
- return true;
-
- _totalLevel = para;
- setOutputLevel();
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_f5_setTempo(uint8 para) {
- _drv->setMusicTempo(para);
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_f6_repeatSection(uint8 para) {
- _dataPtr--;
- _dataPtr[0]--;
-
- if (*_dataPtr) {
- // repeat section until counter has reached zero
- _dataPtr = _drv->_trackPtr + READ_LE_UINT16(_dataPtr + 2);
- } else {
- // reset counter, advance to next section
- _dataPtr[0] = _dataPtr[1];
- _dataPtr += 4;
- }
- return true;
-}
-
-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_VBROFF) | CHS_KEYOFF | CHS_RECALCFREQ;
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_f8_toggleVibrato(uint8 para) {
- if (para == 0x10) {
- if (*_dataPtr++) {
- _flags = (_flags & ~CHS_VBROFF) | CHS_KEYOFF;
- } else {
- _flags |= CHS_VBROFF;
- }
- } else {
- /* 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) {
- _drv->writeReg(_part, para, *_dataPtr++);
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_fb_incOutLevel(uint8 para) {
- _dataPtr--;
- if (_drv->_fading)
- return true;
-
- uint8 val = (_totalLevel + 3);
- if (val > 0x7f)
- val = 0x7f;
-
- _totalLevel = val;
- setOutputLevel();
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_fc_decOutLevel(uint8 para) {
- _dataPtr--;
- if (_drv->_fading)
- return true;
-
- int8 val = (int8) (_totalLevel - 3);
- if (val < 0)
- val = 0;
-
- _totalLevel = (uint8) val;
- setOutputLevel();
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_fd_jump(uint8 para) {
- uint8 *tmp = _drv->_trackPtr + READ_LE_UINT16(_dataPtr - 1);
- _dataPtr = (tmp[1] == 1) ? tmp : (_dataPtr + 1);
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_dummy(uint8 para) {
- _dataPtr--;
- return true;
-}
-
-bool TownsPC98_OpnChannel::control_ff_endOfTrack(uint8 para) {
- uint16 val = READ_LE_UINT16(--_dataPtr);
- if (val) {
- // loop
- _dataPtr = _drv->_trackPtr + val;
- return true;
- } else {
- // quit parsing for active channel
- --_dataPtr;
- _flags |= CHS_EOT;
- _drv->_finishedChannelsFlag |= _idFlag;
- keyOff();
- return false;
- }
-}
-
-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), controlEvents(0) {
-}
-
-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_OpnChannelSSG::control_f1_setTotalLevel(uint8 para) {
- if (!_drv->_fading)
- _totalLevel = para;
- return true;
-}
-
-bool TownsPC98_OpnChannelSSG::control_f4_setAlgorithm(uint8 para) {
- _algorithm = para;
- return true;
-}
-
-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_OpnChannelSSG::control_fb_incOutLevel(uint8 para) {
- _dataPtr--;
- if (_drv->_fading)
- return true;
-
- _totalLevel--;
- if ((int8)_totalLevel < 0)
- _totalLevel = 0;
-
- return true;
-}
-
-bool TownsPC98_OpnChannelSSG::control_fc_decOutLevel(uint8 para) {
- _dataPtr--;
- if (_drv->_fading)
- return true;
-
- if (_totalLevel + 1 < 0x10)
- _totalLevel++;
-
- 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 {
- // end of sfx track - restore ssg music channel
- _flags |= CHS_EOT;
- _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_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), controlEvents(0) {
-}
-
-void TownsPC98_OpnChannelPCM::init() {
- _algorithm = 0x80;
-
- #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(dummy),
- Control(dummy),
- Control(dummy),
- Control(fa_writeReg),
- Control(dummy),
- Control(dummy),
- Control(dummy),
- Control(dummy),
- Control(ff_endOfTrack)
- };
- #undef Control
-
- controlEvents = ctrlEventsPCM;
-}
-
-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;
-
- if (--_ticksLeft)
- return;
-
- uint8 cmd = 0;
- bool loop = true;
-
- while (loop) {
- cmd = *_dataPtr++;
- if (cmd == 0x80) {
- loop = false;
- } 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);
-}
-
-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 {
- // quit parsing for active channel
- --_dataPtr;
- _flags |= CHS_EOT;
- _drv->_finishedRhythmFlag |= _idFlag;
- return false;
- }
-}
-
-TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const uint32 timerbase) : _tlTable(0),
- _tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0), _reg(0), _rand(1), _outN(1),
- _nTick(0), _evpUpdateCnt(0), _evpTimer(0x1f), _pReslt(0x1f), _attack(0), _cont(false), _evpUpdate(true),
- _timer(0), _noiseGenerator(0), _chanEnable(0) {
-
- memset(_channels, 0, sizeof(_channels));
- memset(_updateRequestBuf, 0, sizeof(_updateRequestBuf));
- _reg = new uint8 *[11];
-
- _reg[0] = &_channels[0].frqL;
- _reg[1] = &_channels[0].frqH;
- _reg[2] = &_channels[1].frqL;
- _reg[3] = &_channels[1].frqH;
- _reg[4] = &_channels[2].frqL;
- _reg[5] = &_channels[2].frqH;
- _reg[6] = &_noiseGenerator;
- _reg[7] = &_chanEnable;
- _reg[8] = &_channels[0].vol;
- _reg[9] = &_channels[1].vol;
- _reg[10] = &_channels[2].vol;
-
- reset();
-}
-
-TownsPC98_OpnSquareSineSource::~TownsPC98_OpnSquareSineSource() {
- delete[] _tlTable;
- delete[] _tleTable;
- delete[] _reg;
-}
-
-void TownsPC98_OpnSquareSineSource::init(const int *rsTable, const int *rseTable) {
- if (_ready) {
- reset();
- return;
- }
-
- 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;
- }
-
- 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_OpnSquareSineSource::writeReg(uint8 address, uint8 value, bool force) {
- if (!_ready)
- return;
-
- 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 >= 63) {
- warning("TownsPC98_OpnSquareSineSource: event buffer overflow");
- _updateRequest = -1;
- }
- _updateRequestBuf[++_updateRequest] = value;
- _updateRequestBuf[++_updateRequest] = address;
- return;
- }
-
- *_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;
-
- _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];
- }
-
- finOut /= 3;
- buffer[i << 1] += finOut;
- buffer[(i << 1) + 1] += finOut;
- }
-}
-
-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);
- _reg = new uint8 *[40];
-
- _reg[0] = _reg[1] = _reg[2] = _reg[3] = _reg[4] = _reg[5] = _reg[6] = _reg[7] = _reg[8] = _reg[9] = _reg[10] = _reg[11] = _reg[12] = _reg[13] = _reg[14] = _reg[15] = 0;
- _reg[16] = &_rhChan[0].startPosL;
- _reg[17] = &_rhChan[1].startPosL;
- _reg[18] = &_rhChan[2].startPosL;
- _reg[19] = &_rhChan[3].startPosL;
- _reg[20] = &_rhChan[4].startPosL;
- _reg[21] = &_rhChan[5].startPosL;
- _reg[22] = &_rhChan[0].startPosH;
- _reg[23] = &_rhChan[1].startPosH;
- _reg[24] = &_rhChan[2].startPosH;
- _reg[25] = &_rhChan[3].startPosH;
- _reg[26] = &_rhChan[4].startPosH;
- _reg[27] = &_rhChan[5].startPosH;
- _reg[28] = &_rhChan[0].endPosL;
- _reg[29] = &_rhChan[1].endPosL;
- _reg[30] = &_rhChan[2].endPosL;
- _reg[31] = &_rhChan[3].endPosL;
- _reg[32] = &_rhChan[4].endPosL;
- _reg[33] = &_rhChan[5].endPosL;
- _reg[34] = &_rhChan[0].endPosH;
- _reg[35] = &_rhChan[1].endPosH;
- _reg[36] = &_rhChan[2].endPosH;
- _reg[37] = &_rhChan[3].endPosH;
- _reg[38] = &_rhChan[4].endPosH;
- _reg[39] = &_rhChan[5].endPosH;
-}
-
-void TownsPC98_OpnPercussionSource::init(const uint8 *instrData) {
- if (_ready) {
- reset();
- return;
- }
-
- const uint8 *start = instrData;
- const uint8 *pos = start;
-
- 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_OpnPercussionSource::reset() {
- _timer = 0;
- _totalLevel = 63;
-
- 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_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_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) {
- if (!_ready)
- return;
-
- 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 <<= 1;
-
- buffer[i << 1] += finOut;
- buffer[(i << 1) + 1] += finOut;
- }
-}
-
-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;
-}
-
-void TownsPC98_OpnPercussionSource::advanceInput(RhtChannel *ins) {
- static const int8 adjustIndex[] = {-1, -1, -1, -1, 2, 5, 7, 9 };
-
- 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++;
-
- 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() {
- Common::StackLock lock(_mutex);
- _mixer->stopHandle(_soundHandle);
- delete _ssg;
- delete _prc;
- delete[] _chanInternal;
-
- delete[] _oprRates;
- delete[] _oprRateshift;
- delete[] _oprFrq;
- delete[] _oprAttackDecay;
- delete[] _oprSinTbl;
- delete[] _oprLevelOut;
- delete[] _oprDetune;
-}
-
-bool TownsPC98_OpnCore::init() {
- if (_ready) {
- reset();
- return true;
- }
-
- generateTables();
-
- _chanInternal = new ChanInternal[_numChan];
- for (int i = 0; i < _numChan; i++) {
- memset(&_chanInternal[i], 0, sizeof(ChanInternal));
- for (int j = 0; j < 4; ++j)
- _chanInternal[i].opr[j] = new TownsPC98_OpnOperator(_timerbase, _oprRates, _oprRateshift, _oprAttackDecay, _oprFrq, _oprSinTbl, _oprLevelOut, _oprDetune);
- }
-
- if (_numSSG) {
- _ssg = new TownsPC98_OpnSquareSineSource(_timerbase);
- _ssg->init(&_ssgTables[0], &_ssgTables[16]);
- }
-
- if (_hasPercussion) {
- _prc = new TownsPC98_OpnPercussionSource(_timerbase);
- _prc->init(_percussionData);
- }
-
- _mixer->playStream(Audio::Mixer::kMusicSoundType,
- &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
- _ready = true;
-
- return true;
-}
-
-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;
- }
-
- writeReg(0, 0x27, 0x33);
-
- if (_ssg)
- _ssg->reset();
-
- if (_prc)
- _prc->reset();
-}
-
-void TownsPC98_OpnCore::writeReg(uint8 part, uint8 regAddress, uint8 value) {
- if (_regProtectionFlag || !_ready)
- return;
-
- static const uint8 oprOrdr[] = { 0, 2, 1, 3 };
-
- uint8 h = regAddress & 0xf0;
- uint8 l = (regAddress & 0x0f);
-
- ChanInternal *c = 0;
- TownsPC98_OpnOperator **co = 0;
- TownsPC98_OpnOperator *o = 0;
-
- if (regAddress > 0x2F) {
- c = &_chanInternal[(l & 3) + 3 * part];
- co = c->opr;
- o = c->opr[oprOrdr[(l - (l & 3)) >> 2]];
- } else if (regAddress == 0x28) {
- c = &_chanInternal[(value & 3) + ((value & 4) ? 3 : 0)];
- co = c->opr;
- }
-
- switch (h) {
- case 0x00:
- // ssg
- if (_ssg)
- _ssg->writeReg(l, value);
- break;
- case 0x10:
- // pcm rhythm channel
- if (_prc)
- _prc->writeReg(l, value);
- break;
- case 0x20:
- if (l == 8) {
- // Key on/off
- for (int i = 0; i < 4; i++) {
- if ((value >> (4 + i)) & 1)
- co[oprOrdr[i]]->keyOn();
- else
- co[oprOrdr[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;
-
- case 0x30:
- // detune, multiple
- o->detune((value >> 4) & 7);
- o->multiple(value & 0x0f);
- c->updateEnvelopeParameters = true;
- break;
-
- case 0x40:
- // total level
- o->totalLevel(value & 0x7f);
- break;
-
- case 0x50:
- // rate scaling, attack rate
- o->attackRate(value & 0x1f);
- if (o->scaleRate(value >> 6))
- c->updateEnvelopeParameters = true;
- break;
-
- 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;
-
- case 0x70:
- // secondary decay rate
- o->sustainRate(value & 0x1f);
- break;
-
- case 0x80:
- // secondary amplitude, release rate;
- o->sustainLevel(value >> 4);
- o->releaseRate(value & 0x0f);
- break;
-
- case 0x90:
- warning("TownsPC98_OpnDriver: TRYING TO SSG ENVELOPE SHAPES (NOT SUPPORTED)");
- break;
-
- 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;
-
- 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;
-
- default:
- warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAddress);
- }
-}
-
-int TownsPC98_OpnCore::readBuffer(int16 *buffer, const int numSamples) {
- Common::StackLock lock(_mutex);
-
- memset(buffer, 0, sizeof(int16) * numSamples);
- int32 *tmp = new int32[numSamples];
- int32 *tmpStart = tmp;
- memset(tmp, 0, sizeof(int32) * numSamples);
- int32 samplesLeft = numSamples >> 1;
-
- while (samplesLeft) {
- int32 render = samplesLeft;
-
- 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;
-
- _timers[i].smpTillCbRem += _timers[i].smpPerCbRem;
- if (_timers[i].smpTillCbRem >= _timerbase) {
- _timers[i].smpTillCb++;
- _timers[i].smpTillCbRem -= _timerbase;
- }
- }
- render = MIN(render, _timers[i].smpTillCb);
- }
- }
-
- samplesLeft -= render;
-
- for (int i = 0; i < 2; i++) {
- if (_timers[i].enabled && _timers[i].cb) {
- _timers[i].smpTillCb -= render;
- }
- }
-
- nextTick(tmp, render);
-
- if (_ssg)
- _ssg->nextTick(tmp, render);
- if (_prc)
- _prc->nextTick(tmp, render);
-
- 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;
- }
-
- buffer += (render << 1);
- tmp += (render << 1);
- }
-
- delete[] tmpStart;
- return numSamples;
-}
-
-void TownsPC98_OpnCore::generateTables() {
- delete[] _oprRates;
- _oprRates = new uint8[128];
-
- WRITE_BE_UINT32(_oprRates + 32, _numChan == 6 ? 0x90900000 : 0x00081018);
- WRITE_BE_UINT32(_oprRates + 36, _numChan == 6 ? 0x00001010 : 0x00081018);
- memset(_oprRates, 0x90, 32);
- memset(_oprRates + 96, 0x80, 32);
- uint8 *dst = (uint8 *)_oprRates + 40;
- for (int i = 0; i < 40; i += 4)
- WRITE_BE_UINT32(dst + i, 0x00081018);
- for (int i = 0; i < 48; i += 4)
- WRITE_BE_UINT32(dst + i, 0x00081018);
- dst += 40;
- for (uint8 i = 0; i < 16; i ++) {
- uint8 v = (i < 12) ? i : 12;
- *dst++ = ((4 + v) << 3);
- }
-
- delete[] _oprRateshift;
- _oprRateshift = new uint8[128];
- memset(_oprRateshift, 0, 128);
- dst = (uint8 *)_oprRateshift + 32;
- for (int i = 11; i; i--) {
- memset(dst, i, 4);
- dst += 4;
- }
-
- delete[] _oprFrq;
- _oprFrq = new uint32[0x1000];
- for (uint32 i = 0; i < 0x1000; i++)
- _oprFrq[i] = (uint32)(_baserate * (float)(i << 11));
-
- delete[] _oprAttackDecay;
- _oprAttackDecay = new uint8[152];
- memset(_oprAttackDecay, 0, 152);
- for (int i = 0; i < 36; i++)
- WRITE_BE_UINT32(_oprAttackDecay + (i << 2), _adtStat[i]);
-
- delete[] _oprSinTbl;
- _oprSinTbl = new uint32[1024];
- for (int i = 0; i < 1024; i++) {
- double val = sin((double) (((i << 1) + 1) * PI / 1024.0));
- double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0;
- int32 i_dcb = (int32)(2.0 * d_dcb);
- i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1);
- _oprSinTbl[i] = (i_dcb << 1) + (val >= 0.0 ? 0 : 1);
- }
-
- delete[] _oprLevelOut;
- _oprLevelOut = new int32[0x1a00];
- for (int i = 0; i < 256; i++) {
- double val = floor(65536.0 / pow(2.0, 0.00390625 * (double)(1 + i)));
- int32 val_int = ((int32) val) >> 4;
- _oprLevelOut[i << 1] = (val_int & 1) ? ((val_int >> 1) + 1) << 2 : (val_int >> 1) << 2;
- _oprLevelOut[(i << 1) + 1] = -_oprLevelOut[i << 1];
- for (int ii = 1; ii < 13; ii++) {
- _oprLevelOut[(i << 1) + (ii << 9)] = _oprLevelOut[i << 1] >> ii;
- _oprLevelOut[(i << 1) + (ii << 9) + 1] = -_oprLevelOut[(i << 1) + (ii << 9)];
- }
- }
-
- uint8 *dtt = new uint8[128];
- memset(dtt, 0, 36);
- memset(dtt + 36, 1, 8);
- memcpy(dtt + 44, _detSrc, 84);
-
- delete[] _oprDetune;
- _oprDetune = new int32[256];
- for (int i = 0; i < 128; i++) {
- _oprDetune[i] = (int32) ((float)dtt[i] * _baserate * 64.0);
- _oprDetune[i + 128] = -_oprDetune[i];
- }
-
- delete[] dtt;
-}
-
-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 << 2) / ((_numChan + _numSSG - 3) / 3);
-
- 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),
- _patches(0), _sfxBuffer(0), _musicBuffer(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) {
- _sfxOffsets[0] = _sfxOffsets[1] = 0;
-}
-
-TownsPC98_OpnDriver::~TownsPC98_OpnDriver() {
- reset();
-
- 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;
- }
-
- 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();
-
- Common::StackLock lock(_mutex);
- 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);
-}
-
-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;
- }
-
- Common::StackLock lock(_mutex);
- _sfxData = _sfxBuffer = data;
- _sfxOffsets[0] = READ_LE_UINT16(&_sfxData[(trackNum << 2)]);
- _sfxOffsets[1] = READ_LE_UINT16(&_sfxData[(trackNum << 2) + 2]);
- _sfxPlaying = true;
- _finishedSfxFlag = 0;
-}
-
-void TownsPC98_OpnDriver::reset() {
- Common::StackLock lock(_mutex);
-
- _musicPlaying = false;
- _sfxPlaying = false;
- _fading = false;
- _looping = 0;
- _musicTickCounter = 0;
- _sfxData = 0;
-
- 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();
-}
-
-void TownsPC98_OpnDriver::fadeStep() {
- if (!_musicPlaying)
- return;
-
- Common::StackLock lock(_mutex);
- 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();
- }
-}
-
-void TownsPC98_OpnDriver::timerCallbackB() {
- _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;
-}
-
-void TownsPC98_OpnDriver::timerCallbackA() {
- 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;
-}
-
-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[] = {
- // channel presets
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x01,
- 0x01, 0x80, 0x01, 0x01, 0x00, 0x02,
- 0x02, 0x80, 0x02, 0x02, 0x00, 0x04,
- 0x00, 0x80, 0x03, 0x04, 0x01, 0x08,
- 0x01, 0x80, 0x04, 0x05, 0x01, 0x10,
- 0x02, 0x80, 0x05, 0x06, 0x01, 0x20,
-
- // control event size
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05,
- 0x02, 0x06, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02,
-
- // 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,
-
- // 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,
-
- // 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)
- : Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), _sfxFileData(0),
- _sfxFileIndex((uint)-1), _sfxWDTable(0), _sfxBTTable(0), _parser(0) {
+ : Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), _musicTrackData(0), _sfxFileData(0), _cdaPlaying(0),
+ _sfxFileIndex((uint)-1), _musicFadeTable(0), _sfxWDTable(0), _sfxBTTable(0), _sfxChannel(0x46) {
- _driver = new Towns_EuphonyDriver(_mixer);
- int ret = open();
- if (ret != MERR_ALREADY_OPEN && ret != 0)
- error("couldn't open midi driver");
+ _driver = new TownsEuphonyDriver(_mixer);
}
SoundTowns::~SoundTowns() {
AudioCD.stop();
haltTrack();
+ delete[] _musicTrackData;
delete[] _sfxFileData;
-
- Common::StackLock lock(_mutex);
- _driver->setTimerCallback(0, 0);
- close();
-
- _driver = 0;
}
bool SoundTowns::init() {
_vm->checkCD();
int unused = 0;
+ _musicFadeTable = _vm->staticres()->loadRawData(k1TownsMusicFadeTable, unused);
_sfxWDTable = _vm->staticres()->loadRawData(k1TownsSFXwdTable, unused);
_sfxBTTable = _vm->staticres()->loadRawData(k1TownsSFXbtTable, unused);
+ _musicTrackData = new uint8[50570];
+
+ if (!_driver->init())
+ return false;
- return loadInstruments();
+ if (!loadInstruments())
+ return false;
+
+ _driver->intf()->callback(68);
+ _driver->intf()->callback(70, 0x33);
+ _driver->setOutputVolume(1, 118, 118);
+
+ return true;
}
void SoundTowns::process() {
@@ -3816,10 +94,13 @@ void SoundTowns::playTrack(uint8 track) {
beginFadeOut();
if (_musicEnabled == 2 && trackNum != -1) {
+ _driver->setOutputVolume(1, 118, 118);
AudioCD.play(trackNum+1, loop ? -1 : 1, 0, 0);
AudioCD.updateCD();
+ _cdaPlaying = true;
} else if (_musicEnabled) {
playEuphonyTrack(READ_LE_UINT32(&tTable[tTableIndex]), loop);
+ _cdaPlaying = false;
}
_lastTrack = track;
@@ -3829,15 +110,15 @@ void SoundTowns::haltTrack() {
_lastTrack = -1;
AudioCD.stop();
AudioCD.updateCD();
- if (_parser) {
- Common::StackLock lock(_mutex);
- _parser->setTrack(0);
- _parser->jumpToTick(0);
- _parser->unloadMusic();
- delete _parser;
- _parser = 0;
- }
- _driver->queue()->release();
+ _cdaPlaying = false;
+
+ for (int i = 0; i < 6; i++)
+ _driver->chanVolume(i, 0);
+ for (int i = 0x40; i < 0x46; i++)
+ _driver->chanVolume(i, 0);
+ for (int i = 0; i < 32; i++)
+ _driver->chanEnable(i, 0);
+ _driver->stopParser();
}
void SoundTowns::loadSoundFile(uint file) {
@@ -3851,27 +132,26 @@ void SoundTowns::loadSoundFile(uint file) {
void SoundTowns::playSoundEffect(uint8 track) {
if (!_sfxEnabled || !_sfxFileData)
return;
-
+
if (track == 0 || track == 10) {
- _mixer->stopHandle(_sfxHandle);
+ stopAllSoundEffects();
return;
} else if (track == 1) {
- // sfx fadeout
- _mixer->stopHandle(_sfxHandle);
+ fadeOutSoundEffects();
return;
}
- uint8 note = 0x3c;
+ uint8 note = 60;
if (_sfxFileIndex == 5) {
- if (track == 0x10) {
- note = 0x3e;
- track = 0x0f;
- } else if (track == 0x11) {
- note = 0x40;
- track = 0x0f;
- } else if (track == 0x12) {
- note = 0x41;
- track = 0x0f;
+ if (track == 16) {
+ note = 62;
+ track = 15;
+ } else if (track == 17) {
+ note = 64;
+ track = 15;
+ } else if (track == 18) {
+ note = 65;
+ track = 15;
}
}
@@ -3880,32 +160,37 @@ void SoundTowns::playSoundEffect(uint8 track) {
if (offset == -1)
return;
- uint32 *sfxHeader = (uint32 *)(fileBody + offset);
+ if (!_driver->soundEffectIsPlaying(_sfxChannel ^ 1)) {
+ _sfxChannel ^= 1;
+ } else if (_driver->soundEffectIsPlaying(_sfxChannel)) {
+ _sfxChannel ^= 1;
+ _driver->stopSoundEffect(_sfxChannel);
+ }
+ uint32 *sfxHeader = (uint32 *)(fileBody + offset);
uint32 sfxHeaderID = READ_LE_UINT32(sfxHeader);
- uint32 sfxHeaderInBufferSize = READ_LE_UINT32(&sfxHeader[1]);
- uint32 sfxHeaderOutBufferSize = READ_LE_UINT32(&sfxHeader[3]);
- uint32 sfxRootNoteOffs = READ_LE_UINT32(&sfxHeader[7]);
- uint32 sfxRate = READ_LE_UINT32(&sfxHeader[6]);
+ uint32 playbackBufferSize = sfxHeaderID == 1 ? 30704 : READ_LE_UINT32(&sfxHeader[3]);
- uint32 playbackBufferSize = (sfxHeaderID == 1) ? sfxHeaderInBufferSize : sfxHeaderOutBufferSize;
+ uint8 *sfxPlaybackBuffer = new uint8[playbackBufferSize + 32];
+ memcpy(sfxPlaybackBuffer, fileBody + offset, 32);
- uint8 *sfxPlaybackBuffer = (uint8 *)malloc(playbackBufferSize);
- memset(sfxPlaybackBuffer, 0x80, playbackBufferSize);
+ uint8 *dst = sfxPlaybackBuffer + 32;
+ memset(dst, 0x80, playbackBufferSize);
uint8 *sfxBody = ((uint8 *)sfxHeader) + 0x20;
if (!sfxHeaderID) {
- memcpy(sfxPlaybackBuffer, sfxBody, playbackBufferSize);
+ memcpy(dst, sfxBody, playbackBufferSize);
} else if (sfxHeaderID == 1) {
- Screen::decodeFrame4(sfxBody, sfxPlaybackBuffer, playbackBufferSize);
+ Screen::decodeFrame4(sfxBody, dst, playbackBufferSize);
} else if (_sfxWDTable) {
- uint8 *tgt = sfxPlaybackBuffer;
+ uint8 *tgt = dst;
uint32 sfx_BtTable_Offset = 0;
uint32 sfx_WdTable_Offset = 0;
uint32 sfx_WdTable_Number = 5;
+ uint32 inSize = READ_LE_UINT32(&sfxHeader[1]);
- for (uint32 i = 0; i < sfxHeaderInBufferSize; i++) {
+ for (uint32 i = 0; i < inSize; i++) {
sfx_WdTable_Offset = (sfx_WdTable_Number * 3 << 9) + sfxBody[i] * 6;
sfx_WdTable_Number = READ_LE_UINT16(_sfxWDTable + sfx_WdTable_Offset);
@@ -3917,124 +202,174 @@ void SoundTowns::playSoundEffect(uint8 track) {
}
}
- for (uint32 i = 0; i < playbackBufferSize; i++) {
- if (sfxPlaybackBuffer[i] < 0x80)
- sfxPlaybackBuffer[i] = 0x80 - sfxPlaybackBuffer[i];
- }
+ _driver->chanVolume(_sfxChannel, 127);
+ _driver->chanPanPos(_sfxChannel, 0x40);
+ _driver->chanPitch(_sfxChannel, 0);
+ _driver->playSoundEffect(_sfxChannel, note, 127, sfxPlaybackBuffer);
+}
- playbackBufferSize -= 0x20;
+void SoundTowns::updateVolumeSettings() {
+ if (!_driver)
+ return;
- uint32 outputRate = uint32(11025 * calculatePhaseStep(note, sfxRootNoteOffs, sfxRate, 11025, 0x2000));
+ bool mute = false;
+ _driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume"));
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
- _currentSFX = Audio::makeRawStream(sfxPlaybackBuffer, playbackBufferSize,
- outputRate, Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN);
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX);
+ _driver->setMusicVolume((mute ? 0 : ConfMan.getInt("music_volume")));
+ _driver->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
+}
+
+void SoundTowns::stopAllSoundEffects() {
+ _driver->chanVolume(0x46, 0);
+ _driver->chanVolume(0x47, 0);
+ _driver->stopSoundEffect(0x46);
+ _driver->stopSoundEffect(0x47);
+ _sfxChannel = 0x46;
}
void SoundTowns::beginFadeOut() {
- _lastTrack = -1;
- _driver->fading();
+ if (_cdaPlaying) {
+ for (int i = 118; i > 103; i--) {
+ _driver->setOutputVolume(1, i, i);
+ _vm->delay(2 * _vm->tickLength());
+ }
- // TODO: this should fade out too
- AudioCD.stop();
- AudioCD.updateCD();
-}
+ for (int i = 103; i > 83; i -= 2) {
+ _driver->setOutputVolume(1, i, i);
+ _vm->delay(2 * _vm->tickLength());
+ }
-int SoundTowns::open() {
- if (!_driver)
- return 255;
+ for (int i = 83; i > 58; i -= 2) {
+ _driver->setOutputVolume(1, i, i);
+ _vm->delay(_vm->tickLength());
+ }
- int ret = _driver->open();
- if (ret)
- return ret;
+ for (int i = 58; i > 0; i--)
+ _driver->setOutputVolume(1, i, i);
- _driver->setTimerCallback(this, &onTimer);
- return 0;
-}
+ _driver->setOutputVolume(1, 0, 0);
-void SoundTowns::close() {
- if (_driver)
- _driver->close();
-}
+ } else {
+ if (_lastTrack == -1)
+ return;
-void SoundTowns::send(uint32 b) {
- _driver->send(b);
-}
+ uint32 ticks = 2;
+ int tickAdv = 0;
+
+ uint16 fadeVolCur[12];
+ uint16 fadeVolStep[12];
+
+ for (int i = 0; i < 6; i++) {
+ fadeVolCur[i] = READ_LE_UINT16(&_musicFadeTable[(_lastTrack * 12 + i) * 2]);
+ fadeVolStep[i] = fadeVolCur[i] / 50;
+ fadeVolCur[i + 6] = READ_LE_UINT16(&_musicFadeTable[(_lastTrack * 12 + 6 + i) * 2]);
+ fadeVolStep[i + 6] = fadeVolCur[i + 6] / 30;
+ }
+
+ for (int i = 0; i < 12; i++) {
+ for (int ii = 0; ii < 6; ii++)
+ _driver->chanVolume(ii, fadeVolCur[ii]);
+ for (int ii = 0x40; ii < 0x46; ii++)
+ _driver->chanVolume(ii, fadeVolCur[ii - 0x3a]);
+
+ for (int ii = 0; ii < 6; ii++) {
+ fadeVolCur[ii] -= fadeVolStep[ii];
+ if (fadeVolCur[ii] < 10)
+ fadeVolCur[ii] = 0;
+ fadeVolCur[ii + 6] -= fadeVolStep[ii + 6];
+ if (fadeVolCur[ii + 6] < 10)
+ fadeVolCur[ii + 6] = 0;
+ }
+
+ if (++tickAdv == 3) {
+ tickAdv = 0;
+ ticks += 2;
+ }
+ _vm->delay(ticks * _vm->tickLength());
+ }
+ }
-uint32 SoundTowns::getBaseTempo() {
- return _driver ? _driver->getBaseTempo() : 0;
+ haltTrack();
}
bool SoundTowns::loadInstruments() {
uint8 *twm = _vm->resource()->fileData("twmusic.pak", 0);
if (!twm)
return false;
- _driver->queue()->loadDataToCurrentPosition(twm, 0x8BF0);
- _driver->loadFmInstruments(_driver->queue()->trackData() + 8);
- _driver->queue()->loadDataToCurrentPosition(twm + 0x0CA0, 0xC58A);
- _driver->loadWaveInstruments(_driver->queue()->trackData() + 8);
+ Common::StackLock lock(_mutex);
+
+ Screen::decodeFrame4(twm, _musicTrackData, 50570);
+ for (int i = 0; i < 128; i++)
+ _driver->loadInstrument(0, i, &_musicTrackData[i * 48 + 8]);
+
+ Screen::decodeFrame4(twm + 3232, _musicTrackData, 50570);
+ for (int i = 0; i < 32; i++)
+ _driver->loadInstrument(0x40, i, &_musicTrackData[i * 128 + 8]);
+
+ _driver->unloadWaveTable(-1);
+ uint8 *src = &_musicTrackData[32 * 128 + 8];
+ for (int i = 0; i < 10; i++) {
+ _driver->loadWaveTable(src);
+ src = src + READ_LE_UINT16(&src[12]) + 32;
+ }
+
+ _driver->reserveSoundEffectChannels(2);
+
delete[] twm;
- _driver->queue()->release();
return true;
}
void SoundTowns::playEuphonyTrack(uint32 offset, int loop) {
- uint8 *twm = _vm->resource()->fileData("twmusic.pak", 0);
Common::StackLock lock(_mutex);
- if (!_parser) {
- _parser = new Towns_EuphonyParser(_driver->queue());
- _parser->setMidiDriver(this);
- _parser->setTimerRate(getBaseTempo());
- }
+ uint8 *twm = _vm->resource()->fileData("twmusic.pak", 0);
+ Screen::decodeFrame4(twm + 19312 + offset, _musicTrackData, 50570);
+ delete[] twm;
+
+ const uint8 *src = _musicTrackData + 852;
+ for (int i = 0; i < 32; i++)
+ _driver->chanEnable(i, *src++);
+ for (int i = 0; i < 32; i++)
+ _driver->chanMode(i, *src++);
+ for (int i = 0; i < 32; i++)
+ _driver->chanOrdr(i, *src++);
+ for (int i = 0; i < 32; i++)
+ _driver->chanVolumeShift(i, *src++);
+ for (int i = 0; i < 32; i++)
+ _driver->chanNoteShift(i, *src++);
+
+ src = _musicTrackData + 1748;
+ for (int i = 0; i < 6; i++)
+ _driver->assignChannel(i, *src++);
+ for (int i = 0x40; i < 0x46; i++)
+ _driver->assignChannel(i, *src++);
- _parser->property(MidiParser::mpAutoLoop, loop);
- _parser->loadMusic(twm + 0x4b70 + offset, 0xC58A);
+ uint32 trackSize = READ_LE_UINT32(_musicTrackData + 2048);
+ uint8 startTick = _musicTrackData[2052];
+
+ _driver->setMusicTempo(_musicTrackData[2053]);
- delete[] twm;
-}
+ src = _musicTrackData + 2054;
+ uint32 l = READ_LE_UINT32(src + trackSize);
+ trackSize += (l + 4);
+ l = READ_LE_UINT32(src + trackSize);
+ trackSize += (l + 4);
-void SoundTowns::onTimer(void *data) {
- SoundTowns *music = (SoundTowns *)data;
- Common::StackLock lock(music->_mutex);
- if (music->_parser)
- music->_parser->onTimer();
+ _driver->setMusicLoop(loop);
+ _driver->startMusicTrack(src, trackSize, startTick);
}
-float SoundTowns::calculatePhaseStep(int8 semiTone, int8 semiToneRootkey,
- uint32 sampleRate, uint32 outputRate, int32 pitchWheel) {
- if (semiTone < 0)
- semiTone = 0;
- if (semiTone > 119)
- semiTone = 119;
- if (semiTone < 0)
- semiTone = 0;
- if (semiTone > 119)
- semiTone = 119;
-
- static const float noteFrq[] = {
- 0004.13f, 0004.40f, 0004.64f, 0004.95f, 0005.16f, 0005.50f, 0005.80f, 0006.19f, 0006.60f, 0006.86f,
- 0007.43f, 0007.73f, 0008.25f, 0008.80f, 0009.28f, 0009.90f, 0010.31f, 0011.00f, 0011.60f, 0012.38f,
- 0013.20f, 0013.75f, 0014.85f, 0015.47f, 0016.50f, 0017.60f, 0018.56f, 0019.80f, 0020.63f, 0022.00f,
- 0023.21f, 0024.75f, 0026.40f, 0027.50f, 0029.70f, 0030.94f, 0033.00f, 0035.20f, 0037.16f, 0039.60f,
- 0041.25f, 0044.00f, 0046.41f, 0049.50f, 0052.80f, 0055.00f, 0059.40f, 0061.88f, 0066.00f, 0070.40f,
- 0074.25f, 0079.20f, 0082.50f, 0088.00f, 0092.83f, 0099.00f, 0105.60f, 0110.00f, 0118.80f, 0123.75f,
- 0132.00f, 0140.80f, 0148.50f, 0158.40f, 0165.00f, 0176.00f, 0185.65f, 0198.00f, 0211.20f, 0220.00f,
- 0237.60f, 0247.50f, 0264.00f, 0281.60f, 0297.00f, 0316.80f, 0330.00f, 0352.00f, 0371.30f, 0396.00f,
- 0422.40f, 0440.00f, 0475.20f, 0495.00f, 0528.00f, 0563.20f, 0594.00f, 0633.60f, 0660.00f, 0704.00f,
- 0742.60f, 0792.00f, 0844.80f, 0880.00f, 0950.40f, 0990.00f, 1056.00f, 1126.40f, 1188.00f, 1267.20f,
- 1320.00f, 1408.00f, 1485.20f, 1584.00f, 1689.60f, 1760.00f, 1900.80f, 1980.00f, 2112.00f, 2252.80f,
- 2376.00f, 2534.40f, 2640.00f, 2816.00f, 2970.40f, 3168.00f, 3379.20f, 3520.00f, 3801.60f, 3960.00f
- };
-
- float pwModifier = (pitchWheel - 0x2000) / 0x2000;
- int8 d = pwModifier ? (pwModifier < 0 ? -1 : 1) : 0;
- float rateshift = (noteFrq[semiTone] - ((noteFrq[semiTone] -
- noteFrq[semiTone + d]) * pwModifier * d)) / noteFrq[semiToneRootkey];
-
- return (float)sampleRate * 10.0f * rateshift / outputRate;
+void SoundTowns::fadeOutSoundEffects() {
+ for (int i = 127; i > 0; i-= 12) {
+ _driver->chanVolume(0x46, i);
+ _driver->chanVolume(0x47, i);
+ _vm->delay(_vm->tickLength());
+ }
+ stopAllSoundEffects();
}
SoundPC98::SoundPC98(KyraEngine_v1 *vm, Audio::Mixer *mixer) :
@@ -4048,8 +383,10 @@ SoundPC98::~SoundPC98() {
}
bool SoundPC98::init() {
- _driver = new TownsPC98_OpnDriver(_mixer, TownsPC98_OpnDriver::OD_TYPE26);
- return _driver->init();
+ _driver = new TownsPC98_AudioDriver(_mixer, TownsPC98_AudioDriver::kType26);
+ bool reslt = _driver->init();
+ updateVolumeSettings();
+ return reslt;
}
void SoundPC98::loadSoundFile(uint file) {
@@ -4122,6 +459,18 @@ void SoundPC98::playSoundEffect(uint8 track) {
_driver->loadSoundEffectData(_sfxTrackData, track);
}
+void SoundPC98::updateVolumeSettings() {
+ if (!_driver)
+ return;
+
+ bool mute = false;
+ _driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume"));
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ _driver->setMusicVolume((mute ? 0 : ConfMan.getInt("music_volume")));
+ _driver->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
+}
// KYRA 2
@@ -4136,8 +485,8 @@ SoundTownsPC98_v2::~SoundTownsPC98_v2() {
}
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_AudioDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ?
+ TownsPC98_AudioDriver::kType86 : TownsPC98_AudioDriver::kTypeTowns);
if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
_vm->checkCD();
@@ -4160,7 +509,9 @@ bool SoundTownsPC98_v2::init() {
_useFmSfx = true;
}
- return _driver->init();
+ bool reslt = _driver->init();
+ updateVolumeSettings();
+ return reslt;
}
void SoundTownsPC98_v2::loadSoundFile(Common::String file) {
@@ -4235,7 +586,7 @@ void SoundTownsPC98_v2::beginFadeOut() {
}
int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, uint8, bool) {
- static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 };
+ //static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 };
static const char patternHOF[] = "%s.PCM";
static const char patternLOL[] = "%s.VOC";
@@ -4256,7 +607,7 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle,
if (!src)
return 0;
- uint16 sfxRate = rates[READ_LE_UINT16(src)];
+ //uint16 sfxRate = rates[READ_LE_UINT16(src)];
src += 2;
bool compressed = (READ_LE_UINT16(src) & 1) ? true : false;
src += 2;
@@ -4296,9 +647,7 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle,
sfx[i] = cmd;
}
- uint32 outputRate = uint32(11025 * SoundTowns::calculatePhaseStep(0x3c, 0x3c, sfxRate, 11025, 0x2000));
-
- _currentSFX = Audio::makeRawStream(sfx, outsize, outputRate,
+ _currentSFX = Audio::makeRawStream(sfx, outsize, 11025,
Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h], _currentSFX);
if (handle)
@@ -4315,157 +664,18 @@ void SoundTownsPC98_v2::playSoundEffect(uint8 track) {
_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
-};
-
-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
-};
-
-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
-};
+void SoundTownsPC98_v2::updateVolumeSettings() {
+ if (!_driver)
+ return;
+
+ bool mute = false;
+ _driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume"));
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ _driver->setMusicVolume((mute ? 0 : ConfMan.getInt("music_volume")));
+ _driver->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
+}
} // End of namespace Kyra
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 2f2acd78d1..4b71b1d69d 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -27,25 +27,22 @@
#include "common/md5.h"
#include "kyra/kyra_v1.h"
#include "kyra/kyra_lok.h"
-#include "kyra/lol.h"
#include "kyra/kyra_v2.h"
#include "kyra/kyra_hof.h"
#include "kyra/kyra_mr.h"
#include "kyra/screen.h"
#include "kyra/screen_lok.h"
-#include "kyra/screen_lol.h"
#include "kyra/screen_hof.h"
#include "kyra/screen_mr.h"
#include "kyra/resource.h"
#include "kyra/gui_lok.h"
-#include "kyra/gui_lol.h"
#include "kyra/gui_hof.h"
#include "kyra/gui_mr.h"
#include "kyra/sound_intern.h"
namespace Kyra {
-#define RESFILE_VERSION 70
+#define RESFILE_VERSION 72
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
@@ -305,36 +302,6 @@ const ItemAnimData_v2 *StaticResource::loadShapeAnimData_v2(int id, int &entries
return (const ItemAnimData_v2 *)getData(id, k2ShpAnimDataV2, entries);
}
-#ifdef ENABLE_LOL
-const LoLCharacter *StaticResource::loadCharData(int id, int &entries) {
- return (const LoLCharacter *)getData(id, kLolCharData, entries);
-}
-
-const SpellProperty *StaticResource::loadSpellData(int id, int &entries) {
- return (const SpellProperty *)getData(id, kLolSpellData, entries);
-}
-
-const CompassDef *StaticResource::loadCompassData(int id, int &entries) {
- return (const CompassDef *)getData(id, kLolCompassData, entries);
-}
-
-const FlyingObjectShape *StaticResource::loadFlyingObjectData(int id, int &entries) {
- return (const FlyingObjectShape *)getData(id, kLolFlightShpData, entries);
-}
-
-const uint16 *StaticResource::loadRawDataBe16(int id, int &entries) {
- return (const uint16 *)getData(id, kLolRawDataBe16, entries);
-}
-
-const uint32 *StaticResource::loadRawDataBe32(int id, int &entries) {
- return (const uint32 *)getData(id, kLolRawDataBe32, entries);
-}
-
-const ButtonDef *StaticResource::loadButtonDefs(int id, int &entries) {
- return (const ButtonDef *)getData(id, kLolButtonData, entries);
-}
-#endif // ENABLE_LOL
-
bool StaticResource::prefetchId(int id) {
if (id == -1) {
for (DataMap::const_iterator i = _dataTable.begin(); i != _dataTable.end(); ++i) {
@@ -641,160 +608,6 @@ bool StaticResource::loadShapeAnimData_v2(Common::SeekableReadStream &stream, vo
return true;
}
-#ifdef ENABLE_LOL
-bool StaticResource::loadCharData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
- size = stream.size() / 130;
- LoLCharacter *charData = new LoLCharacter[size];
-
- for (int i = 0; i < size; i++) {
- LoLCharacter *t = &charData[i];
-
- t->flags = stream.readUint16LE();
- stream.read(t->name, 11);
- t->raceClassSex = stream.readByte();
- t->id = stream.readSint16LE();
- t->curFaceFrame = stream.readByte();
- t->tempFaceFrame = stream.readByte();
- t->screamSfx = stream.readByte();
- stream.readUint32LE();
- for (int ii = 0; ii < 8; ii++)
- t->itemsMight[ii] = stream.readUint16LE();
- for (int ii = 0; ii < 8; ii++)
- t->protectionAgainstItems[ii] = stream.readUint16LE();
- t->itemProtection = stream.readUint16LE();
- t->hitPointsCur = stream.readSint16LE();
- t->hitPointsMax = stream.readUint16LE();
- t->magicPointsCur = stream.readSint16LE();
- t->magicPointsMax = stream.readUint16LE();
- t->field_41 = stream.readByte();
- t->damageSuffered = stream.readUint16LE();
- t->weaponHit = stream.readUint16LE();
- t->totalMightModifier = stream.readUint16LE();
- t->totalProtectionModifier = stream.readUint16LE();
- t->might = stream.readUint16LE();
- t->protection = stream.readUint16LE();
- t->nextAnimUpdateCountdown = stream.readSint16LE();
- for (int ii = 0; ii < 11; ii++)
- t->items[ii] = stream.readUint16LE();
- for (int ii = 0; ii < 3; ii++)
- t->skillLevels[ii] = stream.readByte();
- for (int ii = 0; ii < 3; ii++)
- t->skillModifiers[ii] = stream.readByte();
- for (int ii = 0; ii < 3; ii++)
- t->experiencePts[ii] = stream.readUint32LE();
- for (int ii = 0; ii < 5; ii++)
- t->characterUpdateEvents[ii] = stream.readByte();
- for (int ii = 0; ii < 5; ii++)
- t->characterUpdateDelay[ii] = stream.readByte();
- };
-
- ptr = charData;
- return true;
-}
-
-bool StaticResource::loadSpellData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
- size = stream.size() / 28;
- SpellProperty *spellData = new SpellProperty[size];
-
- for (int i = 0; i < size; i++) {
- SpellProperty *t = &spellData[i];
-
- t->spellNameCode = stream.readUint16LE();
- for (int ii = 0; ii < 4; ii++)
- t->mpRequired[ii] = stream.readUint16LE();
- t->field_a = stream.readUint16LE();
- t->field_c = stream.readUint16LE();
- for (int ii = 0; ii < 4; ii++)
- t->hpRequired[ii] = stream.readUint16LE();
- t->field_16 = stream.readUint16LE();
- t->field_18 = stream.readUint16LE();
- t->flags = stream.readUint16LE();
- };
-
- ptr = spellData;
- return true;
-}
-
-bool StaticResource::loadCompassData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
- size = stream.size() / 4;
- CompassDef *defs = new CompassDef[size];
-
- for (int i = 0; i < size; i++) {
- CompassDef *t = &defs[i];
- t->shapeIndex = stream.readByte();
- t->x = stream.readByte();
- t->y = stream.readByte();
- t->flags = stream.readByte();
- };
-
-
- ptr = defs;
- return true;
-}
-
-bool StaticResource::loadFlyingObjectData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
- size = stream.size() / 5;
- FlyingObjectShape *defs = new FlyingObjectShape[size];
-
- for (int i = 0; i < size; i++) {
- FlyingObjectShape *t = &defs[i];
- t->shapeFront = stream.readByte();
- t->shapeBack = stream.readByte();
- t->shapeLeft = stream.readByte();
- t->drawFlags = stream.readByte();
- t->flipFlags = stream.readByte();
- };
-
- ptr = defs;
- return true;
-}
-
-bool StaticResource::loadRawDataBe16(Common::SeekableReadStream &stream, void *&ptr, int &size) {
- size = stream.size() >> 1;
-
- uint16 *r = new uint16[size];
-
- for (int i = 0; i < size; i++)
- r[i] = stream.readUint16BE();
-
- ptr = r;
- return true;
-}
-
-bool StaticResource::loadRawDataBe32(Common::SeekableReadStream &stream, void *&ptr, int &size) {
- size = stream.size() >> 2;
-
- uint32 *r = new uint32[size];
-
- for (int i = 0; i < size; i++)
- r[i] = stream.readUint32BE();
-
- ptr = r;
- return true;
-}
-
-bool StaticResource::loadButtonDefs(Common::SeekableReadStream &stream, void *&ptr, int &size) {
- size = stream.size() / 18;
-
- ButtonDef *r = new ButtonDef[size];
-
- for (int i = 0; i < size; i++) {
- r[i].buttonflags = stream.readUint16BE();
- r[i].keyCode = stream.readUint16BE();
- r[i].keyCode2 = stream.readUint16BE();
- r[i].x = stream.readSint16BE();
- r[i].y = stream.readSint16BE();
- r[i].w = stream.readUint16BE();
- r[i].h = stream.readUint16BE();
- r[i].index = stream.readUint16BE();
- r[i].screenDim = stream.readUint16BE();
- }
-
- ptr = r;
- return true;
-}
-#endif // ENABLE_LOL
-
void StaticResource::freeRawData(void *&ptr, int &size) {
uint8 *data = (uint8 *)ptr;
delete[] data;
@@ -870,58 +683,6 @@ void StaticResource::freeHofShapeAnimDataV2(void *&ptr, int &size) {
size = 0;
}
-#ifdef ENABLE_LOL
-void StaticResource::freeCharData(void *&ptr, int &size) {
- LoLCharacter *d = (LoLCharacter *)ptr;
- delete[] d;
- ptr = 0;
- size = 0;
-}
-
-void StaticResource::freeSpellData(void *&ptr, int &size) {
- SpellProperty *d = (SpellProperty *)ptr;
- delete[] d;
- ptr = 0;
- size = 0;
-}
-
-void StaticResource::freeCompassData(void *&ptr, int &size) {
- CompassDef *d = (CompassDef *)ptr;
- delete[] d;
- ptr = 0;
- size = 0;
-}
-
-void StaticResource::freeFlyingObjectData(void *&ptr, int &size) {
- FlyingObjectShape *d = (FlyingObjectShape *)ptr;
- delete[] d;
- ptr = 0;
- size = 0;
-}
-
-
-void StaticResource::freeRawDataBe16(void *&ptr, int &size) {
- uint16 *data = (uint16 *)ptr;
- delete[] data;
- ptr = 0;
- size = 0;
-}
-
-void StaticResource::freeRawDataBe32(void *&ptr, int &size) {
- uint32 *data = (uint32 *)ptr;
- delete[] data;
- ptr = 0;
- size = 0;
-}
-
-void StaticResource::freeButtonDefs(void *&ptr, int &size) {
- ButtonDef *d = (ButtonDef *)ptr;
- delete[] d;
- ptr = 0;
- size = 0;
-}
-#endif // ENABLE_LOL
-
#pragma mark -
void KyraEngine_LoK::initStaticResource() {
@@ -1360,371 +1121,6 @@ void KyraEngine_MR::initStaticResource() {
_itemStringMap = _staticres->loadRawData(k3ItemStringMap, _itemStringMapSize);
}
-#ifdef ENABLE_LOL
-// TODO: move this to lol.cpp maybe?
-void LoLEngine::initStaticResource() {
- // assign music data
- static const char *pcMusicFileListIntro[] = { "LOREINTR" };
- static const char *pcMusicFileListFinale[] = { "LOREFINL" };
- static const char *pcMusicFileListIngame[] = { "LORE%02d%c" };
-
- static const char *pc98MusicFileListIntro[] = { 0, "lore84.86", "lore82.86", 0, 0, 0, "lore83.86", "lore81.86" };
- static const char *pc98MusicFileListFinale[] = { 0, 0, "lore85.86", "lore86.86", "lore87.86" };
- static const char *pc98MusicFileListIngame[] = { "lore%02d.86" };
-
- memset(_soundData, 0, sizeof(_soundData));
- if (_flags.platform == Common::kPlatformPC) {
- _soundData[0].fileList = pcMusicFileListIntro;
- _soundData[0].fileListLen = ARRAYSIZE(pcMusicFileListIntro);
- _soundData[1].fileList = pcMusicFileListIngame;
- _soundData[1].fileListLen = ARRAYSIZE(pcMusicFileListIngame);
- _soundData[2].fileList = pcMusicFileListFinale;
- _soundData[2].fileListLen = ARRAYSIZE(pcMusicFileListFinale);
- } else if (_flags.platform == Common::kPlatformPC98) {
- _soundData[0].fileList = pc98MusicFileListIntro;
- _soundData[0].fileListLen = ARRAYSIZE(pc98MusicFileListIntro);
- _soundData[1].fileList = pc98MusicFileListIngame;
- _soundData[1].fileListLen = ARRAYSIZE(pc98MusicFileListIngame);
- _soundData[2].fileList = pc98MusicFileListFinale;
- _soundData[2].fileListLen = ARRAYSIZE(pc98MusicFileListFinale);
- }
-
- if (_flags.isDemo)
- return;
-
- _pakFileList = _staticres->loadStrings(kLolIngamePakFiles, _pakFileListSize);
- _charDefaults = _staticres->loadCharData(kLolCharacterDefs, _charDefaultsSize);
- _ingameSoundIndex = (const uint16 *)_staticres->loadRawData(kLolIngameSfxIndex, _ingameSoundIndexSize);
- _musicTrackMap = _staticres->loadRawData(kLolMusicTrackMap, _musicTrackMapSize);
- _ingameGMSoundIndex = _staticres->loadRawData(kLolIngameGMSfxIndex, _ingameGMSoundIndexSize);
- _ingameMT32SoundIndex = _staticres->loadRawData(kLolIngameMT32SfxIndex, _ingameMT32SoundIndexSize);
- _ingamePCSpeakerSoundIndex = _staticres->loadRawData(kLolIngamePcSpkSfxIndex, _ingamePCSpeakerSoundIndexSize);
- _spellProperties = _staticres->loadSpellData(kLolSpellProperties, _spellPropertiesSize);
- _gameShapeMap = (const int8 *)_staticres->loadRawData(kLolGameShapeMap, _gameShapeMapSize);
- _sceneItemOffs = (const int8 *)_staticres->loadRawData(kLolSceneItemOffs, _sceneItemOffsSize);
- _charInvIndex = _staticres->loadRawData(kLolCharInvIndex, _charInvIndexSize);
- _charInvDefs = _staticres->loadRawData(kLolCharInvDefs, _charInvDefsSize);
- _charDefsMan = _staticres->loadRawDataBe16(kLolCharDefsMan, _charDefsManSize);
- _charDefsWoman = _staticres->loadRawDataBe16(kLolCharDefsWoman, _charDefsWomanSize);
- _charDefsKieran = _staticres->loadRawDataBe16(kLolCharDefsKieran, _charDefsKieranSize);
- _charDefsAkshel = _staticres->loadRawDataBe16(kLolCharDefsAkshel, _charDefsAkshelSize);
- _expRequirements = (const int32 *)_staticres->loadRawDataBe32(kLolExpRequirements, _expRequirementsSize);
- _monsterModifiers = _staticres->loadRawDataBe16(kLolMonsterModifiers, _monsterModifiersSize);
- _monsterShiftOffs = (const int8 *)_staticres->loadRawData(kLolMonsterShiftOffsets, _monsterShiftOffsSize);
- _monsterDirFlags = _staticres->loadRawData(kLolMonsterDirFlags, _monsterDirFlagsSize);
- _monsterScaleX = _staticres->loadRawData(kLolMonsterScaleX, _monsterScaleXSize);
- _monsterScaleY = _staticres->loadRawData(kLolMonsterScaleY, _monsterScaleYSize);
- _monsterScaleWH = _staticres->loadRawDataBe16(kLolMonsterScaleWH, _monsterScaleWHSize);
- _inventorySlotDesc = _staticres->loadRawDataBe16(kLolInventoryDesc, _inventorySlotDescSize);
- _levelShpList = _staticres->loadStrings(kLolLevelShpList, _levelShpListSize);
- _levelDatList = _staticres->loadStrings(kLolLevelDatList, _levelDatListSize);
- _compassDefs = _staticres->loadCompassData(kLolCompassDefs, _compassDefsSize);
- _flyingItemShapes = _staticres->loadFlyingObjectData(kLolFlyingObjectShp, _flyingItemShapesSize);
- _itemCost = _staticres->loadRawDataBe16(kLolItemPrices, _itemCostSize);
- _stashSetupData = _staticres->loadRawData(kLolStashSetup, _stashSetupDataSize);
-
- _dscUnk1 = (const int8 *)_staticres->loadRawData(kLolDscUnk1, _dscUnk1Size);
- _dscShapeIndex = (const int8 *)_staticres->loadRawData(kLolDscShapeIndex, _dscShapeIndexSize);
- _dscOvlMap = _staticres->loadRawData(kLolDscOvlMap, _dscOvlMapSize);
- _dscShapeScaleW = _staticres->loadRawDataBe16(kLolDscScaleWidthData, _dscShapeScaleWSize);
- _dscShapeScaleH = _staticres->loadRawDataBe16(kLolDscScaleHeightData, _dscShapeScaleHSize);
- _dscShapeX = (const int16 *)_staticres->loadRawDataBe16(kLolDscX, _dscShapeXSize);
- _dscShapeY = (const int8 *)_staticres->loadRawData(kLolDscY, _dscShapeYSize);
- _dscTileIndex = _staticres->loadRawData(kLolDscTileIndex, _dscTileIndexSize);
- _dscUnk2 = _staticres->loadRawData(kLolDscUnk2, _dscUnk2Size);
- _dscDoorShpIndex = _staticres->loadRawData(kLolDscDoorShapeIndex, _dscDoorShpIndexSize);
- _dscDim1 = (const int8 *)_staticres->loadRawData(kLolDscDimData1, _dscDim1Size);
- _dscDim2 = (const int8 *)_staticres->loadRawData(kLolDscDimData2, _dscDim2Size);
- _dscBlockMap = _staticres->loadRawData(kLolDscBlockMap, _dscBlockMapSize);
- _dscDimMap = _staticres->loadRawData(kLolDscDimMap, _dscDimMapSize);
- _dscDoorMonsterScaleTable = _staticres->loadRawDataBe16(kLolDscDoorScale, _dscDoorMonsterScaleTableSize);
- _dscShapeOvlIndex = _staticres->loadRawData(kLolDscOvlIndex, _dscShapeOvlIndexSize);
- _dscDoor4 = _staticres->loadRawDataBe16(kLolDscDoor4, _dscDoor4Size);
- _dscBlockIndex = (const int8 *)_staticres->loadRawData(kLolDscBlockIndex, _dscBlockIndexSize);
- _dscDoor1 = _staticres->loadRawData(kLolDscDoor1, _dscDoor1Size);
- _dscDoorMonsterX = (const int16 *)_staticres->loadRawDataBe16(kLolDscDoorX, _dscDoorMonsterXSize);
- _dscDoorMonsterY = (const int16 *)_staticres->loadRawDataBe16(kLolDscDoorY, _dscDoorMonsterYSize);
-
- _scrollXTop = _staticres->loadRawData(kLolScrollXTop, _scrollXTopSize);
- _scrollYTop = _staticres->loadRawData(kLolScrollYTop, _scrollYTopSize);
- _scrollXBottom = _staticres->loadRawData(kLolScrollXBottom, _scrollXBottomSize);
- _scrollYBottom = _staticres->loadRawData(kLolScrollYBottom, _scrollYBottomSize);
-
- const char *const *tmpSndList = _staticres->loadStrings(kLolIngameSfxFiles, _ingameSoundListSize);
- if (tmpSndList) {
- _ingameSoundList = new char *[_ingameSoundListSize];
- for (int i = 0; i < _ingameSoundListSize; i++) {
- _ingameSoundList[i] = new char[strlen(tmpSndList[i]) + 1];
- strcpy(_ingameSoundList[i], tmpSndList[i]);
- }
- _staticres->unloadId(kLolIngameSfxFiles);
- }
-
- _buttonData = _staticres->loadButtonDefs(kLolButtonDefs, _buttonDataSize);
- _buttonList1 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList1, _buttonList1Size);
- _buttonList2 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList2, _buttonList2Size);
- _buttonList3 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList3, _buttonList3Size);
- _buttonList4 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList4, _buttonList4Size);
- _buttonList5 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList5, _buttonList5Size);
- _buttonList6 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList6, _buttonList6Size);
- _buttonList7 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList7, _buttonList7Size);
- _buttonList8 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList8, _buttonList8Size);
-
- _autoMapStrings = _staticres->loadRawDataBe16(kLolMapStringId, _autoMapStringsSize);
-
- int tmpSize = 0;
- const uint8 *tmp = _staticres->loadRawData(kLolLegendData, tmpSize);
- tmpSize /= 5;
- if (tmp) {
- _defaultLegendData = new MapLegendData[tmpSize];
- for (int i = 0; i < tmpSize; i++) {
- _defaultLegendData[i].shapeIndex = *tmp++;
- _defaultLegendData[i].enable = *tmp++ ? true : false;
- _defaultLegendData[i].x = (int8)*tmp++;
- _defaultLegendData[i].stringId = READ_LE_UINT16(tmp);
- tmp += 2;
- }
- _staticres->unloadId(kLolLegendData);
- }
-
- tmp = _staticres->loadRawData(kLolMapCursorOvl, tmpSize);
- _mapCursorOverlay = new uint8[tmpSize];
- memcpy(_mapCursorOverlay, tmp, tmpSize);
- _staticres->unloadId(kLolMapCursorOvl);
-
- _updateSpellBookCoords = _staticres->loadRawData(kLolSpellbookCoords, _updateSpellBookCoordsSize);
- _updateSpellBookAnimData = _staticres->loadRawData(kLolSpellbookAnim, _updateSpellBookAnimDataSize);
- _healShapeFrames = _staticres->loadRawData(kLolHealShapeFrames, _healShapeFramesSize);
-
- tmp = _staticres->loadRawData(kLolLightningDefs, tmpSize);
- if (tmp) {
- _lightningProps = new LightningProperty[5];
- for (int i = 0; i < 5; i++) {
- _lightningProps[i].lastFrame = tmp[i << 2];
- _lightningProps[i].frameDiv = tmp[(i << 2) + 1];
- _lightningProps[i].sfxId = READ_LE_UINT16(&tmp[(i << 2) + 2]);
- }
- _staticres->unloadId(kLolLightningDefs);
- }
-
- _fireBallCoords = (const int16 *)_staticres->loadRawDataBe16(kLolFireballCoords, _fireBallCoordsSize);
-
- _buttonCallbacks.clear();
- _buttonCallbacks.reserve(95);
-#define cb(x) _buttonCallbacks.push_back(BUTTON_FUNCTOR(LoLEngine, this, &LoLEngine::x))
- // 0x00
- cb(clickedUpArrow);
- cb(clickedDownArrow);
- _buttonCallbacks.push_back(_buttonCallbacks[1]);
- cb(clickedLeftArrow);
-
- // 0x04
- cb(clickedRightArrow);
- cb(clickedTurnLeftArrow);
- cb(clickedTurnRightArrow);
- cb(clickedAttackButton);
-
- // 0x08
- for (int i = 0; i < 3; ++i)
- _buttonCallbacks.push_back(_buttonCallbacks[7]);
- cb(clickedMagicButton);
-
- // 0x0C
- for (int i = 0; i < 3; ++i)
- _buttonCallbacks.push_back(_buttonCallbacks[11]);
- cb(clickedMagicSubmenu);
-
- // 0x10
- cb(clickedScreen);
- cb(clickedPortraitLeft);
- for (int i = 0; i < 7; ++i)
- _buttonCallbacks.push_back(_buttonCallbacks[17]);
-
- // 0x19
- cb(clickedLiveMagicBarsLeft);
- for (int i = 0; i < 3; ++i)
- _buttonCallbacks.push_back(_buttonCallbacks[25]);
-
- // 0x1D
- cb(clickedPortraitEtcRight);
- for (int i = 0; i < 3; ++i)
- _buttonCallbacks.push_back(_buttonCallbacks[29]);
-
- // 0x21
- cb(clickedCharInventorySlot);
- for (int i = 0; i < 10; ++i)
- _buttonCallbacks.push_back(_buttonCallbacks[33]);
-
- // 0x2C
- cb(clickedExitCharInventory);
- cb(clickedSceneDropItem);
- for (int i = 0; i < 3; ++i)
- _buttonCallbacks.push_back(_buttonCallbacks[45]);
-
- // 0x31
- cb(clickedScenePickupItem);
- cb(clickedInventorySlot);
- for (int i = 0; i < 9; ++i)
- _buttonCallbacks.push_back(_buttonCallbacks[50]);
-
- // 0x3C
- cb(clickedInventoryScroll);
- cb(clickedInventoryScroll);
- cb(clickedWall);
- _buttonCallbacks.push_back(_buttonCallbacks[62]);
-
- // 0x40
- cb(clickedSequenceWindow);
- _buttonCallbacks.push_back(_buttonCallbacks[0]);
- _buttonCallbacks.push_back(_buttonCallbacks[1]);
- _buttonCallbacks.push_back(_buttonCallbacks[3]);
-
- // 0x44
- _buttonCallbacks.push_back(_buttonCallbacks[4]);
- _buttonCallbacks.push_back(_buttonCallbacks[5]);
- _buttonCallbacks.push_back(_buttonCallbacks[6]);
- cb(clickedScroll);
-
- // 0x48
- for (int i = 0; i < 9; ++i)
- _buttonCallbacks.push_back(_buttonCallbacks[71]);
-
- // 0x51
- cb(clickedSpellTargetCharacter);
- for (int i = 0; i < 3; ++i)
- _buttonCallbacks.push_back(_buttonCallbacks[81]);
-
- // 0x55
- cb(clickedSpellTargetScene);
- cb(clickedSceneThrowItem);
- _buttonCallbacks.push_back(_buttonCallbacks[86]);
-
- // 0x58
- cb(clickedOptions);
- cb(clickedRestParty);
- cb(clickedMoneyBox);
- cb(clickedCompass);
-
- // 0x5C
- cb(clickedAutomap);
- cb(clickedLamp);
- cb(clickedStatusIcon);
-#undef cb
-}
-
-void GUI_LoL::initStaticData() {
- GUI_V2_BUTTON(_scrollUpButton, 20, 96, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0);
- GUI_V2_BUTTON(_scrollDownButton, 21, 98, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0);
-
- for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i)
- GUI_V2_BUTTON(_menuButtons[i], i, 0, 0, 0, 0, 0, 0x4487, 0, 0, 0, 0, 0, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0);
-
- if (_vm->gameFlags().isTalkie)
- GUI_LOL_MENU(_mainMenu, 9, 0x4000, 0, 7, -1, -1, -1, -1);
- else
- GUI_LOL_MENU(_mainMenu, 17, 0x4000, 0, 6, -1, -1, -1, -1);
-
- GUI_LOL_MENU_ITEM(_mainMenu.item[0], 0x4001, 16, 23, 176, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_mainMenu.item[1], 0x4002, 16, 40, 176, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_mainMenu.item[2], 0x4003, 16, 57, 176, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_mainMenu.item[3], 0x4004, 16, 74, 176, 15, 0, 0);
-
- if (_vm->gameFlags().isTalkie) {
- GUI_LOL_MENU_ITEM(_mainMenu.item[4], 0x42D9, 16, 91, 176, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_mainMenu.item[5], 0x4006, 16, 108, 176, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_mainMenu.item[6], 0x4005, 88, 127, 104, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
- } else {
- GUI_LOL_MENU_ITEM(_mainMenu.item[4], 0x4006, 16, 91, 176, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_mainMenu.item[5], 0x4005, 88, 110, 104, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
- }
-
- Button::Callback mainMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedMainMenu);
- for (int i = 0; i < _mainMenu.numberOfItems; ++i)
- _mainMenu.item[i].callback = mainMenuFunctor;
-
- GUI_LOL_MENU(_loadMenu, 10, 0x400e, 1, 5, 128, 20, 128, 118);
- GUI_LOL_MENU_ITEM(_loadMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_loadMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_loadMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_loadMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_loadMenu.item[4], 0x4011, 168, 118, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
- Button::Callback loadMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedLoadMenu);
- for (int i = 0; i < 5; ++i)
- _loadMenu.item[i].callback = loadMenuFunctor;
-
- GUI_LOL_MENU(_saveMenu, 10, 0x400d, 1, 5, 128, 20, 128, 118);
- GUI_LOL_MENU_ITEM(_saveMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_saveMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_saveMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_saveMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_saveMenu.item[4], 0x4011, 168, 118, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
- Button::Callback saveMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedSaveMenu);
- for (int i = 0; i < 5; ++i)
- _saveMenu.item[i].callback = saveMenuFunctor;
-
- GUI_LOL_MENU(_deleteMenu, 10, 0x400f, 1, 5, 128, 20, 128, 118);
- GUI_LOL_MENU_ITEM(_deleteMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_deleteMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_deleteMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_deleteMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_deleteMenu.item[4], 0x4011, 168, 118, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
- Button::Callback deleteMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedDeleteMenu);
- for (int i = 0; i < 5; ++i)
- _deleteMenu.item[i].callback = deleteMenuFunctor;
-
- GUI_LOL_MENU(_gameOptions, 17, 0x400c, 0, 6, -1, -1, -1, -1);
- if (_vm->gameFlags().isTalkie) {
- GUI_LOL_MENU_ITEM(_gameOptions.item[0], 0xfff7, 120, 22, 80, 15, 0x406e, 0);
- GUI_LOL_MENU_ITEM(_gameOptions.item[1], 0xfff6, 120, 39, 80, 15, 0x406c, 0);
- GUI_LOL_MENU_ITEM(_gameOptions.item[2], 0xfff5, 120, 56, 80, 15, 0x406d, 0);
- GUI_LOL_MENU_ITEM(_gameOptions.item[3], 0xfff4, 120, 73, 80, 15, 0x42d5, 0);
- GUI_LOL_MENU_ITEM(_gameOptions.item[4], 0xfff3, 120, 90, 80, 15, 0x42d2, 0);
- GUI_LOL_MENU_ITEM(_gameOptions.item[5], 0x4072, 104, 110, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
- } else {
- GUI_LOL_MENU_ITEM(_gameOptions.item[0], 0xfff9, 120, 22, 80, 15, 0x406a, 0);
- GUI_LOL_MENU_ITEM(_gameOptions.item[1], 0xfff8, 120, 39, 80, 15, 0x406b, 0);
- GUI_LOL_MENU_ITEM(_gameOptions.item[2], 0xfff7, 120, 56, 80, 15, 0x406e, 0);
- GUI_LOL_MENU_ITEM(_gameOptions.item[3], 0xfff6, 120, 73, 80, 15, 0x406c, 0);
- GUI_LOL_MENU_ITEM(_gameOptions.item[4], 0xfff5, 120, 90, 80, 15, 0x406d, 0);
- GUI_LOL_MENU_ITEM(_gameOptions.item[5], 0x4072, 104, 110, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
- }
- Button::Callback optionsMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedOptionsMenu);
- for (int i = 0; i < _gameOptions.numberOfItems; ++i)
- _gameOptions.item[i].callback = optionsMenuFunctor;
-
- GUI_LOL_MENU(_audioOptions, 18, 0x42d9, 2, 1, -1, -1, -1, -1);
- GUI_LOL_MENU_ITEM(_audioOptions.item[0], 0x4072, 152, 76, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
- GUI_LOL_MENU_ITEM(_audioOptions.item[1], 3, 128, 22, 114, 14, 0x42db, 0);
- GUI_LOL_MENU_ITEM(_audioOptions.item[2], 4, 128, 39, 114, 14, 0x42da, 0);
- GUI_LOL_MENU_ITEM(_audioOptions.item[3], 5, 128, 56, 114, 14, 0x42dc, 0);
- Button::Callback audioMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedAudioMenu);
- for (int i = 0; i < 4; ++i)
- _audioOptions.item[i].callback = audioMenuFunctor;
-
- GUI_LOL_MENU(_deathMenu, 11, 0x4013, 0, 2, -1, -1, -1, -1);
- GUI_LOL_MENU_ITEM(_deathMenu.item[0], 0x4006, 8, 30, 104, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_deathMenu.item[1], 0x4001, 176, 30, 104, 15, 0, 0);
- Button::Callback deathMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedDeathMenu);
- for (int i = 0; i < 2; ++i)
- _deathMenu.item[i].callback = deathMenuFunctor;
-
- GUI_LOL_MENU(_savenameMenu, 7, 0x4053, 0, 2, -1, -1, -1, -1);
- GUI_LOL_MENU_ITEM(_savenameMenu.item[0], 0x4012, 8, 38, 72, 15, 0, _vm->_keyMap[Common::KEYCODE_RETURN]);
- GUI_LOL_MENU_ITEM(_savenameMenu.item[1], 0x4011, 176, 38, 72, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
- Button::Callback savenameMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedSavenameMenu);
- for (int i = 0; i < 2; ++i)
- _savenameMenu.item[i].callback = savenameMenuFunctor;
-
- GUI_LOL_MENU(_choiceMenu, 11, 0, 0, 2, -1, -1, -1, -1);
- GUI_LOL_MENU_ITEM(_choiceMenu.item[0], 0x4007, 8, 30, 72, 15, 0, 0);
- GUI_LOL_MENU_ITEM(_choiceMenu.item[1], 0x4008, 208, 30, 72, 15, 0, 0);
- Button::Callback choiceMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedChoiceMenu);
- for (int i = 0; i < 2; ++i)
- _choiceMenu.item[i].callback = choiceMenuFunctor;
-}
-
-#endif // ENABLE_LOL
-
const uint8 Screen_LoK_16::_palette16[48] = {
0x00, 0x00, 0x00, 0x02, 0x07, 0x0B, 0x0C, 0x06, 0x04,
0x0E, 0x09, 0x07, 0x00, 0x06, 0x03, 0x00, 0x0C, 0x07,
@@ -2745,263 +2141,5 @@ const int8 KyraEngine_MR::_albumWSAY[] = {
-1, -2, 2, 2, -6, -6, -6, 0
};
-// lands of lore static res
-
-#ifdef ENABLE_LOL
-const ScreenDim Screen_LoL::_screenDimTable256C[] = {
- { 0x00, 0x00, 0x28, 0xC8, 0xC7, 0xCF, 0x00, 0x00 }, // Taken from Intro
- { 0x08, 0x48, 0x18, 0x38, 0xFE, 0x01, 0x00, 0x00 },
- { 0x0E, 0x00, 0x16, 0x78, 0xFE, 0x01, 0x00, 0x00 },
- { 0x0B, 0x7B, 0x1C, 0x12, 0xFE, 0xFC, 0x00, 0x00 },
- { 0x0B, 0x7B, 0x1C, 0x2D, 0xFE, 0xFC, 0x00, 0x00 },
- { 0x55, 0x7B, 0xE9, 0x37, 0xFE, 0xFC, 0x00, 0x00 },
- { 0x0B, 0x8C, 0x10, 0x2B, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (4 entries)
- { 0x04, 0x59, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x00 },
- { 0x05, 0x6E, 0x1E, 0x0C, 0xFE, 0x01, 0x00, 0x00 },
- { 0x07, 0x19, 0x1A, 0x97, 0x00, 0x00, 0x00, 0x00 }, // Ingame main menu box CD version
- { 0x03, 0x1E, 0x22, 0x8C, 0x00, 0x00, 0x00, 0x00 },
- { 0x02, 0x48, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00 },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- { 0x0E, 0x00, 0x16, 0x78, 0xFE, 0x01, 0x00, 0x00 },
- { 0x0D, 0xA2, 0x18, 0x0C, 0xFE, 0x01, 0x00, 0x00 },
- { 0x0F, 0x06, 0x14, 0x6E, 0x01, 0x00, 0x00, 0x00 },
- { 0x1A, 0xBE, 0x0A, 0x07, 0xFE, 0x01, 0x00, 0x00 },
- { 0x07, 0x21, 0x1A, 0x85, 0x00, 0x00, 0x00, 0x00 },
- { 0x03, 0x32, 0x22, 0x62, 0x00, 0x00, 0x00, 0x00 },
- { 0x0B, 0x8C, 0x10, 0x33, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (5 entries, CD version only)
- { 0x0B, 0x8C, 0x10, 0x23, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (3 entries, floppy version only)
-
- { 0x01, 0x20, 0x26, 0x80, 0xDC, 0xFD, 0x00, 0x00 }, // Credits
- { 0x09, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 },
- { 0x19, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 },
- { 0x01, 0x02, 0x26, 0x14, 0x00, 0x0F, 0x0E, 0x00 },
-};
-
-const ScreenDim Screen_LoL::_screenDimTable16C[] = {
- { 0x00, 0x00, 0x28, 0xC8, 0x33, 0x44, 0x00, 0x00 }, // Taken from Intro
- { 0x08, 0x48, 0x18, 0x38, 0x33, 0x44, 0x00, 0x00 },
- { 0x0E, 0x00, 0x16, 0x78, 0x33, 0x44, 0x00, 0x00 },
- { 0x0B, 0x7B, 0x1C, 0x11, 0x33, 0x11, 0x00, 0x00 },
- { 0x0B, 0x7B, 0x1C, 0x2D, 0x33, 0x11, 0x00, 0x00 },
- { 0x55, 0x7B, 0xE9, 0x37, 0x33, 0x11, 0x00, 0x00 },
- { 0x0B, 0x92, 0x10, 0x2A, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (4 entries)
- { 0x04, 0x58, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x00 },
- { 0x05, 0x6C, 0x1E, 0x0D, 0x33, 0x44, 0x00, 0x00 },
- { 0x07, 0x20, 0x1A, 0x86, 0x00, 0x00, 0x00, 0x00 },
- { 0x03, 0x20, 0x22, 0x8C, 0x00, 0x00, 0x00, 0x00 },
- { 0x02, 0x48, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00 },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- { 0x0E, 0x00, 0x16, 0x78, 0x33, 0x44, 0x00, 0x00 },
- { 0x0D, 0xA2, 0x18, 0x0C, 0x33, 0x44, 0x00, 0x00 },
- { 0x0F, 0x06, 0x14, 0x6E, 0x44, 0x00, 0x00, 0x00 },
- { 0x1A, 0xBE, 0x0A, 0x07, 0x33, 0x44, 0x00, 0x00 },
- { 0x07, 0x21, 0x1A, 0x85, 0x00, 0x00, 0x00, 0x00 },
- { 0x03, 0x32, 0x22, 0x62, 0x00, 0x00, 0x00, 0x00 },
- { 0x0B, 0x8C, 0x10, 0x33, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (5 entries, not used here)
- { 0x0B, 0x8C, 0x10, 0x23, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (3 entries)
-
- { 0x01, 0x20, 0x26, 0x80, 0xDC, 0xFD, 0x00, 0x00 }, // Credits (TODO: Check this!)
- { 0x09, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 },
- { 0x19, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 },
- { 0x01, 0x02, 0x26, 0x14, 0x00, 0x0F, 0x0E, 0x00 },
-};
-
-const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable256C);
-
-const char * const LoLEngine::_languageExt[] = {
- "ENG",
- "FRE",
- "GER"
-};
-
-const LoLEngine::CharacterPrev LoLEngine::_charPreviews[] = {
- { "Ak\'shel", 0x060, 0x7F, { 0x0F, 0x08, 0x05 } },
- { "Michael", 0x09A, 0x7F, { 0x06, 0x0A, 0x0F } },
- { "Kieran", 0x0D4, 0x7F, { 0x08, 0x06, 0x08 } },
- { "Conrad", 0x10F, 0x7F, { 0x0A, 0x0C, 0x0A } }
-};
-
-const uint16 LoLEngine::_charPosXPC98[] = {
- 92, 152, 212, 268
-};
-
-const uint8 LoLEngine::_charNamesPC98[][11] = {
- { 0x83, 0x41, 0x83, 0x4E, 0x83, 0x56, 0x83, 0x46, 0x83, 0x8B, 0x00 },
- { 0x83, 0x7D, 0x83, 0x43, 0x83, 0x50, 0x83, 0x8B, 0x00, 0x00, 0x00 },
- { 0x83, 0x4C, 0x81, 0x5B, 0x83, 0x89, 0x83, 0x93, 0x00, 0x00, 0x00 },
- { 0x83, 0x52, 0x83, 0x93, 0x83, 0x89, 0x83, 0x62, 0x83, 0x68, 0x00 }
-};
-
-const uint8 LoLEngine::_chargenFrameTableTalkie[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04,
- 0x05, 0x04, 0x03, 0x02, 0x01,
- 0x00, 0x00, 0x01, 0x02, 0x03,
- 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
- 0x0E, 0x0F, 0x10, 0x11, 0x12
-};
-
-const uint8 LoLEngine::_chargenFrameTableFloppy[] = {
- 0, 1, 2, 3, 4, 5, 4, 3, 2,
- 1, 0, 0, 1, 2, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14, 15
-};
-
-const uint16 LoLEngine::_selectionPosTable[] = {
- 0x6F, 0x00, 0x8F, 0x00, 0xAF, 0x00, 0xCF, 0x00,
- 0xEF, 0x00, 0x6F, 0x20, 0x8F, 0x20, 0xAF, 0x20,
- 0xCF, 0x20, 0xEF, 0x20, 0x6F, 0x40, 0x8F, 0x40,
- 0xAF, 0x40, 0xCF, 0x40, 0xEF, 0x40, 0x10F, 0x00
-};
-
-const uint8 LoLEngine::_selectionChar1IdxTable[] = {
- 0, 0, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 0, 0, 5, 5, 5,
- 5, 5, 5, 5, 0, 0, 5, 5,
- 5, 5, 5
-};
-
-const uint8 LoLEngine::_selectionChar2IdxTable[] = {
- 1, 1, 6, 6, 1, 1, 6, 6,
- 6, 6, 6, 6, 6, 1, 1, 6,
- 6, 6, 1, 1, 6, 6, 6, 6,
- 6, 6, 6
-};
-
-const uint8 LoLEngine::_selectionChar3IdxTable[] = {
- 2, 2, 7, 7, 7, 7, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2,
- 2, 7, 7, 7, 7, 2, 2, 7,
- 7, 7, 7
-};
-
-const uint8 LoLEngine::_selectionChar4IdxTable[] = {
- 3, 3, 8, 8, 8, 8, 3, 3,
- 8, 8, 3, 3, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 3, 3, 8,
- 8, 8, 8
-};
-
-const uint8 LoLEngine::_reminderChar1IdxTable[] = {
- 4, 4, 4, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5,
- 5
-};
-
-const uint8 LoLEngine::_reminderChar2IdxTable[] = {
- 9, 9, 9, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 6
-};
-
-const uint8 LoLEngine::_reminderChar3IdxTable[] = {
- 0xE, 0xE, 0xE, 0x7, 0x7, 0x7, 0x7, 0x7,
- 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
- 0x7
-};
-
-const uint8 LoLEngine::_reminderChar4IdxTable[] = {
- 0xF, 0xF, 0xF, 0x8, 0x8, 0x8, 0x8, 0x8,
- 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
- 0x8
-};
-
-const uint8 LoLEngine::_selectionAnimIndexTable[] = {
- 0, 5, 1, 6, 2, 7, 3, 8
-};
-
-const uint8 LoLEngine::_charInfoFrameTable[] = {
- 0x0, 0x7, 0x8, 0x9, 0xA, 0xB, 0xA, 0x9,
- 0x8, 0x7, 0x0, 0x0, 0x7, 0x8, 0x9, 0xA,
- 0xB, 0xA, 0x9, 0x8, 0x7, 0x0, 0x0, 0x7,
- 0x8, 0x9, 0xA, 0xB, 0xA, 0x9, 0x8, 0x7
-};
-
-const uint8 LoLEngine::_clock2Timers[] = {
- 0x00, 0x10, 0x11, 0x03, 0x04, 0x50,
- 0x51, 0x52, 0x08, 0x09, 0x0A
-};
-
-const uint8 LoLEngine::_numClock2Timers = ARRAYSIZE(LoLEngine::_clock2Timers);
-
-const int8 LoLEngine::_mapCoords[12][4] = {
- { 0, 7, 0, -5 }, { -5, 0, 6, 0 }, { 7, 5, 7, 1 },
- { 5, 6, 4, 6 }, { 0, 7, 0, -1 }, { -3, 0, 6, 0 },
- { 6, 7, 6, -3 }, { -3, 5, 6, 5 }, { 1, 5, 1, 1 },
- { 3, 1, 3, 1 }, { -1, 6, -1, -8 }, { -7, -1, 5, -1 }
-};
-
-const MistOfDoomAnimData LoLEngine::_mistAnimData[] = {
- { 0, 7, 7, 13, 155 },
- { 0, 16, 16, 17, 155 },
- { 0, 24, 24, 24, 174 },
- { 0, 19, 19, 19, 174 },
- { 0, 16, 16, 17, 175 },
-};
-
-const char * const LoLEngine::_outroShapeFileTable[] = {
- "AMAZON.SHP", "ARCHRSLG.SHP", "AVIANWRM.SHP", "BANDIT.SHP", "BOAR.SHP", "CABAL.SHP",
- "GUARD.SHP", "HAG.SHP", "HORNET.SHP", "HURZELL.SHP", "IRONGRZR.SHP", "KNOWLES.SHP",
- "LIZARD.SHP", "MANTHA.SHP", "MINOTAUR.SHP", "MORIBUND.SHP", "ORC.SHP", "ORCLDR.SHP",
- "PENTROG.SHP", "RATMAN.SHP", "ROCKLING.SHP", "SCAVNGR.SHP", "STARK.SHP",
- "SWAMPCIT.SHP", "SWAMPMON.SHP", "THUG.SHP", "VIPER.SHP", "XEOB.SHP"
-};
-
-const uint8 LoLEngine::_outroFrameTable[] = {
- 0, 0, 0, 0, 0, 1, 2, 3,
- 0, 1, 2, 3, 8, 9, 10, 11,
- 8, 9, 10, 11, 4, 5, 6, 7
-};
-
-const int16 LoLEngine::_outroRightMonsterPos[] = {
- 205, 55, 205, 55, 205, 55, 205, 55,
- 205, 56, 207, 57, 208, 58, 210, 59,
- 213, 60, 216, 61, 220, 61, 225, 61,
- 230, 61, 235, 61, 240, 61, 240, 61,
- 240, 61, 240, 61, 240, 61, 240, 61,
- 240, 61, 265, 61, 290, 61, 315, 61
-};
-
-const int16 LoLEngine::_outroLeftMonsterPos[] = {
- 92, 55, 92, 55, 92, 55, 92, 55,
- 92, 56, 90, 57, 85, 58, 77, 59,
- 67, 60, 57, 61, 47, 61, 35, 61,
- 35, 61, 35, 61, 35, 61, 35, 61,
- 35, 61, 35, 61, 35, 61, 35, 61,
- 35, 61, 10, 61, -20, 61, -45, 61
-};
-
-const int16 LoLEngine::_outroRightDoorPos[] = {
- 200, 41, 200, 29, 200, 17, 200, 5,
- 200, -7, 200, -7, 200, -7, 200, -7,
- 200, 5, 200, 17, 200, 29, 200, 41,
- 200, 41, 200, 41, 200, 41, 200, 41,
- 200, 41, 200, 41, 200, 41, 200, 41,
- 200, 41, 200, 41, 200, 41, 200, 41
-};
-
-const int16 LoLEngine::_outroLeftDoorPos[] = {
- 72, 41, 72, 29, 72, 17, 72, 5,
- 72, -7, 72, -7, 72, -7, 72, -7,
- 72, 5, 72, 17, 72, 29, 72, 41,
- 72, 41, 72, 41, 72, 41, 72, 41,
- 72, 41, 72, 41, 72, 41, 72, 41,
- 72, 41, 72, 41, 72, 41, 72, 41
-};
-
-const int LoLEngine::_outroMonsterScaleTableX[] = {
- 0x050, 0x050, 0x050, 0x050, 0x050, 0x05D, 0x070, 0x085,
- 0x0A0, 0x0C0, 0x0E2, 0x100, 0x100, 0x100, 0x100, 0x100,
- 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100
-};
-
-const int LoLEngine::_outroMonsterScaleTableY[] = {
- 0x04C, 0x04C, 0x04C, 0x04C, 0x04C, 0x059, 0x06B, 0x080,
- 0x099, 0x0B8, 0x0D9, 0x100, 0x100, 0x100, 0x100, 0x100,
- 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100
-};
-
-#endif // ENABLE_LOL
-
} // End of namespace Kyra
diff --git a/engines/kyra/staticres_lol.cpp b/engines/kyra/staticres_lol.cpp
new file mode 100644
index 0000000000..3287ee37d6
--- /dev/null
+++ b/engines/kyra/staticres_lol.cpp
@@ -0,0 +1,883 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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.h"
+#include "kyra/lol.h"
+#include "kyra/screen_lol.h"
+#include "kyra/gui_lol.h"
+
+#ifdef ENABLE_LOL
+
+namespace Kyra {
+
+const LoLCharacter *StaticResource::loadCharData(int id, int &entries) {
+ return (const LoLCharacter *)getData(id, kLolCharData, entries);
+}
+
+const SpellProperty *StaticResource::loadSpellData(int id, int &entries) {
+ return (const SpellProperty *)getData(id, kLolSpellData, entries);
+}
+
+const CompassDef *StaticResource::loadCompassData(int id, int &entries) {
+ return (const CompassDef *)getData(id, kLolCompassData, entries);
+}
+
+const FlyingObjectShape *StaticResource::loadFlyingObjectData(int id, int &entries) {
+ return (const FlyingObjectShape *)getData(id, kLolFlightShpData, entries);
+}
+
+const uint16 *StaticResource::loadRawDataBe16(int id, int &entries) {
+ return (const uint16 *)getData(id, kLolRawDataBe16, entries);
+}
+
+const uint32 *StaticResource::loadRawDataBe32(int id, int &entries) {
+ return (const uint32 *)getData(id, kLolRawDataBe32, entries);
+}
+
+const ButtonDef *StaticResource::loadButtonDefs(int id, int &entries) {
+ return (const ButtonDef *)getData(id, kLolButtonData, entries);
+}
+
+bool StaticResource::loadCharData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
+ size = stream.size() / 130;
+ LoLCharacter *charData = new LoLCharacter[size];
+
+ for (int i = 0; i < size; i++) {
+ LoLCharacter *t = &charData[i];
+
+ t->flags = stream.readUint16LE();
+ stream.read(t->name, 11);
+ t->raceClassSex = stream.readByte();
+ t->id = stream.readSint16LE();
+ t->curFaceFrame = stream.readByte();
+ t->tempFaceFrame = stream.readByte();
+ t->screamSfx = stream.readByte();
+ stream.readUint32LE();
+ for (int ii = 0; ii < 8; ii++)
+ t->itemsMight[ii] = stream.readUint16LE();
+ for (int ii = 0; ii < 8; ii++)
+ t->protectionAgainstItems[ii] = stream.readUint16LE();
+ t->itemProtection = stream.readUint16LE();
+ t->hitPointsCur = stream.readSint16LE();
+ t->hitPointsMax = stream.readUint16LE();
+ t->magicPointsCur = stream.readSint16LE();
+ t->magicPointsMax = stream.readUint16LE();
+ t->field_41 = stream.readByte();
+ t->damageSuffered = stream.readUint16LE();
+ t->weaponHit = stream.readUint16LE();
+ t->totalMightModifier = stream.readUint16LE();
+ t->totalProtectionModifier = stream.readUint16LE();
+ t->might = stream.readUint16LE();
+ t->protection = stream.readUint16LE();
+ t->nextAnimUpdateCountdown = stream.readSint16LE();
+ for (int ii = 0; ii < 11; ii++)
+ t->items[ii] = stream.readUint16LE();
+ for (int ii = 0; ii < 3; ii++)
+ t->skillLevels[ii] = stream.readByte();
+ for (int ii = 0; ii < 3; ii++)
+ t->skillModifiers[ii] = stream.readByte();
+ for (int ii = 0; ii < 3; ii++)
+ t->experiencePts[ii] = stream.readUint32LE();
+ for (int ii = 0; ii < 5; ii++)
+ t->characterUpdateEvents[ii] = stream.readByte();
+ for (int ii = 0; ii < 5; ii++)
+ t->characterUpdateDelay[ii] = stream.readByte();
+ };
+
+ ptr = charData;
+ return true;
+}
+
+bool StaticResource::loadSpellData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
+ size = stream.size() / 28;
+ SpellProperty *spellData = new SpellProperty[size];
+
+ for (int i = 0; i < size; i++) {
+ SpellProperty *t = &spellData[i];
+
+ t->spellNameCode = stream.readUint16LE();
+ for (int ii = 0; ii < 4; ii++)
+ t->mpRequired[ii] = stream.readUint16LE();
+ t->field_a = stream.readUint16LE();
+ t->field_c = stream.readUint16LE();
+ for (int ii = 0; ii < 4; ii++)
+ t->hpRequired[ii] = stream.readUint16LE();
+ t->field_16 = stream.readUint16LE();
+ t->field_18 = stream.readUint16LE();
+ t->flags = stream.readUint16LE();
+ };
+
+ ptr = spellData;
+ return true;
+}
+
+bool StaticResource::loadCompassData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
+ size = stream.size() / 4;
+ CompassDef *defs = new CompassDef[size];
+
+ for (int i = 0; i < size; i++) {
+ CompassDef *t = &defs[i];
+ t->shapeIndex = stream.readByte();
+ t->x = stream.readByte();
+ t->y = stream.readByte();
+ t->flags = stream.readByte();
+ };
+
+
+ ptr = defs;
+ return true;
+}
+
+bool StaticResource::loadFlyingObjectData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
+ size = stream.size() / 5;
+ FlyingObjectShape *defs = new FlyingObjectShape[size];
+
+ for (int i = 0; i < size; i++) {
+ FlyingObjectShape *t = &defs[i];
+ t->shapeFront = stream.readByte();
+ t->shapeBack = stream.readByte();
+ t->shapeLeft = stream.readByte();
+ t->drawFlags = stream.readByte();
+ t->flipFlags = stream.readByte();
+ };
+
+ ptr = defs;
+ return true;
+}
+
+bool StaticResource::loadRawDataBe16(Common::SeekableReadStream &stream, void *&ptr, int &size) {
+ size = stream.size() >> 1;
+
+ uint16 *r = new uint16[size];
+
+ for (int i = 0; i < size; i++)
+ r[i] = stream.readUint16BE();
+
+ ptr = r;
+ return true;
+}
+
+bool StaticResource::loadRawDataBe32(Common::SeekableReadStream &stream, void *&ptr, int &size) {
+ size = stream.size() >> 2;
+
+ uint32 *r = new uint32[size];
+
+ for (int i = 0; i < size; i++)
+ r[i] = stream.readUint32BE();
+
+ ptr = r;
+ return true;
+}
+
+bool StaticResource::loadButtonDefs(Common::SeekableReadStream &stream, void *&ptr, int &size) {
+ size = stream.size() / 18;
+
+ ButtonDef *r = new ButtonDef[size];
+
+ for (int i = 0; i < size; i++) {
+ r[i].buttonflags = stream.readUint16BE();
+ r[i].keyCode = stream.readUint16BE();
+ r[i].keyCode2 = stream.readUint16BE();
+ r[i].x = stream.readSint16BE();
+ r[i].y = stream.readSint16BE();
+ r[i].w = stream.readUint16BE();
+ r[i].h = stream.readUint16BE();
+ r[i].index = stream.readUint16BE();
+ r[i].screenDim = stream.readUint16BE();
+ }
+
+ ptr = r;
+ return true;
+}
+
+void StaticResource::freeCharData(void *&ptr, int &size) {
+ LoLCharacter *d = (LoLCharacter *)ptr;
+ delete[] d;
+ ptr = 0;
+ size = 0;
+}
+
+void StaticResource::freeSpellData(void *&ptr, int &size) {
+ SpellProperty *d = (SpellProperty *)ptr;
+ delete[] d;
+ ptr = 0;
+ size = 0;
+}
+
+void StaticResource::freeCompassData(void *&ptr, int &size) {
+ CompassDef *d = (CompassDef *)ptr;
+ delete[] d;
+ ptr = 0;
+ size = 0;
+}
+
+void StaticResource::freeFlyingObjectData(void *&ptr, int &size) {
+ FlyingObjectShape *d = (FlyingObjectShape *)ptr;
+ delete[] d;
+ ptr = 0;
+ size = 0;
+}
+
+
+void StaticResource::freeRawDataBe16(void *&ptr, int &size) {
+ uint16 *data = (uint16 *)ptr;
+ delete[] data;
+ ptr = 0;
+ size = 0;
+}
+
+void StaticResource::freeRawDataBe32(void *&ptr, int &size) {
+ uint32 *data = (uint32 *)ptr;
+ delete[] data;
+ ptr = 0;
+ size = 0;
+}
+
+void StaticResource::freeButtonDefs(void *&ptr, int &size) {
+ ButtonDef *d = (ButtonDef *)ptr;
+ delete[] d;
+ ptr = 0;
+ size = 0;
+}
+
+void LoLEngine::initStaticResource() {
+ // assign music data
+ static const char *pcMusicFileListIntro[] = { "LOREINTR" };
+ static const char *pcMusicFileListFinale[] = { "LOREFINL" };
+ static const char *pcMusicFileListIngame[] = { "LORE%02d%c" };
+
+ static const char *pc98MusicFileListIntro[] = { 0, "lore84.86", "lore82.86", 0, 0, 0, "lore83.86", "lore81.86" };
+ static const char *pc98MusicFileListFinale[] = { 0, 0, "lore85.86", "lore86.86", "lore87.86" };
+ static const char *pc98MusicFileListIngame[] = { "lore%02d.86" };
+
+ memset(_soundData, 0, sizeof(_soundData));
+ if (_flags.platform == Common::kPlatformPC) {
+ _soundData[0].fileList = pcMusicFileListIntro;
+ _soundData[0].fileListLen = ARRAYSIZE(pcMusicFileListIntro);
+ _soundData[1].fileList = pcMusicFileListIngame;
+ _soundData[1].fileListLen = ARRAYSIZE(pcMusicFileListIngame);
+ _soundData[2].fileList = pcMusicFileListFinale;
+ _soundData[2].fileListLen = ARRAYSIZE(pcMusicFileListFinale);
+ } else if (_flags.platform == Common::kPlatformPC98) {
+ _soundData[0].fileList = pc98MusicFileListIntro;
+ _soundData[0].fileListLen = ARRAYSIZE(pc98MusicFileListIntro);
+ _soundData[1].fileList = pc98MusicFileListIngame;
+ _soundData[1].fileListLen = ARRAYSIZE(pc98MusicFileListIngame);
+ _soundData[2].fileList = pc98MusicFileListFinale;
+ _soundData[2].fileListLen = ARRAYSIZE(pc98MusicFileListFinale);
+ }
+
+ if (_flags.isDemo)
+ return;
+
+ _pakFileList = _staticres->loadStrings(kLolIngamePakFiles, _pakFileListSize);
+ _charDefaults = _staticres->loadCharData(kLolCharacterDefs, _charDefaultsSize);
+ _ingameSoundIndex = (const uint16 *)_staticres->loadRawData(kLolIngameSfxIndex, _ingameSoundIndexSize);
+ _musicTrackMap = _staticres->loadRawData(kLolMusicTrackMap, _musicTrackMapSize);
+ _ingameGMSoundIndex = _staticres->loadRawData(kLolIngameGMSfxIndex, _ingameGMSoundIndexSize);
+ _ingameMT32SoundIndex = _staticres->loadRawData(kLolIngameMT32SfxIndex, _ingameMT32SoundIndexSize);
+ _ingamePCSpeakerSoundIndex = _staticres->loadRawData(kLolIngamePcSpkSfxIndex, _ingamePCSpeakerSoundIndexSize);
+ _spellProperties = _staticres->loadSpellData(kLolSpellProperties, _spellPropertiesSize);
+ _gameShapeMap = (const int8 *)_staticres->loadRawData(kLolGameShapeMap, _gameShapeMapSize);
+ _sceneItemOffs = (const int8 *)_staticres->loadRawData(kLolSceneItemOffs, _sceneItemOffsSize);
+ _charInvIndex = _staticres->loadRawData(kLolCharInvIndex, _charInvIndexSize);
+ _charInvDefs = _staticres->loadRawData(kLolCharInvDefs, _charInvDefsSize);
+ _charDefsMan = _staticres->loadRawDataBe16(kLolCharDefsMan, _charDefsManSize);
+ _charDefsWoman = _staticres->loadRawDataBe16(kLolCharDefsWoman, _charDefsWomanSize);
+ _charDefsKieran = _staticres->loadRawDataBe16(kLolCharDefsKieran, _charDefsKieranSize);
+ _charDefsAkshel = _staticres->loadRawDataBe16(kLolCharDefsAkshel, _charDefsAkshelSize);
+ _expRequirements = (const int32 *)_staticres->loadRawDataBe32(kLolExpRequirements, _expRequirementsSize);
+ _monsterModifiers = _staticres->loadRawDataBe16(kLolMonsterModifiers, _monsterModifiersSize);
+ _monsterShiftOffs = (const int8 *)_staticres->loadRawData(kLolMonsterShiftOffsets, _monsterShiftOffsSize);
+ _monsterDirFlags = _staticres->loadRawData(kLolMonsterDirFlags, _monsterDirFlagsSize);
+ _monsterScaleX = _staticres->loadRawData(kLolMonsterScaleX, _monsterScaleXSize);
+ _monsterScaleY = _staticres->loadRawData(kLolMonsterScaleY, _monsterScaleYSize);
+ _monsterScaleWH = _staticres->loadRawDataBe16(kLolMonsterScaleWH, _monsterScaleWHSize);
+ _inventorySlotDesc = _staticres->loadRawDataBe16(kLolInventoryDesc, _inventorySlotDescSize);
+ _levelShpList = _staticres->loadStrings(kLolLevelShpList, _levelShpListSize);
+ _levelDatList = _staticres->loadStrings(kLolLevelDatList, _levelDatListSize);
+ _compassDefs = _staticres->loadCompassData(kLolCompassDefs, _compassDefsSize);
+ _flyingItemShapes = _staticres->loadFlyingObjectData(kLolFlyingObjectShp, _flyingItemShapesSize);
+ _itemCost = _staticres->loadRawDataBe16(kLolItemPrices, _itemCostSize);
+ _stashSetupData = _staticres->loadRawData(kLolStashSetup, _stashSetupDataSize);
+
+ _dscUnk1 = (const int8 *)_staticres->loadRawData(kLolDscUnk1, _dscUnk1Size);
+ _dscShapeIndex = (const int8 *)_staticres->loadRawData(kLolDscShapeIndex, _dscShapeIndexSize);
+ _dscOvlMap = _staticres->loadRawData(kLolDscOvlMap, _dscOvlMapSize);
+ _dscShapeScaleW = _staticres->loadRawDataBe16(kLolDscScaleWidthData, _dscShapeScaleWSize);
+ _dscShapeScaleH = _staticres->loadRawDataBe16(kLolDscScaleHeightData, _dscShapeScaleHSize);
+ _dscShapeX = (const int16 *)_staticres->loadRawDataBe16(kLolDscX, _dscShapeXSize);
+ _dscShapeY = (const int8 *)_staticres->loadRawData(kLolDscY, _dscShapeYSize);
+ _dscTileIndex = _staticres->loadRawData(kLolDscTileIndex, _dscTileIndexSize);
+ _dscUnk2 = _staticres->loadRawData(kLolDscUnk2, _dscUnk2Size);
+ _dscDoorShpIndex = _staticres->loadRawData(kLolDscDoorShapeIndex, _dscDoorShpIndexSize);
+ _dscDim1 = (const int8 *)_staticres->loadRawData(kLolDscDimData1, _dscDim1Size);
+ _dscDim2 = (const int8 *)_staticres->loadRawData(kLolDscDimData2, _dscDim2Size);
+ _dscBlockMap = _staticres->loadRawData(kLolDscBlockMap, _dscBlockMapSize);
+ _dscDimMap = _staticres->loadRawData(kLolDscDimMap, _dscDimMapSize);
+ _dscDoorMonsterScaleTable = _staticres->loadRawDataBe16(kLolDscDoorScale, _dscDoorMonsterScaleTableSize);
+ _dscShapeOvlIndex = _staticres->loadRawData(kLolDscOvlIndex, _dscShapeOvlIndexSize);
+ _dscDoor4 = _staticres->loadRawDataBe16(kLolDscDoor4, _dscDoor4Size);
+ _dscBlockIndex = (const int8 *)_staticres->loadRawData(kLolDscBlockIndex, _dscBlockIndexSize);
+ _dscDoor1 = _staticres->loadRawData(kLolDscDoor1, _dscDoor1Size);
+ _dscDoorMonsterX = (const int16 *)_staticres->loadRawDataBe16(kLolDscDoorX, _dscDoorMonsterXSize);
+ _dscDoorMonsterY = (const int16 *)_staticres->loadRawDataBe16(kLolDscDoorY, _dscDoorMonsterYSize);
+
+ _scrollXTop = _staticres->loadRawData(kLolScrollXTop, _scrollXTopSize);
+ _scrollYTop = _staticres->loadRawData(kLolScrollYTop, _scrollYTopSize);
+ _scrollXBottom = _staticres->loadRawData(kLolScrollXBottom, _scrollXBottomSize);
+ _scrollYBottom = _staticres->loadRawData(kLolScrollYBottom, _scrollYBottomSize);
+
+ const char *const *tmpSndList = _staticres->loadStrings(kLolIngameSfxFiles, _ingameSoundListSize);
+ if (tmpSndList) {
+ _ingameSoundList = new char *[_ingameSoundListSize];
+ for (int i = 0; i < _ingameSoundListSize; i++) {
+ _ingameSoundList[i] = new char[strlen(tmpSndList[i]) + 1];
+ strcpy(_ingameSoundList[i], tmpSndList[i]);
+ }
+ _staticres->unloadId(kLolIngameSfxFiles);
+ }
+
+ _buttonData = _staticres->loadButtonDefs(kLolButtonDefs, _buttonDataSize);
+ _buttonList1 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList1, _buttonList1Size);
+ _buttonList2 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList2, _buttonList2Size);
+ _buttonList3 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList3, _buttonList3Size);
+ _buttonList4 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList4, _buttonList4Size);
+ _buttonList5 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList5, _buttonList5Size);
+ _buttonList6 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList6, _buttonList6Size);
+ _buttonList7 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList7, _buttonList7Size);
+ _buttonList8 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList8, _buttonList8Size);
+
+ _autoMapStrings = _staticres->loadRawDataBe16(kLolMapStringId, _autoMapStringsSize);
+
+ int tempSize;
+ const uint8 *tmp = _staticres->loadRawData(kLolLegendData, tempSize);
+ uint8 entrySize = tempSize / 12;
+ tempSize /= entrySize;
+ if (tempSize) {
+ _defaultLegendData = new MapLegendData[tempSize];
+ for (int i = 0; i < tempSize; i++) {
+ _defaultLegendData[i].shapeIndex = *tmp++;
+ _defaultLegendData[i].enable = *tmp++ ? true : false;
+ _defaultLegendData[i].y = (entrySize == 5) ? (int8)*tmp++ : (i == 10 ? -5 : 0);
+ _defaultLegendData[i].stringId = READ_LE_UINT16(tmp);
+ tmp += 2;
+ }
+ _staticres->unloadId(kLolLegendData);
+ }
+
+ tmp = _staticres->loadRawData(kLolMapCursorOvl, tempSize);
+ _mapCursorOverlay = new uint8[tempSize];
+ memcpy(_mapCursorOverlay, tmp, tempSize);
+ _staticres->unloadId(kLolMapCursorOvl);
+
+ _updateSpellBookCoords = _staticres->loadRawData(kLolSpellbookCoords, _updateSpellBookCoordsSize);
+ _updateSpellBookAnimData = _staticres->loadRawData(kLolSpellbookAnim, _updateSpellBookAnimDataSize);
+ _healShapeFrames = _staticres->loadRawData(kLolHealShapeFrames, _healShapeFramesSize);
+
+ tmp = _staticres->loadRawData(kLolLightningDefs, tempSize);
+ if (tmp) {
+ _lightningProps = new LightningProperty[5];
+ for (int i = 0; i < 5; i++) {
+ _lightningProps[i].lastFrame = tmp[i << 2];
+ _lightningProps[i].frameDiv = tmp[(i << 2) + 1];
+ _lightningProps[i].sfxId = READ_LE_UINT16(&tmp[(i << 2) + 2]);
+ }
+ _staticres->unloadId(kLolLightningDefs);
+ }
+
+ _fireBallCoords = (const int16 *)_staticres->loadRawDataBe16(kLolFireballCoords, _fireBallCoordsSize);
+
+ _buttonCallbacks.clear();
+ _buttonCallbacks.reserve(95);
+#define cb(x) _buttonCallbacks.push_back(BUTTON_FUNCTOR(LoLEngine, this, &LoLEngine::x))
+ // 0x00
+ cb(clickedUpArrow);
+ cb(clickedDownArrow);
+ _buttonCallbacks.push_back(_buttonCallbacks[1]);
+ cb(clickedLeftArrow);
+
+ // 0x04
+ cb(clickedRightArrow);
+ cb(clickedTurnLeftArrow);
+ cb(clickedTurnRightArrow);
+ cb(clickedAttackButton);
+
+ // 0x08
+ for (int i = 0; i < 3; ++i)
+ _buttonCallbacks.push_back(_buttonCallbacks[7]);
+ cb(clickedMagicButton);
+
+ // 0x0C
+ for (int i = 0; i < 3; ++i)
+ _buttonCallbacks.push_back(_buttonCallbacks[11]);
+ cb(clickedMagicSubmenu);
+
+ // 0x10
+ cb(clickedScreen);
+ cb(clickedPortraitLeft);
+ for (int i = 0; i < 7; ++i)
+ _buttonCallbacks.push_back(_buttonCallbacks[17]);
+
+ // 0x19
+ cb(clickedLiveMagicBarsLeft);
+ for (int i = 0; i < 3; ++i)
+ _buttonCallbacks.push_back(_buttonCallbacks[25]);
+
+ // 0x1D
+ cb(clickedPortraitEtcRight);
+ for (int i = 0; i < 3; ++i)
+ _buttonCallbacks.push_back(_buttonCallbacks[29]);
+
+ // 0x21
+ cb(clickedCharInventorySlot);
+ for (int i = 0; i < 10; ++i)
+ _buttonCallbacks.push_back(_buttonCallbacks[33]);
+
+ // 0x2C
+ cb(clickedExitCharInventory);
+ cb(clickedSceneDropItem);
+ for (int i = 0; i < 3; ++i)
+ _buttonCallbacks.push_back(_buttonCallbacks[45]);
+
+ // 0x31
+ cb(clickedScenePickupItem);
+ cb(clickedInventorySlot);
+ for (int i = 0; i < 9; ++i)
+ _buttonCallbacks.push_back(_buttonCallbacks[50]);
+
+ // 0x3C
+ cb(clickedInventoryScroll);
+ cb(clickedInventoryScroll);
+ cb(clickedWall);
+ _buttonCallbacks.push_back(_buttonCallbacks[62]);
+
+ // 0x40
+ cb(clickedSequenceWindow);
+ _buttonCallbacks.push_back(_buttonCallbacks[0]);
+ _buttonCallbacks.push_back(_buttonCallbacks[1]);
+ _buttonCallbacks.push_back(_buttonCallbacks[3]);
+
+ // 0x44
+ _buttonCallbacks.push_back(_buttonCallbacks[4]);
+ _buttonCallbacks.push_back(_buttonCallbacks[5]);
+ _buttonCallbacks.push_back(_buttonCallbacks[6]);
+ cb(clickedScroll);
+
+ // 0x48
+ for (int i = 0; i < 9; ++i)
+ _buttonCallbacks.push_back(_buttonCallbacks[71]);
+
+ // 0x51
+ cb(clickedSpellTargetCharacter);
+ for (int i = 0; i < 3; ++i)
+ _buttonCallbacks.push_back(_buttonCallbacks[81]);
+
+ // 0x55
+ cb(clickedSpellTargetScene);
+ cb(clickedSceneThrowItem);
+ _buttonCallbacks.push_back(_buttonCallbacks[86]);
+
+ // 0x58
+ cb(clickedOptions);
+ cb(clickedRestParty);
+ cb(clickedMoneyBox);
+ cb(clickedCompass);
+
+ // 0x5C
+ cb(clickedAutomap);
+ cb(clickedLamp);
+ cb(clickedStatusIcon);
+#undef cb
+}
+
+void GUI_LoL::initStaticData() {
+ GUI_V2_BUTTON(_scrollUpButton, 20, 96, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0);
+ GUI_V2_BUTTON(_scrollDownButton, 21, 98, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0);
+
+ for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i)
+ GUI_V2_BUTTON(_menuButtons[i], i, 0, 0, 0, 0, 0, 0x4487, 0, 0, 0, 0, 0, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0);
+
+ if (_vm->gameFlags().isTalkie)
+ GUI_LOL_MENU(_mainMenu, 9, 0x4000, 0, 7, -1, -1, -1, -1);
+ else
+ GUI_LOL_MENU(_mainMenu, 17, 0x4000, 0, 6, -1, -1, -1, -1);
+
+ GUI_LOL_MENU_ITEM(_mainMenu.item[0], 0x4001, 16, 23, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[1], 0x4002, 16, 40, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[2], 0x4003, 16, 57, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[3], 0x4004, 16, 74, 176, 15, 0, 0);
+
+ if (_vm->gameFlags().isTalkie) {
+ GUI_LOL_MENU_ITEM(_mainMenu.item[4], 0x42D9, 16, 91, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[5], 0x4006, 16, 108, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[6], 0x4005, 88, 127, 104, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
+ } else {
+ GUI_LOL_MENU_ITEM(_mainMenu.item[4], 0x4006, 16, 91, 176, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_mainMenu.item[5], 0x4005, 88, 110, 104, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
+ }
+
+ Button::Callback mainMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedMainMenu);
+ for (int i = 0; i < _mainMenu.numberOfItems; ++i)
+ _mainMenu.item[i].callback = mainMenuFunctor;
+
+ GUI_LOL_MENU(_loadMenu, 10, 0x400e, 1, 5, 128, 20, 128, 118);
+ GUI_LOL_MENU_ITEM(_loadMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_loadMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_loadMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_loadMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_loadMenu.item[4], 0x4011, 168, 118, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
+ Button::Callback loadMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedLoadMenu);
+ for (int i = 0; i < 5; ++i)
+ _loadMenu.item[i].callback = loadMenuFunctor;
+
+ GUI_LOL_MENU(_saveMenu, 10, 0x400d, 1, 5, 128, 20, 128, 118);
+ GUI_LOL_MENU_ITEM(_saveMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_saveMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_saveMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_saveMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_saveMenu.item[4], 0x4011, 168, 118, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
+ Button::Callback saveMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedSaveMenu);
+ for (int i = 0; i < 5; ++i)
+ _saveMenu.item[i].callback = saveMenuFunctor;
+
+ GUI_LOL_MENU(_deleteMenu, 10, 0x400f, 1, 5, 128, 20, 128, 118);
+ GUI_LOL_MENU_ITEM(_deleteMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_deleteMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_deleteMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_deleteMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_deleteMenu.item[4], 0x4011, 168, 118, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
+ Button::Callback deleteMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedDeleteMenu);
+ for (int i = 0; i < 5; ++i)
+ _deleteMenu.item[i].callback = deleteMenuFunctor;
+
+ GUI_LOL_MENU(_gameOptions, 17, 0x400c, 0, 6, -1, -1, -1, -1);
+ if (_vm->gameFlags().isTalkie) {
+ GUI_LOL_MENU_ITEM(_gameOptions.item[0], 0xfff7, 120, 22, 80, 15, 0x406e, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[1], 0xfff6, 120, 39, 80, 15, 0x406c, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[2], 0xfff5, 120, 56, 80, 15, 0x406d, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[3], 0xfff4, 120, 73, 80, 15, 0x42d5, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[4], 0xfff3, 120, 90, 80, 15, 0x42d2, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[5], 0x4072, 104, 110, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
+ } else {
+ GUI_LOL_MENU_ITEM(_gameOptions.item[0], 0xfff9, 120, 22, 80, 15, 0x406a, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[1], 0xfff8, 120, 39, 80, 15, 0x406b, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[2], 0xfff7, 120, 56, 80, 15, 0x406e, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[3], 0xfff6, 120, 73, 80, 15, 0x406c, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[4], 0xfff5, 120, 90, 80, 15, 0x406d, 0);
+ GUI_LOL_MENU_ITEM(_gameOptions.item[5], 0x4072, 104, 110, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
+ }
+ Button::Callback optionsMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedOptionsMenu);
+ for (int i = 0; i < _gameOptions.numberOfItems; ++i)
+ _gameOptions.item[i].callback = optionsMenuFunctor;
+
+ GUI_LOL_MENU(_audioOptions, 18, 0x42d9, 2, 1, -1, -1, -1, -1);
+ GUI_LOL_MENU_ITEM(_audioOptions.item[0], 0x4072, 152, 76, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
+ GUI_LOL_MENU_ITEM(_audioOptions.item[1], 3, 128, 22, 114, 14, 0x42db, 0);
+ GUI_LOL_MENU_ITEM(_audioOptions.item[2], 4, 128, 39, 114, 14, 0x42da, 0);
+ GUI_LOL_MENU_ITEM(_audioOptions.item[3], 5, 128, 56, 114, 14, 0x42dc, 0);
+ Button::Callback audioMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedAudioMenu);
+ for (int i = 0; i < 4; ++i)
+ _audioOptions.item[i].callback = audioMenuFunctor;
+
+ GUI_LOL_MENU(_deathMenu, 11, 0x4013, 0, 2, -1, -1, -1, -1);
+ GUI_LOL_MENU_ITEM(_deathMenu.item[0], 0x4006, 8, 30, 104, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_deathMenu.item[1], 0x4001, 176, 30, 104, 15, 0, 0);
+ Button::Callback deathMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedDeathMenu);
+ for (int i = 0; i < 2; ++i)
+ _deathMenu.item[i].callback = deathMenuFunctor;
+
+ GUI_LOL_MENU(_savenameMenu, 7, 0x4053, 0, 2, -1, -1, -1, -1);
+ GUI_LOL_MENU_ITEM(_savenameMenu.item[0], 0x4012, 8, 38, 72, 15, 0, _vm->_keyMap[Common::KEYCODE_RETURN]);
+ GUI_LOL_MENU_ITEM(_savenameMenu.item[1], 0x4011, 176, 38, 72, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]);
+ Button::Callback savenameMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedSavenameMenu);
+ for (int i = 0; i < 2; ++i)
+ _savenameMenu.item[i].callback = savenameMenuFunctor;
+
+ GUI_LOL_MENU(_choiceMenu, 11, 0, 0, 2, -1, -1, -1, -1);
+ GUI_LOL_MENU_ITEM(_choiceMenu.item[0], 0x4007, 8, 30, 72, 15, 0, 0);
+ GUI_LOL_MENU_ITEM(_choiceMenu.item[1], 0x4008, 208, 30, 72, 15, 0, 0);
+ Button::Callback choiceMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedChoiceMenu);
+ for (int i = 0; i < 2; ++i)
+ _choiceMenu.item[i].callback = choiceMenuFunctor;
+}
+
+const ScreenDim Screen_LoL::_screenDimTable256C[] = {
+ { 0x00, 0x00, 0x28, 0xC8, 0xC7, 0xCF, 0x00, 0x00 }, // Taken from Intro
+ { 0x08, 0x48, 0x18, 0x38, 0xFE, 0x01, 0x00, 0x00 },
+ { 0x0E, 0x00, 0x16, 0x78, 0xFE, 0x01, 0x00, 0x00 },
+ { 0x0B, 0x7B, 0x1C, 0x12, 0xFE, 0xFC, 0x00, 0x00 },
+ { 0x0B, 0x7B, 0x1C, 0x2D, 0xFE, 0xFC, 0x00, 0x00 },
+ { 0x55, 0x7B, 0xE9, 0x37, 0xFE, 0xFC, 0x00, 0x00 },
+ { 0x0B, 0x8C, 0x10, 0x2B, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (4 entries)
+ { 0x04, 0x59, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x05, 0x6E, 0x1E, 0x0C, 0xFE, 0x01, 0x00, 0x00 },
+ { 0x07, 0x19, 0x1A, 0x97, 0x00, 0x00, 0x00, 0x00 }, // Ingame main menu box CD version
+ { 0x03, 0x1E, 0x22, 0x8C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x02, 0x48, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x0E, 0x00, 0x16, 0x78, 0xFE, 0x01, 0x00, 0x00 },
+ { 0x0D, 0xA2, 0x18, 0x0C, 0xFE, 0x01, 0x00, 0x00 },
+ { 0x0F, 0x06, 0x14, 0x6E, 0x01, 0x00, 0x00, 0x00 },
+ { 0x1A, 0xBE, 0x0A, 0x07, 0xFE, 0x01, 0x00, 0x00 },
+ { 0x07, 0x21, 0x1A, 0x85, 0x00, 0x00, 0x00, 0x00 },
+ { 0x03, 0x32, 0x22, 0x62, 0x00, 0x00, 0x00, 0x00 },
+ { 0x0B, 0x8C, 0x10, 0x33, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (5 entries, CD version only)
+ { 0x0B, 0x8C, 0x10, 0x23, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (3 entries, floppy version only)
+
+ { 0x01, 0x20, 0x26, 0x80, 0xDC, 0xFD, 0x00, 0x00 }, // Credits
+ { 0x09, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x19, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x01, 0x02, 0x26, 0x14, 0x00, 0x0F, 0x0E, 0x00 },
+};
+
+const ScreenDim Screen_LoL::_screenDimTable16C[] = {
+ { 0x00, 0x00, 0x28, 0xC8, 0x33, 0x44, 0x00, 0x00 }, // Taken from Intro
+ { 0x08, 0x48, 0x18, 0x38, 0x33, 0x44, 0x00, 0x00 },
+ { 0x0E, 0x00, 0x16, 0x78, 0x33, 0x44, 0x00, 0x00 },
+ { 0x0B, 0x7B, 0x1C, 0x11, 0x33, 0x11, 0x00, 0x00 },
+ { 0x0B, 0x7B, 0x1C, 0x2D, 0x33, 0x11, 0x00, 0x00 },
+ { 0x55, 0x7B, 0xE9, 0x37, 0x33, 0x11, 0x00, 0x00 },
+ { 0x0B, 0x92, 0x10, 0x2A, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (4 entries)
+ { 0x04, 0x58, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x05, 0x6C, 0x1E, 0x0D, 0x33, 0x44, 0x00, 0x00 },
+ { 0x07, 0x20, 0x1A, 0x86, 0x00, 0x00, 0x00, 0x00 },
+ { 0x03, 0x20, 0x22, 0x8C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x02, 0x48, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x0E, 0x00, 0x16, 0x78, 0x33, 0x44, 0x00, 0x00 },
+ { 0x0D, 0xA2, 0x18, 0x0C, 0x33, 0x44, 0x00, 0x00 },
+ { 0x0F, 0x06, 0x14, 0x6E, 0x44, 0x00, 0x00, 0x00 },
+ { 0x1A, 0xBE, 0x0A, 0x07, 0x33, 0x44, 0x00, 0x00 },
+ { 0x07, 0x21, 0x1A, 0x85, 0x00, 0x00, 0x00, 0x00 },
+ { 0x03, 0x32, 0x22, 0x62, 0x00, 0x00, 0x00, 0x00 },
+ { 0x0B, 0x8C, 0x10, 0x33, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (5 entries, not used here)
+ { 0x0B, 0x8C, 0x10, 0x23, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (3 entries)
+
+ { 0x01, 0x20, 0x26, 0x80, 0xDC, 0xFD, 0x00, 0x00 }, // Credits (TODO: Check this!)
+ { 0x09, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x19, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x01, 0x02, 0x26, 0x14, 0x00, 0x0F, 0x0E, 0x00 },
+};
+
+const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable256C);
+
+const char * const LoLEngine::_languageExt[] = {
+ "ENG",
+ "FRE",
+ "GER"
+};
+
+const LoLEngine::CharacterPrev LoLEngine::_charPreviews[] = {
+ { "Ak\'shel", 0x060, 0x7F, { 0x0F, 0x08, 0x05 } },
+ { "Michael", 0x09A, 0x7F, { 0x06, 0x0A, 0x0F } },
+ { "Kieran", 0x0D4, 0x7F, { 0x08, 0x06, 0x08 } },
+ { "Conrad", 0x10F, 0x7F, { 0x0A, 0x0C, 0x0A } }
+};
+
+const uint16 LoLEngine::_charPosXPC98[] = {
+ 92, 152, 212, 268
+};
+
+const uint8 LoLEngine::_charNamesPC98[][11] = {
+ { 0x83, 0x41, 0x83, 0x4E, 0x83, 0x56, 0x83, 0x46, 0x83, 0x8B, 0x00 },
+ { 0x83, 0x7D, 0x83, 0x43, 0x83, 0x50, 0x83, 0x8B, 0x00, 0x00, 0x00 },
+ { 0x83, 0x4C, 0x81, 0x5B, 0x83, 0x89, 0x83, 0x93, 0x00, 0x00, 0x00 },
+ { 0x83, 0x52, 0x83, 0x93, 0x83, 0x89, 0x83, 0x62, 0x83, 0x68, 0x00 }
+};
+
+const uint8 LoLEngine::_chargenFrameTableTalkie[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x04, 0x03, 0x02, 0x01,
+ 0x00, 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
+ 0x0E, 0x0F, 0x10, 0x11, 0x12
+};
+
+const uint8 LoLEngine::_chargenFrameTableFloppy[] = {
+ 0, 1, 2, 3, 4, 5, 4, 3, 2,
+ 1, 0, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+const uint16 LoLEngine::_selectionPosTable[] = {
+ 0x6F, 0x00, 0x8F, 0x00, 0xAF, 0x00, 0xCF, 0x00,
+ 0xEF, 0x00, 0x6F, 0x20, 0x8F, 0x20, 0xAF, 0x20,
+ 0xCF, 0x20, 0xEF, 0x20, 0x6F, 0x40, 0x8F, 0x40,
+ 0xAF, 0x40, 0xCF, 0x40, 0xEF, 0x40, 0x10F, 0x00
+};
+
+const uint8 LoLEngine::_selectionChar1IdxTable[] = {
+ 0, 0, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 0, 0, 5, 5, 5,
+ 5, 5, 5, 5, 0, 0, 5, 5,
+ 5, 5, 5
+};
+
+const uint8 LoLEngine::_selectionChar2IdxTable[] = {
+ 1, 1, 6, 6, 1, 1, 6, 6,
+ 6, 6, 6, 6, 6, 1, 1, 6,
+ 6, 6, 1, 1, 6, 6, 6, 6,
+ 6, 6, 6
+};
+
+const uint8 LoLEngine::_selectionChar3IdxTable[] = {
+ 2, 2, 7, 7, 7, 7, 2, 2,
+ 7, 7, 7, 7, 7, 7, 7, 2,
+ 2, 7, 7, 7, 7, 2, 2, 7,
+ 7, 7, 7
+};
+
+const uint8 LoLEngine::_selectionChar4IdxTable[] = {
+ 3, 3, 8, 8, 8, 8, 3, 3,
+ 8, 8, 3, 3, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 3, 3, 8,
+ 8, 8, 8
+};
+
+const uint8 LoLEngine::_reminderChar1IdxTable[] = {
+ 4, 4, 4, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5
+};
+
+const uint8 LoLEngine::_reminderChar2IdxTable[] = {
+ 9, 9, 9, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 6
+};
+
+const uint8 LoLEngine::_reminderChar3IdxTable[] = {
+ 0xE, 0xE, 0xE, 0x7, 0x7, 0x7, 0x7, 0x7,
+ 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
+ 0x7
+};
+
+const uint8 LoLEngine::_reminderChar4IdxTable[] = {
+ 0xF, 0xF, 0xF, 0x8, 0x8, 0x8, 0x8, 0x8,
+ 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
+ 0x8
+};
+
+const uint8 LoLEngine::_selectionAnimIndexTable[] = {
+ 0, 5, 1, 6, 2, 7, 3, 8
+};
+
+const uint8 LoLEngine::_charInfoFrameTable[] = {
+ 0x0, 0x7, 0x8, 0x9, 0xA, 0xB, 0xA, 0x9,
+ 0x8, 0x7, 0x0, 0x0, 0x7, 0x8, 0x9, 0xA,
+ 0xB, 0xA, 0x9, 0x8, 0x7, 0x0, 0x0, 0x7,
+ 0x8, 0x9, 0xA, 0xB, 0xA, 0x9, 0x8, 0x7
+};
+
+const uint8 LoLEngine::_clock2Timers[] = {
+ 0x00, 0x10, 0x11, 0x03, 0x04, 0x50,
+ 0x51, 0x52, 0x08, 0x09, 0x0A
+};
+
+const uint8 LoLEngine::_numClock2Timers = ARRAYSIZE(LoLEngine::_clock2Timers);
+
+const int8 LoLEngine::_mapCoords[12][4] = {
+ { 0, 7, 0, -5 }, { -5, 0, 6, 0 }, { 7, 5, 7, 1 },
+ { 5, 6, 4, 6 }, { 0, 7, 0, -1 }, { -3, 0, 6, 0 },
+ { 6, 7, 6, -3 }, { -3, 5, 6, 5 }, { 1, 5, 1, 1 },
+ { 3, 1, 3, 1 }, { -1, 6, -1, -8 }, { -7, -1, 5, -1 }
+};
+
+const MistOfDoomAnimData LoLEngine::_mistAnimData[] = {
+ { 0, 7, 7, 13, 155 },
+ { 0, 16, 16, 17, 155 },
+ { 0, 24, 24, 24, 174 },
+ { 0, 19, 19, 19, 174 },
+ { 0, 16, 16, 17, 175 },
+};
+
+const char * const LoLEngine::_outroShapeFileTable[] = {
+ "AMAZON.SHP", "ARCHRSLG.SHP", "AVIANWRM.SHP", "BANDIT.SHP", "BOAR.SHP", "CABAL.SHP",
+ "GUARD.SHP", "HAG.SHP", "HORNET.SHP", "HURZELL.SHP", "IRONGRZR.SHP", "KNOWLES.SHP",
+ "LIZARD.SHP", "MANTHA.SHP", "MINOTAUR.SHP", "MORIBUND.SHP", "ORC.SHP", "ORCLDR.SHP",
+ "PENTROG.SHP", "RATMAN.SHP", "ROCKLING.SHP", "SCAVNGR.SHP", "STARK.SHP",
+ "SWAMPCIT.SHP", "SWAMPMON.SHP", "THUG.SHP", "VIPER.SHP", "XEOB.SHP"
+};
+
+const uint8 LoLEngine::_outroFrameTable[] = {
+ 0, 0, 0, 0, 0, 1, 2, 3,
+ 0, 1, 2, 3, 8, 9, 10, 11,
+ 8, 9, 10, 11, 4, 5, 6, 7
+};
+
+const int16 LoLEngine::_outroRightMonsterPos[] = {
+ 205, 55, 205, 55, 205, 55, 205, 55,
+ 205, 56, 207, 57, 208, 58, 210, 59,
+ 213, 60, 216, 61, 220, 61, 225, 61,
+ 230, 61, 235, 61, 240, 61, 240, 61,
+ 240, 61, 240, 61, 240, 61, 240, 61,
+ 240, 61, 265, 61, 290, 61, 315, 61
+};
+
+const int16 LoLEngine::_outroLeftMonsterPos[] = {
+ 92, 55, 92, 55, 92, 55, 92, 55,
+ 92, 56, 90, 57, 85, 58, 77, 59,
+ 67, 60, 57, 61, 47, 61, 35, 61,
+ 35, 61, 35, 61, 35, 61, 35, 61,
+ 35, 61, 35, 61, 35, 61, 35, 61,
+ 35, 61, 10, 61, -20, 61, -45, 61
+};
+
+const int16 LoLEngine::_outroRightDoorPos[] = {
+ 200, 41, 200, 29, 200, 17, 200, 5,
+ 200, -7, 200, -7, 200, -7, 200, -7,
+ 200, 5, 200, 17, 200, 29, 200, 41,
+ 200, 41, 200, 41, 200, 41, 200, 41,
+ 200, 41, 200, 41, 200, 41, 200, 41,
+ 200, 41, 200, 41, 200, 41, 200, 41
+};
+
+const int16 LoLEngine::_outroLeftDoorPos[] = {
+ 72, 41, 72, 29, 72, 17, 72, 5,
+ 72, -7, 72, -7, 72, -7, 72, -7,
+ 72, 5, 72, 17, 72, 29, 72, 41,
+ 72, 41, 72, 41, 72, 41, 72, 41,
+ 72, 41, 72, 41, 72, 41, 72, 41,
+ 72, 41, 72, 41, 72, 41, 72, 41
+};
+
+const int LoLEngine::_outroMonsterScaleTableX[] = {
+ 0x050, 0x050, 0x050, 0x050, 0x050, 0x05D, 0x070, 0x085,
+ 0x0A0, 0x0C0, 0x0E2, 0x100, 0x100, 0x100, 0x100, 0x100,
+ 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100
+};
+
+const int LoLEngine::_outroMonsterScaleTableY[] = {
+ 0x04C, 0x04C, 0x04C, 0x04C, 0x04C, 0x059, 0x06B, 0x080,
+ 0x099, 0x0B8, 0x0D9, 0x100, 0x100, 0x100, 0x100, 0x100,
+ 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100
+};
+
+} // End of namespace Kyra
+
+#endif
+
diff --git a/engines/kyra/text_hof.cpp b/engines/kyra/text_hof.cpp
index 48eda97f80..9d20cdd51a 100644
--- a/engines/kyra/text_hof.cpp
+++ b/engines/kyra/text_hof.cpp
@@ -255,7 +255,8 @@ void KyraEngine_HoF::objectChatInit(const char *str, int object, int vocHigh, in
_screen->hideMouse();
- if (textEnabled()) {
+ _chatTextEnabled = textEnabled();
+ if (_chatTextEnabled) {
objectChatPrintText(str, object);
_chatEndTime = _system->getMillis() + chatCalcDuration(str) * _tickLength;
} else {
diff --git a/engines/kyra/text_lok.cpp b/engines/kyra/text_lok.cpp
index 3e45c0f286..40f2217a2b 100644
--- a/engines/kyra/text_lok.cpp
+++ b/engines/kyra/text_lok.cpp
@@ -32,10 +32,9 @@
namespace Kyra {
-void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const char *chatStr, uint8 charNum) {
+void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const char *chatStr, uint8 charNum, const bool printText) {
bool hasUpdatedNPCs = false;
bool runLoop = true;
- bool drawText = textEnabled();
uint8 currPage;
uint32 timeToEnd = strlen(chatStr) * 8 * _tickLength + _system->getMillis();
@@ -92,7 +91,7 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const
_animator->preserveAnyChangedBackgrounds();
_animator->prepDrawAllObjects();
- if (drawText) {
+ if (printText) {
currPage = _screen->_curPage;
_screen->_curPage = 2;
_text->printCharacterText(chatStr, charNum, _characterList[charNum].x1);
@@ -102,7 +101,7 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const
_animator->copyChangedObjectsForward(0);
updateTextFade();
- if (((chatDuration < (int16)(_system->getMillis() - timeAtStart)) && chatDuration != -1 && drawText) || (!drawText && !snd_voiceIsPlaying()))
+ if (((chatDuration < (int16)(_system->getMillis() - timeAtStart)) && chatDuration != -1 && printText) || (!printText && !snd_voiceIsPlaying()))
break;
uint32 nextTime = loopStart + _tickLength;
@@ -137,8 +136,11 @@ void KyraEngine_LoK::endCharacterChat(int8 charNum, int16 convoInitialized) {
_charSayUnk3 = -1;
if (charNum > 4 && charNum < 11) {
- //TODO: weird _game_inventory stuff here
- //warning("STUB: endCharacterChat() for high charnums");
+ _animator->sprites()[_disabledTalkAnimObject].active = 1;
+ _sprites->_anims[_disabledTalkAnimObject].play = true;
+
+ _animator->sprites()[_enabledTalkAnimObject].active = 0;
+ _sprites->_anims[_enabledTalkAnimObject].play = false;
}
if (convoInitialized != 0) {
@@ -225,8 +227,19 @@ int KyraEngine_LoK::initCharacterChat(int8 charNum) {
_animator->restoreAllObjectBackgrounds();
if (charNum > 4 && charNum < 11) {
- // TODO: Fill in weird _game_inventory stuff here
- //warning("STUB: initCharacterChat() for high charnums");
+ const uint8 animDisableTable[] = { 3, 1, 1, 5, 0, 6 };
+ const uint8 animEnableTable[] = { 4, 2, 5, 6, 1, 7 };
+
+ _disabledTalkAnimObject = animDisableTable[charNum - 5];
+ _enabledTalkAnimObject = animEnableTable[charNum - 5];
+
+ _animator->sprites()[_disabledTalkAnimObject].active = 0;
+ _sprites->_anims[_disabledTalkAnimObject].play = false;
+
+ _animator->sprites()[_enabledTalkAnimObject].active = 1;
+ _sprites->_anims[_enabledTalkAnimObject].play = true;
+
+ _charSayUnk2 = _enabledTalkAnimObject;
}
_animator->flagAllObjectsForRefresh();
@@ -279,7 +292,9 @@ void KyraEngine_LoK::characterSays(int vocFile, const char *chatStr, int8 charNu
_text->_talkMessageY = yPos;
_text->_talkMessageH = lineNum * 10;
- if (textEnabled()) {
+ const bool printText = textEnabled();
+
+ if (printText) {
_animator->restoreAllObjectBackgrounds();
_screen->copyRegion(12, _text->_talkMessageY, 12, 136, 296, _text->_talkMessageH, 2, 2);
@@ -296,9 +311,9 @@ void KyraEngine_LoK::characterSays(int vocFile, const char *chatStr, int8 charNu
if (!speechEnabled())
vocFile = -1;
- waitForChatToFinish(vocFile, chatTicks, chatStr, charNum);
+ waitForChatToFinish(vocFile, chatTicks, chatStr, charNum, printText);
- if (textEnabled()) {
+ if (printText) {
_animator->restoreAllObjectBackgrounds();
_screen->copyRegion(12, 136, 12, _text->_talkMessageY, 296, _text->_talkMessageH, 2, 2);
diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp
index ea2dc48031..726d9e339f 100644
--- a/engines/kyra/text_mr.cpp
+++ b/engines/kyra/text_mr.cpp
@@ -265,7 +265,8 @@ void KyraEngine_MR::objectChatInit(const char *str, int object, int vocHigh, int
_screen->hideMouse();
- if (textEnabled()) {
+ _chatTextEnabled = textEnabled();
+ if (_chatTextEnabled) {
objectChatPrintText(str, object);
_chatEndTime = _system->getMillis() + chatCalcDuration(str) * _tickLength;
} else {
diff --git a/engines/kyra/timer_hof.cpp b/engines/kyra/timer_hof.cpp
index 117b84f48a..d8f86e30a2 100644
--- a/engines/kyra/timer_hof.cpp
+++ b/engines/kyra/timer_hof.cpp
@@ -97,6 +97,9 @@ void KyraEngine_HoF::setTimer1DelaySecs(int secs) {
}
void KyraEngine_HoF::setWalkspeed(uint8 newSpeed) {
+ if (!_timer)
+ return;
+
if (newSpeed < 5)
newSpeed = 3;
else
diff --git a/engines/kyra/timer_lok.cpp b/engines/kyra/timer_lok.cpp
index 3a7d1ed0de..6f4948c279 100644
--- a/engines/kyra/timer_lok.cpp
+++ b/engines/kyra/timer_lok.cpp
@@ -48,33 +48,39 @@ void KyraEngine_LoK::setupTimers() {
for (int i = 10; i <= 13; ++i)
_timer->addTimer(i, 0, 420, 1);
- _timer->addTimer(14, TimerV1(timerCheckAnimFlag2), 600, 1);
+ _timer->addTimer(14, TimerV1(timerAsWillowispTimeout), 600, 1);
_timer->addTimer(15, TimerV1(timerUpdateHeadAnims), 11, 1);
- _timer->addTimer(16, TimerV1(timerSetFlags1), 7200, 1);
- _timer->addTimer(17, 0 /*sub_15120*/, 7200, 1);
- _timer->addTimer(18, TimerV1(timerCheckAnimFlag1), 600, 1);
+ _timer->addTimer(16, TimerV1(timerTulipCreator), 7200, 1);
+ _timer->addTimer(17, TimerV1(timerRubyCreator), 7200, 1);
+ _timer->addTimer(18, TimerV1(timerAsInvisibleTimeout), 600, 1);
_timer->addTimer(19, TimerV1(timerRedrawAmulet), 600, 1);
_timer->addTimer(20, 0, 7200, 1);
- _timer->addTimer(21, 0/*sub_1517C*/, 18000, 1);
+ _timer->addTimer(21, TimerV1(timerLavenderRoseCreator), 18000, 1);
_timer->addTimer(22, 0, 7200, 1);
- for (int i = 23; i <= 27; ++i)
- _timer->addTimer(i, 0, 10800, 1);
+ _timer->addTimer(23, 0, 10800, 1);
+ _timer->addTimer(24, TimerV1(timerAcornCreator), 10800, 1);
+ _timer->addTimer(25, 0, 10800, 1);
+ _timer->addTimer(26, TimerV1(timerBlueberryCreator), 10800, 1);
+ _timer->addTimer(27, 0, 10800, 1);
_timer->addTimer(28, 0, 21600, 1);
_timer->addTimer(29, 0, 7200, 1);
_timer->addTimer(30, 0, 10800, 1);
_timer->addTimer(31, TimerV1(timerFadeText), -1, 1);
- _timer->addTimer(32, TimerV1(updateAnimFlag1), 9, 1);
- _timer->addTimer(33, TimerV1(updateAnimFlag2), 3, 1);
+ _timer->addTimer(32, TimerV1(timerWillowispFrameTimer), 9, 1);
+ _timer->addTimer(33, TimerV1(timerInvisibleFrameTimer), 3, 1);
}
void KyraEngine_LoK::timerUpdateHeadAnims(int timerNum) {
static int8 currentFrame = 0;
- static const int8 frameTable[] = {4, 5, 4, 5, 4, 5, 0, 1, 4, 5,
- 4, 4, 6, 4, 8, 1, 9, 4, -1};
+ static const int8 frameTable[] = {
+ 4, 5, 4, 5, 4, 5, 0, 1,
+ 4, 5, 4, 4, 6, 4, 8, 1,
+ 9, 4, -1
+ };
if (_talkingCharNum < 0)
return;
@@ -89,19 +95,51 @@ void KyraEngine_LoK::timerUpdateHeadAnims(int timerNum) {
_animator->animRefreshNPC(_talkingCharNum);
}
-void KyraEngine_LoK::timerSetFlags1(int timerNum) {
+void KyraEngine_LoK::timerTulipCreator(int timerNum) {
if (_currentCharacter->sceneId == 0x1C)
return;
- int rndNr = _rnd.getRandomNumberRng(0, 3);
+ setItemCreationFlags(17, 3);
+}
+
+void KyraEngine_LoK::timerRubyCreator(int timerNum) {
+ if (_currentCharacter->sceneId == 0x23)
+ return;
+
+ setItemCreationFlags(22, 4);
+}
+
+void KyraEngine_LoK::timerLavenderRoseCreator(int timerNum) {
+ if (_currentCharacter->sceneId == 0x06)
+ return;
+
+ setItemCreationFlags(0, 4);
+}
+
+void KyraEngine_LoK::timerAcornCreator(int timerNum) {
+ if (_currentCharacter->sceneId == 0x1F)
+ return;
+
+ setItemCreationFlags(72, 5);
+}
- for (int i = 0; i < 4; i++) {
- if (!queryGameFlag(rndNr + 17)) {
- setGameFlag(rndNr + 17);
+void KyraEngine_LoK::timerBlueberryCreator(int timerNum) {
+ if (_currentCharacter->sceneId == 0x28)
+ return;
+
+ setItemCreationFlags(26, 7);
+}
+
+void KyraEngine_LoK::setItemCreationFlags(int offset, int count) {
+ int rndNr = _rnd.getRandomNumberRng(0, count);
+
+ for (int i = 0; i <= count; i++) {
+ if (!queryGameFlag(rndNr + offset)) {
+ setGameFlag(rndNr + offset);
break;
} else {
rndNr++;
- if (rndNr > 3)
+ if (rndNr > count)
rndNr = 0;
}
}
@@ -111,16 +149,14 @@ void KyraEngine_LoK::timerFadeText(int timerNum) {
_fadeText = true;
}
-void KyraEngine_LoK::updateAnimFlag1(int timerNum) {
- if (_brandonStatusBit & 2) {
+void KyraEngine_LoK::timerWillowispFrameTimer(int timerNum) {
+ if (_brandonStatusBit & 2)
_brandonStatusBit0x02Flag = 1;
- }
}
-void KyraEngine_LoK::updateAnimFlag2(int timerNum) {
- if (_brandonStatusBit & 0x20) {
+void KyraEngine_LoK::timerInvisibleFrameTimer(int timerNum) {
+ if (_brandonStatusBit & 0x20)
_brandonStatusBit0x20Flag = 1;
- }
}
void KyraEngine_LoK::setTextFadeTimerCountdown(int16 countdown) {
@@ -130,19 +166,14 @@ void KyraEngine_LoK::setTextFadeTimerCountdown(int16 countdown) {
_timer->setCountdown(31, countdown*60);
}
-void KyraEngine_LoK::timerSetFlags2(int timerNum) {
- if (!((uint32 *)(_flagsTable+0x2D))[timerNum])
- ((uint32 *)(_flagsTable+0x2D))[timerNum] = 1;
-}
-
-void KyraEngine_LoK::timerCheckAnimFlag1(int timerNum) {
+void KyraEngine_LoK::timerAsInvisibleTimeout(int timerNum) {
if (_brandonStatusBit & 0x20) {
checkAmuletAnimFlags();
_timer->setCountdown(18, -1);
}
}
-void KyraEngine_LoK::timerCheckAnimFlag2(int timerNum) {
+void KyraEngine_LoK::timerAsWillowispTimeout(int timerNum) {
if (_brandonStatusBit & 0x2) {
checkAmuletAnimFlags();
_timer->setCountdown(14, -1);
@@ -157,6 +188,9 @@ void KyraEngine_LoK::timerRedrawAmulet(int timerNum) {
}
void KyraEngine_LoK::setWalkspeed(uint8 newSpeed) {
+ if (!_timer)
+ return;
+
static const uint8 speeds[] = { 11, 9, 6, 5, 3 };
assert(newSpeed < ARRAYSIZE(speeds));
diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp
index 8a598591bb..d0e54f996b 100644
--- a/engines/kyra/vqa.cpp
+++ b/engines/kyra/vqa.cpp
@@ -260,8 +260,8 @@ bool VQAMovie::open(const char *filename) {
_header.bits = 8;
}
- setX((Screen::SCREEN_W - _header.width) / 2);
- setY((Screen::SCREEN_H - _header.height) / 2);
+ _x = (Screen::SCREEN_W - _header.width) / 2;
+ _y = (Screen::SCREEN_H - _header.height) / 2;
_frameInfo = new uint32[_header.numFrames];
_frame = new byte[_header.width * _header.height];
diff --git a/engines/kyra/vqa.h b/engines/kyra/vqa.h
index c1448a4865..129d526e98 100644
--- a/engines/kyra/vqa.h
+++ b/engines/kyra/vqa.h
@@ -56,9 +56,6 @@ public:
// It's unlikely that we ever want to change the movie position from
// its default.
- void setX(int x) { _x = x; }
- void setY(int y) { _y = y; }
-
void setDrawPage(int page) { _drawPage = page; }
bool open(const char *filename);
diff --git a/engines/lure/debugger.cpp b/engines/lure/debugger.cpp
index 3abc079a05..1cfe0804e4 100644
--- a/engines/lure/debugger.cpp
+++ b/engines/lure/debugger.cpp
@@ -105,7 +105,7 @@ bool Debugger::cmd_enterRoom(int argc, const char **argv) {
if (!remoteFlag)
res.getActiveHotspot(PLAYER_ID)->setRoomNumber(roomNumber);
- _detach_now = true;
+ detach();
return false;
}
diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp
index 36c1cf237d..dd2a702e2a 100644
--- a/engines/lure/detection.cpp
+++ b/engines/lure/detection.cpp
@@ -196,7 +196,11 @@ static const ADParams detectionParams = {
// Flags
kADFlagUseExtraAsHint,
// Additional GUI options (for every game}
- Common::GUIO_NOSPEECH
+ Common::GUIO_NOSPEECH,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class LureMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/lure/fights.cpp b/engines/lure/fights.cpp
index 53539677c8..789c9d924e 100644
--- a/engines/lure/fights.cpp
+++ b/engines/lure/fights.cpp
@@ -132,8 +132,7 @@ void FightsManager::fightLoop() {
}
Screen::getReference().update();
- if (game.debugger().isAttached())
- game.debugger().onFrame();
+ game.debugger().onFrame();
g_system->delayMillis(10);
}
diff --git a/engines/lure/game.cpp b/engines/lure/game.cpp
index d0f98b9c34..e77ac25716 100644
--- a/engines/lure/game.cpp
+++ b/engines/lure/game.cpp
@@ -56,8 +56,6 @@ Game::Game() {
_debugFlag = gDebugLevel >= ERROR_BASIC;
_soundFlag = true;
- _musicVolume = ConfMan.getBool("music_mute") ? 0 : MIN(255, ConfMan.getInt("music_volume"));
- _sfxVolume = ConfMan.getBool("sfx_mute") ? 0 : MIN(255, ConfMan.getInt("sfx_volume"));
}
Game::~Game() {
@@ -281,8 +279,7 @@ void Game::execute() {
system.updateScreen();
system.delayMillis(10);
- if (_debugger->isAttached())
- _debugger->onFrame();
+ _debugger->onFrame();
}
room.leaveRoom();
diff --git a/engines/lure/game.h b/engines/lure/game.h
index 3864e9c205..123ac0dca7 100644
--- a/engines/lure/game.h
+++ b/engines/lure/game.h
@@ -48,8 +48,6 @@ class Game {
private:
Debugger *_debugger;
bool _fastTextFlag, _soundFlag;
- uint8 _sfxVolume;
- uint8 _musicVolume;
uint8 _state;
uint16 _tellCommands[MAX_TELL_COMMANDS * 3 + 1];
int _numTellCommands;
@@ -87,8 +85,6 @@ public:
bool &debugFlag() { return _debugFlag; }
bool fastTextFlag() { return _fastTextFlag; }
bool soundFlag() { return _soundFlag; }
- 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/sound.cpp b/engines/lure/sound.cpp
index e725b7c31a..a75545c330 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -50,13 +50,13 @@ SoundManager::SoundManager() {
_soundData = NULL;
_paused = false;
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- _isRoland = midiDriver != MD_ADLIB;
- _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32);
+ _isRoland = MidiDriver::getMusicType(dev) != MT_ADLIB;
+ _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
Common::set_to(_channelsInUse, _channelsInUse + NUM_CHANNELS, false);
- _driver = MidiDriver::createMidi(midiDriver);
+ _driver = MidiDriver::createMidi(dev);
int statusCode = _driver->open();
if (statusCode) {
warning("Sound driver returned error code %d", statusCode);
@@ -72,6 +72,8 @@ SoundManager::SoundManager() {
_channelsInner[index].volume = 90;
}
}
+
+ syncSounds();
}
SoundManager::~SoundManager() {
@@ -288,16 +290,21 @@ uint8 SoundManager::descIndexOf(uint8 soundNumber) {
// Used to sync the volume for all channels with the Config Manager
//
void SoundManager::syncSounds() {
- Game &game = Game::getReference();
musicInterface_TidySounds();
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+ _musicVolume = mute ? 0 : MIN(255, ConfMan.getInt("music_volume"));
+ _sfxVolume = mute ? 0 : MIN(255, ConfMan.getInt("sfx_volume"));
+
g_system->lockMutex(_soundMutex);
MusicListIterator i;
for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
if ((*i)->isMusic())
- (*i)->setVolume(game.musicVolume());
+ (*i)->setVolume(_musicVolume);
else
- (*i)->setVolume(game.sfxVolume());
+ (*i)->setVolume(_sfxVolume);
}
g_system->unlockMutex(_soundMutex);
}
@@ -599,9 +606,9 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
}
if (_isMusic)
- setVolume(ConfMan.getInt("music_volume"));
+ setVolume(Sound.musicVolume());
else
- setVolume(ConfMan.getInt("sfx_volume"));
+ setVolume(Sound.sfxVolume());
_passThrough = false;
@@ -658,8 +665,7 @@ void MidiMusic::setVolume(int volume) {
_volume = volume;
- Game &game = Game::getReference();
- volume *= _isMusic ? game.musicVolume() : game.sfxVolume();
+ volume *= _isMusic ? Sound.musicVolume() : Sound.sfxVolume();
for (int i = 0; i < _numChannels; ++i) {
if (_channels[_channelNumber + i].midiChannel != NULL)
@@ -707,8 +713,7 @@ void MidiMusic::send(uint32 b) {
// Adjust volume changes by song and master volume
byte volume = (byte)((b >> 16) & 0x7F);
_channels[channel].volume = volume;
- Game &game = Game::getReference();
- int master_volume = _isMusic ? game.musicVolume() : game.sfxVolume();
+ int master_volume = _isMusic ? Sound.musicVolume() : Sound.sfxVolume();
volume = volume * _volume * master_volume / 65025;
b = (b & 0xFF00FFFF) | (volume << 16);
} else if ((b & 0xF0) == 0xC0) {
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index c41cec48fe..6d248fbd20 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -105,7 +105,7 @@ public:
bool isMusic() {return _isMusic; }
};
-class SoundManager: public Common::Singleton<SoundManager> {
+class SoundManager : public Common::Singleton<SoundManager> {
private:
// Outer sound interface properties
MemoryBlock *_descs;
@@ -128,11 +128,15 @@ private:
Common::MutexRef _soundMutex;
bool _paused;
+ uint _musicVolume;
+ uint _sfxVolume;
+
// Internal support methods
void bellsBodge();
void musicInterface_TidySounds();
static void onTimer(void *data);
void doTimer();
+
public:
SoundManager();
~SoundManager();
@@ -156,9 +160,11 @@ public:
void fadeOut();
void pause() { _paused = true; }
void resume() { _paused = false; }
- bool getPaused() { return _paused; }
- bool hasNativeMT32() { return _nativeMT32; }
- bool isRoland() { return _isRoland; }
+ bool getPaused() const { return _paused; }
+ bool hasNativeMT32() const { return _nativeMT32; }
+ bool isRoland() const { return _isRoland; }
+ uint musicVolume() const { return _musicVolume; }
+ uint sfxVolume() const { return _sfxVolume; }
// The following methods implement the external sound player module
void musicInterface_Initialise();
diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp
index fe46e121f0..37314eff44 100644
--- a/engines/m4/animation.cpp
+++ b/engines/m4/animation.cpp
@@ -26,181 +26,510 @@
#include "m4/assets.h"
#include "m4/animation.h"
#include "m4/compression.h"
+#include "m4/mads_scene.h"
namespace M4 {
// TODO: this code needs cleanup
-Animation::Animation(MadsM4Engine *vm) {
- _vm = vm;
- _playing = false;
+MadsAnimation::MadsAnimation(MadsM4Engine *vm, MadsView *view): Animation(vm), _view(view) {
+ _font = NULL;
+ _resetFlag = false;
+ _freeFlag = false;
+ _skipLoad = false;
+ _unkIndex = -1;
+ _messageCtr= 0;
+ _field12 = 0;
+
+ _currentFrame = 0;
+ _oldFrameEntry = 0;
+ _nextFrameTimer = _madsVm->_currentTimer;
+ _nextScrollTimer = 0;
}
-void Animation::loadFullScreen(const char *filename) {
- _vm->_palette->deleteAllRanges();
- load(filename);
+MadsAnimation::~MadsAnimation() {
+ for (uint i = 0; i < _messages.size(); ++i) {
+ if (_messages[i].kernelMsgIndex >= 0)
+ _view->_kernelMessages.remove(_messages[i].kernelMsgIndex);
+ }
+
+ // Further deletion logic
+ if (_field12) {
+ _view->_spriteSlots.deleteSprites(_spriteListIndexes[_spriteListIndex]);
+ }
}
-void Animation::load(const char *filename) {
- MadsPack anim(filename, _vm);
+#define FILENAME_SIZE 13
+
+/**
+ * Initialises and loads the data of an animation
+ */
+void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface) {
+ MadsPack anim(filename.c_str(), _vm);
+ bool madsRes = filename[0] == '*';
char buffer[20];
+ int streamIndex = 1;
// Chunk 1: header
// header
- // TODO: there are some unknown fields here, plus we don't read
- // the entire chunk
+
Common::SeekableReadStream *animStream = anim.getItemStream(0);
- Common::SeekableReadStream *spriteSeriesStream;
- //printf("Chunk 0, size %i\n", animStream->size());
- _seriesCount = animStream->readUint16LE();
- _frameCount = animStream->readUint16LE();
- _frameEntryCount = animStream->readUint16LE();
-
- // Unknown
- for (int i = 0; i < 43; i++)
- animStream->readByte();
-
- _spriteSeriesNames = new Common::String[_seriesCount];
- printf("%i sprite series\n", _seriesCount);
-
- // TODO: for now, we only load the first sprite series
- if (_seriesCount > 1)
- printf("TODO: Anim has %i sprite series, for now, we only load the first one\n", _seriesCount);
- _seriesCount = 1; // TODO
-
- for (int i = 0; i < _seriesCount; i++) {
- animStream->read(buffer, 13);
- _spriteSeriesNames[i] = Common::String(buffer);
- //printf("%03d: %s\n", i, _spriteSeriesNames[i].c_str());
-
- spriteSeriesStream = _vm->res()->get(_spriteSeriesNames[i].c_str());
- _spriteSeries = new SpriteAsset(_vm, spriteSeriesStream,
- spriteSeriesStream->size(), _spriteSeriesNames[i].c_str());
- _vm->res()->toss(_spriteSeriesNames[i].c_str());
-
- // Adjust the palette of the sprites in the sprite series
- // so that they can be displayed on screen correctly
- RGBList *palData = new RGBList(_spriteSeries->getColorCount(), _spriteSeries->getPalette(), true);
- _vm->_palette->addRange(palData);
-
- for (int k = 0; k < _spriteSeries->getCount(); k++) {
- M4Sprite *spr = _spriteSeries->getFrame(k);
- spr->translate(palData); // sprite pixel translation
- }
+
+ int spriteListCount = animStream->readUint16LE();
+ int miscEntriesCount = animStream->readUint16LE();
+ int frameEntryCount = animStream->readUint16LE();
+ int messagesCount = animStream->readUint16LE();
+ animStream->skip(1);
+ _flags = animStream->readByte();
+
+ animStream->skip(2);
+ _animMode = animStream->readUint16LE();
+ _roomNumber = animStream->readUint16LE();
+ animStream->skip(2);
+ _field12 = animStream->readUint16LE() != 0;
+ _spriteListIndex = animStream->readUint16LE();
+ _scrollX = animStream->readSint16LE();
+ _scrollY = animStream->readSint16LE();
+ _scrollTicks = animStream->readUint16LE();
+ animStream->skip(8);
+
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ _interfaceFile = Common::String(buffer);
+
+ for (int i = 0; i < 10; ++i) {
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ _spriteSetNames[i] = Common::String(buffer);
}
- //printf("End pos: %i\n", animStream->pos());
+ animStream->skip(81);
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ _lbmFilename = Common::String(buffer);
- delete animStream;
+ animStream->skip(365);
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ _spritesFilename = Common::String(buffer);
+
+ animStream->skip(48);
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ _soundName = Common::String(buffer);
- // ------------------
-
- // Chunk 2: anim info
- AnimationFrame frame;
- animStream = anim.getItemStream(1);
- //printf("Chunk 1, size %i\n", animStream->size());
-
- _frameEntries = new AnimationFrame[_frameEntryCount];
-
- for (int i = 0; i < _frameEntryCount; i++) {
-
- frame.animFrameIndex = animStream->readUint16LE();
- frame.u = animStream->readByte();
- frame.seriesIndex = animStream->readByte();
- frame.seriesFrameIndex = animStream->readUint16LE();
- frame.x = animStream->readUint16LE();
- frame.y = animStream->readUint16LE();
- frame.v = animStream->readByte();
- frame.w = animStream->readByte();
-
- _frameEntries[i] = frame;
-
- /*
- printf(
- "animFrameIndex = %4d, "
- "u = %3d, "
- "seriesIndex = %3d, "
- "seriesFrameIndex = %6d, "
- "x = %3d, "
- "y = %3d, "
- "v = %3d, "
- "w = %3d\n",
-
- frame.animFrameIndex,
- frame.u,
- frame.seriesIndex,
- frame.seriesFrameIndex,
- frame.x,
- frame.y,
- frame.v,
- frame.w
- );
- */
- }
- //printf("End pos: %i\n", animStream->pos());
+ animStream->skip(13);
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ _dsrName = Common::String(buffer);
+
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ Common::String fontResource(buffer);
+
+ if (_animMode == 4)
+ flags |= 0x4000;
+ if (flags & 0x100)
+ loadInterface(surface, depthSurface);
+
+ // Initialise the reference list
+ for (int i = 0; i < spriteListCount; ++i)
+ _spriteListIndexes.push_back(-1);
delete animStream;
- // Chunk 3: unknown (seems to be sound data?)
- // TODO
-}
+ if (messagesCount > 0) {
+ // Chunk 2
+ // Following is a list of any messages for the animation
+
+ animStream = anim.getItemStream(streamIndex++);
+
+ for (int i = 0; i < messagesCount; ++i) {
+ AnimMessage rec;
+ rec.soundId = animStream->readSint16LE();
+ animStream->read(rec.msg, 64);
+ animStream->skip(4);
+ rec.pos.x = animStream->readSint16LE();
+ rec.pos.y = animStream->readSint16LE();
+ rec.flags = animStream->readUint16LE();
+ rec.rgb1.r = animStream->readByte() << 2;
+ rec.rgb1.g = animStream->readByte() << 2;
+ rec.rgb1.b = animStream->readByte() << 2;
+ rec.rgb2.r = animStream->readByte() << 2;
+ rec.rgb2.g = animStream->readByte() << 2;
+ rec.rgb2.b = animStream->readByte() << 2;
+ animStream->skip(2); // Space for kernelMsgIndex
+ rec.kernelMsgIndex = -1;
+ animStream->skip(6);
+ rec.startFrame = animStream->readUint16LE();
+ rec.endFrame = animStream->readUint16LE();
+ animStream->skip(2);
+
+ _messages.push_back(rec);
+ }
-Animation::~Animation() {
- //delete[] _spriteSeriesNames;
- //delete[] _spriteSeries;
- //delete[] _frameEntries;
+ delete animStream;
+ }
+
+ if (frameEntryCount > 0) {
+ // Chunk 3: animation frame info
+ animStream = anim.getItemStream(streamIndex++);
+
+ for (int i = 0; i < frameEntryCount; i++) {
+ AnimFrameEntry rec;
+ rec.frameNumber = animStream->readUint16LE();
+ rec.seqIndex = animStream->readByte();
+ rec.spriteSlot.spriteListIndex = animStream->readByte();
+ rec.spriteSlot.frameNumber = animStream->readUint16LE();
+ rec.spriteSlot.xp = animStream->readSint16LE();
+ rec.spriteSlot.yp = animStream->readSint16LE();
+ rec.spriteSlot.depth = animStream->readSByte();
+ rec.spriteSlot.scale = (int8)animStream->readByte();
+
+ _frameEntries.push_back(rec);
+ }
+
+ delete animStream;
+ }
+
+ if (miscEntriesCount > 0) {
+ // Chunk 4: Misc Data
+ animStream = anim.getItemStream(streamIndex);
+
+ for (int i = 0; i < miscEntriesCount; ++i) {
+ AnimMiscEntry rec;
+ rec.soundNum = animStream->readByte();
+ rec.msgIndex = animStream->readSByte();
+ rec.numTicks = animStream->readUint16LE();
+ rec.posAdjust.x = animStream->readUint16LE();
+ rec.posAdjust.y = animStream->readUint16LE();
+ animStream->readUint16LE();
+
+ _miscEntries.push_back(rec);
+ }
+
+ delete animStream;
+ }
+
+ // If the animation specifies a font, then load it for access
+ if (_flags & ANIM_CUSTOM_FONT) {
+ Common::String fontName;
+ if (madsRes)
+ fontName += "*";
+ fontName += fontResource;
+
+ if (fontName != "")
+ _font = _vm->_font->getFont(fontName.c_str());
+ else
+ warning("Attempted to set a font with an empty name");
+ }
+
+ // If a speech file is specified, then load it
+ if (!_dsrName.empty())
+ _vm->_sound->loadDSRFile(_dsrName.c_str());
+
+ // Load all the sprite sets for the animation
+ for (int i = 0; i < spriteListCount; ++i) {
+ if (_field12 && (i == _spriteListIndex))
+ // Skip over field, since it's manually loaded
+ continue;
+
+ _spriteListIndexes[i] = _view->_spriteSlots.addSprites(_spriteSetNames[i].c_str());
+ }
+
+
+ if (_field12) {
+ Common::String resName;
+ if (madsRes)
+ resName += "*";
+ resName += _spriteSetNames[_spriteListIndex];
+
+ _spriteListIndexes[_spriteListIndex] = _view->_spriteSlots.addSprites(resName.c_str());
+ }
+
+ // TODO: Unknown section about handling sprite set list combined with messages size
+
+ // TODO: The original has two separate loops for the loop below based on _animMode == 4. Is it
+ // perhaps that in that mode the sprite frames has a different format..?
+
+ // Remap the sprite list index fields from the initial value to the indexes of the loaded
+ // sprite sets for the animation
+ for (uint i = 0; i < _frameEntries.size(); ++i) {
+ int idx = _frameEntries[i].spriteSlot.spriteListIndex;
+ _frameEntries[i].spriteSlot.spriteListIndex = _spriteListIndexes[idx];
+ }
+
+ if (hasScroll())
+ _nextScrollTimer = _madsVm->_currentTimer + _scrollTicks;
}
-void Animation::start() {
- _curFrame = 0;
- _curFrameEntry = 0;
- //for (int i = 0; i < _seriesCount; i++) {
- //_spriteSeries[i] = new SpriteSeries((char*)_spriteSeriesNames[i].c_str());
- //}
- _playing = true;
- updateAnim();
+/**
+ * Loads an animation file for display
+ */
+void MadsAnimation::load(const Common::String &filename, int abortTimers) {
+ initialise(filename, 0, NULL, NULL);
+ _messageCtr = 0;
+ _skipLoad = true;
+
+/* TODO: figure out extra stuff in this routine
+ if (_field12) {
+ _unkIndex = -1;
+ int listIndex = _spriteListIndexes[_spriteListIndex];
+ SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(listIndex);
+ ..?..
+ }
+*/
+
+ // Initialise miscellaneous fields
+ _currentFrame = 0;
+ _oldFrameEntry = 0;
+ _nextFrameTimer = _madsVm->_currentTimer;
+ _abortTimers = abortTimers;
+ _abortMode = _madsVm->scene()->_abortTimersMode2;
+
+ if (_madsVm->_scene)
+ _actionNouns = _madsVm->scene()->_action._action;
+
+ // Initialise kernel message list
+ for (uint i = 0; i < _messages.size(); ++i)
+ _messages[i].kernelMsgIndex = -1;
}
-bool Animation::updateAnim() {
- if (!_playing)
- return true;
+void MadsAnimation::update() {
+ if (_field12) {
+ int spriteListIndex = _spriteListIndexes[_spriteListIndex];
+ int newIndex = -1;
+
+ for (uint idx = _oldFrameEntry; idx < _frameEntries.size(); ++idx) {
+ if (_frameEntries[idx].frameNumber > _currentFrame)
+ break;
+ if (_frameEntries[idx].spriteSlot.spriteListIndex == spriteListIndex)
+ newIndex = _frameEntries[idx].spriteSlot.frameNumber;
+ }
+
+ if (newIndex >= 0)
+ load1(newIndex);
+ }
+
+ // Check for scroll change
+ bool screenChanged = false;
+
+ // Handle any scrolling of the screen surface
+ if (hasScroll() && (_madsVm->_currentTimer >= _nextScrollTimer)) {
+ _view->_bgSurface->scrollX(_scrollX);
+ _view->_bgSurface->scrollY(_scrollY);
+
+ _nextScrollTimer = _madsVm->_currentTimer + _scrollTicks;
+ screenChanged = true;
+ }
+
+ // If it's not time for the next frame, then exit
+ if (_madsVm->_currentTimer < _nextFrameTimer) {
+ if (screenChanged)
+ _view->_spriteSlots.fullRefresh();
+ return;
+ }
+
+ // Loop checks for any prior animation sprite slots to be expired
+ for (int slotIndex = 0; slotIndex < _view->_spriteSlots.startIndex; ++slotIndex) {
+ if (_view->_spriteSlots[slotIndex].seqIndex >= 0x80) {
+ // Flag the frame as animation sprite slot
+ _view->_spriteSlots[slotIndex].spriteType = EXPIRED_SPRITE;
+ }
+ }
+
+ // Validate the current frame
+ if (_currentFrame >= (int)_miscEntries.size()) {
+ // Is the animation allowed to be repeated?
+ if (_resetFlag) {
+ _currentFrame = 0;
+ _oldFrameEntry = 0;
+ } else {
+ _freeFlag = true;
+ return;
+ }
+ }
- // Get the scene background surface
- M4Surface *bg = _vm->_scene->getBackgroundSurface();
+ // Handle starting any sound for this frame
+ AnimMiscEntry &misc = _miscEntries[_currentFrame];
+ if (misc.soundNum)
+ _vm->_sound->playSound(misc.soundNum);
- while (_frameEntries[_curFrameEntry].animFrameIndex == _curFrame) {
- AnimationFrame *frame = &_frameEntries[_curFrameEntry];
- int seriesFrameIndex = (frame->seriesFrameIndex & 0x7FFF) - 1;
+ // Handle any offset adjustment for sprites as of this frame
+ if (_view->_posAdjust.x != misc.posAdjust.x) {
+ _view->_posAdjust.x = misc.posAdjust.x;
+ screenChanged = true;
+ }
+ if (_view->_posAdjust.y != misc.posAdjust.y) {
+ _view->_posAdjust.y = misc.posAdjust.y;
+ screenChanged = true;
+ }
- // Write the sprite onto the screen
- M4Sprite *spr = _spriteSeries->getFrame(seriesFrameIndex);
- // FIXME: correct x, y
- spr->copyTo(bg, frame->x, frame->y, (int)spr->getTransparentColor());
+ if (screenChanged) {
+ // Signal the entire screen needs refreshing
+ _view->_spriteSlots.fullRefresh();
+ }
- // HACK: wait a bit
- g_system->delayMillis(100);
+ int spriteSlotsMax = _view->_spriteSlots.startIndex;
+
+ // Main frame animation loop - frames get animated by being placed, as necessary, into the
+ // main sprite slot array
+ while ((uint)_oldFrameEntry < _frameEntries.size()) {
+ if (_frameEntries[_oldFrameEntry].frameNumber > _currentFrame)
+ break;
+ else if (_frameEntries[_oldFrameEntry].frameNumber == _currentFrame) {
+ // Found the correct frame
+ int spriteSlotIndex = 0;
+ int index = 0;
+
+ for (;;) {
+ if ((spriteSlotIndex == 0) && (index < spriteSlotsMax)) {
+ int seqIndex = _frameEntries[_oldFrameEntry].seqIndex - _view->_spriteSlots[index].seqIndex;
+ if (seqIndex == 0x80) {
+ if (_view->_spriteSlots[index] == _frameEntries[_oldFrameEntry].spriteSlot) {
+ _view->_spriteSlots[index].spriteType = SPRITE_ZERO;
+ spriteSlotIndex = -1;
+ }
+ }
+ ++index;
+ continue;
+ }
+
+ if (spriteSlotIndex == 0) {
+ int slotIndex = _view->_spriteSlots.getIndex();
+ MadsSpriteSlot &slot = _view->_spriteSlots[slotIndex];
+ slot.copy(_frameEntries[_oldFrameEntry].spriteSlot);
+ slot.seqIndex = _frameEntries[_oldFrameEntry].seqIndex + 0x80;
+
+ SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(
+ _view->_spriteSlots[slotIndex].spriteListIndex);
+ slot.spriteType = spriteSet.isBackground() ? BACKGROUND_SPRITE : FOREGROUND_SPRITE;
+ }
+ break;
+ }
+ }
+
+ ++_oldFrameEntry;
+ }
- //printf("_curFrameEntry = %d\n", _curFrameEntry);
- _curFrameEntry++;
+ // Handle the display of any messages
+ for (uint idx = 0; idx < _messages.size(); ++idx) {
+ if (_messages[idx].kernelMsgIndex >= 0) {
+ // Handle currently active message
+ if ((_currentFrame < _messages[idx].startFrame) || (_currentFrame > _messages[idx].endFrame)) {
+ _view->_kernelMessages.remove(_messages[idx].kernelMsgIndex);
+ _messages[idx].kernelMsgIndex = -1;
+ --_messageCtr;
+ }
+ } else if ((_currentFrame >= _messages[idx].startFrame) && (_currentFrame <= _messages[idx].endFrame)) {
+ // Start displaying the message
+ AnimMessage &me = _messages[idx];
+
+ // The colour index to use is dependant on how many messages are currently on-screen
+ uint8 colIndex;
+ switch (_messageCtr) {
+ case 1:
+ colIndex = 252;
+ break;
+ case 2:
+ colIndex = 16;
+ break;
+ default:
+ colIndex = 250;
+ break;
+ }
+
+ _vm->_palette->setEntry(colIndex, me.rgb1.r, me.rgb1.g, me.rgb1.b);
+ _vm->_palette->setEntry(colIndex + 1, me.rgb2.r, me.rgb2.g, me.rgb2.b);
+
+ // Add a kernel message to display the given text
+ me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 0x101 + 0x100, 0, 0, INDEFINITE_TIMEOUT, me.msg);
+ assert(me.kernelMsgIndex >= 0);
+
+ // Play the associated sound, if it exists
+ if (me.soundId > 0)
+ _vm->_sound->playDSRSound(me.soundId - 1, 255, false);
+ ++_messageCtr;
+ }
}
- //printf("_curFrame = %d\n", _curFrame);
+ // Move to the next frame
+ _currentFrame++;
+ if (_currentFrame >= (int)_miscEntries.size()) {
+ // Animation is complete
+ if (_abortTimers != 0) {
+ _view->_abortTimers = _abortTimers;
+ _view->_abortTimersMode = _abortMode;
+
+ if (_abortMode != ABORTMODE_1) {
+ // Copy the noun list
+ if (_madsVm->_scene)
+ _madsVm->scene()->_action._action = _actionNouns;
+ }
+ }
+ }
- _curFrame++;
- if (_curFrame >= _frameCount) // anim done
- stop();
+ int frameNum = MIN(_currentFrame, (int)_miscEntries.size() - 1);
+ _nextFrameTimer = _madsVm->_currentTimer + _miscEntries[frameNum].numTicks;
+}
+
+void MadsAnimation::setCurrentFrame(int frameNumber) {
+ _currentFrame = frameNumber;
+ _oldFrameEntry = 0;
+ _freeFlag = false;
- return _curFrame >= _frameCount;
+ _nextScrollTimer = _nextFrameTimer = _madsVm->_currentTimer;
}
-void Animation::stop() {
- _playing = false;
+int MadsAnimation::getCurrentFrame() {
+ return _currentFrame;
+}
+
+void MadsAnimation::load1(int frameNumber) {
+ if (_skipLoad)
+ return;
+
+ Common::Point pt;
+ int listIndex = _spriteListIndexes[_spriteListIndex];
+ SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(listIndex);
+
+ if (_unkIndex < 0) {
+ M4Surface *frame = spriteSet.getFrame(0);
+ pt.x = frame->bounds().left;
+ pt.y = frame->bounds().top;
+ } else {
+ pt.x = _unkList[_unkIndex].x;
+ pt.y = _unkList[_unkIndex].y;
+ _unkIndex = 1 - _unkIndex;
+ }
+
+ if (proc1(spriteSet, pt, frameNumber))
+ error("proc1 failure");
+}
+
+bool MadsAnimation::proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber) {
+ return 0;
+}
- for (int i = 0; i < _seriesCount; i++) {
- // TODO: cleanup
- //delete _spriteSeries[i];
- //_spriteSeries[i] = NULL;
+void MadsAnimation::loadInterface(M4Surface *&interfaceSurface, M4Surface *&depthSurface) {
+ if (_animMode <= 2) {
+ MadsSceneResources sceneResources;
+ sceneResources.load(_roomNumber, _interfaceFile.c_str(), 0, depthSurface, interfaceSurface);
+
+ } else if (_animMode == 4) {
+ // Load a scene interface
+ interfaceSurface->madsLoadInterface(_interfaceFile);
+ } else {
+ // This mode allocates two large surfaces for the animation
+ // TODO: Are these ever properly freed?
+error("Anim mode %d - need to check free logic", _animMode);
+ assert(!interfaceSurface);
+ assert(!depthSurface);
+ depthSurface = new M4Surface(MADS_SURFACE_WIDTH, MADS_SCREEN_HEIGHT);
+ interfaceSurface = new M4Surface(MADS_SURFACE_WIDTH, MADS_SCREEN_HEIGHT);
+ depthSurface->clear();
+ interfaceSurface->clear();
}
}
diff --git a/engines/m4/animation.h b/engines/m4/animation.h
index 2dfe0d887e..a7a6b57c32 100644
--- a/engines/m4/animation.h
+++ b/engines/m4/animation.h
@@ -29,41 +29,100 @@
#include "m4/m4.h"
#include "m4/graphics.h"
#include "m4/assets.h"
+#include "m4/mads_views.h"
+#include "common/array.h"
namespace M4 {
-struct AnimationFrame {
- uint16 animFrameIndex;
- byte u;
- byte seriesIndex;
- uint16 seriesFrameIndex;
- uint16 x, y;
- byte v, w;
+class MadsView;
+class SpriteSlotSubset;
+
+class AnimMessage {
+public:
+ int16 soundId;
+ char msg[64];
+ Common::Point pos;
+ RGB8 rgb1, rgb2;
+ uint16 flags;
+ int startFrame, endFrame;
+ int kernelMsgIndex;
+};
+
+class AnimFrameEntry {
+public:
+ int frameNumber;
+ int seqIndex;
+ SpriteSlotSubset spriteSlot;
};
-class Animation {
- public:
- Animation(MadsM4Engine *vm);
- ~Animation();
-
- void load(const char *filename);
- void loadFullScreen(const char *filename);
- void start();
- bool updateAnim();
- void stop();
-
- private:
- bool _playing;
- MadsM4Engine *_vm;
- int _seriesCount;
- int _frameCount;
- int _frameEntryCount;
- AnimationFrame *_frameEntries;
- Common::String *_spriteSeriesNames;
- SpriteAsset *_spriteSeries;
- int _curFrame, _curFrameEntry;
+class AnimMiscEntry {
+public:
+ int soundNum;
+ int msgIndex;
+ int numTicks;
+ Common::Point posAdjust;
+};
+
+#define ANIM_SPRITE_SET_SIZE 50
+
+enum MadsAnimationFlags {ANIM_CUSTOM_FONT = 0x20, ANIM_HAS_SOUND = 0x8000};
+
+class MadsAnimation: public Animation {
+private:
+ MadsView *_view;
+
+ int _spriteListCount;
+ Common::Array<AnimMessage> _messages;
+ Common::Array<AnimFrameEntry> _frameEntries;
+ Common::Array<AnimMiscEntry> _miscEntries;
+ Font *_font;
+
+ uint8 _flags;
+ int _animMode;
+ int _roomNumber;
+ bool _field12;
+ int _spriteListIndex;
+ int _scrollX;
+ int _scrollY;
+ int _scrollTicks;
+ Common::String _interfaceFile;
+ Common::String _spriteSetNames[10];
+ Common::String _lbmFilename;
+ Common::String _spritesFilename;
+ Common::String _soundName;
+ Common::String _dsrName;
+ Common::Array<int> _spriteListIndexes;
+
+ int _currentFrame, _oldFrameEntry;
+ bool _resetFlag;
+ bool _freeFlag;
+ bool _skipLoad;
+ int _unkIndex;
+ Common::Point _unkList[2];
+ uint32 _nextFrameTimer;
+ uint32 _nextScrollTimer;
+ int _messageCtr;
+ int _abortTimers;
+ AbortTimerMode _abortMode;
+ ActionDetails _actionNouns;
+
+ void load1(int frameNumber);
+ bool proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber);
+ void loadInterface(M4Surface *&interfaceSurface, M4Surface *&depthSurface);
+ bool hasScroll() const { return (_scrollX != 0) || (_scrollY != 0); }
+public:
+ MadsAnimation(MadsM4Engine *vm, MadsView *view);
+ virtual ~MadsAnimation();
+
+ virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface);
+ virtual void load(const Common::String &filename, int abortTimers);
+ virtual void update();
+ virtual void setCurrentFrame(int frameNumber);
+ virtual int getCurrentFrame();
bool freeFlag() const { return _freeFlag; }
+ bool getAnimMode() const { return _animMode; }
+ int roomNumber() const { return _roomNumber; }
};
} // End of namespace M4
diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp
index e604019901..23122eb960 100644
--- a/engines/m4/assets.cpp
+++ b/engines/m4/assets.cpp
@@ -30,13 +30,13 @@
namespace M4 {
-BaseAsset::BaseAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : _vm(vm) {
+BaseAsset::BaseAsset(MadsM4Engine *vm) : _vm(vm) {
}
BaseAsset::~BaseAsset() {
}
-MachineAsset::MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
+MachineAsset::MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
uint32 stateCount = stream->readUint32LE();
for (uint32 curState = 0; curState < stateCount; curState++) {
uint32 stateOffset = stream->readUint32LE();
@@ -61,7 +61,7 @@ uint32 MachineAsset::getStateOffset(uint32 state) {
return _stateTable[state];
}
-SequenceAsset::SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
+SequenceAsset::SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
_localVarCount = stream->readUint32LE();
_codeSize = size - 4;
_code = new byte[_codeSize];
@@ -78,7 +78,7 @@ void SequenceAsset::getCode(byte *&code, uint32 &codeSize) {
}
-DataAsset::DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
+DataAsset::DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
_recCount = stream->readUint32LE();
_recSize = stream->readUint32LE();
@@ -98,7 +98,9 @@ long *DataAsset::getRow(int index) {
return &_data[_recSize * index];
}
-SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) : BaseAsset(vm, stream, size, name) {
+SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name,
+ bool asStream, int flags) :
+ BaseAsset(vm) {
_stream = stream;
_palInterface = NULL;
_paletteData = NULL;
@@ -106,10 +108,24 @@ SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, i
if (_vm->isM4()) {
loadM4SpriteAsset(vm, stream, asStream);
} else {
- loadMadsSpriteAsset(vm, stream);
+ loadMadsSpriteAsset(vm, stream, flags);
}
}
+SpriteAsset::SpriteAsset(MadsM4Engine *vm, const char *name): BaseAsset(vm) {
+ _stream = vm->res()->get(name);
+ _palInterface = NULL;
+ _paletteData = NULL;
+
+ if (_vm->isM4()) {
+ loadM4SpriteAsset(vm, _stream, true);
+ } else {
+ loadMadsSpriteAsset(vm, _stream, 0);
+ }
+
+ vm->res()->toss(name);
+}
+
SpriteAsset::~SpriteAsset() {
if (_palInterface) {
// Internally stored palette translation data, so release it
@@ -121,6 +137,8 @@ SpriteAsset::~SpriteAsset() {
for (Common::Array<SpriteAssetFrame>::iterator it = _frames.begin(); it != _frames.end(); ++it) {
delete (*it).frame;
}
+
+ delete _charInfo;
}
void SpriteAsset::loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream) {
@@ -185,7 +203,7 @@ void SpriteAsset::loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream
}
-void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream) {
+void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int flags) {
int curFrame = 0;
uint32 frameOffset = 0;
MadsPack sprite(stream);
@@ -195,11 +213,19 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre
_maxHeight = 0;
Common::SeekableReadStream *spriteStream = sprite.getItemStream(0);
- for (int i = 0; i < 19; i++) {
- spriteStream->readUint16LE();
- }
+ _mode = spriteStream->readByte();
+ spriteStream->skip(1);
+ int type1 = spriteStream->readUint16LE();
+ int type2 = spriteStream->readUint16LE();
+ _isBackground = (type1 != 0) && (type2 < 4);
+ spriteStream->skip(32);
_frameCount = spriteStream->readUint16LE();
- // we skip the rest of the data
+
+ if (_vm->isM4() || ((flags & SPRITE_SET_CHAR_INFO) == 0))
+ _charInfo = NULL;
+ else
+ _charInfo = new MadsSpriteSetCharInfo(spriteStream);
+
delete spriteStream;
// Get the palette data
@@ -216,12 +242,15 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre
spriteStream = sprite.getItemStream(1);
Common::SeekableReadStream *spriteDataStream = sprite.getItemStream(3);
SpriteAssetFrame frame;
+ Common::Array<int> frameSizes;
for (curFrame = 0; curFrame < _frameCount; curFrame++) {
frame.stream = 0;
frame.comp = 0;
frameOffset = spriteStream->readUint32LE();
_frameOffsets.push_back(frameOffset);
- spriteStream->readUint32LE(); // frame size
+ uint32 frameSize = spriteStream->readUint32LE();
+ frameSizes.push_back(frameSize);
+
frame.x = spriteStream->readUint16LE();
frame.y = spriteStream->readUint16LE();
frame.w = spriteStream->readUint16LE();
@@ -229,9 +258,44 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre
if (curFrame == 0)
debugC(1, kDebugGraphics, "%i frames, x = %i, y = %i, w = %i, h = %i\n", _frameCount, frame.x, frame.y, frame.w, frame.h);
- frame.frame = new M4Sprite(spriteDataStream, frame.x, frame.y, frame.w, frame.h, false);
+ if (_mode == 0) {
+ // Create a frame and decompress the raw pixel data
+ uint32 currPos = (uint32)spriteDataStream->pos();
+ frame.frame = new M4Sprite(spriteDataStream, frame.x, frame.y, frame.w, frame.h, false);
+ assert((uint32)spriteDataStream->pos() == (currPos + frameSize));
+ }
+
_frames.push_back(frame);
}
+
+ if (_mode != 0) {
+ // Handle decompressing Fab encoded data
+ for (curFrame = 0; curFrame < _frameCount; curFrame++) {
+ FabDecompressor fab;
+
+ int srcSize = (curFrame == (_frameCount - 1)) ? spriteDataStream->size() - _frameOffsets[curFrame] :
+ _frameOffsets[curFrame + 1] - _frameOffsets[curFrame];
+ byte *srcData = (byte *)malloc(srcSize);
+ assert(srcData);
+ spriteDataStream->read(srcData, srcSize);
+
+ byte *destData = (byte *)malloc(frameSizes[curFrame]);
+ assert(destData);
+
+ fab.decompress(srcData, srcSize, destData, frameSizes[curFrame]);
+
+ // Load the frame
+ Common::MemoryReadStream *rs = new Common::MemoryReadStream(destData, frameSizes[curFrame]);
+ _frames[curFrame].frame = new M4Sprite(rs, _frames[curFrame].x, _frames[curFrame].y,
+ _frames[curFrame].w, _frames[curFrame].h, false);
+ delete rs;
+
+ free(srcData);
+ free(destData);
+ }
+ }
+
+
delete spriteStream;
delete spriteDataStream;
}
@@ -302,7 +366,12 @@ void SpriteAsset::loadFrameHeader(SpriteAssetFrame &frameHeader, bool isBigEndia
}
M4Sprite *SpriteAsset::getFrame(int frameIndex) {
- return _frames[frameIndex].frame;
+ if ((uint)frameIndex < _frames.size()) {
+ return _frames[frameIndex].frame;
+ } else {
+ warning("SpriteAsset::getFrame: Invalid frame %d, out of %d", frameIndex, _frames.size());
+ return _frames[_frames.size() - 1].frame;
+ }
}
void SpriteAsset::loadStreamingFrame(M4Sprite *frame, int frameIndex, int destX, int destY) {
@@ -560,4 +629,23 @@ int32 AssetManager::getSpriteFrameCount(int32 hash) {
return _CELS[hash]->getCount();
}
+//--------------------------------------------------------------------------
+
+MadsSpriteSetCharInfo::MadsSpriteSetCharInfo(Common::SeekableReadStream *s) {
+ _totalFrames = s->readByte();
+ s->skip(1);
+ _numEntries = s->readUint16LE();
+
+ for (int i = 0; i < 16; ++i)
+ _frameList[i] = s->readUint16LE();
+ for (int i = 0; i < 16; ++i)
+ _frameList2[i] = s->readUint16LE();
+ for (int i = 0; i < 16; ++i)
+ _ticksList[i] = s->readUint16LE();
+
+ _unk1 = s->readUint16LE();
+ _ticksAmount = s->readByte();
+ _yScale = s->readByte();
+}
+
} // End of namespace M4
diff --git a/engines/m4/assets.h b/engines/m4/assets.h
index 7b0ce24dc4..3ae7fb2e22 100644
--- a/engines/m4/assets.h
+++ b/engines/m4/assets.h
@@ -44,12 +44,14 @@ namespace M4 {
#define CELS__PAL MKID_BE(' PAL') //' PAL'
#define CELS___SS MKID_BE(' SS') //' SS'
+#define SPRITE_SET_CHAR_INFO 4
+
class MadsM4Engine;
class Palette;
class BaseAsset {
public:
- BaseAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name);
+ BaseAsset(MadsM4Engine *vm);
~BaseAsset();
const Common::String getName() const { return _name; }
protected:
@@ -100,12 +102,28 @@ struct SpriteAssetFrame {
M4Sprite *frame;
};
+class MadsSpriteSetCharInfo {
+public:
+ MadsSpriteSetCharInfo(Common::SeekableReadStream *s);
+
+ int _totalFrames;
+ int _numEntries;
+ int _frameList2[16];
+ int _frameList[16];
+ int _ticksList[16];
+ int _unk1;
+ int _ticksAmount;
+ int _yScale;
+};
+
class SpriteAsset : public BaseAsset {
public:
- SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream = false);
+ SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name,
+ bool asStream = false, int flags = 0);
+ SpriteAsset(MadsM4Engine *vm, const char *name);
~SpriteAsset();
void loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream);
- void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream);
+ void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int flags);
int32 getCount() { return _frameCount; }
int32 getFrameRate() const { return _frameRate; }
int32 getPixelSpeed() const { return _pixelSpeed; }
@@ -113,6 +131,7 @@ public:
int32 getFrameHeight(int index);
int32 getMaxFrameWidth() const { return _maxWidth; }
int32 getMaxFrameHeight() const { return _maxHeight; }
+ bool isBackground() const { return _isBackground; }
M4Sprite *getFrame(int frameIndex);
void loadStreamingFrame(M4Sprite *frame, int frameIndex, int destX, int destY);
RGB8* getPalette() { return _palette; }
@@ -122,7 +141,10 @@ public:
void translate(Palette *palette);
int32 getFrameSize(int index);
M4Sprite *operator[](int index) { return getFrame(index); }
+public:
+ MadsSpriteSetCharInfo *_charInfo;
protected:
+ Common::SeekableReadStream *_stream;
RGB8 _palette[256];
uint32 _colorCount;
uint32 _srcSize;
@@ -132,7 +154,11 @@ protected:
Common::Array<uint32> _frameOffsets;
Common::Array<SpriteAssetFrame> _frames;
uint32 _frameStartOffset;
- Common::SeekableReadStream *_stream;
+
+ // MADS sprite set fields
+ uint8 _mode;
+ bool _isBackground;
+
int32 parseSprite(bool isBigEndian = false);
void loadFrameHeader(SpriteAssetFrame &frameHeader, bool isBigEndian = false);
private:
diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp
index 0c2e80df0e..9a92cb04d1 100644
--- a/engines/m4/console.cpp
+++ b/engines/m4/console.cpp
@@ -104,8 +104,8 @@ bool Console::cmdListHotSpots(int argc, const char **argv) {
if (_vm->isM4()) {
DebugPrintf("Scene parallax\n");
_m4Vm->scene()->getSceneResources().parallax->dump();
- DebugPrintf("Scene props\n");
- _vm->_scene->getSceneResources().props->dump();
+ DebugPrintf("Scene dynamic hotspots\n");
+ _vm->_scene->getSceneResources().dynamicHotspots->dump();
}
return true;
}
@@ -197,7 +197,7 @@ bool Console::cmdShowSprite(int argc, const char **argv) {
if (y >= bg->height())
break;
- spr->copyTo(bg, x, y, (int)spr->getTransparentColor());
+ spr->copyTo(bg, x, y, (int)spr->getTransparencyIndex());
x += spr->width();
yMax = MAX(yMax, spr->height());
@@ -400,9 +400,9 @@ bool M4Console::cmdSceneInfo(int argc, const char **argv) {
DebugPrintf("Scene resources:\n");
DebugPrintf("artBase: %s\n", _m4Vm->scene()->getSceneResources().artBase);
DebugPrintf("pictureBase: %s\n", _m4Vm->scene()->getSceneResources().pictureBase);
- DebugPrintf("hotspotCount: %i\n", _m4Vm->scene()->getSceneResources().hotspotCount);
+ DebugPrintf("hotspotCount: %i\n", _m4Vm->scene()->getSceneResources().hotspots->size());
DebugPrintf("parallaxCount: %i\n", _m4Vm->scene()->getSceneResources().parallaxCount);
- DebugPrintf("propsCount: %i\n", _m4Vm->scene()->getSceneResources().propsCount);
+ DebugPrintf("dynHotspotCount: %i\n", _m4Vm->scene()->getSceneResources().dynamicHotspots->size());
DebugPrintf("frontY: %i\n", _m4Vm->scene()->getSceneResources().frontY);
DebugPrintf("backY: %i\n", _m4Vm->scene()->getSceneResources().backY);
DebugPrintf("frontScale: %i\n", _m4Vm->scene()->getSceneResources().frontScale);
diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp
index 746ced5d11..aab2fc95ce 100644
--- a/engines/m4/converse.cpp
+++ b/engines/m4/converse.cpp
@@ -858,8 +858,8 @@ void Converse::loadConversationMads(const char *convName) {
if (buffer[curPos - 1] == '\0') {
// end of string
//printf("%s\n", buffer);
- buf = new char[strlen(buffer)];
- sprintf(buf, "%s", buffer);
+ buf = new char[strlen(buffer) + 1];
+ strcpy(buf, buffer);
_convStrings.push_back(buf);
curPos = 0;
*buffer = 0;
diff --git a/engines/m4/detection.cpp b/engines/m4/detection.cpp
index 9493226c1a..4b204996f3 100644
--- a/engines/m4/detection.cpp
+++ b/engines/m4/detection.cpp
@@ -400,7 +400,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NOMIDI
+ Common::GUIO_NOMIDI,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class M4MetaEngine : public AdvancedMetaEngine {
diff --git a/engines/m4/events.cpp b/engines/m4/events.cpp
index c0ca412f11..c66609844a 100644
--- a/engines/m4/events.cpp
+++ b/engines/m4/events.cpp
@@ -57,6 +57,10 @@ Events::Events(MadsM4Engine *vm) : _vm(vm) {
_console = new MadsConsole(_madsVm);
}
+Events::~Events() {
+ delete _console;
+}
+
M4EventType Events::handleEvents() {
static int oldX = -1, oldY = -1;
static uint32 dclickTime = 0;
@@ -252,7 +256,8 @@ bool Mouse::setCursorNum(int cursorIndex) {
_cursor = _cursorSprites->getFrame(cursorIndex);
// Set the cursor to the sprite
- CursorMan.replaceCursor((const byte *)_cursor->getBasePtr(), _cursor->width(), _cursor->height(), _cursor->xOffset, _cursor->yOffset, 0);
+ CursorMan.replaceCursor((const byte *)_cursor->getBasePtr(), _cursor->width(), _cursor->height(),
+ _cursor->xOffset, _cursor->yOffset, TRANSPARENT_COLOUR_INDEX);
return true;
}
diff --git a/engines/m4/events.h b/engines/m4/events.h
index 43b61c8f0d..1c1418d5f8 100644
--- a/engines/m4/events.h
+++ b/engines/m4/events.h
@@ -78,6 +78,7 @@ private:
public:
bool quitFlag;
Events(MadsM4Engine *vm);
+ virtual ~Events();
Common::Event &event() { return _event; }
Common::EventType type() { return _event.type; }
diff --git a/engines/m4/font.cpp b/engines/m4/font.cpp
index f8dec65412..b5965732e5 100644
--- a/engines/m4/font.cpp
+++ b/engines/m4/font.cpp
@@ -29,23 +29,48 @@
namespace M4 {
-Font::Font(MadsM4Engine *vm) : _vm(vm) {
+FontManager::~FontManager() {
+ for (uint i = 0; i < _entries.size(); ++i)
+ delete _entries[i];
+ _entries.clear();
+}
+
+Font *FontManager::getFont(const char *filename) {
+ // Append an extension if the filename doesn't already have one
+ char buffer[20];
+ strncpy(buffer, filename, 19);
+ if (!strchr(buffer, '.'))
+ strcat(buffer, ".ff");
+
+ // Check if the font is already loaded
+ for (uint i = 0; i < _entries.size(); ++i) {
+ if (!strcmp(_entries[i]->_filename, buffer))
+ return _entries[i];
+ }
+
+ Font *f = new Font(_vm, buffer);
+ _entries.push_back(f);
+ return f;
+}
+
+void FontManager::setFont(const char *filename) {
+ _currentFont = getFont(filename);
+}
+
+//--------------------------------------------------------------------------
+
+Font::Font(MadsM4Engine *vm, const char *filename) : _vm(vm) {
_sysFont = true;
- _filename = NULL;
+ strncpy(_filename, filename, 19);
+ _filename[19] = '\0';
+
//TODO: System font
_fontColors[0] = _vm->_palette->BLACK;
_fontColors[1] = _vm->_palette->WHITE;
_fontColors[2] = _vm->_palette->BLACK;
_fontColors[3] = _vm->_palette->DARK_GRAY;
-}
-
-void Font::setFont(const char *filename) {
- if ((_filename != NULL) && (strcmp(filename, _filename) == 0))
- // Already using specified font, so don't bother reloading
- return;
_sysFont = false;
- _filename = filename;
if (_vm->isM4())
setFontM4(filename);
@@ -134,20 +159,21 @@ Font::~Font() {
}
}
-void Font::setColor(uint8 color) {
+void Font::setColour(uint8 colour) {
if (_sysFont)
- _fontColors[1] = color;
+ _fontColors[1] = colour;
else
- _fontColors[3] = color;
+ _fontColors[3] = colour;
}
-void Font::setColors(uint8 alt1, uint8 alt2, uint8 foreground) {
+void Font::setColours(uint8 col1, uint8 col2, uint8 col3) {
if (_sysFont)
- _fontColors[1] = foreground;
+ _fontColors[1] = col3;
else {
- _fontColors[1] = alt1;
- _fontColors[2] = alt2;
- _fontColors[3] = foreground;
+ _fontColors[0] = 0xFF;
+ _fontColors[1] = col1;
+ _fontColors[2] = col2;
+ _fontColors[3] = col3;
}
}
diff --git a/engines/m4/font.h b/engines/m4/font.h
index e64f80b70d..19d15faa1e 100644
--- a/engines/m4/font.h
+++ b/engines/m4/font.h
@@ -59,19 +59,11 @@ namespace M4 {
class Font {
public:
- Font(MadsM4Engine *vm);
+ Font(MadsM4Engine *vm, const char *filename);
~Font();
- Font *getFont(const char *filename) {
- // TODO: Proper separation of font instances
- setFont(filename);
- return this;
- }
- void setFont(const char *filename);
- void setColor(uint8 color);
- void setColors(uint8 alt1, uint8 alt2, uint8 foreground);
- void setColour(uint8 colour) { setColor(colour); }
- void setColours(uint8 alt1, uint8 alt2, uint8 foreground) { setColors(alt1, alt2, foreground); }
+ void setColour(uint8 colour);
+ void setColours(uint8 col1, uint8 col2, uint8 col3);
int32 getWidth(const char *text, int spaceWidth = -1);
int32 getHeight() const { return _maxHeight; }
@@ -80,7 +72,8 @@ public:
int32 writeString(M4Surface *surface, const char *text, int x, int y, int width = 0, int spaceWidth = -1) {
return write(surface, text, x, y, width, spaceWidth, _fontColors);
}
-
+public:
+ char _filename[20];
private:
void setFontM4(const char *filename);
void setFontMads(const char *filename);
@@ -91,10 +84,39 @@ private:
uint16 *_charOffs;
uint8 *_charData;
bool _sysFont;
- const char *_filename;
uint8 _fontColors[4];
};
+class FontEntry {
+public:
+ Font *_font;
+
+ FontEntry() {
+ _font = NULL;
+ }
+ ~FontEntry() {
+ delete _font;
+ }
+};
+
+class FontManager {
+private:
+ MadsM4Engine *_vm;
+ Common::Array<Font *> _entries;
+ Font *_currentFont;
+public:
+ FontManager(MadsM4Engine *vm): _vm(vm) { _currentFont = NULL; }
+ ~FontManager();
+
+ Font *getFont(const char *filename);
+ void setFont(const char *filename);
+
+ Font *current() {
+ assert(_currentFont);
+ return _currentFont;
+ }
+};
+
} // End of namespace M4
#endif
diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp
index 1768c71787..a96229a0b3 100644
--- a/engines/m4/globals.cpp
+++ b/engines/m4/globals.cpp
@@ -282,6 +282,9 @@ MadsGlobals::MadsGlobals(MadsEngine *vm): Globals(vm) {
playerSpriteChanged = false;
dialogType = DIALOG_NONE;
sceneNumber = -1;
+ for (int i = 0; i < 3; ++i)
+ actionNouns[i] = 0;
+ _difficultyLevel = 0;
}
MadsGlobals::~MadsGlobals() {
@@ -351,16 +354,16 @@ void MadsGlobals::loadMadsMessagesInfo() {
//printf("%i messages\n", count);
for (int i = 0; i < count; i++) {
- MessageItem *curMessage = new MessageItem();
- curMessage->id = messageS->readUint32LE();
- curMessage->offset = messageS->readUint32LE();
- curMessage->uncompSize = messageS->readUint16LE();
+ MessageItem curMessage;
+ curMessage.id = messageS->readUint32LE();
+ curMessage.offset = messageS->readUint32LE();
+ curMessage.uncompSize = messageS->readUint16LE();
if (i > 0)
- _madsMessages[i - 1]->compSize = curMessage->offset - _madsMessages[i - 1]->offset;
+ _madsMessages[i - 1].compSize = curMessage.offset - _madsMessages[i - 1].offset;
if (i == count - 1)
- curMessage->compSize = messageS->size() - curMessage->offset;
+ curMessage.compSize = messageS->size() - curMessage.offset;
//printf("id: %i, offset: %i, uncomp size: %i\n", curMessage->id, curMessage->offset, curMessage->uncompSize);
_madsMessages.push_back(curMessage);
@@ -382,7 +385,7 @@ void MadsGlobals::loadMadsObjects() {
int MadsGlobals::messageIndexOf(uint32 messageId) {
for (uint i = 0; i < _madsMessages.size(); ++i)
{
- if (_madsMessages[i]->id == messageId)
+ if (_madsMessages[i].id == messageId)
return i;
}
return -1;
@@ -395,15 +398,15 @@ const char *MadsGlobals::loadMessage(uint index) {
}
FabDecompressor fab;
- byte *compData = new byte[_madsMessages[index]->compSize];
- byte *buffer = new byte[_madsMessages[index]->uncompSize];
+ byte *compData = new byte[_madsMessages[index].compSize];
+ byte *buffer = new byte[_madsMessages[index].uncompSize];
Common::SeekableReadStream *messageS = _vm->res()->get("messages.dat");
- messageS->seek(_madsMessages[index]->offset, SEEK_SET);
- messageS->read(compData, _madsMessages[index]->compSize);
- fab.decompress(compData, _madsMessages[index]->compSize, buffer, _madsMessages[index]->uncompSize);
+ messageS->seek(_madsMessages[index].offset, SEEK_SET);
+ messageS->read(compData, _madsMessages[index].compSize);
+ fab.decompress(compData, _madsMessages[index].compSize, buffer, _madsMessages[index].uncompSize);
- for (int i = 0; i < _madsMessages[index]->uncompSize - 1; i++)
+ for (int i = 0; i < _madsMessages[index].uncompSize - 1; i++)
if (buffer[i] == '\0') buffer[i] = '\n';
_vm->res()->toss("messages.dat");
@@ -526,7 +529,9 @@ void MadsObject::load(Common::SeekableReadStream *stream) {
roomNumber = READ_LE_UINT16(&obj[2]);
article = (MADSArticles)obj[4];
vocabCount = obj[5] & 0x7f;
- assert(vocabCount <= 3);
+ // Phantom / Dragon
+ if (vocabCount > 3)
+ warning("MadsObject::load(), vocab cound > 3 (it's %d)", vocabCount);
for (int i = 0; i < vocabCount; ++i) {
vocabList[i].flags1 = obj[6 + i * 4];
diff --git a/engines/m4/globals.h b/engines/m4/globals.h
index a052a4c868..2bfedf1449 100644
--- a/engines/m4/globals.h
+++ b/engines/m4/globals.h
@@ -28,6 +28,7 @@
#include "common/scummsys.h"
#include "common/array.h"
+#include "common/hashmap.h"
#include "common/rect.h"
#include "common/file.h"
#include "common/list.h"
@@ -149,7 +150,7 @@ public:
void pauseGame(bool value);
};
-#define TOTAL_NUM_VARIABLES 256
+#define TOTAL_NUM_VARIABLES 210
#define PLAYER_INVENTORY 2
@@ -223,6 +224,13 @@ struct MadsConfigData {
int screenFades;
};
+#define GET_GLOBAL(x) (_madsVm->globals()->_globals[x])
+#define GET_GLOBAL32(x) (((uint32)_madsVm->globals()->_globals[x + 1] << 16) | _madsVm->globals()->_globals[x])
+#define SET_GLOBAL(x,y) _madsVm->globals()->_globals[x] = y
+#define SET_GLOBAL32(x,y) { _madsVm->globals()->_globals[x] = (y) & 0xffff; _madsVm->globals()->_globals[(x) + 1] = (y) >> 16; }
+
+typedef Common::HashMap<uint16, uint16> IntStorage;
+
class MadsGlobals : public Globals {
private:
struct MessageItem {
@@ -235,7 +243,7 @@ private:
MadsEngine *_vm;
Common::Array<char* > _madsVocab;
Common::Array<char* > _madsQuotes;
- Common::Array<MessageItem* > _madsMessages;
+ Common::Array<MessageItem> _madsMessages;
MadsObjectArray _madsObjects;
Common::List<int> _visitedScenes;
public:
@@ -243,12 +251,16 @@ public:
~MadsGlobals();
// MADS variables
- int _globals[TOTAL_NUM_VARIABLES];
+ uint16 _globals[TOTAL_NUM_VARIABLES];
MadsConfigData _config;
bool playerSpriteChanged;
MadsDialogType dialogType;
int sceneNumber;
int previousScene;
+ int16 _nextSceneId;
+ uint16 actionNouns[3];
+ IntStorage _dataMap;
+ int _difficultyLevel;
void loadMadsVocab();
uint32 getVocabSize() { return _madsVocab.size(); }
diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp
index 893c415576..423dda5e7e 100644
--- a/engines/m4/graphics.cpp
+++ b/engines/m4/graphics.cpp
@@ -65,10 +65,28 @@ void RGBList::setRange(int start, int count, const RGB8 *src) {
Common::copy(&src[0], &src[count], &_data[start]);
}
+/**
+ * Creates a duplicate of the given rgb list
+ */
+RGBList *RGBList::clone() const {
+ RGBList *dest = new RGBList(_size, _data, false);
+ _madsVm->_palette->addRange(dest);
+ return dest;
+}
+
//--------------------------------------------------------------------------
#define VGA_COLOR_TRANS(x) (x == 0x3f ? 255 : x << 2)
+M4Surface::~M4Surface() {
+ if (_rgbList) {
+ _madsVm->_palette->deleteRange(_rgbList);
+ delete _rgbList;
+ }
+ if (_ownsData)
+ free();
+}
+
void M4Surface::loadCodesM4(Common::SeekableReadStream *source) {
if (!source) {
free();
@@ -324,6 +342,16 @@ void M4Surface::clear() {
Common::set_to((byte *)pixels, (byte *)pixels + w * h, _vm->_palette->BLACK);
}
+void M4Surface::reset() {
+ ::free(pixels);
+ pixels = NULL;
+ if (_rgbList) {
+ _vm->_palette->deleteRange(_rgbList);
+ delete _rgbList;
+ _rgbList = NULL;
+ }
+}
+
void M4Surface::frameRect(const Common::Rect &r, uint8 color) {
Graphics::Surface::frameRect(r, color);
}
@@ -333,7 +361,7 @@ void M4Surface::fillRect(const Common::Rect &r, uint8 color) {
}
void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY,
- int transparentColor) {
+ int transparentColour) {
// Validation of the rectangle and position
if ((destX >= w) || (destY >= h))
return;
@@ -362,13 +390,13 @@ void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int dest
byte *destPtr = (byte *)pixels + (destY * width()) + destX;
for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
- if (transparentColor == -1)
+ if (transparentColour == -1)
// No transparency, so copy line over
Common::copy(srcPtr, srcPtr + copyRect.width(), destPtr);
else {
// Copy each byte one at a time checking for the transparency color
for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr)
- if (srcPtr[xCtr] != transparentColor) destPtr[xCtr] = srcPtr[xCtr];
+ if (srcPtr[xCtr] != transparentColour) destPtr[xCtr] = srcPtr[xCtr];
}
srcPtr += src->width();
@@ -378,6 +406,174 @@ void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int dest
src->freeData();
}
+/**
+ * Copies a given image onto a destination surface with scaling, transferring only pixels that meet
+ * the specified depth requirement on a secondary surface contain depth information
+ */
+void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth,
+ M4Surface *depthsSurface, int scale, int transparentColour) {
+
+ if (scale == 100) {
+ // Copy the specified area
+ Common::Rect copyRect(0, 0, src->width(), src->height());
+
+ if (destX < 0) {
+ copyRect.left += -destX;
+ destX = 0;
+ } else if (destX + copyRect.width() > w) {
+ copyRect.right -= destX + copyRect.width() - w;
+ }
+ if (destY < 0) {
+ copyRect.top += -destY;
+ destY = 0;
+ } else if (destY + copyRect.height() > h) {
+ copyRect.bottom -= destY + copyRect.height() - h;
+ }
+
+ if (!copyRect.isValidRect())
+ return;
+
+ byte *data = src->getBasePtr();
+ byte *srcPtr = data + (src->width() * copyRect.top + copyRect.left);
+ byte *depthsData = depthsSurface->getBasePtr();
+ byte *depthsPtr = depthsData + (depthsSurface->pitch * destY) + destX;
+ byte *destPtr = (byte *)pixels + (destY * pitch) + destX;
+
+ // 100% scaling variation
+ for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
+ // Copy each byte one at a time checking against the depth
+ for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) {
+ if ((depth <= (depthsPtr[xCtr] & 0x7f)) && (srcPtr[xCtr] != transparentColour))
+ destPtr[xCtr] = srcPtr[xCtr];
+ }
+
+ srcPtr += src->width();
+ depthsPtr += depthsSurface->width();
+ destPtr += width();
+ }
+
+ src->freeData();
+ depthsSurface->freeData();
+ return;
+ }
+
+ // Start of draw logic for scaled sprites
+ const byte *srcPixelsP = src->getBasePtr();
+
+ int destRight = this->width() - 1;
+ int destBottom = this->height() - 1;
+ bool normalFrame = true; // TODO: false for negative frame numbers
+ int frameWidth = src->width();
+ int frameHeight = src->height();
+
+ int highestDim = MAX(frameWidth, frameHeight);
+ bool lineDist[MADS_SURFACE_WIDTH];
+ int distIndex = 0;
+ int distXCount = 0, distYCount = 0;
+
+ int distCtr = 0;
+ do {
+ distCtr += scale;
+ if (distCtr < 100) {
+ lineDist[distIndex] = false;
+ } else {
+ lineDist[distIndex] = true;
+ distCtr -= 100;
+
+ if (distIndex < frameWidth)
+ ++distXCount;
+
+ if (distIndex < frameHeight)
+ ++distYCount;
+ }
+ } while (++distIndex < highestDim);
+
+ destX -= distXCount / 2;
+ destY -= distYCount - 1;
+
+ // Check x bounding area
+ int spriteLeft = 0;
+ int spriteWidth = distXCount;
+ int widthAmount = destX + distXCount - 1;
+
+ if (destX < 0) {
+ spriteWidth += destX;
+ spriteLeft -= destX;
+ }
+ widthAmount -= destRight;
+ if (widthAmount > 0)
+ spriteWidth -= widthAmount;
+
+ int spriteRight = spriteLeft + spriteWidth;
+ if (spriteWidth <= 0)
+ return;
+ if (!normalFrame) {
+ destX += distXCount - 1;
+ spriteLeft = -(distXCount - spriteRight);
+ spriteRight = (-spriteLeft + spriteWidth);
+ }
+
+ // Check y bounding area
+ int spriteTop = 0;
+ int spriteHeight = distYCount;
+ int heightAmount = destY + distYCount - 1;
+
+ if (destY < 0) {
+ spriteHeight += destY;
+ spriteTop -= destY;
+ }
+ heightAmount -= destBottom;
+ if (heightAmount > 0)
+ spriteHeight -= heightAmount;
+ int spriteBottom = spriteTop + spriteHeight;
+
+ if (spriteHeight <= 0)
+ return;
+
+ byte *destPixelsP = this->getBasePtr(destX + spriteLeft, destY + spriteTop);
+ const byte *depthPixelsP = depthsSurface->getBasePtr(destX + spriteLeft, destY + spriteTop);
+
+ spriteLeft = (spriteLeft * (normalFrame ? 1 : -1));
+
+ // Loop through the lines of the sprite
+ for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src->pitch) {
+ if (!lineDist[yp])
+ // Not a display line, so skip it
+ continue;
+ // Check whether the sprite line is in the display range
+ ++sprY;
+ if ((sprY >= spriteBottom) || (sprY < spriteTop))
+ continue;
+
+ // Found a line to display. Loop through the pixels
+ const byte *srcP = srcPixelsP;
+ const byte *depthP = depthPixelsP;
+ byte *destP = destPixelsP;
+ for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) {
+ if (xp < spriteLeft)
+ // Not yet reached start of display area
+ continue;
+ if (!lineDist[sprX++])
+ // Not a display pixel
+ continue;
+
+ if ((*srcP != transparentColour) && (depth <= (*depthP & 0x7f)))
+ *destP = *srcP;
+
+ ++destP;
+ ++depthP;
+ }
+
+ // Move to the next destination line
+ destPixelsP += this->pitch;
+ depthPixelsP += depthsSurface->pitch;
+ }
+
+ src->freeData();
+ depthsSurface->freeData();
+ this->freeData();
+}
+
void M4Surface::loadBackgroundRiddle(const char *sceneName) {
char resourceName[20];
Common::SeekableReadStream *stream;
@@ -389,17 +585,24 @@ void M4Surface::loadBackgroundRiddle(const char *sceneName) {
}
void M4Surface::loadBackground(int sceneNumber, RGBList **palData) {
- clear(); // clear previous scene
-
if (_vm->isM4() || (_vm->getGameType() == GType_RexNebular)) {
char resourceName[20];
Common::SeekableReadStream *stream;
if (_vm->getGameType() == GType_RexNebular) {
// Load Rex Nebular screen
+ bool hasPalette = palData != NULL;
+ if (!hasPalette)
+ palData = &_rgbList;
+
sprintf(resourceName, "rm%d.art", sceneNumber);
stream = _vm->_resourceManager->get(resourceName);
rexLoadBackground(stream, palData);
+
+ if (!hasPalette) {
+ _vm->_palette->addRange(_rgbList);
+ this->translate(_rgbList);
+ }
} else {
// Loads M4 game scene
if (palData)
@@ -542,16 +745,6 @@ void M4Surface::rexLoadBackground(Common::SeekableReadStream *source, RGBList **
int sceneWidth = sourceUnc->readUint16LE();
int sceneHeight = sourceUnc->readUint16LE();
int sceneSize = sceneWidth * sceneHeight;
- if (sceneWidth > this->width()) {
- warning("Background width is %i, too large to fit in screen. Setting it to %i", sceneWidth, this->width());
- sceneWidth = this->width();
- sceneSize = sceneWidth * sceneHeight;
- }
- if (sceneHeight > this->height()) {
- warning("Background height is %i, too large to fit in screen.Setting it to %i", sceneHeight, this->height());
- sceneHeight = this->height();
- sceneSize = sceneWidth * sceneHeight;
- }
// Set palette
if (!palData) {
@@ -567,6 +760,7 @@ void M4Surface::rexLoadBackground(Common::SeekableReadStream *source, RGBList **
sourceUnc = packData.getItemStream(1);
assert((int)sourceUnc->size() >= sceneSize);
+ create(sceneWidth, sceneHeight, 1);
byte *pData = (byte *)pixels;
sourceUnc->read(pData, sceneSize);
@@ -636,10 +830,8 @@ void M4Surface::m4LoadBackground(Common::SeekableReadStream *source) {
delete tileBuffer;
}
-void M4Surface::madsloadInterface(int index, RGBList **palData) {
- char resourceName[20];
- sprintf(resourceName, "i%d.int", index);
- MadsPack intFile(resourceName, _vm);
+void M4Surface::madsLoadInterface(const Common::String &filename) {
+ MadsPack intFile(filename.c_str(), _vm);
RGB8 *palette = new RGB8[16];
// Chunk 0, palette
@@ -653,7 +845,7 @@ void M4Surface::madsloadInterface(int index, RGBList **palData) {
intStream->readByte();
intStream->readByte();
}
- *palData = new RGBList(16, palette, true);
+ _rgbList = new RGBList(16, palette, true);
delete intStream;
// Chunk 1, data
@@ -661,22 +853,108 @@ void M4Surface::madsloadInterface(int index, RGBList **palData) {
create(320, 44, 1);
intStream->read(pixels, 320 * 44);
delete intStream;
+
+ // Translate the interface palette
+ _vm->_palette->addRange(_rgbList);
+ this->translate(_rgbList);
}
+void M4Surface::scrollX(int xAmount) {
+ if (xAmount == 0)
+ return;
+
+ byte buffer[80];
+ int direction = (xAmount > 0) ? -1 : 1;
+ int xSize = ABS(xAmount);
+ assert(xSize <= 80);
+
+ byte *srcP = (byte *)getBasePtr(0, 0);
+
+ for (int y = 0; y < height(); ++y, srcP += pitch) {
+ if (direction < 0) {
+ // Copy area to be overwritten
+ Common::copy(srcP, srcP + xSize, &buffer[0]);
+ // Shift the remainder of the line over the given area
+ Common::copy(srcP + xSize, srcP + width(), srcP);
+ // Move buffered area to the end of the line
+ Common::copy(&buffer[0], &buffer[xSize], srcP + width() - xSize);
+ } else {
+ // Copy area to be overwritten
+ Common::copy_backward(srcP + width() - xSize, srcP + width(), &buffer[80]);
+ // Shift the remainder of the line over the given area
+ Common::copy_backward(srcP, srcP + width() - xSize, srcP + width());
+ // Move buffered area to the start of the line
+ Common::copy_backward(&buffer[80 - xSize], &buffer[80], srcP + xSize);
+ }
+ }
+}
+
+void M4Surface::scrollY(int yAmount) {
+ if (yAmount == 0)
+ return;
+
+ int direction = (yAmount > 0) ? 1 : -1;
+ int ySize = ABS(yAmount);
+ assert(ySize < (height() / 2));
+ assert(width() == pitch);
+
+ int blockSize = ySize * width();
+ byte *tempData = (byte *)malloc(blockSize);
+ byte *pixelsP = (byte *)getBasePtr(0, 0);
+
+ if (direction > 0) {
+ // Buffer the lines to be overwritten
+ byte *srcP = (byte *)getBasePtr(0, height() - ySize);
+ Common::copy(srcP, srcP + (pitch * ySize), tempData);
+ // Vertically shift all the lines
+ Common::copy_backward(pixelsP, pixelsP + (pitch * (height() - ySize)),
+ pixelsP + (pitch * height()));
+ // Transfer the buffered lines top the top of the screen
+ Common::copy(tempData, tempData + blockSize, pixelsP);
+ } else {
+ // Buffer the lines to be overwritten
+ Common::copy(pixelsP, pixelsP + (pitch * ySize), tempData);
+ // Vertically shift all the lines
+ Common::copy(pixelsP + (pitch * ySize), pixelsP + (pitch * height()), pixelsP);
+ // Transfer the buffered lines to the bottom of the screen
+ Common::copy(tempData, tempData + blockSize, pixelsP + (pitch * (height() - ySize)));
+ }
+
+ ::free(tempData);
+}
+
+
void M4Surface::translate(RGBList *list, bool isTransparent) {
byte *p = getBasePtr(0, 0);
byte *palIndexes = list->palIndexes();
for (int i = 0; i < width() * height(); ++i, ++p) {
- if (!isTransparent || (*p != 0)) {
- assert(*p < list->size());
- *p = palIndexes[*p];
+ if (!isTransparent || (*p != TRANSPARENT_COLOUR_INDEX)) {
+ if (*p < list->size())
+ *p = palIndexes[*p];
+ else
+ warning("Pal index %d exceeds list size %d", *p, list->size());
}
}
freeData();
}
+M4Surface *M4Surface::flipHorizontal() const {
+ M4Surface *dest = new M4Surface(width(), height());
+ dest->_rgbList = (this->_rgbList == NULL) ? NULL : this->_rgbList->clone();
+
+ byte *destP = dest->getBasePtr();
+
+ for (int y = 0; y < height(); ++y) {
+ const byte *srcP = getBasePtr(width() - 1, y);
+ for (int x = 0; x < width(); ++x)
+ *destP++ = *srcP--;
+ }
+
+ return dest;
+}
+
//--------------------------------------------------------------------------
// Palette class
//
diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h
index 4c89c50b8a..ecb5048b26 100644
--- a/engines/m4/graphics.h
+++ b/engines/m4/graphics.h
@@ -35,6 +35,13 @@
namespace M4 {
+#define MADS_SURFACE_WIDTH 320
+#define MADS_SURFACE_HEIGHT 156
+#define MADS_SCREEN_HEIGHT 200
+#define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2)
+
+#define TRANSPARENT_COLOUR_INDEX 0xFF
+
struct BGR8 {
uint8 b, g, r;
};
@@ -68,6 +75,7 @@ public:
int size() { return _size; }
RGB8 &operator[](int idx) { return _data[idx]; }
void setRange(int start, int count, const RGB8 *src);
+ RGBList *clone() const;
};
// M4Surface
@@ -89,19 +97,36 @@ class M4Surface : protected Graphics::Surface {
private:
byte _color;
bool _isScreen;
+ RGBList *_rgbList;
+ bool _ownsData;
void rexLoadBackground(Common::SeekableReadStream *source, RGBList **palData = NULL);
void madsLoadBackground(int roomNumber, RGBList **palData = NULL);
void m4LoadBackground(Common::SeekableReadStream *source);
public:
M4Surface(bool isScreen = false) {
- create(g_system->getWidth(), g_system->getHeight(), 1);
+ create(g_system->getWidth(), isScreen ? g_system->getHeight() : MADS_SURFACE_HEIGHT, 1);
_isScreen = isScreen;
+ _rgbList = NULL;
+ _ownsData = true;
}
M4Surface(int width_, int height_) {
create(width_, height_, 1);
_isScreen = false;
+ _rgbList = NULL;
+ _ownsData = true;
}
+ M4Surface(int width_, int height_, byte *srcPixels, int pitch_) {
+ bytesPerPixel = 1;
+ w = width_;
+ h = height_;
+ pitch = pitch_;
+ pixels = srcPixels;
+ _rgbList = NULL;
+ _ownsData = false;
+ }
+
+ virtual ~M4Surface();
// loads a .COD file into the M4Surface
// TODO: maybe move this to the rail system? check where it makes sense
@@ -112,7 +137,8 @@ public:
// loads the specified background
void loadBackground(int sceneNumber, RGBList **palData = NULL);
void loadBackgroundRiddle(const char *sceneName);
- void madsloadInterface(int index, RGBList **palData);
+ void madsLoadInterface(int index, RGBList **palData = NULL);
+ void madsLoadInterface(const Common::String &filename);
void setColor(byte value) { _color = value; }
void setColour(byte value) { _color = value; }
@@ -131,6 +157,7 @@ public:
inline Common::Rect bounds() const { return Common::Rect(0, 0, width(), height()); }
inline int width() const { return w; }
inline int height() const { return h; }
+ inline int getPitch() const { return pitch; }
void setSize(int sizeX, int sizeY) { create(sizeX, sizeY, 1); }
inline byte *getBasePtr() {
return (byte *)pixels;
@@ -143,10 +170,12 @@ public:
}
void freeData();
void clear();
+ void reset();
void frameRect(const Common::Rect &r, uint8 color);
void fillRect(const Common::Rect &r, uint8 color);
- void copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY,
- int transparentColor = -1);
+ void copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY, int transparentColour = -1);
+ void copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surface *depthSurface,
+ int scale, int transparentColour = -1);
void update() {
if (_isScreen) {
@@ -156,18 +185,26 @@ public:
}
// copyTo methods
- inline void copyTo(M4Surface *dest, int transparentColor = -1) {
- dest->copyFrom(this, Common::Rect(width(), height()), 0, 0, transparentColor);
+ inline void copyTo(M4Surface *dest, int transparentColour = -1) {
+ dest->copyFrom(this, Common::Rect(width(), height()), 0, 0, transparentColour);
}
- inline void copyTo(M4Surface *dest, int x, int y, int transparentColor = -1) {
- dest->copyFrom(this, Common::Rect(width(), height()), x, y, transparentColor);
+ inline void copyTo(M4Surface *dest, int x, int y, int transparentColour = -1) {
+ dest->copyFrom(this, Common::Rect(width(), height()), x, y, transparentColour);
}
inline void copyTo(M4Surface *dest, const Common::Rect &srcBounds, int destX, int destY,
- int transparentColor = -1) {
- dest->copyFrom(this, srcBounds, destX, destY, transparentColor);
+ int transparentColour = -1) {
+ dest->copyFrom(this, srcBounds, destX, destY, transparentColour);
+ }
+ inline void copyTo(M4Surface *dest, int destX, int destY, int depth, M4Surface *depthsSurface, int scale,
+ int transparentColour = -1) {
+ dest->copyFrom(this, destX, destY, depth, depthsSurface, scale, transparentColour);
}
+ void scrollX(int xAmount);
+ void scrollY(int yAmount);
+
void translate(RGBList *list, bool isTransparent = false);
+ M4Surface *flipHorizontal() const;
};
enum FadeType {FT_TO_GREY, FT_TO_COLOR, FT_TO_BLOCK};
diff --git a/engines/m4/hotspot.cpp b/engines/m4/hotspot.cpp
index 9849cc7416..27180c5eb8 100644
--- a/engines/m4/hotspot.cpp
+++ b/engines/m4/hotspot.cpp
@@ -185,9 +185,9 @@ void HotSpotList::dump() {
uint32 HotSpotList::readHotSpotInteger(Common::SeekableReadStream* hotspotStream) {
if (_vm->isM4())
- return hotspotStream->readUint32LE();
+ return hotspotStream->readSint32LE();
else
- return hotspotStream->readUint16LE();
+ return hotspotStream->readSint16LE();
}
void HotSpotList::loadHotSpots(Common::SeekableReadStream* hotspotStream, int hotspotCount) {
@@ -196,7 +196,7 @@ void HotSpotList::loadHotSpots(Common::SeekableReadStream* hotspotStream, int ho
char buffer[256];
uint32 strLength = 0;
uint32 index = 0;
- uint32 feetX, feetY;
+ int feetX, feetY;
int cursorOffset = (_vm ->isM4()) ? 0 : 1;
for (int i = 0; i < hotspotCount; i++) {
@@ -206,6 +206,7 @@ void HotSpotList::loadHotSpots(Common::SeekableReadStream* hotspotStream, int ho
y2 = readHotSpotInteger(hotspotStream);
index = add(new HotSpot(x1, y1, x2, y2), i == 0);
currentHotSpot = get(index);
+ currentHotSpot->setIndex(index);
feetX = readHotSpotInteger(hotspotStream);
feetY = readHotSpotInteger(hotspotStream);
currentHotSpot->setFeet(feetX, feetY);
diff --git a/engines/m4/hotspot.h b/engines/m4/hotspot.h
index 5bb4f5888a..f650d5ff54 100644
--- a/engines/m4/hotspot.h
+++ b/engines/m4/hotspot.h
@@ -73,6 +73,8 @@ public:
int getFeetY() { return _feetY; }
int8 getArticle() const { return _articleNumber; }
Common::Rect getRect() const;
+ int getIndex() const { return _index; }
+ void setIndex(int index) { _index = index; }
int32 area() const { return (_rect.width() - 1) * (_rect.height() - 1); }
bool pointInside(int x, int y) { return _rect.contains(x, y); }
@@ -83,6 +85,7 @@ private:
bool _active;
int _feetX, _feetY;
uint8 _facing, _cursor;
+ int _index;
// Unused in Orion Burger, used in MADS games
uint8 _syntax;
@@ -101,6 +104,7 @@ public:
int add(HotSpot *hotspot, bool head = false);
HotSpot *get(int index) { return _hotspots[index]; }
HotSpot &operator[](int idx) { return *get(idx); }
+ int size() const { return _hotspots.size(); }
void remove(HotSpot *hotspot);
void unlinkItem(HotSpot *hotspot);
void clear();
diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp
index 897fb468cd..824896ad33 100644
--- a/engines/m4/m4.cpp
+++ b/engines/m4/m4.cpp
@@ -147,20 +147,24 @@ MadsM4Engine::~MadsM4Engine() {
delete _random;
delete _animation;
delete _palette;
+ delete _globals;
+ delete _sound;
+ delete _driver;
+ delete _resourceManager;
}
Common::Error MadsM4Engine::run() {
// Initialize backend
_screen = new M4Surface(true); // Special form for creating screen reference
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
- MidiDriver *driver = MidiDriver::createMidi(midiDriver);
+ _driver = MidiDriver::createMidi(dev);
if (native_mt32)
- driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+ _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
- _midi = new MidiPlayer(this, driver);
+ _midi = new MidiPlayer(this, _driver);
_midi->setGM(true);
_midi->setNativeMT32(native_mt32);
@@ -305,8 +309,6 @@ M4Engine::M4Engine(OSystem *syst, const M4GameDescription *gameDesc): MadsM4Engi
}
M4Engine::~M4Engine() {
- delete _resourceManager;
- delete _globals;
delete _converse;
}
@@ -502,8 +504,6 @@ MadsEngine::MadsEngine(OSystem *syst, const M4GameDescription *gameDesc): MadsM4
}
MadsEngine::~MadsEngine() {
- delete _globals;
- delete _resourceManager;
}
Common::Error MadsEngine::run() {
@@ -516,7 +516,6 @@ Common::Error MadsEngine::run() {
// Set up needed common functionality
MadsM4Engine::run();
- _scene = new MadsScene(this);
_palette->setMadsSystemPalette();
_mouse->init("cursor.ss", NULL);
@@ -540,16 +539,20 @@ Common::Error MadsEngine::run() {
//for (int i = 0; i < _globals->getMessagesSize(); i++)
//printf("%s\n----------\n", _globals->loadMessage(i));
- if ((getGameType() == GType_RexNebular) || (getGameType() == GType_DragonSphere)) {
- loadMenu(MAIN_MENU);
+ if (getGameType() == GType_RexNebular) {
+ MadsGameLogic::initialiseGlobals();
+ _scene = NULL;
+ loadMenu(MAIN_MENU);
} else {
- if (getGameType() == GType_DragonSphere) {
- _scene->loadScene(FIRST_SCENE);
- } else if (getGameType() == GType_Phantom) {
- //_scene->loadScene(FIRST_SCENE);
- _scene->loadScene(106); // a more interesting scene
- }
+ // Test code
+ _scene = new MadsScene(this);
+
+ startScene(FIRST_SCENE);
+ RGBList *_bgPalData;
+ _scene->loadBackground(FIRST_SCENE, &_bgPalData);
+ _palette->addRange(_bgPalData);
+ _scene->translate(_bgPalData);
_scene->show();
@@ -568,15 +571,6 @@ Common::Error MadsEngine::run() {
_viewManager->systemHotkeys().add(Common::KEYCODE_ESCAPE, &escapeHotkeyHandler);
_viewManager->systemHotkeys().add(Common::KEYCODE_KP_MULTIPLY, &textviewHotkeyHandler);
- // Load the general game SFX/voices
- if (getGameType() == GType_RexNebular) {
- _sound->loadDSRFile("rex009.dsr");
- } else if (getGameType() == GType_Phantom) {
- _sound->loadDSRFile("phan009.dsr");
- } else if (getGameType() == GType_DragonSphere) {
- _sound->loadDSRFile("drag009.dsr");
- }
-
uint32 nextFrame = g_system->getMillis();
while (!_events->quitFlag) {
eventHandler();
diff --git a/engines/m4/m4.h b/engines/m4/m4.h
index 1f34bd3685..9e3035957a 100644
--- a/engines/m4/m4.h
+++ b/engines/m4/m4.h
@@ -29,6 +29,7 @@
#include "common/scummsys.h"
#include "common/util.h"
#include "common/random.h"
+#include "sound/mididrv.h"
#include "engines/engine.h"
@@ -41,6 +42,7 @@
#include "m4/events.h"
#include "m4/font.h"
#include "m4/scene.h"
+#include "m4/mads_player.h"
#include "m4/mads_scene.h"
#include "m4/m4_scene.h"
#include "m4/actor.h"
@@ -123,7 +125,7 @@ enum {
struct M4GameDescription;
-#define GAME_FRAME_DELAY 50
+#define GAME_FRAME_DELAY 20
#define VALIDATE_MADS assert(!_vm->isM4())
@@ -144,6 +146,7 @@ protected:
void shutdown();
+ MidiDriver *_driver;
MidiPlayer *_midi;
public:
@@ -212,6 +215,7 @@ private:
public:
MadsConversation _converse;
uint32 _currentTimer;
+ MadsPlayer _player;
public:
MadsEngine(OSystem *syst, const M4GameDescription *gameDesc);
virtual ~MadsEngine();
@@ -220,6 +224,12 @@ public:
MadsGlobals *globals() { return (MadsGlobals *)_globals; }
MadsScene *scene() { return (MadsScene *)_scene; }
+ void startScene(int sceneNum) {
+ if (!_scene)
+ _scene = new MadsScene(this);
+ _scene->show();
+ _scene->loadScene(101);
+ }
};
class M4Engine : public MadsM4Engine {
diff --git a/engines/m4/m4_scene.cpp b/engines/m4/m4_scene.cpp
index 79122a9564..475fdba653 100644
--- a/engines/m4/m4_scene.cpp
+++ b/engines/m4/m4_scene.cpp
@@ -45,7 +45,7 @@ M4Scene::M4Scene(M4Engine *vm): _sceneResources(), Scene(vm, &_sceneResources) {
_sceneResources.hotspots = new HotSpotList();
_sceneResources.parallax = new HotSpotList();
- _sceneResources.props = new HotSpotList();
+ _sceneResources.dynamicHotspots = new HotSpotList();
_interfaceSurface = new M4InterfaceView(vm);
}
@@ -74,9 +74,9 @@ void M4Scene::loadSceneResources(int sceneNumber) {
if (sceneS != NULL) {
sceneS->read(_sceneResources.artBase, MAX_CHK_FILENAME_SIZE);
sceneS->read(_sceneResources.pictureBase, MAX_CHK_FILENAME_SIZE);
- _sceneResources.hotspotCount = sceneS->readUint32LE();
+ int hotspotCount = sceneS->readUint32LE();
_sceneResources.parallaxCount = sceneS->readUint32LE();
- _sceneResources.propsCount = sceneS->readUint32LE();
+ int dynHotspotCount = sceneS->readUint32LE();
_sceneResources.frontY = sceneS->readUint32LE();
_sceneResources.backY = sceneS->readUint32LE();
_sceneResources.frontScale = sceneS->readUint32LE();
@@ -99,11 +99,11 @@ void M4Scene::loadSceneResources(int sceneNumber) {
// Clear current hotspot lists
_sceneResources.hotspots->clear();
_sceneResources.parallax->clear();
- _sceneResources.props->clear();
+ _sceneResources.dynamicHotspots->clear();
- _sceneResources.hotspots->loadHotSpots(sceneS, _sceneResources.hotspotCount);
+ _sceneResources.hotspots->loadHotSpots(sceneS, hotspotCount);
_sceneResources.parallax->loadHotSpots(sceneS, _sceneResources.parallaxCount);
- _sceneResources.props->loadHotSpots(sceneS, _sceneResources.propsCount);
+ _sceneResources.dynamicHotspots->loadHotSpots(sceneS, dynHotspotCount);
// Note that toss() deletes the MemoryReadStream
_vm->res()->toss(filename);
@@ -207,7 +207,7 @@ void M4Scene::leaveScene() {
Scene::leaveScene();
}
-void M4Scene::checkHotspotAtMousePos(int x, int y) {
+void M4Scene::mouseMove(int x, int y) {
if (_vm->getGameType() == GType_Riddle)
return;
diff --git a/engines/m4/m4_scene.h b/engines/m4/m4_scene.h
index 329582caf4..2216779a3e 100644
--- a/engines/m4/m4_scene.h
+++ b/engines/m4/m4_scene.h
@@ -69,7 +69,7 @@ public:
virtual void leaveScene();
virtual void loadSceneCodes(int sceneNumber, int index = 0);
virtual void show();
- virtual void checkHotspotAtMousePos(int x, int y);
+ virtual void mouseMove(int x, int y);
virtual void leftClick(int x, int y);
virtual void rightClick(int x, int y);
virtual void update();
diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp
index 954916700c..5e19e90533 100644
--- a/engines/m4/mads_anim.cpp
+++ b/engines/m4/mads_anim.cpp
@@ -441,7 +441,12 @@ void TextviewView::processText() {
AnimviewView::AnimviewView(MadsM4Engine *vm):
View(vm, Common::Rect(0, 0, vm->_screen->width(), vm->_screen->height())),
- _bgSurface(vm->_screen->width(), MADS_SURFACE_HEIGHT) {
+ MadsView(this), _backgroundSurface(MADS_SURFACE_WIDTH, MADS_SURFACE_HEIGHT),
+ _codeSurface(MADS_SURFACE_WIDTH, MADS_SURFACE_HEIGHT) {
+
+ MadsView::_bgSurface = &_backgroundSurface;
+ MadsView::_depthSurface = &_codeSurface;
+ MadsView::setViewport(Common::Rect(0, MADS_Y_OFFSET, MADS_SURFACE_WIDTH, MADS_Y_OFFSET + MADS_SURFACE_HEIGHT));
_screenType = VIEWID_ANIMVIEW;
_screenFlags.layer = LAYER_BACKGROUND;
@@ -452,27 +457,36 @@ AnimviewView::AnimviewView(MadsM4Engine *vm):
_palData = NULL;
_previousUpdate = 0;
_transition = kTransitionNone;
+ _activeAnimation = NULL;
+ _bgLoadFlag = true;
+ _startFrame = -1;
+ _scriptDone = false;
+
reset();
// Set up system palette colors
_vm->_palette->setMadsSystemPalette();
+ // Block reserved palette ranges
+ _vm->_palette->blockRange(16, 2);
+ _vm->_palette->blockRange(250, 4);
+
clear();
- _bgSurface.clear();
+ _backgroundSurface.clear();
- int y = (height() - MADS_SURFACE_HEIGHT) / 2;
setColor(2);
- hLine(0, width() - 1, y - 2);
- hLine(0, width() - 1, height() - y + 1);
+ hLine(0, width() - 1, MADS_Y_OFFSET - 2);
+ hLine(0, width() - 1, MADS_Y_OFFSET + MADS_SURFACE_HEIGHT + 2);
}
AnimviewView::~AnimviewView() {
if (_script)
_vm->res()->toss(_resourceName);
+ delete _activeAnimation;
}
void AnimviewView::reset() {
- _bgSurface.clear();
+ _backgroundSurface.clear();
_soundDriverLoaded = false;
}
@@ -504,34 +518,51 @@ bool AnimviewView::onEvent(M4EventType eventType, int32 param, int x, int y, boo
}
void AnimviewView::updateState() {
- if (!_script)
- return;
+ MadsView::update();
- // Only update state if wait period has expired
- if (_previousUpdate > 0) {
- if (g_system->getMillis() - _previousUpdate < 100)
- return;
+ if (!_script || _scriptDone)
+ return;
- _previousUpdate = g_system->getMillis();
+ if (!_activeAnimation) {
+ readNextCommand();
+ assert(_activeAnimation);
}
- // Check if we're ready for the next command
- bool animRunning = false;
- if (!animRunning) {
- if (_script->eos() || _script->err()) {
- scriptDone();
- return;
- }
+ // Update the current animation
+ _activeAnimation->update();
+ if (_activeAnimation->freeFlag()) {
+ delete _activeAnimation;
+ _activeAnimation = NULL;
+
+ // Clear up current background and sprites
+ _backgroundSurface.reset();
+ clearLists();
+
+ // Reset flags
+ _startFrame = -1;
readNextCommand();
- // FIXME: Replace flag with proper animation end check
- animRunning = true;
+ // Check if script is finished
+ if (_scriptDone) {
+ scriptDone();
+ return;
+ }
}
+
+ refresh();
}
void AnimviewView::readNextCommand() {
+static bool tempFlag = true;//****DEBUG - Temporarily allow me to skip several intro scenes ****
+
while (!_script->eos() && !_script->err()) {
+ if (!tempFlag) {
+ tempFlag = true;
+ strncpy(_currentLine, _script->readLine().c_str(), 79);
+ strncpy(_currentLine, _script->readLine().c_str(), 79);
+ }
+
strncpy(_currentLine, _script->readLine().c_str(), 79);
// Process any switches on the line
@@ -559,49 +590,27 @@ void AnimviewView::readNextCommand() {
break;
}
- if (strchr(_currentLine, '.') == NULL)
- strcat(_currentLine, ".aa");
-
- AAFile aaFile(_currentLine, _vm);
-
- // Initial validation
- if (aaFile.flags & AA_HAS_FONT) {
- assert(_vm->_resourceManager->resourceExists(aaFile.fontResource.c_str()));
- }
-
- for (int seriesCtr = 0; seriesCtr < aaFile.seriesCount; ++seriesCtr)
- assert(_vm->_resourceManager->resourceExists(aaFile.filenames[seriesCtr].c_str()));
-
- // Start sound
- if (aaFile.flags & AA_HAS_SOUND) {
- char buffer[100];
- strcpy(buffer, aaFile.soundName.c_str());
- buffer[0] = 'A'; // A for AdLib resource
-
- /*Common::SeekableReadStream *stream = */_vm->_resourceManager->get(buffer);
-
- _vm->_resourceManager->toss(buffer);
+ if (!_currentLine[0]) {
+ // A blank line at this point means that the end of the animation has been reached
+ _scriptDone = true;
+ return;
}
+ if (strchr(_currentLine, '.') == NULL)
+ strcat(_currentLine, ".aa");
- char artFile[80];
- sprintf(artFile, "rm%d.art", aaFile.roomNumber);
+ uint16 flags = 0;
+ if (_bgLoadFlag)
+ flags |= 0x100;
- // Not all scenes have a background. If there is one, refresh it
- if (_vm->_resourceManager->resourceExists(artFile)) {
- if (_palData) {
- _vm->_palette->deleteRange(_palData);
- delete _palData;
- }
- _bgSurface.loadBackground(aaFile.roomNumber, &_palData);
- _vm->_palette->addRange(_palData);
- _bgSurface.translate(_palData);
- }
+ _activeAnimation = new MadsAnimation(_vm, this);
+ _activeAnimation->initialise(_currentLine, flags, &_backgroundSurface, &_codeSurface);
- // Grab what the final palete will be
- RGB8 destPalette[256];
- _vm->_palette->grabPalette(destPalette, 0, 256);
+ if (_startFrame != -1)
+ _activeAnimation->setCurrentFrame(_startFrame);
+ _spriteSlots.fullRefresh();
+/*
// Handle scene transition
switch (_transition) {
case kTransitionNone:
@@ -631,16 +640,14 @@ void AnimviewView::readNextCommand() {
// nothing to do
break;
}
-
- // Refresh the view
- int yp = (height() - _bgSurface.height()) / 2;
- _bgSurface.copyTo(this, 0, yp);
+*/
_vm->_resourceManager->toss(_currentLine);
}
void AnimviewView::scriptDone() {
+return;
AnimviewCallback fn = _callback;
MadsM4Engine *vm = _vm;
@@ -655,6 +662,7 @@ void AnimviewView::scriptDone() {
Switches are: (taken from the help of the original executable)
-b Toggle background load status off/on.
-c:char Specify sound card id letter.
+ -f:num Specify a specific starting frame number
-g Stay in graphics mode on exit.
-h[:ex] Disable EMS/XMS high memory support.
-i Switch sound interrupts mode off/on.
@@ -698,61 +706,41 @@ void AnimviewView::processCommand() {
str_upper(commandStr);
char *param = commandStr;
- if (!strncmp(commandStr, "X", 1)) {
- //printf("X ");
- } else if (!strncmp(commandStr, "W", 1)) {
- //printf("W ");
- } else if (!strncmp(commandStr, "R", 1)) {
- param = param + 2;
- //printf("R:%s ", param);
- } else if (!strncmp(commandStr, "O", 1)) {
+ switch (commandStr[0]) {
+ case 'B':
+ // Toggle background load flag
+ _bgLoadFlag = !_bgLoadFlag;
+ break;
+
+ case 'F':
+ // Start animation at a specific frame
+ ++param;
+ assert(*param == ':');
+ _startFrame = atoi(++param);
+ break;
+
+ case 'O':
param = param + 2;
//printf("O:%i ", atoi(param));
_transition = atoi(param);
- } else {
- error("Unknown response command: '%s'", commandStr);
- }
-}
+ break;
-AAFile::AAFile(const char *resourceName, MadsM4Engine* vm): MadsPack(resourceName, vm) {
- Common::MemoryReadStream stream1(*getItemStream(1));
- Common::MemoryReadStream stream2(*getItemStream(2));
-
- Common::MemoryReadStream stream(*getItemStream(0));
-
- seriesCount = stream.readUint16LE();
- frameCount = stream.readUint16LE();
- frameEntryCount = stream.readUint16LE();
- stream.skip(3);
- flags = stream.readByte();
- stream.skip(4);
- roomNumber = stream.readUint16LE();
- stream.skip(10);
- frameTicks = stream.readUint16LE();
-
- stream.skip(21);
- for (int i = 0; i < 10; ++i) {
- char filename[13];
- stream.read(filename, 13);
- filenames.push_back(Common::String(filename, 13));
- }
-
- stream.skip(81);
- char name[100];
- stream.read(name, 13);
- lbmFilename = Common::String(name, 13);
+ case 'R':
+ param = param + 2;
+ //printf("R:%s ", param);
+ break;
- stream.skip(365);
- stream.read(name, 13);
- spritesFilename = Common::String(name, 13);
+ case 'W':
+ //printf("W ");
+ break;
- stream.skip(48);
- stream.read(name, 13);
- soundName = Common::String(name, 13);
+ case 'X':
+ //printf("X ");
+ break;
- stream.skip(26);
- stream.read(name, 14);
- fontResource = Common::String(name, 14);
+ default:
+ error("Unknown response command: '%s'", commandStr);
+ }
}
}
diff --git a/engines/m4/mads_anim.h b/engines/m4/mads_anim.h
index 680c5ff901..b33ea24071 100644
--- a/engines/m4/mads_anim.h
+++ b/engines/m4/mads_anim.h
@@ -28,24 +28,12 @@
#include "m4/viewmgr.h"
#include "m4/compression.h"
+#include "m4/animation.h"
#include "common/str-array.h"
namespace M4 {
-enum SceneTransition {
- kTransitionNone = 0,
- kTransitionFadeIn = 1,
- kTransitionFadeIn2 = 2,
- kTransitionBoxInBottomLeft = 3,
- kTransitionBoxInBottomRight = 4,
- kTransitionBoxInTopLeft = 5,
- kTransitionBoxInTopRight = 6,
- kTransitionPanLeftToRight = 7,
- kTransitionPanRightToLeft = 8,
- kTransitionCircleIn = 9
-};
-
typedef void (*TextviewCallback)(MadsM4Engine *vm);
class TextviewView : public View {
@@ -89,36 +77,22 @@ public:
typedef void (*AnimviewCallback)(MadsM4Engine *vm);
-class AAFile : public MadsPack {
-public:
- AAFile(const char *resourceName, MadsM4Engine* vm);
-
- uint16 seriesCount;
- uint16 frameCount;
- uint16 frameEntryCount;
- uint8 flags;
- uint16 roomNumber;
- uint16 frameTicks;
- Common::StringArray filenames;
- Common::String lbmFilename;
- Common::String spritesFilename;
- Common::String soundName;
- Common::String fontResource;
-};
-
-enum AAFlags {AA_HAS_FONT = 0x20, AA_HAS_SOUND = 0x8000};
-
-class AnimviewView : public View {
+class AnimviewView : public View, MadsView {
private:
char _resourceName[80];
Common::SeekableReadStream *_script;
+ bool _scriptDone;
uint32 _previousUpdate;
char _currentLine[80];
- M4Surface _bgSurface;
+ M4Surface _backgroundSurface;
+ M4Surface _codeSurface;
AnimviewCallback _callback;
bool _soundDriverLoaded;
RGBList *_palData;
int _transition;
+ MadsAnimation *_activeAnimation;
+ bool _bgLoadFlag;
+ int _startFrame;
void reset();
void readNextCommand();
diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp
index d0b7021f38..e7c20b237d 100644
--- a/engines/m4/mads_logic.cpp
+++ b/engines/m4/mads_logic.cpp
@@ -29,6 +29,114 @@
namespace M4 {
+void MadsGameLogic::initialiseGlobals() {
+ // Clear the entire globals list
+ Common::set_to(&_madsVm->globals()->_globals[0], &_madsVm->globals()->_globals[TOTAL_NUM_VARIABLES], 0);
+
+ SET_GLOBAL(4, 8);
+ SET_GLOBAL(33, 1);
+ SET_GLOBAL(10, 0xFFFF);
+ SET_GLOBAL(13, 0xFFFF);
+ SET_GLOBAL(15, 0xFFFF);
+ SET_GLOBAL(19, 0xFFFF);
+ SET_GLOBAL(20, 0xFFFF);
+ SET_GLOBAL(21, 0xFFFF);
+ SET_GLOBAL(95, 0xFFFF);
+
+ // TODO: unknown sub call
+
+ // Put the values 0 through 3 in a random ordering in global slots 83 - 86
+ for (int idx = 0; idx < 4; ) {
+ int randVal = _madsVm->_random->getRandomNumber(4);
+ SET_GLOBAL(83 + idx, randVal);
+
+ // Check whether the given value has already been used
+ bool flag = false;
+ for (int idx2 = 0; idx2 < idx; ++idx2) {
+ if (randVal == GET_GLOBAL(83 + idx2))
+ flag = true;
+ }
+
+ if (!flag)
+ ++idx;
+ }
+
+ // Put the values 0 through 3 in a random ordering in global slots 87 - 90
+ for (int idx = 0; idx < 4; ) {
+ int randVal = _madsVm->_random->getRandomNumber(3);
+ SET_GLOBAL(87 + idx, randVal);
+
+ // Check whether the given value has already been used
+ bool flag = false;
+ for (int idx2 = 0; idx2 < idx; ++idx2) {
+ if (randVal == GET_GLOBAL(87 + idx2))
+ flag = true;
+ }
+
+ if (!flag)
+ ++idx;
+ }
+
+ // Miscellaneous global settings
+ SET_GLOBAL(120, 501);
+ SET_GLOBAL(121, 0xFFFF);
+ SET_GLOBAL(110, 0xFFFF);
+ SET_GLOBAL(119, 1);
+ SET_GLOBAL(134, 4);
+ SET_GLOBAL(190, 201);
+ SET_GLOBAL(191, 301);
+ SET_GLOBAL(192, 413);
+ SET_GLOBAL(193, 706);
+ SET_GLOBAL(194, 801);
+ SET_GLOBAL(195, 551);
+ SET_GLOBAL(196, 752);
+
+ // Fill out the globals 200 - 209 with unique random number values less than 10000
+ for (int idx = 0; idx < 10; ) {
+ int randVal = _madsVm->_random->getRandomNumber(9999);
+ SET_GLOBAL(200 + idx, randVal);
+
+ // Check whether the given value has already been used
+ bool flag = false;
+ for (int idx2 = 0; idx2 < idx; ++idx2) {
+ if (randVal == GET_GLOBAL(87 + idx2))
+ flag = true;
+ }
+
+ if (!flag)
+ ++idx;
+ }
+
+ switch (_madsVm->globals()->_difficultyLevel) {
+ case 1:
+ // Very hard
+ SET_GLOBAL(35, 0);
+ // TODO: object set room
+ SET_GLOBAL(137, 5);
+ SET_GLOBAL(136, 0);
+ break;
+
+ case 2:
+ // Hard
+ SET_GLOBAL(35, 0);
+ // TODO: object set room
+ SET_GLOBAL(136, 0xFFFF);
+ SET_GLOBAL(137, 6);
+ break;
+
+ case 3:
+ // Easy
+ SET_GLOBAL(35, 2);
+ // TODO: object set room
+ break;
+ }
+
+ _madsVm->_player._direction = 8;
+ _madsVm->_player._newDirection = 8;
+
+ // TODO: unknown processing routine getting called for 'RXM' and 'ROX'
+}
+
/*--------------------------------------------------------------------------*/
const char *MadsSceneLogic::formAnimName(char sepChar, int16 suffixNum) {
@@ -54,13 +162,13 @@ void MadsSceneLogic::getSceneSpriteSet() {
strcpy(prefix, "");
_madsVm->globals()->playerSpriteChanged = true;
- _madsVm->scene()->loadPlayerSprites(prefix);
+ _madsVm->_player.loadSprites(prefix);
// if ((_sceneNumber == 105) ((_sceneNumber == 109) && (word_84800 != 0)))
// _madsVm->globals()->playerSpriteChanged = true;
-// _vm->_palette->setEntry(16, 0x38, 0xFF, 0xFF);
-// _vm->_palette->setEntry(17, 0x38, 0xb4, 0xb4);
+ _vm->_palette->setEntry(16, 0x38, 0xFF, 0xFF);
+ _vm->_palette->setEntry(17, 0x38, 0xb4, 0xb4);
}
void MadsSceneLogic::getAnimName() {
@@ -69,6 +177,10 @@ void MadsSceneLogic::getAnimName() {
strcpy(_madsVm->scene()->_aaName, newName);
}
+IntStorage &MadsSceneLogic::dataMap() {
+ return _madsVm->globals()->_dataMap;
+}
+
/*--------------------------------------------------------------------------*/
uint16 MadsSceneLogic::loadSpriteSet(uint16 suffixNum, uint16 sepChar) {
@@ -77,32 +189,31 @@ uint16 MadsSceneLogic::loadSpriteSet(uint16 suffixNum, uint16 sepChar) {
return _madsVm->scene()->loadSceneSpriteSet(resName);
}
-uint16 MadsSceneLogic::startReversibleSpriteSequence(uint16 srcSpriteIdx, int v0, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) {
- M4Sprite *spriteFrame = _madsVm->scene()->_spriteSlots.getSprite(srcSpriteIdx).getFrame(1);
+uint16 MadsSceneLogic::startReversibleSpriteSequence(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) {
+ M4Sprite *spriteFrame = _madsVm->scene()->_spriteSlots.getSprite(srcSpriteIdx).getFrame(0);
uint8 depth = _madsVm->_rails->getDepth(Common::Point(spriteFrame->x + (spriteFrame->width() / 2),
spriteFrame->y + (spriteFrame->height() / 2)));
- return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0,
- -1, 100, depth - 1, 1, ANIMTYPE_REVERSIBLE, 0, 0);
+ return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0,
+ true, 100, depth - 1, 1, ANIMTYPE_REVERSIBLE, 0, 0);
}
-uint16 MadsSceneLogic::startCycledSpriteSequence(uint16 srcSpriteIdx, int v0, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) {
- M4Sprite *spriteFrame = _madsVm->scene()->_spriteSlots.getSprite(srcSpriteIdx).getFrame(1);
-warning("%d %dx%d %d/%d", srcSpriteIdx, spriteFrame->x, spriteFrame->y, spriteFrame->width(), spriteFrame->height());
+uint16 MadsSceneLogic::startCycledSpriteSequence(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) {
+ M4Sprite *spriteFrame = _madsVm->scene()->_spriteSlots.getSprite(srcSpriteIdx).getFrame(0);
uint8 depth = _madsVm->_rails->getDepth(Common::Point(spriteFrame->x + (spriteFrame->width() / 2),
spriteFrame->y + (spriteFrame->height() / 2)));
- return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0,
- -1, 100, depth - 1, 1, ANIMTYPE_CYCLED, 0, 0);
+ return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0,
+ true, 100, depth - 1, 1, ANIMTYPE_CYCLED, 0, 0);
}
-uint16 MadsSceneLogic::startSpriteSequence3(uint16 srcSpriteIdx, int v0, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) {
- M4Sprite *spriteFrame = _madsVm->scene()->_spriteSlots.getSprite(srcSpriteIdx).getFrame(1);
+uint16 MadsSceneLogic::startSpriteSequence3(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) {
+ M4Sprite *spriteFrame = _madsVm->scene()->_spriteSlots.getSprite(srcSpriteIdx).getFrame(0);
uint8 depth = _madsVm->_rails->getDepth(Common::Point(spriteFrame->x + (spriteFrame->width() / 2),
spriteFrame->y + (spriteFrame->height() / 2)));
- return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0,
- -1, 100, depth - 1, -1, ANIMTYPE_CYCLED, 0, 0);
+ return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0,
+ true, 100, depth - 1, -1, ANIMTYPE_CYCLED, 0, 0);
}
void MadsSceneLogic::activateHotspot(int idx, bool active) {
@@ -147,6 +258,60 @@ void MadsSceneLogic::lowRoomsEntrySound() {
}
}
+void MadsSceneLogic::getPlayerSpritesPrefix() {
+ _madsVm->_sound->playSound(5);
+
+ char oldName[80];
+ strcpy(oldName, _madsVm->_player._spritesPrefix);
+
+ if ((_madsVm->globals()->_nextSceneId <= 103) || (_madsVm->globals()->_nextSceneId == 111))
+ strcpy(_madsVm->_player._spritesPrefix, (_madsVm->globals()->_globals[0] == SEX_FEMALE) ? "ROX" : "RXM");
+ else if (_madsVm->globals()->_nextSceneId <= 110)
+ strcpy(_madsVm->_player._spritesPrefix, "RXSM");
+ else if (_madsVm->globals()->_nextSceneId == 112)
+ strcpy(_madsVm->_player._spritesPrefix, "");
+
+ if (strcmp(oldName, _madsVm->_player._spritesPrefix) != 0)
+ _madsVm->_player._spritesChanged = true;
+
+ if ((_madsVm->globals()->_nextSceneId == 105) ||
+ ((_madsVm->globals()->_nextSceneId == 109) && (_madsVm->globals()->_globals[15] != 0))) {
+ // TODO: unknown flag setting
+ _madsVm->_player._spritesChanged = true;
+ }
+
+ _madsVm->_palette->setEntry(16, 40, 255, 255);
+ _madsVm->_palette->setEntry(17, 40, 180, 180);
+
+}
+
+void MadsSceneLogic::getPlayerSpritesPrefix2() {
+ _madsVm->_sound->playSound(5);
+
+ char oldName[80];
+ strcpy(oldName, _madsVm->_player._spritesPrefix);
+
+ if ((_madsVm->globals()->_nextSceneId == 213) || (_madsVm->globals()->_nextSceneId == 216))
+ strcpy(_madsVm->_player._spritesPrefix, "");
+ else if (_madsVm->globals()->_globals[0] == SEX_MALE)
+ strcpy(_madsVm->_player._spritesPrefix, "RXM");
+ else
+ strcpy(_madsVm->_player._spritesPrefix, "ROX");
+
+ // TODO: unknown flag setting for next scene Id > 212
+
+ if (strcmp(oldName, _madsVm->_player._spritesPrefix) != 0)
+ _madsVm->_player._spritesChanged = true;
+
+/* if ((_madsVm->globals()->_nextSceneId == 203) && (_madsVm->globals()->_nextSceneId == 204) &&
+ (_madsVm->globals()->_globals[0x22] == 0))
+ // TODO: unknown flag set
+*/
+ _madsVm->_palette->setEntry(16, 40, 255, 255);
+ _madsVm->_palette->setEntry(17, 40, 180, 180);
+}
+
+
/*--------------------------------------------------------------------------*/
/**
@@ -160,7 +325,7 @@ void MadsSceneLogic::selectScene(int sceneNum) {
assert(sceneNum == 101);
_sceneNumber = sceneNum;
-
+ Common::set_to(&_spriteIndexes[0], &_spriteIndexes[50], 0);
}
void MadsSceneLogic::setupScene() {
@@ -170,7 +335,11 @@ void MadsSceneLogic::setupScene() {
// sub_1e754(animName, 3);
- getSceneSpriteSet();
+ if ((_sceneNumber >= 101) && (_sceneNumber <= 112))
+ getPlayerSpritesPrefix();
+ else
+ getPlayerSpritesPrefix2();
+
getAnimName();
}
@@ -185,20 +354,18 @@ void MadsSceneLogic::enterScene() {
_spriteIndexes[12] = loadSpriteSet(8, 'x');
_spriteIndexes[13] = loadSpriteSet(0, 'x');
- _spriteIndexes[15] = startCycledSpriteSequence(_spriteIndexes[0], 0, 5, 0, 0, 25);
-
- _spriteIndexes[16] = startCycledSpriteSequence(_spriteIndexes[1], 0, 4, 0, 1, 0);
- _spriteIndexes[17] = startCycledSpriteSequence(_spriteIndexes[2], 0, 4, 0, 1, 0);
-
-// _madsVm->scene()->_sequenceList.addSubEntry(_spriteIndexes[17], SM_FRAME_INDEX, 7, 70);
+ _spriteIndexes[15] = startCycledSpriteSequence(_spriteIndexes[0], false, 5, 0, 0, 25);
+ _spriteIndexes[16] = startCycledSpriteSequence(_spriteIndexes[1], false, 4, 0, 1, 0);
+ _spriteIndexes[17] = startCycledSpriteSequence(_spriteIndexes[2], false, 4, 0, 1, 0);
- _spriteIndexes[18] = startReversibleSpriteSequence(_spriteIndexes[3], 0, 10, 0, 0, 60);
- _spriteIndexes[19] = startCycledSpriteSequence(_spriteIndexes[4], 0, 5, 0, 1, 0);
- _spriteIndexes[20] = startCycledSpriteSequence(_spriteIndexes[5], 0, 10, 0, 2, 0);
- _spriteIndexes[21] = startCycledSpriteSequence(_spriteIndexes[6], 0, 6, 0, 0, 0);
+ _madsVm->scene()->_sequenceList.addSubEntry(_spriteIndexes[17], SM_FRAME_INDEX, 7, 70);
- _spriteIndexes[23] = startCycledSpriteSequence(_spriteIndexes[8], 0, 6, 0, 10, 4);
- _spriteIndexes[24] = startCycledSpriteSequence(_spriteIndexes[9], 0, 6, 0, 32, 47);
+ _spriteIndexes[18] = startReversibleSpriteSequence(_spriteIndexes[3], false, 10, 0, 0, 60);
+ _spriteIndexes[19] = startCycledSpriteSequence(_spriteIndexes[4], false, 5, 0, 1, 0);
+ _spriteIndexes[20] = startCycledSpriteSequence(_spriteIndexes[5], false, 10, 0, 2, 0);
+ _spriteIndexes[21] = startCycledSpriteSequence(_spriteIndexes[6], false, 6, 0, 0, 0);
+ _spriteIndexes[23] = startCycledSpriteSequence(_spriteIndexes[8], false, 6, 0, 10, 4);
+ _spriteIndexes[24] = startCycledSpriteSequence(_spriteIndexes[9], false, 6, 0, 32, 47);
activateHotspot(0x137, false); // SHIELD MODULATOR
// shield_panel_opened = 0;
@@ -206,16 +373,119 @@ void MadsSceneLogic::enterScene() {
if (_madsVm->globals()->previousScene != -1)
_madsVm->globals()->_globals[10] = 0;
if (_madsVm->globals()->previousScene != -2) {
- //playerPos = (100, 152);
+ _madsVm->_player._playerPos = Common::Point(100, 152);
}
- // TODO: EXTRA STUFF
+ if ((_madsVm->globals()->previousScene == 112) ||
+ ((_madsVm->globals()->previousScene != -2) && (_spriteIndexes[29] != 0))) {
+ // Returning from probe cutscene?
+ _spriteIndexes[29] = -1;
+ _madsVm->_player._playerPos = Common::Point(161, 123);
+ _madsVm->_player._direction = 9;
+
+ // TODO: Extra flags setting
+ _spriteIndexes[25] = startCycledSpriteSequence(_spriteIndexes[10], false, 3, 0, 0, 0);
+ _madsVm->scene()->_sequenceList.setAnimRange(_spriteIndexes[25], 17, 17);
+ activateHotspot(0x47, false); // CHAIR
+ /*timer_unk1 = */_madsVm->scene()->_dynamicHotspots.add(0x47, 0x13F /*SIT_IN*/, -1,
+ Common::Rect(159, 84, 159+33, 84+36));
+
+ //if (_madsVm->globals()->previousScene == 112)
+ // room101Check();
+ } else {
+ _spriteIndexes[26] = startCycledSpriteSequence(_spriteIndexes[11], false, 6, 0, 0, 0);
+ _madsVm->scene()->_sequenceList.setDepth(_spriteIndexes[26], 4);
+ }
+
+ _madsVm->globals()->loadQuoteSet(0x31, 0x32, 0x37, 0x38, 0x39, -1);
+
+ if (_madsVm->globals()->_globals[10]) {
+ const char *animName = MADSResourceManager::getResourceName('S', 'e', EXTTYPE_AA, NULL, -1);
+ _madsVm->scene()->loadAnimation(animName, 71);
+ _madsVm->_player._playerPos = Common::Point(68, 140);
+ _madsVm->_player._direction = 4;
+ _madsVm->_player._visible = false;
+ _madsVm->_player._stepEnabled = false;
+
+ dataMap()[0x56FC] = 0;
+ dataMap()[0x5482] = 0;
+ dataMap()[0x5484] = 30;
+ }
+
+ _madsVm->globals()->_dataMap[0x5486] = 0;
lowRoomsEntrySound();
}
+void MadsSceneLogic::doPreactions() {
+ warning("Still to do preactions logic");
+}
+
void MadsSceneLogic::doAction() {
+ warning("Still to do actions logic");
+}
+
+void MadsSceneLogic::doSceneStep() {
+ // TODO: Sound handling
+
+ switch (_madsVm->scene()->_abortTimers) {
+ case 70:
+ _madsVm->_sound->playSound(9);
+ break;
+ case 71:
+ _madsVm->globals()->_globals[10] = 0;
+ _madsVm->_player._visible = true;
+ _madsVm->_player._stepEnabled = true;
+
+ _madsVm->_player._priorTimer = _madsVm->_currentTimer - _madsVm->_player._ticksAmount;
+ break;
+ case 72:
+ case 73:
+ // TODO: Method that should be scripted
+ break;
+
+ default:
+ break;
+ }
+
+ // Wake up message sequence
+ Animation *anim = _madsVm->scene()->activeAnimation();
+ if (anim) {
+ if ((anim->getCurrentFrame() == 6) && (dataMap()[0x5482] == 0)) {
+ dataMap()[0x5482]++;
+ _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]),
+ 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(49));
+ dataMap()[0x5484] += 14;
+ }
+ if ((anim->getCurrentFrame() == 7) && (dataMap()[0x5482] == 1)) {
+ dataMap()[0x5482]++;
+ _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]),
+ 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(54));
+ dataMap()[0x5484] += 14;
+ }
+
+ if ((anim->getCurrentFrame() == 10) && (dataMap()[0x5482] == 2)) {
+ dataMap()[0x5482]++;
+ _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]),
+ 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(55));
+ dataMap()[0x5484] += 14;
+ }
+
+ if ((anim->getCurrentFrame() == 17) && (dataMap()[0x5482] == 3)) {
+ dataMap()[0x5482]++;
+ _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]),
+ 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(56));
+ dataMap()[0x5484] += 14;
+ }
+
+ if ((anim->getCurrentFrame() == 20) && (dataMap()[0x5482] == 4)) {
+ dataMap()[0x5482]++;
+ _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]),
+ 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(50));
+ dataMap()[0x5484] += 14;
+ }
+ }
}
}
diff --git a/engines/m4/mads_logic.h b/engines/m4/mads_logic.h
index a589556a21..ec6eff368b 100644
--- a/engines/m4/mads_logic.h
+++ b/engines/m4/mads_logic.h
@@ -29,17 +29,21 @@
#ifndef M4_MADS_LOGIC_H
#define M4_MADS_LOGIC_H
+#include "m4/mads_views.h"
+
namespace M4 {
class MadsSceneLogic {
private:
// Library interface methods
uint16 loadSpriteSet(uint16 suffixNum, uint16 sepChar);
- uint16 startReversibleSpriteSequence(uint16 srcSpriteIdx, int v0, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks);
- uint16 startCycledSpriteSequence(uint16 srcSpriteIdx, int v0, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks);
- uint16 startSpriteSequence3(uint16 srcSpriteIdx, int v0, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks);
+ uint16 startReversibleSpriteSequence(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks);
+ uint16 startCycledSpriteSequence(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks);
+ uint16 startSpriteSequence3(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks);
void activateHotspot(int idx, bool active);
void lowRoomsEntrySound();
+ void getPlayerSpritesPrefix();
+ void getPlayerSpritesPrefix2();
private:
int _sceneNumber;
int16 _spriteIndexes[50];
@@ -48,12 +52,21 @@ private:
const char *formAnimName(char sepChar, int16 suffixNum);
void getSceneSpriteSet();
void getAnimName();
+
+ IntStorage &dataMap();
public:
void selectScene(int sceneNum);
void setupScene();
void enterScene();
+ void doPreactions();
void doAction();
+ void doSceneStep();
+};
+
+class MadsGameLogic {
+public:
+ static void initialiseGlobals();
};
}
diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp
index 64f18fa11d..1ee6b3d265 100644
--- a/engines/m4/mads_menus.cpp
+++ b/engines/m4/mads_menus.cpp
@@ -49,7 +49,7 @@ RexMainMenuView::RexMainMenuView(MadsM4Engine *vm):
_skipFlag = false;
// Load the background for the Rex Nebular game
- _bgSurface = new M4Surface(width(), MADS_SURFACE_HEIGHT);
+ _bgSurface = new M4Surface();
_bgSurface->loadBackground(REX_MENUSCREEN, &_bgPalData);
_vm->_palette->addRange(_bgPalData);
_bgSurface->translate(_bgPalData);
@@ -163,7 +163,7 @@ bool RexMainMenuView::onEvent(M4EventType eventType, int32 param, int x, int y,
if (_highlightedIndex != -1) {
M4Sprite *spr = _menuItem->getFrame(_highlightedIndex);
const Common::Point &pt = _menuItemPosList[_highlightedIndex];
- spr->copyTo(this, pt.x, row + pt.y, 0);
+ spr->copyTo(this, pt.x, row + pt.y, spr->getTransparencyIndex());
}
}
} else {
@@ -211,10 +211,12 @@ void RexMainMenuView::updateState() {
M4Sprite *spr = _menuItem->getFrame(0);
itemSize = _menuItem->getFrame(0)->height();
spr->copyTo(this, _menuItemPosList[_menuItemIndex - 1].x,
- _menuItemPosList[_menuItemIndex - 1].y + row + (itemSize / 2) - (spr->height() / 2), 0);
+ _menuItemPosList[_menuItemIndex - 1].y + row + (itemSize / 2) - (spr->height() / 2),
+ spr->getTransparencyIndex());
delete _menuItem;
- copyTo(_bgSurface, Common::Rect(0, row, width(), row + MADS_SURFACE_HEIGHT), 0, 0);
+ copyTo(_bgSurface, Common::Rect(0, row, width(), row + MADS_SURFACE_HEIGHT), 0, 0,
+ spr->getTransparencyIndex());
}
// Get the next sprite set
@@ -275,7 +277,7 @@ void RexMainMenuView::updateState() {
_bgSurface->copyTo(this, 0, row);
M4Sprite *spr = _menuItem->getFrame(_frameIndex);
spr->copyTo(this, _menuItemPosList[_menuItemIndex - 1].x, _menuItemPosList[_menuItemIndex - 1].y +
- row + (itemSize / 2) - (spr->height() / 2), 0);
+ row + (itemSize / 2) - (spr->height() / 2), spr->getTransparencyIndex());
}
int RexMainMenuView::getHighlightedItem(int x, int y) {
@@ -293,7 +295,7 @@ int RexMainMenuView::getHighlightedItem(int x, int y) {
}
void RexMainMenuView::handleAction(MadsGameAction action) {
- MadsM4Engine *vm = _vm;
+ MadsEngine *vm = (MadsEngine *)_vm;
vm->_mouse->cursorOff();
vm->_viewManager->deleteView(this);
@@ -303,8 +305,7 @@ void RexMainMenuView::handleAction(MadsGameAction action) {
// Load a sample starting scene - note that, currently, calling loadScene automatically
// removes this menu screen from being displayed
vm->_mouse->cursorOn();
- vm->_scene->show();
- vm->_scene->loadScene(101);
+ vm->startScene(101);
return;
case SHOW_INTRO:
@@ -325,7 +326,7 @@ void RexMainMenuView::handleAction(MadsGameAction action) {
// Activate the scene display with the specified scene
bool altAdvert = vm->_random->getRandomNumber(1000) >= 500;
- vm->_scene->loadScene(altAdvert ? 995 : 996);
+ vm->startScene(altAdvert ? 995 : 996);
vm->_viewManager->addView(vm->_scene);
vm->_viewManager->refreshAll();
@@ -532,7 +533,7 @@ void DragonMainMenuView::updateState() {
_itemPalData.push_back(palData);
spr = _menuItem->getFrame(1);
- spr->copyTo(this, spr->xOffset - 140, spr->yOffset - spr->height(), (int)spr->getTransparentColor());
+ spr->copyTo(this, spr->xOffset - 140, spr->yOffset - spr->height(), spr->getTransparencyIndex());
_vm->_mouse->cursorOn();
}
@@ -808,7 +809,7 @@ void RexDialogView::setFrame(int frameNumber, int depth) {
}
void RexDialogView::initVars() {
- _word_8502C = -1;
+ _v8502C = -1;
_selectedLine = -1;
_lineIndex = 0;
_enterFlag = false;
diff --git a/engines/m4/mads_menus.h b/engines/m4/mads_menus.h
index e964c5866d..a0fc6fb3bc 100644
--- a/engines/m4/mads_menus.h
+++ b/engines/m4/mads_menus.h
@@ -136,7 +136,7 @@ protected:
int _dialogSelectedLine;
Common::StringArray _saveList;
- int _word_8502C;
+ int _v8502C;
int _selectedLine;
int _lineIndex;
bool _enterFlag;
diff --git a/engines/m4/mads_player.cpp b/engines/m4/mads_player.cpp
new file mode 100644
index 0000000000..de09e97640
--- /dev/null
+++ b/engines/m4/mads_player.cpp
@@ -0,0 +1,792 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "m4/m4.h"
+#include "m4/mads_player.h"
+#include "m4/mads_scene.h"
+
+namespace M4 {
+
+const int MadsPlayer::_directionListIndexes[32] = {
+ 0, 7, 4, 3, 6, 0, 2, 5, 0, 1, 9, 4, 1, 2, 7, 9, 3, 8, 9, 6, 7, 2, 3, 6, 1, 7, 9, 4, 7, 8, 0, 0
+};
+
+MadsPlayer::MadsPlayer() {
+ _playerPos = Common::Point(160, 78);
+ _ticksAmount = 3;
+ _forceRefresh = true;
+ _stepEnabled = true;
+ _visible = true;
+ _yScale = 0;
+ _moving = false;
+
+ _spriteListStart = 0;
+ //TODO:unknown vars
+ _special = 0;
+ _next = 0;
+ _unk4 = false;
+
+ _spritesChanged = true;
+
+ _direction = 0;
+ _newDirection = 0;
+ _priorTimer = 0;
+ _priorVisible = false;
+ _visible3 = false;
+ _spriteListIdx = 0;
+ _currentScale = 0;
+ strcpy(_spritesPrefix, "");
+ for (int idx = 0; idx < 8; ++idx)
+ _spriteSetsPresent[idx] = false;
+ _frameNum = 0;
+ _frameOffset = 0;
+ _unk1 = 0;
+ _frameCount = 0;
+ _frameListIndex = 0;
+ _actionIndex = 0;
+ _routeCount = 0;
+
+ resetActionList();
+}
+
+/**
+ * Loads the sprite set for the player
+ */
+bool MadsPlayer::loadSprites(const char *prefix) {
+ const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' };
+ char setName[80];
+ bool result = true;
+
+ if (prefix)
+ strcpy(_spritesPrefix, prefix);
+
+ _spriteSetCount = 0;
+ int prefixLen = strlen(_spritesPrefix);
+
+ if (prefixLen == 0) {
+ // No player sprites at at all
+ for (int idx = 0; idx < 8; ++idx)
+ _spriteSetsPresent[idx] = false;
+ } else {
+ strcpy(setName, "*");
+ strcat(setName, _spritesPrefix);
+ strcat(setName, "_0.SS");
+
+ char *digitP = strchr(setName, '_') + 1;
+
+ for (int idx = 0; idx < 8; ++idx) {
+ *digitP = suffixList[idx];
+ _spriteSetsPresent[idx] = true;
+
+ int setIndex = _madsVm->scene()->_spriteSlots.addSprites(setName, true, SPRITE_SET_CHAR_INFO);
+ if (setIndex < 0) {
+ if (idx < 5)
+ break;
+ _spriteSetsPresent[idx] = false;
+ } else {
+ ++_spriteSetCount;
+ }
+
+ if (idx == 0)
+ _spriteListStart = setIndex;
+ }
+
+ result = 0;
+ // TODO: Unknown flag
+ _spritesChanged = false;
+ }
+
+ return result;
+}
+
+/**
+ * Called each frame to update the display of the player
+ */
+void MadsPlayer::update() {
+ if (_forceRefresh || (_visible != _priorVisible)) {
+ // If there's an existing player sprite visible, flag it for expiry
+ int slotIndex = getSpriteSlot();
+ if (slotIndex >= 0)
+ _madsVm->scene()->_spriteSlots[slotIndex].spriteType = EXPIRED_SPRITE;
+
+ // Figure out the depth for the sprite
+ int newDepth = 1;
+ int yp = MIN(_playerPos.y, (int16)155);
+
+ for (int idx = 1; idx < 15; ++idx) {
+ if (_madsVm->scene()->getSceneResources()._depthBands[newDepth] >= yp)
+ newDepth = idx + 1;
+ }
+ _currentDepth = newDepth;
+
+ // Get the scale
+ int newScale = getScale(_playerPos.y);
+ _currentScale = MIN(newScale, 100);
+
+ if (_visible) {
+ // Player sprite needs to be rendered
+ MadsSpriteSlot slot;
+ slot.spriteType = FOREGROUND_SPRITE;
+ slot.seqIndex = PLAYER_SEQ_INDEX;
+ slot.spriteListIndex = _spriteListStart + _spriteListIdx;
+ slot.frameNumber = _frameOffset + _frameNum;
+ slot.xp = _playerPos.x;
+ slot.yp = _playerPos.y + (_yScale * newScale) / 100;
+ slot.depth = newDepth;
+ slot.scale = newScale;
+
+ if (slotIndex >= 0) {
+ // Check if the existing player slot has the same details, and can be re-used
+ MadsSpriteSlot &s2 = _madsVm->scene()->_spriteSlots[slotIndex];
+ bool equal = (s2.seqIndex == slot.seqIndex) && (s2.spriteListIndex == slot.spriteListIndex)
+ && (s2.frameNumber == slot.frameNumber) && (s2.xp == slot.xp) && (s2.yp == slot.yp)
+ && (s2.depth == slot.depth) && (s2.scale == slot.scale);
+
+ if (equal)
+ // Undo the prior expiry of the player sprite
+ s2.spriteType = SPRITE_ZERO;
+ else
+ slotIndex = -1;
+ }
+
+ if (slotIndex < 0) {
+ // New slot needed, so allocate one and copy the slot data
+ slotIndex = _madsVm->scene()->_spriteSlots.getIndex();
+ _madsVm->scene()->_spriteSlots[slotIndex] = slot;
+ }
+
+ // TODO: Meaning of _v844c0 block
+
+ }
+ }
+
+ _visible3 = _priorVisible = _visible;
+ _forceRefresh = false;
+}
+
+/**
+ * Updates the animation frame for the player
+ */
+void MadsPlayer::updateFrame() {
+ SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx);
+ assert(spriteSet._charInfo);
+
+ if (!spriteSet._charInfo->_numEntries) {
+ _frameNum = 1;
+ } else {
+ _frameListIndex = _actionList[_actionIndex];
+
+ if (!_visible) {
+ _unk2 = 0;
+ } else {
+ _unk2 = _actionList2[_actionIndex];
+
+ if (_actionIndex > 0)
+ --_actionIndex;
+ }
+
+ // Set the player frame number
+ int frameIndex = ABS(_frameListIndex);
+ _frameNum = (_frameListIndex <= 0) ? spriteSet._charInfo->_frameList[frameIndex] :
+ spriteSet._charInfo->_frameList2[frameIndex];
+
+ // Set next waiting period in ticks
+ if (frameIndex == 0)
+ setTicksAmount();
+ else
+ _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksList[frameIndex];
+ }
+}
+
+void MadsPlayer::setupFrame() {
+ resetActionList();
+ _frameOffset = 0;
+ _spriteListIdx = _directionListIndexes[_direction];
+ if (!_spriteSetsPresent[_spriteListIdx]) {
+ // Direction isn't present, so use alternate direction, with entries flipped
+ _spriteListIdx -= 4;
+ _frameOffset = 0x8000;
+ }
+
+ SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx);
+ assert(spriteSet._charInfo);
+ _unk1 = MAX(spriteSet._charInfo->_unk1, 100);
+ setTicksAmount();
+
+ _frameCount = spriteSet._charInfo->_totalFrames;
+ if (_frameCount == 0)
+ _frameCount = spriteSet.getCount();
+
+ _yScale = spriteSet._charInfo->_yScale;
+
+ if ((_frameNum <= 0) || (_frameNum > _frameCount))
+ _frameNum = 1;
+ _forceRefresh = true;
+}
+
+void MadsPlayer::step() {
+ if (_visible && _stepEnabled && !_moving && (_direction == _newDirection) && (_madsVm->_currentTimer >= GET_GLOBAL32(2))) {
+ if (_actionIndex == 0) {
+ int randVal = _vm->_random->getRandomNumber(29999);
+
+ if (GET_GLOBAL(0) == SEX_MALE) {
+ switch (_direction) {
+ case 1:
+ case 3:
+ case 7:
+ case 9:
+ if (randVal < 200) {
+ queueAction(-1, 0);
+ queueAction(1, 0);
+ }
+ break;
+
+ case 2:
+ if (randVal < 500) {
+ for (int i = 0; i < 10; ++i)
+ queueAction((randVal < 250) ? 1 : 2, 0);
+ } else if (randVal < 750) {
+ for (int i = 0; i < 5; ++i)
+ queueAction(1, 0);
+ queueAction(0, 0);
+ for (int i = 0; i < 5; ++i)
+ queueAction(2, 0);
+ }
+ break;
+
+ case 4:
+ case 6:
+ if (randVal < 500) {
+ for (int i = 0; i < 10; ++i)
+ queueAction(1, 0);
+ }
+ break;
+
+ case 5:
+ case 8:
+ if (randVal < 200) {
+ queueAction(-1, 0);
+ queueAction(1, 0);
+ }
+ break;
+ }
+ }
+ }
+
+ SET_GLOBAL32(2, GET_GLOBAL32(2) + 6);
+ }
+
+ if (GET_GLOBAL(138) == 1) {
+ uint32 diff = _madsVm->_currentTimer - GET_GLOBAL32(142);
+ if (diff > 60) {
+ SET_GLOBAL32(144, GET_GLOBAL32(144) + 1);
+ } else {
+ SET_GLOBAL32(144, GET_GLOBAL32(144) + diff);
+ }
+
+ SET_GLOBAL32(142, _madsVm->_currentTimer);
+ }
+}
+
+void MadsPlayer::nextFrame() {
+ if (_madsVm->_currentTimer >= (_priorTimer + _ticksAmount)) {
+ _priorTimer = _madsVm->_currentTimer;
+
+ if (_moving)
+ move();
+ else
+ idle();
+
+ // Post update logic
+ if (_moving) {
+ ++_frameNum;
+ if (_frameNum > _frameCount)
+ _frameNum = 1;
+ _forceRefresh = true;
+ } else if (!_forceRefresh) {
+ idle();
+ }
+
+ // Final update
+ update();
+ }
+}
+
+void MadsPlayer::setDest(int destX, int destY, int facing) {
+ resetActionList();
+ setTicksAmount();
+ _moving = true;
+ _destFacing = facing;
+
+ _madsVm->scene()->getSceneResources().setRouteNode(_madsVm->scene()->getSceneResources()._nodes.size() - 2,
+ _playerPos, _madsVm->scene()->_depthSurface);
+ _madsVm->scene()->getSceneResources().setRouteNode(_madsVm->scene()->getSceneResources()._nodes.size() - 1,
+ Common::Point(destX, destY), _madsVm->scene()->_depthSurface);
+
+ bool v = _madsVm->scene()->getDepthHighBit(Common::Point(destX, destY));
+ setupRoute(v);
+ _next = 0;
+
+ if (_routeCount > 0) {
+ Common::Point srcPos = _playerPos;
+ for (int routeCtr = _routeCount - 1; (routeCtr >= 0) && (_next == 0); --routeCtr) {
+ int idx = _routeIndexes[routeCtr];
+ const Common::Point &pt = _madsVm->scene()->getSceneResources()._nodes[idx].pt;
+
+ _next = scanPath(_madsVm->scene()->_depthSurface, srcPos, pt);
+ srcPos = pt;
+ }
+ }
+}
+
+
+int MadsPlayer::getScale(int yp) {
+ MadsSceneResources &r = _madsVm->scene()->getSceneResources();
+
+ int scale = (r.bandsRange() == 0) ? r._maxScale : (yp - r._yBandsStart) * r.scaleRange() / r.bandsRange()
+ + r._minScale;
+
+ return MIN(scale, 100);
+}
+
+/**
+ * Scans through the scene's sprite slot list to find any sprite displaying the player
+ */
+int MadsPlayer::getSpriteSlot() {
+ MadsSpriteSlots &slots = _madsVm->scene()->_spriteSlots;
+ for (int i = 0; i < slots.startIndex; ++i) {
+ if ((slots[i].seqIndex == PLAYER_SEQ_INDEX) && (slots[i].spriteType >= SPRITE_ZERO))
+ return i;
+ }
+ return -1;
+}
+
+void MadsPlayer::setTicksAmount() {
+ SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx);
+ assert(spriteSet._charInfo);
+ _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksAmount;
+ if (_madsVm->_player._ticksAmount == 0)
+ _madsVm->_player._ticksAmount = 6;
+}
+
+void MadsPlayer::resetActionList() {
+ _actionList[0] = 0;
+ _actionList2[0] = 0;
+ _actionIndex = 0;
+ _unk2 = 0;
+ _unk3 = 0;
+}
+
+int MadsPlayer::queueAction(int action1, int action2) {
+ SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx);
+ assert(spriteSet._charInfo);
+
+ if ((action1 < spriteSet._charInfo->_numEntries) && (_actionIndex < 11)) {
+ ++_actionIndex;
+ _actionList[_actionIndex] = action1;
+ _actionList2[_actionIndex] = action2;
+ return false;
+ }
+
+ return true;
+}
+
+void MadsPlayer::idle() {
+ if (_direction != _newDirection) {
+ // The direction has changed, so reset for new direction
+ dirChanged();
+ return;
+ }
+
+ SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx);
+ assert(spriteSet._charInfo);
+ if (spriteSet._charInfo->_numEntries == 0)
+ // No entries, so exit immediately
+ return;
+
+ int frameIndex = ABS(_frameListIndex);
+ int direction = (_frameListIndex < 0) ? -1 : 1;
+
+ if (frameIndex >= spriteSet._charInfo->_numEntries)
+ // Reset back to the start of the list
+ _frameListIndex = 0;
+ else {
+ _frameNum += direction;
+ _forceRefresh = true;
+
+ if (spriteSet._charInfo->_frameList2[frameIndex] < _frameNum) {
+ _unk3 = _unk2;
+ updateFrame();
+ }
+ if (spriteSet._charInfo->_frameList[frameIndex] < _frameNum) {
+ _unk3 = _unk2;
+ updateFrame();
+ }
+ }
+}
+
+void MadsPlayer::move() {
+ bool routeFlag = false;
+
+ if (_moving) {
+ int idx = _routeCount;
+ while (!_v844C0 && (_destPos.x == _playerPos.x) && (_destPos.y == _playerPos.y)) {
+ if (idx != 0) {
+ --idx;
+ SceneNode &node = _madsVm->scene()->getSceneResources()._nodes[_routeIndexes[idx]];
+ _destPos = node.pt;
+ routeFlag = true;
+ } else if (_v844BE == idx) {
+ // End of walking path
+ _routeCount = 0;
+ _moving = false;
+ turnToDestFacing();
+ routeFlag = true;
+ idx = _routeCount;
+ } else {
+ _v844C0 = _v844BE;
+ _v844BC = true;
+ _v844BE = 0;
+ _stepEnabled = true;
+ routeFlag = false;
+ }
+
+ if (!_moving)
+ break;
+ }
+ _routeCount = idx;
+ }
+
+ if (routeFlag && _moving)
+ startMovement();
+
+ if (_newDirection != _direction)
+ dirChanged();
+ else if (!_moving)
+ updateFrame();
+
+ int var1 = _unk1;
+ if (_unk4 && (_hypotenuse > 0)) {
+ int v1 = -(_currentScale - 100) * (_posDiff.x - 1) / _hypotenuse + _currentScale;
+ var1 = MAX(1, 10000 / (v1 * _currentScale * var1));
+ }
+
+ if (!_moving || (_direction != _newDirection))
+ return;
+
+ Common::Point newPos = _playerPos;
+
+ if (_v8452E < var1) {
+ do {
+ if (_v8452C < _posDiff.x)
+ _v8452C += _posDiff.y;
+ if (_v8452C >= _posDiff.x) {
+ if ((_posChange.y > 0) || (_v844C0 != 0))
+ newPos.y += _yDirection;
+ --_posChange.y;
+ _v8452C -= _posDiff.x;
+ }
+
+ if (_v8452C < _posDiff.x) {
+ if ((_posChange.x > 0) || (_v844C0 != 0))
+ newPos.x += _xDirection;
+ --_posChange.x;
+ }
+
+ if ((_v844BC == 0) && (_v844C0 == 0) && (_v844BE == 0)) {
+ routeFlag = _madsVm->scene()->getDepthHighBit(newPos);
+
+ if (_special == 0)
+ _special = _madsVm->scene()->getDepthHighBits(newPos);
+ }
+
+ _v8452E += _v84530;
+
+ } while ((_v8452E < var1) && !routeFlag && ((_posChange.x > 0) || (_posChange.y > 0) || (_v844C0 != 0)));
+ }
+
+ _v8452E -= var1;
+
+ if (routeFlag)
+ moveComplete();
+ else {
+ if (!_v844C0) {
+ // If the move is complete, make sure the position is exactly on the given destination
+ if (_posChange.x == 0)
+ newPos.x = _destPos.x;
+ if (_posChange.y == 0)
+ newPos.y = _destPos.y;
+ }
+
+ _playerPos = newPos;
+ }
+}
+
+void MadsPlayer::dirChanged() {
+ int dirIndex = 0, dirIndex2 = 0;
+ int newDir = 0, newDir2 = 0;
+
+ if (_direction != _newDirection) {
+ // Find the index for the given direction in the player direction list
+ int tempDir = _direction;
+ do {
+ ++dirIndex;
+ newDir += tempDir;
+ tempDir = _directionListIndexes[tempDir + 10];
+ } while (tempDir != _newDirection);
+ }
+
+
+ if (_direction != _newDirection) {
+ // Find the index for the given direction in the player direction list
+ int tempDir = _direction;
+ do {
+ ++dirIndex2;
+ newDir2 += tempDir;
+ tempDir = _directionListIndexes[tempDir + 20];
+ } while (tempDir != _newDirection);
+ }
+
+ int diff = dirIndex - dirIndex2;
+ if (diff == 0)
+ diff = newDir - newDir2;
+
+ _direction = (diff >= 0) ? _directionListIndexes[_direction + 20] : _directionListIndexes[_direction + 10];
+ setupFrame();
+ if ((_direction == _newDirection) && !_moving)
+ updateFrame();
+
+ _priorTimer += 1;
+}
+
+void MadsPlayer::moveComplete() {
+ reset();
+ //todo: Unknown flag
+}
+
+void MadsPlayer::reset() {
+ _destPos = _playerPos;
+ _destFacing = 5;
+ _newDirection = _direction;
+
+ _madsVm->scene()->_action._startWalkFlag = false;
+ _madsVm->scene()->_action._walkFlag = false;
+ _moving = false;
+ _v844BC = false;
+ _v844C0 = false;
+ _v844BE = 0;
+ _next = 0;
+ _routeCount = 0;
+}
+
+/**
+ * Scans along an edge connecting two points within the depths/walk surface, and returns the information of the first
+ * pixel high nibble encountered with a non-zero value
+ */
+int MadsPlayer::scanPath(M4Surface *depthSurface, const Common::Point &srcPos, const Common::Point &destPos) {
+ // For compressed depth surfaces, always return 0
+ if (_madsVm->scene()->getSceneResources()._depthStyle != 2)
+ return 0;
+
+ int yDiff = destPos.y - srcPos.y;
+ int yAmount = MADS_SURFACE_WIDTH;
+
+ if (yDiff < 0) {
+ yDiff = -yDiff;
+ yAmount = -yAmount;
+ }
+
+ int xDiff = destPos.x - srcPos.y;
+ int xDirection = 1;
+ int xAmount = 0;
+ if (xDiff < 0) {
+ xDiff = -xDiff;
+ xDirection = -xDirection;
+ xAmount = MIN(yDiff, xDiff);
+ }
+
+ ++xDiff;
+ ++yDiff;
+
+ const byte *srcP = depthSurface->getBasePtr(srcPos.x, srcPos.y);
+ int index = xAmount;
+
+ // Outer horizontal movement loop
+ for (int yIndex = 0; yIndex < yDiff; ++yIndex) {
+ index += yDiff;
+ int v = (*srcP & 0x7F) >> 4;
+ if (v)
+ return v;
+
+ // Inner loop for handling vertical movement
+ while (index >= xDiff) {
+ index -= xDiff;
+
+ v = (*srcP & 0x7F) >> 4;
+ if (v)
+ return v;
+
+ srcP += yAmount;
+ }
+
+ srcP += xDirection;
+ }
+
+ return 0;
+}
+
+/**
+ * Starts a player moving to a given destination
+ */
+void MadsPlayer::startMovement() {
+ int xDiff = _destPos.x - _playerPos.x;
+ int yDiff = _destPos.y - _playerPos.y;
+ int srcScale = getScale(_playerPos.y);
+ int destScale = getScale(_destPos.y);
+
+ // Sets the X direction
+ if (xDiff > 0)
+ _xDirection = 1;
+ else if (xDiff < 0)
+ _xDirection = -1;
+ else
+ _xDirection = 0;
+
+ // Sets the Y direction
+ if (yDiff > 0)
+ _yDirection = 1;
+ else if (yDiff < 0)
+ _yDirection = -1;
+ else
+ _yDirection = 0;
+
+ xDiff = ABS(xDiff);
+ yDiff = ABS(yDiff);
+ int scaleDiff = ABS(srcScale - destScale);
+
+ int xAmt100 = xDiff * 100;
+ int yAmt100 = yDiff * 100;
+ int xAmt33 = xDiff * 33;
+
+ int scaleAmount = (_unk4 ? scaleDiff * 3 : 0) + 100 * yDiff / 100;
+ int scaleAmount100 = scaleAmount * 100;
+
+ // Figure out direction that will need to be moved in
+ int majorDir;
+ if (xDiff == 0)
+ majorDir = 1;
+ else if (yDiff == 0)
+ majorDir = 3;
+ else {
+ if ((scaleAmount < xDiff) && ((xAmt33 / scaleAmount) >= 141))
+ majorDir = 3;
+ else if (yDiff <= xDiff)
+ majorDir = 2;
+ else if ((scaleAmount100 / xDiff) >= 141)
+ majorDir = 1;
+ else
+ majorDir = 2;
+ }
+
+ switch (majorDir) {
+ case 1:
+ _newDirection = (_yDirection <= 0) ? 8 : 2;
+ break;
+ case 2: {
+ _newDirection = ((_yDirection <= 0) ? 9 : 3) - ((_xDirection <= 0) ? 2 : 0);
+ break;
+ }
+ case 3:
+ _newDirection = (_xDirection <= 0) ? 4 : 6;
+ break;
+ default:
+ break;
+ }
+
+ _hypotenuse = SqrtF16(xAmt100 * xAmt100 + yAmt100 * yAmt100);
+ _posDiff.x = xDiff + 1;
+ _posDiff.y = yDiff + 1;
+ _posChange.x = xDiff;
+ _posChange.y = yDiff;
+
+ int majorChange = MAX(xDiff, yDiff);
+ _v84530 = (majorChange == 0) ? 0 : _hypotenuse / majorChange;
+
+ if (_playerPos.x > _destPos.x)
+ _v8452C = MAX(_posChange.x, _posChange.y);
+ else
+ _v8452C = 0;
+
+ _hypotenuse /= 100;
+ _v8452E = -_v84530;
+}
+
+void MadsPlayer::turnToDestFacing() {
+ if (_destFacing != 5)
+ _newDirection = _destFacing;
+}
+
+void MadsPlayer::setupRoute(bool bitFlag) {
+ // Reset the flag set of nodes in use
+ SceneNodeList &nodes = _madsVm->scene()->getSceneResources()._nodes;
+ for (uint i = 0; i < nodes.size(); ++i)
+ nodes[i].active = false;
+
+ // Start constructing route node list
+ _routeLength = 0x3FFF;
+ _routeCount = 0;
+
+ setupRouteNode(_tempRoute, nodes.size() - 1, bitFlag ? 0xC000 : 0x8000, 0);
+}
+
+void MadsPlayer::setupRouteNode(int *routeIndexP, int nodeIndex, int flags, int routeLength) {
+ SceneNodeList &nodes = _madsVm->scene()->getSceneResources()._nodes;
+ SceneNode &currentNode = nodes[nodeIndex];
+ currentNode.active = true;
+
+ *routeIndexP++ = nodeIndex;
+
+ int subIndex = nodes.size() - 2;
+ int indexVal = nodes[nodeIndex].indexes[subIndex];
+ if (indexVal & flags) {
+ routeLength += indexVal & 0x3FFF;
+ if (routeLength < _routeLength) {
+ // Found a new shorter route to destination, so set up the route with the found one
+ Common::copy(_tempRoute, routeIndexP, _routeIndexes);
+ _routeCount = routeIndexP - _tempRoute;
+ _routeLength = indexVal & 0x3FFF;
+ }
+ } else {
+ for (int idx = nodes.size() - 2; idx > 0; --idx) {
+ int nodePos = idx - 1;
+ if (!nodes[nodePos].active && ((currentNode.indexes[nodePos] & flags) != 0))
+ setupRouteNode(routeIndexP, nodePos, 0x8000, indexVal & 0x3fff);
+ }
+ }
+
+ currentNode.active = false;
+}
+
+} // End of namespace M4
diff --git a/engines/m4/mads_player.h b/engines/m4/mads_player.h
new file mode 100644
index 0000000000..6a9b7b4ca1
--- /dev/null
+++ b/engines/m4/mads_player.h
@@ -0,0 +1,116 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef M4_MADS_PLAYER_H
+#define M4_MADS_PLAYER_H
+
+#include "common/scummsys.h"
+#include "m4/mads_scene.h"
+
+namespace M4 {
+
+#define PLAYER_SEQ_INDEX -2
+
+class MadsPlayer {
+private:
+ int getScale(int yp);
+ int getSpriteSlot();
+ void setTicksAmount();
+ void resetActionList();
+ int queueAction(int v0, int v1);
+ void idle();
+ void move();
+ void dirChanged();
+ void reset();
+ int scanPath(M4Surface *depthSurface, const Common::Point &srcPos, const Common::Point &destPos);
+ void startMovement();
+ void setupRouteNode(int *routeIndexP, int nodeIndex, int flags, int routeLength);
+public:
+ char _spritesPrefix[16];
+ int _spriteSetCount;
+ bool _spriteSetsPresent[8];
+ Common::Point _playerPos;
+ Common::Point _destPos;
+ Common::Point _posChange;
+ Common::Point _posDiff;
+ int _hypotenuse;
+ uint32 _priorTimer;
+ uint _ticksAmount;
+ int16 _direction, _newDirection;
+ bool _stepEnabled;
+ bool _visible, _priorVisible;
+ bool _visible3;
+ bool _forceRefresh;
+ int16 _currentScale;
+ int16 _yScale;
+ int16 _currentDepth;
+ int16 _spriteListStart, _spriteListIdx;
+ bool _spritesChanged;
+ uint16 _frameOffset, _frameNum;
+ bool _moving;
+ int _unk1;
+ int _frameCount;
+ int _frameListIndex;
+ int _actionIndex;
+ int _actionList[12];
+ int _actionList2[12];
+ int _unk2;
+ int _unk3;
+ int _xDirection, _yDirection;
+ int _destFacing;
+ int _special;
+ int _next;
+ int _routeCount;
+ int _routeOffset;
+ int _tempRoute[MAX_ROUTE_NODES];
+ int _routeIndexes[MAX_ROUTE_NODES];
+ bool _unk4;
+ bool _v844BC;
+ int _v844BE;
+ bool _v844C0;
+ int _v8452E;
+ int _v8452C;
+ int _v84530;
+ int _routeLength;
+
+ static const int _directionListIndexes[32];
+public:
+ MadsPlayer();
+
+ bool loadSprites(const char *prefix);
+ void update();
+ void updateFrame();
+ void setupFrame();
+ void step();
+ void nextFrame();
+ void setDest(int destX, int destY, int facing);
+ void turnToDestFacing();
+ void setupRoute(bool bitFlag);
+ void moveComplete();
+};
+
+} // End of namespace M4
+
+#endif
diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp
index 8073db32db..d44fa2a753 100644
--- a/engines/m4/mads_scene.cpp
+++ b/engines/m4/mads_scene.cpp
@@ -37,18 +37,42 @@
#include "m4/mads_views.h"
#include "m4/compression.h"
#include "m4/staticres.h"
+#include "m4/animation.h"
namespace M4 {
+static const int INV_ANIM_FRAME_SPEED = 2;
+static const int INVENTORY_X = 160;
+static const int INVENTORY_Y = 159;
+static const int SCROLLER_DELAY = 200;
+
+//--------------------------------------------------------------------------
+
+void SceneNode::load(Common::SeekableReadStream *stream) {
+ // Get the next data block
+ pt.x = stream->readUint16LE();
+ pt.y = stream->readUint16LE();
+
+ for (int i = 0; i < MAX_ROUTE_NODES; ++i)
+ indexes[i] = stream->readUint16LE();
+}
+
+//--------------------------------------------------------------------------
+
MadsScene::MadsScene(MadsEngine *vm): _sceneResources(), Scene(vm, &_sceneResources), MadsView(this) {
_vm = vm;
+ _activeAnimation = NULL;
+ MadsView::_bgSurface = Scene::_backgroundSurface;
+ MadsView::_depthSurface = Scene::_walkSurface;
_interfaceSurface = new MadsInterfaceView(vm);
- for (int i = 0; i < 3; ++i)
- actionNouns[i] = 0;
+ _showMousePos = false;
+ _mouseMsgIndex = -1;
}
MadsScene::~MadsScene() {
+ delete _activeAnimation;
+ _activeAnimation = NULL;
leaveScene();
_vm->_viewManager->deleteView(_interfaceSurface);
}
@@ -56,8 +80,10 @@ MadsScene::~MadsScene() {
/**
* Secondary scene loading code
*/
-void MadsScene::loadScene2(const char *aaName) {
+void MadsScene::loadScene2(const char *aaName, int sceneNumber) {
// TODO: Completely finish
+ _madsVm->globals()->previousScene = _madsVm->globals()->sceneNumber;
+ _madsVm->globals()->sceneNumber = sceneNumber;
_spriteSlots.clear();
_sequenceList.clear();
@@ -68,6 +94,13 @@ void MadsScene::loadScene2(const char *aaName) {
// Load scene walk paths
loadSceneCodes(_currentScene);
+
+ // Initialise the scene animation
+ uint16 flags = 0x4100;
+ if (_madsVm->globals()->_config.textWindowStill)
+ flags |= 0x200;
+
+ _sceneAnimation->initialise(aaName, flags, _interfaceSurface, NULL);
}
/**
@@ -76,27 +109,12 @@ void MadsScene::loadScene2(const char *aaName) {
void MadsScene::loadSceneTemporary() {
/* Existing code that eventually needs to be replaced with the proper MADS code */
// Set system palette entries
- _vm->_palette->blockRange(0, 7);
+ _vm->_palette->blockRange(0, 18);
RGB8 sysColors[3] = { {0x1f<<2, 0x2d<<2, 0x31<<2, 0}, {0x24<<2, 0x37<<2, 0x3a<<2, 0},
{0x00<<2, 0x10<<2, 0x16<<2, 0}};
_vm->_palette->setPalette(&sysColors[0], 4, 3);
- _backgroundSurface->loadBackground(_currentScene, &_palData);
- _vm->_palette->addRange(_palData);
- _backgroundSurface->translate(_palData);
-
- if (_currentScene < 900) {
- _interfaceSurface->madsloadInterface(0, &_interfacePal);
- _vm->_palette->addRange(_interfacePal);
- _interfaceSurface->translate(_interfacePal);
- _backgroundSurface->copyFrom(_interfaceSurface, Common::Rect(0, 0, 320, 44), 0, 200 - 44);
-
- _interfaceSurface->initialise();
- }
-
- // Don't load other screen resources for system screens
- if (_currentScene >= 900)
- return;
+ _interfaceSurface->initialise();
loadSceneHotspots(_currentScene);
@@ -112,25 +130,57 @@ void MadsScene::loadScene(int sceneNumber) {
// Handle common scene setting
Scene::loadScene(sceneNumber);
-
- _madsVm->globals()->previousScene = _madsVm->globals()->sceneNumber;
- _madsVm->globals()->sceneNumber = sceneNumber;
+ _madsVm->globals()->_nextSceneId = sceneNumber;
// Existing ScummVM code that needs to be eventually replaced with MADS code
loadSceneTemporary();
+ _madsVm->_player._spritesChanged = true;
+ _madsVm->globals()->clearQuotes();
+ _dynamicHotspots.reset();
+
// Signal the script engine what scene is to be active
_sceneLogic.selectScene(sceneNumber);
- _sceneLogic.setupScene();
// Add the scene if necessary to the list of scenes that have been visited
_vm->globals()->addVisitedScene(sceneNumber);
+ if (_vm->getGameType() == GType_RexNebular)
+ _sceneLogic.setupScene();
+
+ // TODO: Unknown code
+
// Secondary scene load routine
- loadScene2("*I0.AA");
+ if (_vm->getGameType() == GType_RexNebular)
+ // Secondary scene load routine
+ loadScene2("*I0.AA", sceneNumber);
+
+ _madsVm->_player.loadSprites(NULL);
+
+ switch (_madsVm->globals()->_config.screenFades) {
+ case 0:
+ _abortTimers2 = 2;
+ break;
+ case 2:
+ _abortTimers2 = 21;
+ break;
+ default:
+ _abortTimers2 = 20;
+ break;
+ }
+ _abortTimers = 0;
+ _abortTimersMode2 = ABORTMODE_1;
+
// Do any scene specific setup
- _sceneLogic.enterScene();
+ if (_vm->getGameType() == GType_RexNebular)
+ _sceneLogic.enterScene();
+
+ // Miscellaneous player setup
+ _madsVm->_player._destPos = _madsVm->_player._destPos;
+ _madsVm->_player._newDirection = _madsVm->_player._direction;
+ _madsVm->_player.setupFrame();
+ _madsVm->_player.updateFrame();
// Purge resources
_vm->res()->purge();
@@ -145,26 +195,28 @@ void MadsScene::loadSceneHotspots(int sceneNumber) {
int hotspotCount = hotspotStream->readUint16LE();
delete hotspotStream;
- _sceneResources.hotspotCount = hotspotCount;
-
hotspotStream = hotSpotData.getItemStream(1);
// Clear current hotspot lists
_sceneResources.hotspots->clear();
-
- _sceneResources.hotspots->loadHotSpots(hotspotStream, _sceneResources.hotspotCount);
+ _sceneResources.hotspots->loadHotSpots(hotspotStream, hotspotCount);
delete hotspotStream;
}
void MadsScene::leaveScene() {
_sceneResources.hotspots->clear();
- _sceneResources.props->clear();
+ _sceneResources.dynamicHotspots->clear();
delete _sceneResources.hotspots;
- delete _sceneResources.props;
+ delete _sceneResources.dynamicHotspots;
delete _walkSurface;
+ if (_activeAnimation) {
+ delete _activeAnimation;
+ _activeAnimation = NULL;
+ }
+
Scene::leaveScene();
}
@@ -183,69 +235,46 @@ void MadsScene::loadSceneCodes(int sceneNumber, int index) {
sceneS = walkData.getItemStream(0);
_walkSurface->loadCodesMads(sceneS);
_vm->res()->toss(filename);
- } else if (_vm->getGameType() == GType_RexNebular) {
- // For Rex Nebular, the walk areas are part of the scene info
- byte *destP = _walkSurface->getBasePtr(0, 0);
- const byte *srcP = _sceneResources.walkData;
- byte runLength;
- while ((runLength = *srcP++) != 0) {
- Common::set_to(destP, destP + runLength, *srcP++);
- destP += runLength;
- }
}
}
-void MadsScene::checkHotspotAtMousePos(int x, int y) {
+void MadsScene::mouseMove(int x, int y) {
HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
if (currentHotSpot != NULL) {
_vm->_mouse->setCursorNum(currentHotSpot->getCursor());
- // This is the "easy" interface, which updates the status text when the mouse is moved
- // TODO: toggle this code for easy/normal interface mode
- char statusText[50];
- int verbId = 0;//***DEBUG****_currentAction;
- if (verbId == kVerbNone)
- verbId = currentHotSpot->getVerbID();
- if (verbId == kVerbNone)
- verbId = kVerbWalkTo;
+ _action._selectedRow = -1;
+ _action._actionMode = ACTMODE_NONE;
+ _action._actionMode2 = ACTMODE2_4;
+ _action._hotspotId = currentHotSpot->getIndex();
- sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(verbId), currentHotSpot->getVocab());
-
- statusText[0] = toupper(statusText[0]); // capitalize first letter
- setStatusText(statusText);
} else {
_vm->_mouse->setCursorNum(0);
- setStatusText("");
}
}
void MadsScene::leftClick(int x, int y) {
- HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
- if (currentHotSpot != NULL) {
- char statusText[50];
- if (currentHotSpot->getVerbID() != 0) {
- sprintf(statusText, "%s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab());
- } else {
- sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(kVerbWalkTo), currentHotSpot->getVocab());
- }
-
- statusText[0] = toupper(statusText[0]); // capitalize first letter
- setStatusText(statusText);
- }
+ // TODO: figure out the rest of Scene_leftClick, and implements relevant parts in the interface class
+ _action._v86F4C = -1;
+ _action._v86F4E = 0;
+ _customDest = _madsVm->_mouse->currentPos();
+ _action._selectedAction = -1;
+ _action._v86F4A = true;
}
void MadsScene::rightClick(int x, int y) {
- // ***DEBUG*** - sample dialog display
- int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a);
- const char *msg = _madsVm->globals()->loadMessage(idx);
- Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG");
- _vm->_viewManager->addView(dlg);
- _vm->_viewManager->moveToFront(dlg);
+ if (_vm->getGameType() == GType_RexNebular) {
+ // ***DEBUG*** - sample dialog display
+ int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a);
+ const char *msg = _madsVm->globals()->loadMessage(idx);
+ Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG");
+ _vm->_viewManager->addView(dlg);
+ _vm->_viewManager->moveToFront(dlg);
+ }
}
void MadsScene::setAction(int action, int objectId) {
VALIDATE_MADS;
- char statusText[50];
error("todo");
// TODO: Actually executing actions directly for objects. Also, some object actions are special in that
@@ -262,7 +291,7 @@ void MadsScene::setAction(int action, int objectId) {
_currentAction = action;
}
*/
- setStatusText(statusText);
+// setStatusText(statusText);
}
/**
@@ -277,75 +306,166 @@ void MadsScene::drawElements() {
void MadsScene::update() {
- // Copy the bare scene in
- _backgroundSurface->copyTo(this);
-
// Draw all the various elements
drawElements();
_action.set();
- const char *sStatusText = _action.statusText();
+}
- // Handle display of any status text
- if (sStatusText[0]) {
- // Text colors are inverted in Dragonsphere
- if (_vm->getGameType() == GType_DragonSphere)
- _vm->_font->setColors(_vm->_palette->BLACK, _vm->_palette->WHITE, _vm->_palette->BLACK);
- else
- _vm->_font->setColors(_vm->_palette->WHITE, _vm->_palette->BLACK, _vm->_palette->BLACK);
+void MadsScene::updateState() {
+ if (!_abortTimers && !_madsVm->_player._unk3) {
+ if (_dynamicHotspots._changed)
+ _dynamicHotspots.refresh();
- _vm->_font->setFont(FONT_MAIN_MADS);
- _vm->_font->writeString(this, sStatusText, (width() - _vm->_font->getWidth(sStatusText)) / 2, 142, 0);
+// int v = (_madsVm->_player._stepEnabled && !_action._startWalkFlag && !_abortTimers2) ? 1 : 0;
+// _screenObjects.check(v, false);
}
- //***DEBUG***
- _spriteSlots.getSprite(0).getFrame(1)->copyTo(this, 120, 90, 0);
-}
+ // Handle starting off any selected action
+ bool doPreAction = false;
+ if ((_action._selectedAction != 0) && _madsVm->_player._stepEnabled &&
+ !_action._startWalkFlag && !_abortTimers && !_madsVm->_player._unk3) {
+ // Start the action
+ _action.startAction();
-void MadsScene::updateState() {
- _sequenceList.tick();
+ if (_action._action.verbId == kVerbLookAt) {
+ _action._action.verbId = kVerbLook;
+ _action._savedFields.selectedRow = 0;
+ }
+ doPreAction = true;
+ }
+ if (doPreAction || ((_abortTimers != 0) && (_abortTimersMode == ABORTMODE_2)))
+ doPreactions();
+
+ checkStartWalk();
+
+ if (_action._inProgress && !_madsVm->_player._moving && !_action._startWalkFlag &&
+ (_madsVm->_player._newDirection == _madsVm->_player._direction)) {
+ // Reached the end of action movement, so ready to actually do action
+ doAction();
+ } else if ((_abortTimers != 0) && (_abortTimersMode == ABORTMODE_0))
+ // Do an action designated by scripts
+ doAction();
+
+ bool freeFlag = false;
+ if (_currentScene != _nextScene)
+ freeFlag = true;
+ else {
+ doSceneStep();
+
+ if (_currentScene != _nextScene)
+ freeFlag = true;
+ else {
+ // Update the player
+ _madsVm->_player.nextFrame();
+
+ // Handle updating the animation
+ if (!_abortTimers && (_activeAnimation))
+ _activeAnimation->update();
+
+ // Handle refreshing the mouse position display
+ if (_mouseMsgIndex != -1)
+ _madsVm->scene()->_kernelMessages.remove(_mouseMsgIndex);
+ if (_showMousePos) {
+ char buffer[20];
+ sprintf(buffer, "(%d,%d)", _madsVm->_mouse->currentPos().x, _madsVm->_mouse->currentPos().y);
+
+ _mouseMsgIndex = _madsVm->scene()->_kernelMessages.add(Common::Point(5, 5), 0x203, 0, 0, 1, buffer);
+ }
+ }
+ }
+ if (_madsVm->globals()->_config.easyMouse)
+ _action.refresh();
+
if ((_activeAnimation) && !_abortTimers) {
_activeAnimation->update();
- if (((MadsAnimation *) _activeAnimation)->freeFlag()) {
+ if (((MadsAnimation *) _activeAnimation)->freeFlag() || freeFlag) {
delete _activeAnimation;
_activeAnimation = NULL;
}
}
- _kernelMessages.update();
+ MadsView::update();
+
+ // Remove the animation if it's been completed
+ if ((_activeAnimation) && ((MadsAnimation *)_activeAnimation)->freeFlag())
+ freeAnimation();
+
+ if ((_action._selectedAction != 0) || !_madsVm->_player._stepEnabled) {
+ _action.clear();
+ _action._selectedAction = 0;
+ }
}
-int MadsScene::loadSceneSpriteSet(const char *setName) {
- char resName[100];
- strcpy(resName, setName);
+void MadsScene::checkStartWalk() {
+ if (_action._startWalkFlag && _action._walkFlag) {
+ _madsVm->_player.setDest(_destPos.x, _destPos.y, _destFacing);
+ _action._startWalkFlag = false;
+ }
+}
- // Append a '.SS' if it doesn't alreayd have an extension
- if (!strchr(resName, '.'))
- strcat(resName, ".SS");
+void MadsScene::doPreactions() {
+ if ((_screenObjects._v832EC == 0) || (_screenObjects._v832EC == 2)) {
+ _abortTimersMode2 = ABORTMODE_2;
+ _action.checkAction();
- return _spriteSlots.addSprites(resName);
+ _sceneLogic.doPreactions();
+
+ if (_abortTimersMode == ABORTMODE_2)
+ _abortTimers = 0;
+ }
}
-void MadsScene::loadPlayerSprites(const char *prefix) {
- const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' };
- char setName[80];
+void MadsScene::doSceneStep() {
+ // Step through the scene
+ _sceneLogic.doSceneStep();
- strcpy(setName, "*");
- strcat(setName, prefix);
- strcat(setName, "_0.SS");
- char *digitP = strchr(setName, '_') + 1;
+ _madsVm->_player.step();
+ _madsVm->_player._unk3 = 0;
- for (int idx = 0; idx < 8; ++idx) {
- *digitP = suffixList[idx];
+ if (_abortTimersMode == ABORTMODE_1)
+ _abortTimers = 0;
+}
- if (_vm->res()->resourceExists(setName)) {
- loadSceneSpriteSet(setName);
- return;
- }
+void MadsScene::doAction() {
+ warning("TODO MadsScene::doAction");
+}
+
+
+/**
+ * Does extra work at cleaning up the animation, and then deletes it
+ */
+void MadsScene::freeAnimation() {
+ if (!_activeAnimation)
+ return;
+
+ MadsAnimation *anim = (MadsAnimation *)_activeAnimation;
+ if (anim->freeFlag()) {
+ _madsVm->scene()->_spriteSlots.clear();
+ _madsVm->scene()->_spriteSlots.fullRefresh();
+ _madsVm->scene()->_sequenceList.scan();
}
- error("Couldn't find player sprites");
+ if (_madsVm->_player._visible) {
+ _madsVm->_player._forceRefresh = true;
+ _madsVm->_player.update();
+ }
+
+ delete _activeAnimation;
+ _activeAnimation = NULL;
+}
+
+
+int MadsScene::loadSceneSpriteSet(const char *setName) {
+ char resName[100];
+ strcpy(resName, setName);
+
+ // Append a '.SS' if it doesn't alreayd have an extension
+ if (!strchr(resName, '.'))
+ strcat(resName, ".SS");
+
+ return _spriteSlots.addSprites(resName);
}
enum boxSprites {
@@ -446,274 +566,676 @@ void MadsScene::showMADSV2TextBox(char *text, int x, int y, char *faceName) {
boxSprites->getFrame(bottomRight)->copyTo(_backgroundSurface, curX, curY + 1);
}
+void MadsScene::loadAnimation(const Common::String &animName, int abortTimers) {
+ if (_activeAnimation)
+ error("Multiple active animations are not allowed");
+
+ MadsAnimation *anim = new MadsAnimation(_vm, this);
+ anim->load(animName.c_str(), abortTimers);
+ _activeAnimation = anim;
+}
+
+bool MadsScene::getDepthHighBit(const Common::Point &pt) {
+ const byte *p = _depthSurface->getBasePtr(pt.x, pt.y);
+ if (_sceneResources._depthStyle == 2)
+ return ((*p << 4) & 0x80) != 0;
+
+ return (*p & 0x80) != 0;
+}
+
+bool MadsScene::getDepthHighBits(const Common::Point &pt) {
+ if (_sceneResources._depthStyle == 2)
+ return 0;
+
+ const byte *p = _depthSurface->getBasePtr(pt.x, pt.y);
+ return (*p & 0x70) >> 4;
+}
+
/*--------------------------------------------------------------------------*/
-MadsAction::MadsAction() {
- clear();
-}
-
-void MadsAction::clear() {
- _actionMode = ACTMODE_NONE;
- _actionMode2 = ACTMODE2_0;
- _word_86F42 = 0;
- _word_86F4E = 0;
- _articleNumber = 0;
- _lookFlag = false;
- _word_86F4A = 0;
- _statusText[0] = '\0';
- _selectedRow = -1;
- _currentHotspot = -1;
- _word_86F3A = -1;
- _word_86F4C = -1;
- //word_86F3A/word_86F4C
- _currentAction = kVerbNone;
- _objectNameId = -1;
- _objectDescId = -1;
- _word_83334 = -1;
-}
-
-void MadsAction::appendVocab(int vocabId, bool capitalise) {
- char *s = _statusText + strlen(_statusText);
- const char *vocabStr = _madsVm->globals()->getVocab(vocabId);
- strcpy(s, vocabStr);
- if (capitalise)
- *s = toupper(*s);
-
- strcat(s, " ");
-}
-
-void MadsAction::set() {
- int hotspotCount = _madsVm->scene()->getSceneResources().hotspotCount;
- bool flag = false;
- _currentAction = -1;
- _objectNameId = -1;
- _objectDescId = -1;
-
- if (_actionMode == ACTMODE_TALK) {
- // Handle showing the conversation selection. Rex at least doesn't actually seem to use this
- if (_selectedRow >= 0) {
- const char *desc = _madsVm->_converse[_selectedRow].desc;
- if (desc)
- strcpy(_statusText, desc);
- }
- } else if (_lookFlag && (_selectedRow == 0)) {
- // Two 'look' actions in succession, so the action becomes 'Look around'
- strcpy(_statusText, lookAroundStr);
+void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface) {
+ char buffer1[80];
+ const char *sceneName;
+
+ // TODO: Initialise spriteSet / xp_list
+
+ if (sceneNumber > 0) {
+ sceneName = MADSResourceManager::getResourceName(RESPREFIX_RM, sceneNumber, ".DAT");
} else {
- if ((_actionMode == ACTMODE_OBJECT) && (_selectedRow >= 0) && (_flags1 == 2) && (_flags2 == 0)) {
- // Use/to action
- int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
- MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
-
- _objectNameId = objEntry->descId;
- _currentAction = objEntry->vocabList[_selectedRow].vocabId;
-
- // Set up the status text stirng
- strcpy(_statusText, useStr);
- appendVocab(_objectNameId);
- strcpy(_statusText, toStr);
- appendVocab(_currentAction);
- } else {
- // Handling for if an action has been selected
- if (_selectedRow >= 0) {
- if (_actionMode == ACTMODE_VERB) {
- // Standard verb action
- _currentAction = verbList[_selectedRow].verb;
- } else {
- // Selected action on an inventory object
- int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
- MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
+ strcpy(buffer1, "*");
+ strcat(buffer1, resName);
+ sceneName = buffer1; // TODO: Check whether this needs to be converted to 'HAG form'
+ }
- _currentAction = objEntry->vocabList[_selectedRow].vocabId;
- }
+ Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneName);
+ MadsPack sceneInfo(rawStream);
- appendVocab(_currentAction, true);
+ // Chunk 0:
+ // Basic scene info
+ Common::SeekableReadStream *stream = sceneInfo.getItemStream(0);
- if (_currentAction == kVerbLook) {
- // Add in the word 'add'
- strcat(_statusText, atStr);
- strcat(_statusText, " ");
- }
- }
+ if (_vm->getGameType() == GType_RexNebular) {
+ int resSceneId = stream->readUint16LE();
+ assert(resSceneId == sceneNumber);
+ } else {
+ char roomFilename[10];
+ char roomFilenameExpected[10];
+ sprintf(roomFilenameExpected, "*RM%d", sceneNumber);
- // Handling for if a hotspot has been selected/highlighted
- if ((_currentHotspot >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_flags1 == 2)) {
- flag = true;
+ stream->read(roomFilename, 6);
+ roomFilename[6] = 0;
+ assert(!strcmp(roomFilename, roomFilenameExpected));
+ }
- strcat(_statusText, englishMADSArticleList[_articleNumber]);
- strcat(_statusText, " ");
- }
+ // TODO: The following is wrong for Phantom/Dragon
+ _artFileNum = stream->readUint16LE();
+ _depthStyle = stream->readUint16LE();
+ _width = stream->readUint16LE();
+ _height = stream->readUint16LE();
+
+ stream->skip(24);
- if (_currentHotspot >= 0) {
- if (_selectedRow < 0) {
- int verbId;
-
- if (_currentHotspot < hotspotCount) {
- // Get the verb Id from the hotspot
- verbId = (*_madsVm->scene()->getSceneResources().hotspots)[_currentHotspot].getVerbID();
- } else {
- // Get the verb Id from the scene object
- verbId = (*_madsVm->scene()->getSceneResources().props)[_currentHotspot - hotspotCount].getVerbID();
- }
-
- if (verbId > 0) {
- // Set the specified action
- _currentAction = verbId;
- appendVocab(_currentAction, true);
- } else {
- // Default to a standard 'walk to'
- _currentAction = kVerbWalkTo;
- strcat(_statusText, walkToStr);
- }
- }
+ int nodeCount = stream->readUint16LE();
+ _yBandsEnd = stream->readUint16LE();
+ _yBandsStart = stream->readUint16LE();
+ _maxScale = stream->readSint16LE();
+ _minScale = stream->readSint16LE();
+ for (int i = 0; i < DEPTH_BANDS_SIZE; ++i)
+ _depthBands[i] = stream->readUint16LE();
+ stream->skip(2);
+
+ // Load in any scene objects
+ for (int i = 0; i < nodeCount; ++i) {
+ SceneNode rec;
+ rec.load(stream);
+ _nodes.push_back(rec);
+ }
+ for (int i = 0; i < 20 - nodeCount; ++i)
+ stream->skip(48);
- if ((_actionMode2 == ACTMODE2_2) || (_actionMode2 == ACTMODE2_5)) {
- // Get name from given inventory object
- int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_currentHotspot);
- _objectNameId = _madsVm->globals()->getObject(objectId)->descId;
- } else if (_currentHotspot < hotspotCount) {
- // Get name from scene hotspot
- _objectNameId = (*_madsVm->scene()->getSceneResources().hotspots)[_currentHotspot].getVocabID();
- } else {
- // Get name from temporary scene hotspot
- _objectNameId = (*_madsVm->scene()->getSceneResources().props)[_currentHotspot].getVocabID();
+ // Add two extra nodes in that will be used for player movement
+ for (int i = 0; i < 2; ++i) {
+ SceneNode rec;
+ _nodes.push_back(rec);
+ }
+
+ int setCount = stream->readUint16LE();
+ stream->readUint16LE();
+ for (int i = 0; i < setCount; ++i) {
+ char buffer2[64];
+ Common::String s(buffer2, 64);
+ _setNames.push_back(s);
+ }
+
+ delete stream;
+
+ // Initialise a copy of the surfaces if they weren't provided
+ bool dsFlag = false, ssFlag = false;
+ if (!surface) {
+ surface = new M4Surface(_width, _height);
+ ssFlag = true;
+ } else if ((_width != surface->width()) || (_height != surface->height()))
+ surface->setSize(_width, _height);
+
+ if (!depthSurface) {
+ depthSurface = new M4Surface(_width, _height);
+ dsFlag = true;
+ } else if ((_width != depthSurface->width()) || (_height != depthSurface->height()))
+ depthSurface->setSize(_width, _height);
+
+
+ // For Rex Nebular, read in the scene's compressed walk surface information
+ if (_vm->getGameType() == GType_RexNebular) {
+ assert(depthSurface);
+ stream = sceneInfo.getItemStream(1);
+ byte *walkData = (byte *)malloc(stream->size());
+ stream->read(walkData, stream->size());
+
+ // For Rex Nebular, the walk areas are part of the scene info
+ byte *destP = depthSurface->getBasePtr(0, 0);
+ const byte *srcP = walkData;
+ byte runLength;
+
+ // Run length encoded depth data
+ while ((runLength = *srcP++) != 0) {
+ if (_depthStyle == 2) {
+ // 2-bit depth pixels
+ byte byteVal = *srcP++;
+ for (int byteCtr = 0; byteCtr < runLength; ++byteCtr) {
+ byte v = byteVal;
+ for (int bitCtr = 0; bitCtr < 4; ++bitCtr, v >>= 2)
+ *destP++ = (((v & 1) + 1) << 3) - 1;
}
+ } else {
+ // 8-bit depth pixels
+ Common::set_to(destP, destP + runLength, *srcP++);
+ destP += runLength;
}
}
- if ((_currentHotspot >= 0) && (_articleNumber > 0) && !flag) {
- if (_articleNumber == -1) {
- if (_word_86F3A >= 0) {
- int articleNum = 0;
+ free(walkData);
+ delete stream;
+ }
- if ((_word_86F42 == 2) || (_word_86F42 == 5)) {
- int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_currentHotspot);
- articleNum = _madsVm->globals()->getObject(objectId)->article;
- } else if (_word_86F3A < hotspotCount) {
- articleNum = (*_madsVm->scene()->getSceneResources().hotspots)[_currentHotspot].getArticle();
- } else {
+ _vm->_resourceManager->toss(sceneName);
- }
- }
+ // Load the surface artwork
+ surface->loadBackground(_artFileNum);
- } else if ((_articleNumber == kVerbLook) || (_vm->getGameType() != GType_RexNebular) ||
- (strcmp(_madsVm->globals()->getVocab(_objectDescId), fenceStr) != 0)) {
- // Write out the article
- strcat(_statusText, englishMADSArticleList[_articleNumber]);
- } else {
- // Special case for a 'fence' entry in Rex Nebular
- strcat(_statusText, overStr);
- }
+ // Final cleanup
+ if (ssFlag)
+ delete surface;
+ if (dsFlag)
+ delete depthSurface;
+}
+
+void MadsSceneResources::setRouteNode(int nodeIndex, const Common::Point &pt, M4Surface *depthSurface) {
+ int flags, hypotenuse;
+
+ _nodes[nodeIndex].pt = pt;
+
+ // Recalculate inter-node lengths
+ for (uint idx = 0; idx < _nodes.size(); ++idx) {
+ int entry;
+ if (idx == (uint)nodeIndex) {
+ entry = 0x3FFF;
+ } else {
+ // Process the node
+ flags = getRouteFlags(pt, _nodes[idx].pt, depthSurface);
+
+ int xDiff = ABS(_nodes[idx].pt.x - pt.x);
+ int yDiff = ABS(_nodes[idx].pt.y - pt.y);
+ hypotenuse = SqrtF16(xDiff * xDiff + yDiff * yDiff);
- strcat(_statusText, " ");
+ if (hypotenuse >= 0x3FFF)
+ // Shouldn't ever be this large
+ hypotenuse = 0x3FFF;
+
+ entry = hypotenuse | flags;
+ _nodes[idx].indexes[nodeIndex] = entry;
+ _nodes[nodeIndex].indexes[idx] = entry;
+ }
+ }
+}
+
+int MadsSceneResources::getRouteFlags(const Common::Point &src, const Common::Point &dest, M4Surface *depthSurface) {
+ int result = 0x8000;
+ bool flag = false;
+
+ int xDiff = ABS(dest.x - src.x);
+ int yDiff = ABS(dest.y - src.y);
+ int xDirection = dest.x >= src.x ? 1 : -1;
+ int yDirection = dest.y >= src.y ? depthSurface->width() : -depthSurface->width();
+ int majorDiff = 0;
+ if (dest.x < src.x)
+ majorDiff = MAX(xDiff, yDiff);
+ ++xDiff;
+ ++yDiff;
+
+ byte *srcP = depthSurface->getBasePtr(src.x, src.y);
+
+ int totalCtr = majorDiff;
+ for (int xCtr = 0; xCtr < xDiff; ++xCtr, srcP += xDirection) {
+ totalCtr += yDiff;
+
+ if ((*srcP & 0x80) == 0)
+ flag = false;
+ else if (!flag) {
+ flag = true;
+ result -= 0x4000;
+ if (result == 0)
+ break;
}
- // Append object description if necessary
- if (_word_86F3A >= 0)
- appendVocab(_objectDescId);
+ while (totalCtr >= xDiff) {
+ totalCtr -= xDiff;
- // Remove any trailing space character
- int statusLen = strlen(_statusText);
- if ((statusLen > 0) && (_statusText[statusLen - 1] == ' '))
- _statusText[statusLen - 1] = '\0';
+ if ((*srcP & 0x80) == 0)
+ flag = false;
+ else if (!flag) {
+ flag = true;
+ result -= 0x4000;
+ if (result == 0)
+ break;
+ }
+
+ srcP += yDirection;
+ }
+ if (result == 0)
+ break;
}
- _word_83334 = -1;
+ return result;
}
/*--------------------------------------------------------------------------*/
-void MadsSceneResources::load(int sId) {
- const char *sceneInfoStr = MADSResourceManager::getResourceName(RESPREFIX_RM, sId, ".DAT");
- Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneInfoStr);
- MadsPack sceneInfo(rawStream);
+/*--------------------------------------------------------------------------
+ * MadsInterfaceView handles the user interface section at the bottom of
+ * game screens in MADS games
+ *--------------------------------------------------------------------------
+ */
- // Basic scene info
- Common::SeekableReadStream *stream = sceneInfo.getItemStream(0);
+MadsInterfaceView::MadsInterfaceView(MadsM4Engine *vm): GameInterfaceView(vm,
+ Common::Rect(0, MADS_SURFACE_HEIGHT, vm->_screen->width(), vm->_screen->height())) {
+ _screenType = VIEWID_INTERFACE;
+ _highlightedElement = -1;
+ _topIndex = 0;
+ _selectedObject = -1;
+ _cheatKeyCtr = 0;
+
+ _objectSprites = NULL;
+ _objectPalData = NULL;
+
+ /* Set up the rect list for screen elements */
+ // Actions
+ for (int i = 0; i < 10; ++i)
+ _screenObjects.addRect((i / 5) * 32 + 1, (i % 5) * 8 + MADS_SURFACE_HEIGHT + 2,
+ ((i / 5) + 1) * 32 + 3, ((i % 5) + 1) * 8 + MADS_SURFACE_HEIGHT + 2);
+
+ // Scroller elements (up arrow, scroller, down arrow)
+ _screenObjects.addRect(73, 160, 82, 167);
+ _screenObjects.addRect(73, 168, 82, 190);
+ _screenObjects.addRect(73, 191, 82, 198);
+
+ // Inventory object names
+ for (int i = 0; i < 5; ++i)
+ _screenObjects.addRect(89, 158 + i * 8, 160, 166 + i * 8);
+
+ // Full rectangle area for all vocab actions
+ for (int i = 0; i < 5; ++i)
+ _screenObjects.addRect(239, 158 + i * 8, 320, 166 + i * 8);
+}
- int resSceneId = stream->readUint16LE();
- assert(resSceneId == sId);
+MadsInterfaceView::~MadsInterfaceView() {
+ delete _objectSprites;
+}
- artFileNum = stream->readUint16LE();
- field_4 = stream->readUint16LE();
- width = stream->readUint16LE();
- height = stream->readUint16LE();
- assert((width == 320) && (height == 156));
-
- stream->skip(24);
+void MadsInterfaceView::setFontMode(InterfaceFontMode newMode) {
+ switch (newMode) {
+ case ITEM_NORMAL:
+ _vm->_font->current()->setColours(4, 4, 0xff);
+ break;
+ case ITEM_HIGHLIGHTED:
+ _vm->_font->current()->setColours(5, 5, 0xff);
+ break;
+ case ITEM_SELECTED:
+ _vm->_font->current()->setColours(6, 6, 0xff);
+ break;
+ }
+}
- objectCount = stream->readUint16LE();
+void MadsInterfaceView::initialise() {
+ // Build up the inventory list
+ _inventoryList.clear();
- stream->skip(40);
+ for (uint i = 0; i < _madsVm->globals()->getObjectsSize(); ++i) {
+ MadsObject *obj = _madsVm->globals()->getObject(i);
+ if (obj->roomNumber == PLAYER_INVENTORY)
+ _inventoryList.push_back(i);
+ }
- for (int i = 0; i < objectCount; ++i) {
- objects[i].load(stream);
+ // If the inventory has at least one object, select it
+ if (_inventoryList.size() > 0)
+ setSelectedObject(_inventoryList[0]);
+}
+
+void MadsInterfaceView::setSelectedObject(int objectNumber) {
+ char resName[80];
+
+ // Load inventory resource
+ if (_objectSprites) {
+ _vm->_palette->deleteRange(_objectPalData);
+ delete _objectSprites;
}
- // For Rex Nebular, read in the scene's compressed walk surface information
- if (_vm->getGameType() == GType_RexNebular) {
- delete walkData;
+ // Check to make sure the object is in the inventory, and also visible on-screen
+ int idx = _inventoryList.indexOf(objectNumber);
+ if (idx == -1) {
+ // Object wasn't found, so return
+ _selectedObject = -1;
+ return;
+ }
- stream = sceneInfo.getItemStream(1);
- walkData = (byte *)malloc(stream->size());
- stream->read(walkData, stream->size());
+ // Found the object
+ if (idx < _topIndex)
+ _topIndex = idx;
+ else if (idx >= (_topIndex + 5))
+ _topIndex = MAX(0, idx - 4);
+
+ _selectedObject = objectNumber;
+ sprintf(resName, "*OB%.3dI.SS", objectNumber);
+
+ Common::SeekableReadStream *data = _vm->res()->get(resName);
+ _objectSprites = new SpriteAsset(_vm, data, data->size(), resName);
+ _vm->res()->toss(resName);
+
+ // Slot it into available palette space
+ _objectPalData = _objectSprites->getRgbList();
+ _vm->_palette->addRange(_objectPalData);
+ _objectSprites->translate(_objectPalData, true);
+
+ _objectFrameNumber = 0;
+}
+
+void MadsInterfaceView::addObjectToInventory(int objectNumber) {
+ if (_inventoryList.indexOf(objectNumber) == -1) {
+ _madsVm->globals()->getObject(objectNumber)->roomNumber = PLAYER_INVENTORY;
+ _inventoryList.push_back(objectNumber);
}
- _vm->_resourceManager->toss(sceneInfoStr);
+ setSelectedObject(objectNumber);
}
-/*--------------------------------------------------------------------------*/
+void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
+ _vm->_font->setFont(FONT_INTERFACE_MADS);
+ char buffer[100];
+
+ // Check to see if any dialog is currently active
+ bool dialogVisible = _vm->_viewManager->getView(LAYER_DIALOG) != NULL;
+
+ // Highlighting logic for action list
+ int actionIndex = 0;
+ for (int x = 0; x < 2; ++x) {
+ for (int y = 0; y < 5; ++y, ++actionIndex) {
+ // Determine the font colour depending on whether an item is selected. Note that the first action,
+ // 'Look', is always 'selected', even when another action is clicked on
+ setFontMode((_highlightedElement == actionIndex) ? ITEM_HIGHLIGHTED :
+ ((actionIndex == 0) ? ITEM_SELECTED : ITEM_NORMAL));
+
+ // Get the verb action and capitalise it
+ const char *verbStr = _madsVm->globals()->getVocab(kVerbLook + actionIndex);
+ strcpy(buffer, verbStr);
+ if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
+
+ // Display the verb
+ const Common::Rect r(_screenObjects[actionIndex]);
+ _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0);
+ }
+ }
-/**
- * Adds a new entry to the timed on-screen text display list
- */
-/*
-void MadsScreenText::draw(M4Surface *surface) {
+ // Check for highlighting of the scrollbar controls
+ if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_SCROLLER) || (_highlightedElement == SCROLL_DOWN)) {
+ // Highlight the control's borders
+ const Common::Rect r(_screenObjects[_highlightedElement]);
+ destSurface->frameRect(r, 5);
+ }
+
+ // Draw the horizontal line in the scroller representing the current top selected
+ const Common::Rect scroller(_screenObjects[SCROLL_SCROLLER]);
+ int yP = (_inventoryList.size() < 2) ? 0 : (scroller.height() - 5) * _topIndex / (_inventoryList.size() - 1);
+ destSurface->setColor(4);
+ destSurface->hLine(scroller.left + 2, scroller.right - 3, scroller.top + 2 + yP);
+
+ // List inventory items
+ for (uint i = 0; i < 5; ++i) {
+ if ((_topIndex + i) >= _inventoryList.size())
+ break;
+
+ const char *descStr = _madsVm->globals()->getVocab(_madsVm->globals()->getObject(
+ _inventoryList[_topIndex + i])->descId);
+ strcpy(buffer, descStr);
+ if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
+
+ const Common::Rect r(_screenObjects[INVLIST_START + i]);
+
+ // Set the highlighting of the inventory item
+ if (_highlightedElement == (int)(INVLIST_START + i)) setFontMode(ITEM_HIGHLIGHTED);
+ else if (_selectedObject == _inventoryList[_topIndex + i]) setFontMode(ITEM_SELECTED);
+ else setFontMode(ITEM_NORMAL);
+
+ // Write out it's description
+ _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0);
+ }
+
+ // Handle the display of any currently selected object
+ if (_objectSprites) {
+ // Display object sprite. Note that the frame number isn't used directly, because it would result
+ // in too fast an animation
+ M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED);
+ spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, TRANSPARENT_COLOUR_INDEX);
+
+ if (!_madsVm->globals()->_config.invObjectsStill && !dialogVisible) {
+ // If objects need to be animated, move to the next frame
+ if (++_objectFrameNumber >= (_objectSprites->getCount() * INV_ANIM_FRAME_SPEED))
+ _objectFrameNumber = 0;
+ }
+
+ // List the vocab actions for the currently selected object
+ MadsObject *obj = _madsVm->globals()->getObject(_selectedObject);
+ int yIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1);
+
+ for (int i = 0; i < obj->vocabCount; ++i) {
+ const Common::Rect r(_screenObjects[VOCAB_START + i]);
+
+ // Get the vocab description and capitalise it
+ const char *descStr = _madsVm->globals()->getVocab(obj->vocabList[i].vocabId);
+ strcpy(buffer, descStr);
+ if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
+
+ // Set the highlighting and display the entry
+ setFontMode((i == yIndex) ? ITEM_HIGHLIGHTED : ITEM_NORMAL);
+ _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0);
+ }
+ }
}
-void MadsScreenText::timedDisplay() {
- for (int idx = 0; !_abortTimedText && (idx < OLD_TEXT_DISPLAY_SIZE); ++idx) {
- if (((_timedText[idx].flags & TEXTFLAG_ACTIVE) != 0) &&
- (_timedText[idx].frameTimer <= g_system->getMillis()))
- // Add the specified entry
- addTimedText(&_timedText[idx]);
+bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) {
+ MadsAction &act = _madsVm->scene()->_action;
+
+ // If the mouse isn't being held down, then reset the repeated scroll timer
+ if (eventType != MEVENT_LEFT_HOLD)
+ _nextScrollerTicks = 0;
+
+ // Handle various event types
+ switch (eventType) {
+ case MEVENT_MOVE:
+ // If the cursor isn't in "wait mode", don't do any processing
+ if (_vm->_mouse->getCursorNum() == CURSOR_WAIT)
+ return true;
+
+ // Ensure the cursor is the standard arrow
+ _vm->_mouse->setCursorNum(CURSOR_ARROW);
+
+ // Check if any interface element is currently highlighted
+ _highlightedElement = _screenObjects.find(Common::Point(x, y));
+
+ return true;
+
+ case MEVENT_LEFT_CLICK:
+ // Left mouse click
+ {
+ // Check if an inventory object was selected
+ if ((_highlightedElement >= INVLIST_START) && (_highlightedElement < (INVLIST_START + 5))) {
+ // Ensure there is an inventory item listed in that cell
+ uint idx = _highlightedElement - INVLIST_START;
+ if ((_topIndex + idx) < _inventoryList.size()) {
+ // Set the selected object
+ setSelectedObject(_inventoryList[_topIndex + idx]);
+ }
+ } else if ((_highlightedElement >= ACTIONS_START) && (_highlightedElement < (ACTIONS_START + 10))) {
+ // A standard action was selected
+ int verbId = kVerbLook + (_highlightedElement - ACTIONS_START);
+ warning("Selected action #%d", verbId);
+
+ } else if ((_highlightedElement >= VOCAB_START) && (_highlightedElement < (VOCAB_START + 5))) {
+ // A vocab action was selected
+ MadsObject *obj = _madsVm->globals()->getObject(_selectedObject);
+ int vocabIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1);
+ if (vocabIndex >= 0) {
+ act._actionMode = ACTMODE_OBJECT;
+ act._actionMode2 = ACTMODE2_2;
+ act._flags1 = obj->vocabList[1].flags1;
+ act._flags2 = obj->vocabList[1].flags2;
+
+ act._action.verbId = _selectedObject;
+ act._articleNumber = act._flags2;
+ }
+ }
+ }
+ return true;
+
+ case MEVENT_LEFT_HOLD:
+ // Left mouse hold
+ // Handle the scroller - the up/down buttons allow for multiple actions whilst the mouse is held down
+ if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_DOWN)) {
+ if ((_nextScrollerTicks == 0) || (g_system->getMillis() >= _nextScrollerTicks)) {
+ // Handle scroll up/down action
+ _nextScrollerTicks = g_system->getMillis() + SCROLLER_DELAY;
+
+ if ((_highlightedElement == SCROLL_UP) && (_topIndex > 0))
+ --_topIndex;
+ if ((_highlightedElement == SCROLL_DOWN) && (_topIndex < (int)(_inventoryList.size() - 1)))
+ ++_topIndex;
+ }
+ }
+ return true;
+
+ case MEVENT_LEFT_DRAG:
+ // Left mouse drag
+ // Handle the the the scroller area that can be dragged to adjust the top displayed index
+ if (_highlightedElement == SCROLL_SCROLLER) {
+ // Calculate the new top index based on the Y position
+ const Common::Rect r(_screenObjects[SCROLL_SCROLLER]);
+ _topIndex = CLIP((int)(_inventoryList.size() - 1) * (y - r.top - 2) / (r.height() - 5),
+ 0, (int)_inventoryList.size() - 1);
+ }
+ return true;
+
+ case KEVENT_KEY:
+ if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX)
+ handleCheatKey(param1);
+ handleKeypress(param1);
+ return true;
+
+ default:
+ break;
}
+
+ return false;
}
-void MadsScreenText::addTimedText(TimedText *entry) {
- if ((entry->flags & TEXTFLAG_40) != 0) {
- this->setActive2(entry->textDisplayIndex);
- entry->flags &= 0x7F;
- return;
+bool MadsInterfaceView::handleCheatKey(int32 keycode) {
+ switch (keycode) {
+ case Common::KEYCODE_SPACE:
+ // TODO: Move player to current destination
+ return true;
+
+ case Common::KEYCODE_c | (Common::KBD_CTRL << 24):
+ // Toggle display of mouse position
+ _madsVm->scene()->_showMousePos = !_madsVm->scene()->_showMousePos;
+ break;
+
+ case Common::KEYCODE_t | (Common::KEYCODE_LALT << 24):
+ case Common::KEYCODE_t | (Common::KEYCODE_RALT << 24):
+ {
+ // Teleport to room
+ //Scene *sceneView = (Scene *)vm->_viewManager->getView(VIEWID_SCENE);
+
+
+ return true;
}
- if ((entry->flags & TEXTFLAG_8) == 0)
- // FIXME: Adjust timeouts for ScumVM's milli counter
- entry->timeout -= 3;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+const char *CHEAT_SEQUENCE = "widepipe";
- if ((entry->flags & TEXTFLAG_4) != 0) {
- Text4A &rec = _text4A[entry->unk4AIndex];
- if ((rec.field25 != 0) || (rec.active == 0))
- entry->timeout = 0;
+bool MadsInterfaceView::handleKeypress(int32 keycode) {
+ int flags = keycode >> 24;
+ int kc = keycode & 0xffff;
+
+ // Capitalise the letter if necessary
+ if (_cheatKeyCtr < CHEAT_SEQUENCE_MAX) {
+ if ((flags & Common::KBD_CTRL) && (kc == CHEAT_SEQUENCE[_cheatKeyCtr])) {
+ ++_cheatKeyCtr;
+ if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX)
+ Dialog::display(_vm, 22, cheatingEnabledDesc);
+ return true;
+ } else {
+ _cheatKeyCtr = 0;
+ }
}
- if ((entry->timeout == 0) && !_abortTimedText) {
- entry->flags |= TEXTFLAG_40;
+ // Handle the various keys
+ if ((keycode == Common::KEYCODE_ESCAPE) || (keycode == Common::KEYCODE_F1)) {
+ // Game menu
+ _madsVm->globals()->dialogType = DIALOG_GAME_MENU;
+ leaveScene();
+ return false;
+ } else if (flags & Common::KBD_CTRL) {
+ // Handling of the different control key combinations
+ switch (kc) {
+ case Common::KEYCODE_i:
+ // Mouse to inventory
+ warning("TODO: Mouse to inventory");
+ break;
+
+ case Common::KEYCODE_k:
+ // Toggle hotspots
+ warning("TODO: Toggle hotspots");
+ break;
+
+ case Common::KEYCODE_p:
+ // Player stats
+ warning("TODO: Player stats");
+ break;
+
+ case Common::KEYCODE_q:
+ // Quit game
+ break;
+
+ case Common::KEYCODE_s:
+ // Activate sound
+ warning("TODO: Activate sound");
+ break;
+
+ case Common::KEYCODE_t:
+ // Rotate player - This was Ctrl-U in the original, but in ScummVM Ctrl-U is a global mute key
+ _madsVm->_player._newDirection = _madsVm->_player._directionListIndexes[_madsVm->_player._newDirection + 10];
+ break;
+
+ case Common::KEYCODE_v: {
+ // Release version
+ Dialog *dlg = new Dialog(_vm, GameReleaseInfoStr, GameReleaseTitleStr);
+ _vm->_viewManager->addView(dlg);
+ _vm->_viewManager->moveToFront(dlg);
+ return false;
+ }
- if (entry->field_1C) {
- _abortTimedText = entry->field_1C;
- //word_84208 = entry->field_1D;
-
- if (entry->field_1D != 1) {
- // Restore the action list
- for (int i = 0; i < 3; ++i)
- _madsVm->scene()->actionNouns[i] = entry->actionNouns[i];
- }
+ default:
+ break;
+ }
+ } else if ((flags & Common::KBD_ALT) && (kc == Common::KEYCODE_q)) {
+ // Quit Game
+
+ } else {
+ // Standard keypresses
+ switch (kc) {
+ case Common::KEYCODE_F2:
+ // Save game
+ _madsVm->globals()->dialogType = DIALOG_SAVE;
+ leaveScene();
+ break;
+ case Common::KEYCODE_F3:
+ // Restore game
+ _madsVm->globals()->dialogType = DIALOG_RESTORE;
+ leaveScene();
+ break;
}
}
+//DIALOG_OPTIONS
+ return false;
+}
- // TODO: code from 'loc_244ec' onwards
+void MadsInterfaceView::leaveScene() {
+ // Close the scene
+ View *view = _madsVm->_viewManager->getView(VIEWID_SCENE);
+ _madsVm->_viewManager->deleteView(view);
}
-*/
} // End of namespace M4
diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h
index f7625bb761..7723058cc7 100644
--- a/engines/m4/mads_scene.h
+++ b/engines/m4/mads_scene.h
@@ -33,96 +33,81 @@
namespace M4 {
#define INTERFACE_HEIGHT 106
+class MadsInterfaceView;
-struct SpriteSlot {
- int16 spriteId;
- int16 scale;
- uint16 spriteListIndex;
-};
+#define DEPTH_BANDS_SIZE 15
+#define MAX_ROUTE_NODES 22
+
+enum ScreenCategory {CAT_NONE = 0, CAT_ACTION = 1, CAT_INV_LIST = 2, CAT_INV_VOCAB, CAT_HOTSPOT = 4,
+ CAT_INV_ANIM = 6, CAT_6, CAT_INV_SCROLLER = 7, CAT_12 = 12};
+
+class SceneNode {
+public:
+ Common::Point pt;
+ int indexes[MAX_ROUTE_NODES];
-struct DirtyArea {
bool active;
- bool active2;
- Common::Rect bounds;
-};
+ SceneNode() {
+ active = false;
+ }
-class MadsSceneResources: public SceneResources {
-public:
- int sceneId;
- int artFileNum;
- int field_4;
- int width;
- int height;
-
- int objectCount;
- MadsObject objects[32];
-
- int walkSize;
- byte *walkData;
-
- MadsSceneResources() { walkSize = 0; walkData = NULL; }
- ~MadsSceneResources() { delete walkData; }
- void load(int sceneId);
+ void load(Common::SeekableReadStream *stream);
};
-enum MadsActionMode {ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, ACTMODE_TALK = 6};
-enum MAdsActionMode2 {ACTMODE2_0 = 0, ACTMODE2_2 = 2, ACTMODE2_5 = 5};
+typedef Common::Array<SceneNode> SceneNodeList;
-class MadsAction {
+class MadsSceneResources: public SceneResources {
private:
- char _statusText[100];
-
- void appendVocab(int vocabId, bool capitalise = false);
-public:
- int _currentHotspot;
- int _objectNameId;
- int _objectDescId;
- int _currentAction;
- int8 _flags1, _flags2;
- MadsActionMode _actionMode;
- MAdsActionMode2 _actionMode2;
- int _articleNumber;
- bool _lookFlag;
- int _selectedRow;
- // Unknown fields
- int16 _word_86F3A;
- int16 _word_86F42;
- int16 _word_86F4E;
- int16 _word_86F4A;
- int16 _word_83334;
- int16 _word_86F4C;
-
+ int getRouteFlags(const Common::Point &src, const Common::Point &dest, M4Surface *depthSurface);
public:
- MadsAction();
-
- void clear();
- void set();
- const char *statusText() const { return _statusText; }
+ int _sceneId;
+ int _artFileNum;
+ int _depthStyle;
+ int _width;
+ int _height;
+ SceneNodeList _nodes;
+ Common::Array<Common::String> _setNames;
+ int _yBandsStart, _yBandsEnd;
+ int _maxScale, _minScale;
+ int _depthBands[DEPTH_BANDS_SIZE];
+
+ MadsSceneResources() {}
+ ~MadsSceneResources() {}
+ void load(int sceneId, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface);
+ int bandsRange() const { return _yBandsEnd - _yBandsStart; }
+ int scaleRange() const { return _maxScale - _minScale; }
+ void setRouteNode(int nodeIndex, const Common::Point &pt, M4Surface *depthSurface);
};
-#define DIRTY_AREA_SIZE 90
-
class MadsScene : public Scene, public MadsView {
private:
MadsEngine *_vm;
MadsSceneResources _sceneResources;
- MadsAction _action;
+ Animation *_activeAnimation;
MadsSceneLogic _sceneLogic;
SpriteAsset *_playerSprites;
- DirtyArea _dirtyAreas[DIRTY_AREA_SIZE];
+ int _mouseMsgIndex;
+ int _highlightedHotspot;
void drawElements();
- void loadScene2(const char *aaName);
+ void loadScene2(const char *aaName, int sceneNumber);
void loadSceneTemporary();
void loadSceneHotspots(int sceneNumber);
void clearAction();
void appendActionVocab(int vocabId, bool capitalise);
void setAction();
+ void checkStartWalk();
+ void doPreactions();
+ void doSceneStep();
+ void doAction();
public:
char _aaName[100];
- uint16 actionNouns[3];
+ bool _showMousePos;
+ Common::Point _destPos;
+ int _destFacing;
+ Common::Point _customDest;
public:
MadsScene(MadsEngine *vm);
virtual ~MadsScene();
@@ -132,7 +117,7 @@ public:
virtual void leaveScene();
virtual void loadSceneCodes(int sceneNumber, int index = 0);
virtual void show();
- virtual void checkHotspotAtMousePos(int x, int y);
+ virtual void mouseMove(int x, int y);
virtual void leftClick(int x, int y);
virtual void rightClick(int x, int y);
virtual void setAction(int action, int objectId = -1);
@@ -141,13 +126,65 @@ public:
virtual void updateState();
int loadSceneSpriteSet(const char *setName);
- void loadPlayerSprites(const char *prefix);
void showMADSV2TextBox(char *text, int x, int y, char *faceName);
+ void loadAnimation(const Common::String &animName, int abortTimers);
+ Animation *activeAnimation() const { return _activeAnimation; }
+ void freeAnimation();
MadsInterfaceView *getInterface() { return (MadsInterfaceView *)_interfaceSurface; }
MadsSceneResources &getSceneResources() { return _sceneResources; }
- MadsAction &getAction() { return _action; }
- void setStatusText(const char *text) {}//***DEPRECATED***
+ bool getDepthHighBit(const Common::Point &pt);
+ bool getDepthHighBits(const Common::Point &pt);
+};
+
+#define CHEAT_SEQUENCE_MAX 8
+
+class IntegerList : public Common::Array<int> {
+public:
+ int indexOf(int v) {
+ for (uint i = 0; i < size(); ++i)
+ if (operator [](i) == v)
+ return i;
+ return -1;
+ }
+};
+
+enum InterfaceFontMode {ITEM_NORMAL, ITEM_HIGHLIGHTED, ITEM_SELECTED};
+
+enum InterfaceObjects {ACTIONS_START = 0, SCROLL_UP = 10, SCROLL_SCROLLER = 11, SCROLL_DOWN = 12,
+ INVLIST_START = 13, VOCAB_START = 18};
+
+class MadsInterfaceView : public GameInterfaceView {
+private:
+ IntegerList _inventoryList;
+ RectList _screenObjects;
+ int _highlightedElement;
+ int _topIndex;
+ uint32 _nextScrollerTicks;
+ int _cheatKeyCtr;
+
+ // Object display fields
+ int _selectedObject;
+ SpriteAsset *_objectSprites;
+ RGBList *_objectPalData;
+ int _objectFrameNumber;
+
+ void setFontMode(InterfaceFontMode newMode);
+ bool handleCheatKey(int32 keycode);
+ bool handleKeypress(int32 keycode);
+ void leaveScene();
+public:
+ MadsInterfaceView(MadsM4Engine *vm);
+ ~MadsInterfaceView();
+
+ virtual void initialise();
+ virtual void setSelectedObject(int objectNumber);
+ virtual void addObjectToInventory(int objectNumber);
+ int getSelectedObject() { return _selectedObject; }
+ int getInventoryObject(int objectIndex) { return _inventoryList[objectIndex]; }
+
+ void onRefresh(RectList *rects, M4Surface *destSurface);
+ bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents);
};
} // End of namespace M4
diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp
index e50c35bc04..3e5f0c2ac9 100644
--- a/engines/m4/mads_views.cpp
+++ b/engines/m4/mads_views.cpp
@@ -24,6 +24,7 @@
*/
#include "m4/m4_views.h"
+#include "m4/animation.h"
#include "m4/dialogs.h"
#include "m4/events.h"
#include "m4/font.h"
@@ -36,14 +37,324 @@
namespace M4 {
-static const int INV_ANIM_FRAME_SPEED = 2;
-static const int INVENTORY_X = 160;
-static const int INVENTORY_Y = 159;
-static const int SCROLLER_DELAY = 200;
+MadsAction::MadsAction(MadsView &owner): _owner(owner) {
+ clear();
+ _currentAction = kVerbNone;
+ _startWalkFlag = false;
+ _statusTextIndex = -1;
+ _selectedAction = 0;
+ _inProgress = false;
+}
+
+void MadsAction::clear() {
+ _v83338 = 1;
+ _actionMode = ACTMODE_NONE;
+ _actionMode2 = ACTMODE2_0;
+ _v86F42 = 0;
+ _v86F4E = 0;
+ _articleNumber = 0;
+ _lookFlag = false;
+ _v86F4A = 0;
+ _statusText[0] = '\0';
+ _selectedRow = -1;
+ _hotspotId = -1;
+ _v86F3A = -1;
+ _v86F4C = -1;
+ _action.verbId = -1;
+ _action.objectNameId = -1;
+ _action.indirectObjectId = -1;
+ _textChanged = true;
+ _walkFlag = false;
+}
+
+void MadsAction::appendVocab(int vocabId, bool capitalise) {
+ char *s = _statusText + strlen(_statusText);
+ const char *vocabStr = _madsVm->globals()->getVocab(vocabId);
+ strcpy(s, vocabStr);
+ if (capitalise)
+ *s = toupper(*s);
+
+ strcat(s, " ");
+}
+
+void MadsAction::set() {
+ int hotspotCount = _madsVm->scene()->getSceneResources().hotspots->size();
+ bool flag = false;
+ strcpy(_statusText, "");
+
+ _currentAction = -1;
+ _action.objectNameId = -1;
+ _action.indirectObjectId = -1;
+
+ if (_actionMode == ACTMODE_TALK) {
+ // Handle showing the conversation selection. Rex at least doesn't actually seem to use this
+ if (_selectedRow >= 0) {
+ const char *desc = _madsVm->_converse[_selectedRow].desc;
+ if (desc)
+ strcpy(_statusText, desc);
+ }
+ } else if (_lookFlag && (_selectedRow == 0)) {
+ // Two 'look' actions in succession, so the action becomes 'Look around'
+ strcpy(_statusText, lookAroundStr);
+ } else {
+ if ((_actionMode == ACTMODE_OBJECT) && (_selectedRow >= 0) && (_flags1 == 2) && (_flags2 == 0)) {
+ // Use/to action
+ int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
+ MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
+
+ _action.objectNameId = objEntry->descId;
+ _currentAction = objEntry->vocabList[_selectedRow].vocabId;
+
+ // Set up the status text stirng
+ strcpy(_statusText, useStr);
+ appendVocab(_action.objectNameId);
+ strcpy(_statusText, toStr);
+ appendVocab(_currentAction);
+ } else {
+ // Handling for if an action has been selected
+ if (_selectedRow >= 0) {
+ if (_actionMode == ACTMODE_VERB) {
+ // Standard verb action
+ _currentAction = verbList[_selectedRow].verb;
+ } else {
+ // Selected action on an inventory object
+ int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
+ MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
+
+ _currentAction = objEntry->vocabList[_selectedRow].vocabId;
+ }
+
+ appendVocab(_currentAction, true);
+
+ if (_currentAction == kVerbLook) {
+ // Add in the word 'add'
+ strcat(_statusText, atStr);
+ strcat(_statusText, " ");
+ }
+ }
+
+ // Handling for if a hotspot has been selected/highlighted
+ if ((_hotspotId >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_flags1 == 2)) {
+ flag = true;
+
+ strcat(_statusText, englishMADSArticleList[_articleNumber]);
+ strcat(_statusText, " ");
+ }
+
+ if (_hotspotId >= 0) {
+ if (_selectedRow < 0) {
+ int verbId;
+
+ if (_hotspotId < hotspotCount) {
+ // Get the verb Id from the hotspot
+ verbId = (*_madsVm->scene()->getSceneResources().hotspots)[_hotspotId].getVerbID();
+ } else {
+ // Get the verb Id from the scene object
+ verbId = (*_madsVm->scene()->getSceneResources().dynamicHotspots)[_hotspotId - hotspotCount].getVerbID();
+ }
+
+ if (verbId > 0) {
+ // Set the specified action
+ _currentAction = verbId;
+ appendVocab(_currentAction, true);
+ } else {
+ // Default to a standard 'walk to'
+ _currentAction = kVerbWalkTo;
+ strcat(_statusText, walkToStr);
+ }
+ }
+
+ if ((_actionMode2 == ACTMODE2_2) || (_actionMode2 == ACTMODE2_5)) {
+ // Get name from given inventory object
+ int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_hotspotId);
+ _action.objectNameId = _madsVm->globals()->getObject(objectId)->descId;
+ } else if (_hotspotId < hotspotCount) {
+ // Get name from scene hotspot
+ _action.objectNameId = (*_madsVm->scene()->getSceneResources().hotspots)[_hotspotId].getVocabID();
+ } else {
+ // Get name from temporary scene hotspot
+ _action.objectNameId = (*_madsVm->scene()->getSceneResources().dynamicHotspots)[_hotspotId].getVocabID();
+ }
+ appendVocab(_action.objectNameId);
+ }
+ }
+
+ if ((_hotspotId >= 0) && (_articleNumber > 0) && !flag) {
+ if (_articleNumber == -1) {
+ if (_v86F3A >= 0) {
+ int articleNum = 0;
+
+ if ((_v86F42 == 2) || (_v86F42 == 5)) {
+ int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_hotspotId);
+ articleNum = _madsVm->globals()->getObject(objectId)->article;
+ } else if (_v86F3A < hotspotCount) {
+ articleNum = (*_madsVm->scene()->getSceneResources().hotspots)[_hotspotId].getArticle();
+ } else {
+
+ }
+ }
+
+ } else if ((_articleNumber == kVerbLook) || (_vm->getGameType() != GType_RexNebular) ||
+ (strcmp(_madsVm->globals()->getVocab(_action.indirectObjectId), fenceStr) != 0)) {
+ // Write out the article
+ strcat(_statusText, englishMADSArticleList[_articleNumber]);
+ } else {
+ // Special case for a 'fence' entry in Rex Nebular
+ strcat(_statusText, overStr);
+ }
+
+ strcat(_statusText, " ");
+ }
+
+ // Append object description if necessary
+ if (_v86F3A >= 0)
+ appendVocab(_action.indirectObjectId);
+
+ // Remove any trailing space character
+ int statusLen = strlen(_statusText);
+ if ((statusLen > 0) && (_statusText[statusLen - 1] == ' '))
+ _statusText[statusLen - 1] = '\0';
+ }
+
+ _textChanged = true;
+}
+
+void MadsAction::refresh() {
+ // Exit immediately if nothing has changed
+ if (!_textChanged)
+ return;
+
+ // Remove any old copy of the status text
+ if (_statusTextIndex >= 0) {
+ _owner._textDisplay.expire(_statusTextIndex);
+ _statusTextIndex = -1;
+ }
+
+ if (strlen(_statusText) != 0) {
+ if ((_owner._screenObjects._v832EC == 0) || (_owner._screenObjects._v832EC == 2)) {
+ Font *font = _madsVm->_font->getFont(FONT_MAIN_MADS);
+ int textSpacing = -1;
+
+ int strWidth = font->getWidth(_statusText);
+ if (strWidth > 320) {
+ // Too large to fit, so fall back on interface font
+ font = _madsVm->_font->getFont(FONT_INTERFACE_MADS);
+ strWidth = font->getWidth(_statusText, 0);
+ textSpacing = 0;
+ }
+
+ // Add a new text display entry to display the status text at the bottom of the screen area
+ uint colours = (_vm->getGameType() == GType_DragonSphere) ? 0x0300 : 0x0003;
+
+ _statusTextIndex = _owner._textDisplay.add(160 - (strWidth / 2),
+ MADS_SURFACE_HEIGHT + _owner._posAdjust.y - 13, colours, textSpacing, _statusText, font);
+ }
+ }
+
+ _textChanged = false;
+}
+
+void MadsAction::startAction() {
+ _madsVm->_player.moveComplete();
+
+ _inProgress = true;
+ _v8453A = 0;
+ _savedFields.selectedRow = _selectedRow;
+ _savedFields.articleNumber = _articleNumber;
+ _savedFields.actionMode = _actionMode;
+ _savedFields.actionMode2 = _actionMode2;
+ _savedFields.lookFlag = _lookFlag;
+ int savedHotspotId = _hotspotId;
+ int savedV86F3A = _v86F3A;
+ int savedV86F42 = _v86F42;
+
+ // Copy the action to be active
+ _activeAction = _action;
+ strcpy(_dialogTitle, _statusText);
+
+ if ((_savedFields.actionMode2 == ACTMODE2_4) && (savedV86F42 == 0))
+ _v8453A = true;
+
+ _startWalkFlag = false;
+ int hotspotId = -1;
+ HotSpotList &dynHotspots = *_madsVm->scene()->getSceneResources().dynamicHotspots;
+ HotSpotList &hotspots = *_madsVm->scene()->getSceneResources().hotspots;
+
+ if (!_savedFields.lookFlag && (_madsVm->scene()->_screenObjects._v832EC != 1)) {
+ if (_savedFields.actionMode2 == ACTMODE2_4)
+ hotspotId = savedHotspotId;
+ else if (savedV86F42 == 4)
+ hotspotId = savedV86F3A;
+
+ if (hotspotId >= hotspots.size()) {
+ HotSpot &hs = dynHotspots[hotspotId - hotspots.size()];
+ if ((hs.getFeetX() == -1) || (hs.getFeetX() == -3)) {
+ if (_v86F4A && ((hs.getFeetX() == -3) || (_savedFields.selectedRow < 0))) {
+ _startWalkFlag = true;
+ _madsVm->scene()->_destPos = _madsVm->scene()->_customDest;
+ }
+ } else if ((hs.getFeetX() >= 0) && ((_savedFields.actionMode == ACTMODE_NONE) || (hs.getCursor() < 2))) {
+ _startWalkFlag = true;
+ _madsVm->scene()->_destPos.x = hs.getFeetX();
+ _madsVm->scene()->_destPos.y = hs.getFeetY();
+ }
+ _madsVm->scene()->_destFacing = hs.getFacing();
+ hotspotId = -1;
+ }
+ }
+
+ if (hotspotId >= 0) {
+ HotSpot &hs = hotspots[hotspotId];
+ if ((hs.getFeetX() == -1) || (hs.getFeetX() == -3)) {
+ if (_v86F4A && ((hs.getFeetX() == -3) || (_savedFields.selectedRow < 0))) {
+ _startWalkFlag = true;
+ _madsVm->scene()->_destPos = _madsVm->scene()->_customDest;
+ }
+ } else if ((hs.getFeetX() >= 0) && ((_savedFields.actionMode == ACTMODE_NONE) || (hs.getCursor() < 2))) {
+ _startWalkFlag = true;
+ _madsVm->scene()->_destPos.x = hs.getFeetX();
+ _madsVm->scene()->_destPos.y = hs.getFeetY();
+ }
+ _madsVm->scene()->_destFacing = hs.getFacing();
+ }
+
+ _walkFlag = _startWalkFlag;
+}
+
+void MadsAction::checkAction() {
+ if (isAction(kVerbLookAt) || isAction(kVerbThrow))
+ _startWalkFlag = 0;
+}
+
+bool MadsAction::isAction(int verbId, int objectNameId, int indirectObjectId) {
+ if (_activeAction.verbId != verbId)
+ return false;
+ if ((objectNameId != 0) && (_activeAction.objectNameId != objectNameId))
+ return false;
+ if ((indirectObjectId != 0) && (_activeAction.indirectObjectId != indirectObjectId))
+ return false;
+ return true;
+}
+
+//--------------------------------------------------------------------------
+
+bool MadsSpriteSlot::operator==(const SpriteSlotSubset &other) const {
+ return (spriteListIndex == other.spriteListIndex) && (frameNumber == other.frameNumber) &&
+ (xp == other.xp) && (yp == other.yp) && (depth == other.depth) && (scale == other.scale);
+}
+
+void MadsSpriteSlot::copy(const SpriteSlotSubset &other) {
+ spriteListIndex = other.spriteListIndex;
+ frameNumber = other.frameNumber;
+ xp = other.xp;
+ yp = other.yp;
+ depth = other.depth;
+ scale = other.scale;
+}
//--------------------------------------------------------------------------
-MadsSpriteSlots::MadsSpriteSlots() {
+MadsSpriteSlots::MadsSpriteSlots(MadsView &owner): _owner(owner) {
for (int i = 0; i < SPRITE_SLOTS_SIZE; ++i) {
MadsSpriteSlot rec;
_entries.push_back(rec);
@@ -52,6 +363,23 @@ MadsSpriteSlots::MadsSpriteSlots() {
startIndex = 0;
}
+MadsSpriteSlots::~MadsSpriteSlots() {
+ for (uint i = 0; i < _sprites.size(); ++i)
+ delete _sprites[i];
+}
+
+void MadsSpriteSlots::clear() {
+ _owner._textDisplay.clear();
+ for (uint i = 0; i < _sprites.size(); ++i)
+ delete _sprites[i];
+ _sprites.clear();
+
+ // Reset the sprite slots list back to a single entry for a full screen refresh
+ startIndex = 1;
+ _entries[0].spriteType = FULL_SCREEN_REFRESH;
+ _entries[0].seqIndex = -1;
+}
+
int MadsSpriteSlots::getIndex() {
if (startIndex == SPRITE_SLOTS_SIZE)
error("Run out of sprite slots");
@@ -59,25 +387,48 @@ int MadsSpriteSlots::getIndex() {
return startIndex++;
}
-int MadsSpriteSlots::addSprites(const char *resName) {
+int MadsSpriteSlots::addSprites(const char *resName, bool suppressErrors, int flags) {
+ // If errors are suppressed, first check if the resource exists
+ if (suppressErrors) {
+ if (!_vm->res()->resourceExists(resName))
+ return -1;
+ }
+
// Get the sprite set
Common::SeekableReadStream *data = _vm->res()->get(resName);
- SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName);
+ SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName, false, flags);
spriteSet->translate(_madsVm->_palette);
+ assert(spriteSet != NULL);
- _sprites.push_back(SpriteList::value_type(spriteSet));
+ _sprites.push_back(spriteSet);
_vm->res()->toss(resName);
return _sprites.size() - 1;
}
+int MadsSpriteSlots::addSprites(SpriteAsset *spriteSet) {
+ _sprites.push_back(spriteSet);
+
+ return _sprites.size() - 1;
+}
+
+void MadsSpriteSlots::deleteSprites(int listIndex) {
+ if (listIndex < 0)
+ return;
+
+ delete _sprites[listIndex];
+ _sprites[listIndex] = NULL;
+ if (listIndex == ((int)_sprites.size() - 1))
+ _sprites.remove_at(listIndex);
+}
+
/*
* Deletes the sprite slot with the given timer entry
*/
-void MadsSpriteSlots::deleteTimer(int timerIndex) {
+void MadsSpriteSlots::deleteTimer(int seqIndex) {
for (int idx = 0; idx < startIndex; ++idx) {
- if (_entries[idx].timerIndex == timerIndex)
- _entries[idx].spriteId = -1;
+ if (_entries[idx].seqIndex == seqIndex)
+ _entries[idx].spriteType = EXPIRED_SPRITE;
}
}
@@ -95,13 +446,53 @@ bool sortHelper(const DepthEntry &entry1, const DepthEntry &entry2) {
typedef Common::List<DepthEntry> DepthList;
-void MadsSpriteSlots::draw(View *view) {
+void MadsSpriteSlots::drawBackground() {
+ // Draw all active sprites onto the background surface
+ for (int i = 0; i < startIndex; ++i) {
+ MadsSpriteSlot &slot = _entries[i];
+
+ if (slot.spriteType >= 0) {
+ _owner._dirtyAreas[i].active = false;
+ } else {
+ _owner._dirtyAreas[i].textActive = true;
+ _owner._dirtyAreas.setSpriteSlot(i, slot);
+
+ if (slot.spriteType == BACKGROUND_SPRITE) {
+ SpriteAsset &spriteSet = getSprite(slot.spriteListIndex);
+ M4Sprite *frame = spriteSet.getFrame((slot.frameNumber & 0x7fff) - 1);
+ int xp = slot.xp;
+ int yp = slot.yp;
+
+ if (_entries[i].scale != -1) {
+ // Adjust position based on frame size
+ xp -= frame->width() / 2;
+ yp -= frame->height() / 2;
+ }
+
+ if (slot.depth > 1) {
+ // Draw the frame with depth processing
+ _owner._bgSurface->copyFrom(frame, xp, yp, slot.depth, _owner._depthSurface, 100,
+ frame->getTransparencyIndex());
+ } else {
+ // No depth, so simply draw the image
+ frame->copyTo(_owner._bgSurface, xp, yp, frame->getTransparencyIndex());
+ }
+ }
+ }
+ }
+
+ // Flag any remaining dirty areas as inactive
+ for (uint i = startIndex; i < DIRTY_AREAS_TEXT_DISPLAY_IDX; ++i)
+ _owner._dirtyAreas[i].active = false;
+}
+
+void MadsSpriteSlots::drawForeground(M4Surface *viewport) {
DepthList depthList;
// Get a list of sprite object depths for active objects
for (int i = 0; i < startIndex; ++i) {
- if (_entries[i].spriteId >= 0) {
- DepthEntry rec(_entries[i].depth, i);
+ if (_entries[i].spriteType >= SPRITE_ZERO) {
+ DepthEntry rec(16 - _entries[i].depth, i);
depthList.push_back(rec);
}
}
@@ -115,42 +506,78 @@ void MadsSpriteSlots::draw(View *view) {
DepthEntry &de = *i;
MadsSpriteSlot &slot = _entries[de.index];
assert(slot.spriteListIndex < (int)_sprites.size());
- SpriteAsset &spriteSet = *_sprites[slot.spriteListIndex].get();
+ SpriteAsset &spriteSet = *_sprites[slot.spriteListIndex];
+
+ // Get the sprite frame
+ int frameNumber = slot.frameNumber & 0x7fff;
+ bool flipped = (slot.frameNumber & 0x8000) != 0;
+ M4Sprite *sprite = spriteSet.getFrame(frameNumber - 1);
- if (slot.scale < 100) {
+ M4Surface *spr = sprite;
+ if (flipped) {
+ // Create a flipped copy of the sprite temporarily
+ spr = sprite->flipHorizontal();
+ }
+
+ if ((slot.scale < 100) && (slot.scale != -1)) {
// Minimalised drawing
- assert(slot.spriteListIndex < (int)_sprites.size());
- M4Sprite *spr = spriteSet.getFrame(slot.frameNumber - 1);
- spr->draw1(view, slot.scale, slot.depth, slot.xp, slot.yp);
+ viewport->copyFrom(spr, slot.xp, slot.yp, slot.depth, _owner._depthSurface, slot.scale,
+ sprite->getTransparencyIndex());
} else {
int xp, yp;
- M4Sprite *spr = spriteSet.getFrame(slot.frameNumber - 1);
if (slot.scale == -1) {
- xp = slot.xp; // - widthAdjust;
- yp = slot.yp; // - heightAdjust;
+ xp = slot.xp - _owner._posAdjust.x;
+ yp = slot.yp - _owner._posAdjust.y;
} else {
- xp = slot.xp - (spr->width() / 2); // - widthAdjust;
- yp = slot.yp - spr->height() + 1; // - heightAdjust;
+ xp = slot.xp - (spr->width() / 2) - _owner._posAdjust.x;
+ yp = slot.yp - spr->height() - _owner._posAdjust.y + 1;
}
if (slot.depth > 1) {
- spr->draw2(view, slot.depth, xp, yp);
+ // Draw the frame with depth processing
+ viewport->copyFrom(spr, xp, yp, slot.depth, _owner._depthSurface, 100, sprite->getTransparencyIndex());
} else {
- spr->draw3(view, xp, yp);
+ // No depth, so simply draw the image
+ spr->copyTo(viewport, xp, yp, sprite->getTransparencyIndex());
}
}
+
+ // Free sprite if it was a flipped one
+ if (flipped)
+ delete spr;
+ }
+}
+
+void MadsSpriteSlots::setDirtyAreas() {
+ for (int i = 0; i < startIndex; ++i) {
+ if (_entries[i].spriteType >= 0) {
+ _owner._dirtyAreas.setSpriteSlot(i, _entries[i]);
+
+ _owner._dirtyAreas[i].textActive = (_entries[i].spriteType <= 0) ? 0 : 1;
+ _entries[i].spriteType = 0;
+ }
}
}
/**
+ * Flags the entire screen to be redrawn during the next drawing cycle
+ */
+void MadsSpriteSlots::fullRefresh() {
+ int idx = getIndex();
+
+ _entries[idx].spriteType = FULL_SCREEN_REFRESH;
+ _entries[idx].seqIndex = -1;
+}
+
+/**
* Removes any sprite slots that are no longer needed
*/
void MadsSpriteSlots::cleanUp() {
// Delete any entries that aren't needed
int idx = 0;
while (idx < startIndex) {
- if (_entries[idx].spriteId >= 0) {
+ if (_entries[idx].spriteType < 0) {
_entries.remove_at(idx);
--startIndex;
} else {
@@ -168,10 +595,11 @@ void MadsSpriteSlots::cleanUp() {
//--------------------------------------------------------------------------
-MadsTextDisplay::MadsTextDisplay() {
+MadsTextDisplay::MadsTextDisplay(MadsView &owner): _owner(owner) {
for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) {
MadsTextDisplayEntry rec;
rec.active = false;
+ rec.expire = 0;
_entries.push_back(rec);
}
}
@@ -206,22 +634,35 @@ int MadsTextDisplay::add(int xp, int yp, uint fontColour, int charSpacing, const
return usedSlot;
}
-void MadsTextDisplay::draw(View *view) {
- for (uint idx = 0; idx < _entries.size(); ++idx) {
+void MadsTextDisplay::setDirtyAreas() {
+ // Determine dirty areas for active text areas
+ for (uint idx = 0, dirtyIdx = DIRTY_AREAS_TEXT_DISPLAY_IDX; dirtyIdx < DIRTY_AREAS_SIZE; ++idx, ++dirtyIdx) {
+ if ((_entries[idx].expire >= 0) || !_entries[idx].active)
+ _owner._dirtyAreas[dirtyIdx].active = false;
+ else {
+ _owner._dirtyAreas[dirtyIdx].textActive = true;
+ _owner._dirtyAreas.setTextDisplay(dirtyIdx, _entries[idx]);
+ }
+ }
+}
+
+void MadsTextDisplay::setDirtyAreas2() {
+ // Determine dirty areas for active text areas
+ for (uint idx = 0, dirtyIdx = DIRTY_AREAS_TEXT_DISPLAY_IDX; dirtyIdx < DIRTY_AREAS_SIZE; ++idx, ++dirtyIdx) {
if (_entries[idx].active && (_entries[idx].expire >= 0)) {
- _entries[idx].font->setColours(_entries[idx].colour1,
- (_entries[idx].colour2 == 0) ? _entries[idx].colour1 : _entries[idx].colour2, 0xff);
- _entries[idx].font->writeString(view, _entries[idx].msg,
- _entries[idx].bounds.left, _entries[idx].bounds.top, _entries[idx].bounds.width(),
- _entries[idx].spacing);
+ _owner._dirtyAreas.setTextDisplay(dirtyIdx, _entries[idx]);
+ _owner._dirtyAreas[dirtyIdx].textActive = (_entries[idx].expire <= 0) ? 0 : 1;
}
}
+}
- // Clear up any now text display entries that are to be expired
+void MadsTextDisplay::draw(M4Surface *view) {
for (uint idx = 0; idx < _entries.size(); ++idx) {
- if (_entries[idx].expire < 0) {
- _entries[idx].active = false;
- _entries[idx].expire = 0;
+ if (_entries[idx].active && (_entries[idx].expire >= 0)) {
+ _entries[idx].font->setColours(_entries[idx].colour1, _entries[idx].colour2, 0);
+ _entries[idx].font->writeString(view, _entries[idx].msg,
+ _entries[idx].bounds.left, _entries[idx].bounds.top, _entries[idx].bounds.width(),
+ _entries[idx].spacing);
}
}
}
@@ -242,12 +683,13 @@ void MadsTextDisplay::cleanUp() {
MadsKernelMessageList::MadsKernelMessageList(MadsView &owner): _owner(owner) {
for (int i = 0; i < TIMED_TEXT_SIZE; ++i) {
- MadsKernelMessageListEntry rec;
+ MadsKernelMessageEntry rec;
_entries.push_back(rec);
}
_owner._textSpacing = -1;
_talkFont = _vm->_font->getFont(FONT_CONVERSATION_MADS);
+ word_8469E = 0;
}
void MadsKernelMessageList::clear() {
@@ -258,20 +700,20 @@ void MadsKernelMessageList::clear() {
_talkFont = _vm->_font->getFont(FONT_CONVERSATION_MADS);
}
-int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 flags, uint8 v2, uint32 timeout, const char *msg) {
+int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 flags, uint8 abortTimers, uint32 timeout, const char *msg) {
// Find a free slot
uint idx = 0;
while ((idx < _entries.size()) && ((_entries[idx].flags & KMSG_ACTIVE) != 0))
++idx;
if (idx == _entries.size()) {
- if (v2 == 0)
+ if (abortTimers == 0)
return -1;
error("MadsKernelList overflow");
}
- MadsKernelMessageListEntry &rec = _entries[idx];
- rec.msg = msg;
+ MadsKernelMessageEntry &rec = _entries[idx];
+ strcpy(rec.msg, msg);
rec.flags = flags | KMSG_ACTIVE;
rec.colour1 = fontColour & 0xff;
rec.colour2 = fontColour >> 8;
@@ -279,56 +721,56 @@ int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 f
rec.textDisplayIndex = -1;
rec.timeout = timeout;
rec.frameTimer = _madsVm->_currentTimer;
- rec.field_1C = v2;
+ rec.abortTimers = abortTimers;
rec.abortMode = _owner._abortTimersMode2;
for (int i = 0; i < 3; ++i)
- rec.actionNouns[i] = _madsVm->scene()->actionNouns[i];
+ rec.actionNouns[i] = _madsVm->globals()->actionNouns[i];
- if (flags & KMSG_2)
- rec.frameTimer = _owner._ticksAmount + _owner._newTimeout;
+ if (flags & KMSG_PLAYER_TIMEOUT)
+ rec.frameTimer = _madsVm->_player._ticksAmount + _madsVm->_player._priorTimer;
return idx;
}
-int MadsKernelMessageList::addQuote(int quoteId, int v2, uint32 timeout) {
+int MadsKernelMessageList::addQuote(int quoteId, int abortTimers, uint32 timeout) {
const char *quoteStr = _madsVm->globals()->getQuote(quoteId);
- return add(Common::Point(0, 0), 0x1110, KMSG_2 | KMSG_20, v2, timeout, quoteStr);
+ return add(Common::Point(0, 0), 0x1110, KMSG_PLAYER_TIMEOUT | KMSG_CENTER_ALIGN, abortTimers, timeout, quoteStr);
}
-void MadsKernelMessageList::unk1(int msgIndex, int v1, int v2) {
+void MadsKernelMessageList::scrollMessage(int msgIndex, int numTicks, bool quoted) {
if (msgIndex < 0)
return;
- _entries[msgIndex].flags |= (v2 == 0) ? KMSG_8 : (KMSG_8 | KMSG_1);
+ _entries[msgIndex].flags |= quoted ? (KMSG_SCROLL | KMSG_QUOTED) : KMSG_SCROLL;
_entries[msgIndex].msgOffset = 0;
- _entries[msgIndex].field_E = v1;
+ _entries[msgIndex].numTicks = numTicks;
_entries[msgIndex].frameTimer2 = _madsVm->_currentTimer;
const char *msgP = _entries[msgIndex].msg;
_entries[msgIndex].asciiChar = *msgP;
_entries[msgIndex].asciiChar2 = *(msgP + 1);
- if (_entries[msgIndex].flags & KMSG_2)
- _entries[msgIndex].frameTimer2 = _owner._ticksAmount + _owner._newTimeout;
+ if (_entries[msgIndex].flags & KMSG_PLAYER_TIMEOUT)
+ _entries[msgIndex].frameTimer2 = _madsVm->_player._ticksAmount + _madsVm->_player._priorTimer;
_entries[msgIndex].frameTimer = _entries[msgIndex].frameTimer2;
}
void MadsKernelMessageList::setSeqIndex(int msgIndex, int seqIndex) {
if (msgIndex >= 0) {
- _entries[msgIndex].flags |= KMSG_4;
+ _entries[msgIndex].flags |= KMSG_SEQ_ENTRY;
_entries[msgIndex].sequenceIndex = seqIndex;
}
}
void MadsKernelMessageList::remove(int msgIndex) {
- MadsKernelMessageListEntry &rec = _entries[msgIndex];
+ MadsKernelMessageEntry &rec = _entries[msgIndex];
if (rec.flags & KMSG_ACTIVE) {
- if (rec.flags & KMSG_8) {
- //*(rec.msg + rec.msgOffset) = rec.asciiChar;
- //*(rec.msg + rec.msgOffset + 1) = rec.asciiChar2;
+ if (rec.flags & KMSG_SCROLL) {
+ *(rec.msg + rec.msgOffset) = rec.asciiChar;
+ *(rec.msg + rec.msgOffset + 1) = rec.asciiChar2;
}
if (rec.textDisplayIndex >= 0)
@@ -345,8 +787,150 @@ void MadsKernelMessageList::reset() {
// sub_20454
}
+void MadsKernelMessageList::update() {
+ uint32 currentTimer = _madsVm->_currentTimer;
+
+ for (uint i = 0; i < _entries.size(); ++i) {
+ if (((_entries[i].flags & KMSG_ACTIVE) != 0) && (currentTimer >= _entries[i].frameTimer))
+ processText(i);
+ }
+}
+
+void MadsKernelMessageList::processText(int msgIndex) {
+ MadsKernelMessageEntry &msg = _entries[msgIndex];
+ uint32 currentTimer = _madsVm->_currentTimer;
+ bool flag = false;
+
+ if ((msg.flags & KMSG_EXPIRE) != 0) {
+ _owner._textDisplay.expire(msg.textDisplayIndex);
+ msg.flags &= !KMSG_ACTIVE;
+ return;
+ }
+
+ if ((msg.flags & KMSG_SCROLL) == 0) {
+ msg.timeout -= 3;
+ }
+
+ if (msg.flags & KMSG_SEQ_ENTRY) {
+ MadsSequenceEntry &seqEntry = _owner._sequenceList[msg.sequenceIndex];
+ if (seqEntry.doneFlag || !seqEntry.active)
+ msg.timeout = 0;
+ }
+
+ if ((msg.timeout <= 0) && (_owner._abortTimers == 0)) {
+ msg.flags |= KMSG_EXPIRE;
+ if (msg.abortTimers != 0) {
+ _owner._abortTimers = msg.abortTimers;
+ _owner._abortTimersMode = msg.abortMode;
+
+ if (_owner._abortTimersMode != ABORTMODE_1) {
+ for (int i = 0; i < 3; ++i)
+ _madsVm->globals()->actionNouns[i] = msg.actionNouns[i];
+ }
+ }
+ }
+
+ msg.frameTimer = currentTimer + 3;
+ int x1 = 0, y1 = 0;
+
+ if (msg.flags & KMSG_SEQ_ENTRY) {
+ MadsSequenceEntry &seqEntry = _owner._sequenceList[msg.sequenceIndex];
+ if (!seqEntry.nonFixed) {
+ SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(seqEntry.spriteListIndex);
+ M4Sprite *frame = spriteSet.getFrame(seqEntry.frameIndex - 1);
+ x1 = frame->bounds().left;
+ y1 = frame->bounds().top;
+ } else {
+ x1 = seqEntry.msgPos.x;
+ y1 = seqEntry.msgPos.y;
+ }
+ }
+
+ if (msg.flags & KMSG_PLAYER_TIMEOUT) {
+ if (word_8469E != 0) {
+ // TODO: Figure out various flags
+ } else {
+ x1 = 160;
+ y1 = 78;
+ }
+ }
+
+ x1 += msg.position.x;
+ y1 += msg.position.y;
+
+ if ((msg.flags & KMSG_SCROLL) && (msg.frameTimer >= currentTimer)) {
+ msg.msg[msg.msgOffset] = msg.asciiChar;
+ char *msgP = &msg.msg[++msg.msgOffset];
+ *msgP = msg.asciiChar2;
+
+ msg.asciiChar = *msgP;
+ msg.asciiChar2 = *(msgP + 1);
+
+ if (!msg.asciiChar) {
+ // End of message
+ *msgP = '\0';
+ msg.flags &= ~KMSG_SCROLL;
+ } else if (msg.flags & KMSG_QUOTED) {
+ *msgP = '"';
+ *(msgP + 1) = '\0';
+ }
+
+ msg.frameTimer = msg.frameTimer2 = currentTimer + msg.numTicks;
+ flag = true;
+ }
+
+ int strWidth = _talkFont->getWidth(msg.msg, _owner._textSpacing);
+
+ if (msg.flags & (KMSG_RIGHT_ALIGN | KMSG_CENTER_ALIGN)) {
+ x1 -= (msg.flags & KMSG_CENTER_ALIGN) ? strWidth / 2 : strWidth;
+ }
+
+ // Make sure text appears entirely on-screen
+ int x2 = x1 + strWidth;
+ if (x2 > MADS_SURFACE_WIDTH)
+ x1 -= x2 - MADS_SURFACE_WIDTH;
+ if (x1 > (MADS_SURFACE_WIDTH - 1))
+ x1 = MADS_SURFACE_WIDTH - 1;
+ if (x1 < 0)
+ x1 = 0;
+
+ if (y1 > (MADS_SURFACE_HEIGHT - 1))
+ y1 = MADS_SURFACE_HEIGHT - 1;
+ if (y1 < 0)
+ y1 = 0;
+
+ if (msg.textDisplayIndex >= 0) {
+ MadsTextDisplayEntry textEntry = _owner._textDisplay[msg.textDisplayIndex];
+
+ if (flag || (textEntry.bounds.left != x1) || (textEntry.bounds.top != y1)) {
+ // Mark the associated text entry as deleted, so it can be re-created
+ _owner._textDisplay.expire(msg.textDisplayIndex);
+ msg.textDisplayIndex = -1;
+ }
+ }
+
+ if (msg.textDisplayIndex < 0) {
+ // Need to create a new text display entry for this message
+ int idx = _owner._textDisplay.add(x1, y1, msg.colour1 | (msg.colour2 << 8), _owner._textSpacing, msg.msg, _talkFont);
+ if (idx >= 0)
+ msg.textDisplayIndex = idx;
+ }
+}
+
//--------------------------------------------------------------------------
+ScreenObjects::ScreenObjects(MadsView &owner): _owner(owner) {
+ _v832EC = 0;
+ _v7FECA = 0;
+ _v7FED6 = 0;
+ _v8332A = 0;
+ _yp = 0;
+ _v8333C = 0;
+ _selectedObject = 0;
+ _category = 0;
+ _objectIndex = 0;
+}
+
/**
* Clears the entries list
*/
@@ -399,27 +983,52 @@ void ScreenObjects::setActive(int category, int idx, bool active) {
}
}
+void ScreenObjects::check(bool scanFlag, bool mouseClick) {
+ if (!mouseClick || _v832EC)
+ _v7FECA = 0;
+
+ if (!_v7FED6 && !_v8332A && !_yp && (_v8333C != 0)) {
+ if (scanFlag) {
+ _category = CAT_NONE;
+ _selectedObject = scanBackwards(_madsVm->_mouse->currentPos().x, _madsVm->_mouse->currentPos().y,
+ LAYER_GUI);
+
+ if (_selectedObject > 0) {
+ ScreenObjectEntry &obj = _entries[_selectedObject];
+ _category = obj.category & 7;
+ _objectIndex = obj.index;
+ }
+
+ // TODO: Other stuff related to the user interface
+ }
+ }
+
+ _owner._action.refresh();
+}
+
/*--------------------------------------------------------------------------*/
MadsDynamicHotspots::MadsDynamicHotspots(MadsView &owner): _owner(owner) {
for (int i = 0; i < DYNAMIC_HOTSPOTS_SIZE; ++i) {
DynamicHotspot rec;
rec.active = false;
+ _entries.push_back(rec);
}
- _flag = true;
+ _changed = true;
_count = 0;
}
-int MadsDynamicHotspots::add(int descId, int field14, int timerIndex, const Common::Rect &bounds) {
+int MadsDynamicHotspots::add(int descId, int field14, int seqIndex, const Common::Rect &bounds) {
// Find a free slot
uint idx = 0;
- while ((idx < _entries.size()) && !_entries[idx].active)
+ while ((idx < _entries.size()) && _entries[idx].active)
++idx;
if (idx == _entries.size())
error("MadsDynamicHotspots overflow");
_entries[idx].active = true;
_entries[idx].descId = descId;
+ _entries[idx].seqIndex = seqIndex;
_entries[idx].bounds = bounds;
_entries[idx].pos.x = -3;
_entries[idx].pos.y = 0;
@@ -429,8 +1038,10 @@ int MadsDynamicHotspots::add(int descId, int field14, int timerIndex, const Comm
_entries[idx].field_17 = 0;
++_count;
- _flag = true;
- _owner._sequenceList[timerIndex].dynamicHotspotIndex = idx;
+ _changed = true;
+
+ if (seqIndex >= 0)
+ _owner._sequenceList[seqIndex].dynamicHotspotIndex = idx;
return idx;
}
@@ -454,12 +1065,12 @@ int MadsDynamicHotspots::set17(int index, int v) {
void MadsDynamicHotspots::remove(int index) {
if (_entries[index].active) {
- if (_entries[index].timerIndex >= 0)
- _owner._sequenceList[_entries[index].timerIndex].dynamicHotspotIndex = -1;
+ if (_entries[index].seqIndex >= 0)
+ _owner._sequenceList[_entries[index].seqIndex].dynamicHotspotIndex = -1;
_entries[index].active = false;
--_count;
- _flag = true;
+ _changed = true;
}
}
@@ -468,7 +1079,160 @@ void MadsDynamicHotspots::reset() {
_entries[i].active = false;
_count = 0;
- _flag = false;
+ _changed = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void MadsDirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) {
+ if (bounds.left % 2) {
+ --bounds.left;
+ ++width;
+ }
+
+ if (bounds.left < 0)
+ bounds.left = 0;
+ else if (bounds.left > maxWidth)
+ bounds.left = maxWidth;
+ int right = bounds.left + width;
+ if (right < 0)
+ right = 0;
+ if (right > maxWidth)
+ right = maxWidth;
+
+ bounds.right = right;
+ bounds2.left = bounds.width() / 2;
+ bounds2.right = bounds.left + (bounds.width() + 1) / 2 - 1;
+
+ if (bounds.top < 0)
+ bounds.top = 0;
+ else if (bounds.top > maxHeight)
+ bounds.top = maxHeight;
+ int bottom = bounds.top + height;
+ if (bottom < 0)
+ bottom = 0;
+ if (bottom > maxHeight)
+ bottom = maxHeight;
+
+ bounds.bottom = bottom;
+ bounds2.top = bounds.height() / 2;
+ bounds2.bottom = bounds.top + (bounds.height() + 1) / 2 - 1;
+
+ active = true;
+}
+
+/*--------------------------------------------------------------------------*/
+
+MadsDirtyAreas::MadsDirtyAreas(MadsView &owner): _owner(owner) {
+ for (int i = 0; i < DIRTY_AREAS_SIZE; ++i) {
+ MadsDirtyArea rec;
+ rec.active = false;
+ _entries.push_back(rec);
+ }
+}
+
+void MadsDirtyAreas::setSpriteSlot(int dirtyIdx, const MadsSpriteSlot &spriteSlot) {
+ int width, height;
+ MadsDirtyArea &dirtyArea = _entries[dirtyIdx];
+
+ if (spriteSlot.spriteType == FULL_SCREEN_REFRESH) {
+ // Special entry to refresh the entire screen
+ dirtyArea.bounds.left = 0;
+ dirtyArea.bounds.top = 0;
+ width = MADS_SURFACE_WIDTH;
+ height = MADS_SURFACE_HEIGHT;
+ } else {
+ // Standard sprite slots
+ dirtyArea.bounds.left = spriteSlot.xp - _owner._posAdjust.x;
+ dirtyArea.bounds.top = spriteSlot.yp - _owner._posAdjust.y;
+
+ SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(spriteSlot.spriteListIndex);
+ M4Sprite *frame = spriteSet.getFrame(((spriteSlot.frameNumber & 0x7fff) - 1) & 0x7f);
+
+ if (spriteSlot.scale == -1) {
+ width = frame->width();
+ height = frame->height();
+ } else {
+ width = frame->width() * spriteSlot.scale / 100;
+ height = frame->height() * spriteSlot.scale / 100;
+
+ dirtyArea.bounds.left -= width / 2;
+ dirtyArea.bounds.top += -(height - 1);
+ }
+ }
+
+ dirtyArea.setArea(width, height, MADS_SURFACE_WIDTH, MADS_SURFACE_HEIGHT);
+}
+
+void MadsDirtyAreas::setTextDisplay(int dirtyIdx, const MadsTextDisplayEntry &textDisplay) {
+ MadsDirtyArea &dirtyArea = _entries[dirtyIdx];
+ dirtyArea.bounds.left = textDisplay.bounds.left;
+ dirtyArea.bounds.top = textDisplay.bounds.top;
+
+ dirtyArea.setArea(textDisplay.bounds.width(), textDisplay.bounds.height(), MADS_SURFACE_WIDTH, MADS_SURFACE_HEIGHT);
+}
+
+/**
+ * Merge together any designated dirty areas that overlap
+ * @param startIndex 1-based starting dirty area starting index
+ * @param count Number of entries to process
+ */
+void MadsDirtyAreas::merge(int startIndex, int count) {
+return;//***DEBUG***
+ if (startIndex >= count)
+ return;
+
+ for (int outerCtr = startIndex - 1, idx = 0; idx < count; ++outerCtr, ++idx) {
+ if (!_entries[outerCtr].active)
+ continue;
+
+ for (int innerCtr = outerCtr + 1; innerCtr < count; ++innerCtr) {
+ if (!_entries[innerCtr].active || !intersects(outerCtr, innerCtr))
+ continue;
+
+ if (_entries[outerCtr].textActive && _entries[innerCtr].textActive)
+ mergeAreas(outerCtr, innerCtr);
+ }
+ }
+}
+
+/**
+ * Returns true if two dirty areas intersect
+ */
+bool MadsDirtyAreas::intersects(int idx1, int idx2) {
+ return _entries[idx1].bounds2.intersects(_entries[idx2].bounds2);
+}
+
+void MadsDirtyAreas::mergeAreas(int idx1, int idx2) {
+ MadsDirtyArea &da1 = _entries[idx1];
+ MadsDirtyArea &da2 = _entries[idx2];
+
+ da1.bounds.extend(da2.bounds);
+
+ da1.bounds2.left = da1.bounds.width() / 2;
+ da1.bounds2.right = da1.bounds.left + (da1.bounds.width() + 1) / 2 - 1;
+ da1.bounds2.top = da1.bounds.height() / 2;
+ da1.bounds2.bottom = da1.bounds.top + (da1.bounds.height() + 1) / 2 - 1;
+
+ da2.active = false;
+ da1.textActive = true;
+}
+
+void MadsDirtyAreas::copy(M4Surface *dest, M4Surface *src, const Common::Point &posAdjust) {
+ for (uint i = 0; i < _entries.size(); ++i) {
+ const Common::Rect &srcBounds = _entries[i].bounds;
+
+ Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y,
+ srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y);
+
+ if (_entries[i].active && _entries[i].bounds.isValidRect())
+ src->copyTo(dest, bounds, _entries[i].bounds.left, _entries[i].bounds.top);
+ }
+}
+
+void MadsDirtyAreas::clear() {
+ for (uint i = 0; i < _entries.size(); ++i)
+ _entries[i].active = false;
}
/*--------------------------------------------------------------------------*/
@@ -501,15 +1265,15 @@ bool MadsSequenceList::addSubEntry(int index, SequenceSubEntryMode mode, int fra
return false;
}
-int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, int triggerCountdown, int delayTicks, int extraTicks, int numTicks,
- int height, int width, char field_12, char scale, uint8 depth, int frameInc, SpriteAnimType animType, int numSprites,
+int MadsSequenceList::add(int spriteListIndex, bool flipped, int frameIndex, int triggerCountdown, int delayTicks, int extraTicks, int numTicks,
+ int msgX, int msgY, bool nonFixed, char scale, uint8 depth, int frameInc, SpriteAnimType animType, int numSprites,
int frameStart) {
// Find a free slot
- uint timerIndex = 0;
- while ((timerIndex < _entries.size()) && (_entries[timerIndex].active))
- ++timerIndex;
- if (timerIndex == _entries.size())
+ uint seqIndex = 0;
+ while ((seqIndex < _entries.size()) && (_entries[seqIndex].active))
+ ++seqIndex;
+ if (seqIndex == _entries.size())
error("TimerList full");
if (frameStart <= 0)
@@ -520,77 +1284,76 @@ int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, int trigg
frameInc = 0;
// Set the list entry fields
- _entries[timerIndex].active = true;
- _entries[timerIndex].spriteListIndex = spriteListIndex;
- _entries[timerIndex].field_2 = v0;
- _entries[timerIndex].frameIndex = frameIndex;
- _entries[timerIndex].frameStart = frameStart;
- _entries[timerIndex].numSprites = numSprites;
- _entries[timerIndex].animType = animType;
- _entries[timerIndex].frameInc = frameInc;
- _entries[timerIndex].depth = depth;
- _entries[timerIndex].scale = scale;
- _entries[timerIndex].field_12 = field_12;
- _entries[timerIndex].width = width;
- _entries[timerIndex].height = height;
- _entries[timerIndex].numTicks = numTicks;
- _entries[timerIndex].extraTicks = extraTicks;
-
- _entries[timerIndex].timeout = _madsVm->_currentTimer + delayTicks;
-
- _entries[timerIndex].triggerCountdown = triggerCountdown;
- _entries[timerIndex].doneFlag = false;
- _entries[timerIndex].field_13 = 0;
- _entries[timerIndex].dynamicHotspotIndex = -1;
- _entries[timerIndex].entries.count = 0;
- _entries[timerIndex].abortMode = _owner._abortTimersMode2;
+ _entries[seqIndex].active = true;
+ _entries[seqIndex].spriteListIndex = spriteListIndex;
+ _entries[seqIndex].flipped = flipped;
+ _entries[seqIndex].frameIndex = frameIndex;
+ _entries[seqIndex].frameStart = frameStart;
+ _entries[seqIndex].numSprites = numSprites;
+ _entries[seqIndex].animType = animType;
+ _entries[seqIndex].frameInc = frameInc;
+ _entries[seqIndex].depth = depth;
+ _entries[seqIndex].scale = scale;
+ _entries[seqIndex].nonFixed = nonFixed;
+ _entries[seqIndex].msgPos.x = msgX;
+ _entries[seqIndex].msgPos.y = msgY;
+ _entries[seqIndex].numTicks = numTicks;
+ _entries[seqIndex].extraTicks = extraTicks;
+
+ _entries[seqIndex].timeout = _madsVm->_currentTimer + delayTicks;
+
+ _entries[seqIndex].triggerCountdown = triggerCountdown;
+ _entries[seqIndex].doneFlag = false;
+ _entries[seqIndex].field_13 = 0;
+ _entries[seqIndex].dynamicHotspotIndex = -1;
+ _entries[seqIndex].entries.count = 0;
+ _entries[seqIndex].abortMode = _owner._abortTimersMode2;
for (int i = 0; i < 3; ++i)
- _entries[timerIndex].actionNouns[i] = _madsVm->scene()->actionNouns[i];
+ _entries[seqIndex].actionNouns[i] = _madsVm->globals()->actionNouns[i];
- return timerIndex;
+ return seqIndex;
}
-void MadsSequenceList::remove(int timerIndex) {
- if (_entries[timerIndex].active) {
- if (_entries[timerIndex].dynamicHotspotIndex >= 0)
- _owner._dynamicHotspots.remove(_entries[timerIndex].dynamicHotspotIndex);
+void MadsSequenceList::remove(int seqIndex) {
+ if (_entries[seqIndex].active) {
+ if (_entries[seqIndex].dynamicHotspotIndex >= 0)
+ _owner._dynamicHotspots.remove(_entries[seqIndex].dynamicHotspotIndex);
}
- _entries[timerIndex].active = false;
- _owner._spriteSlots.deleteTimer(timerIndex);
+ _entries[seqIndex].active = false;
+ _owner._spriteSlots.deleteTimer(seqIndex);
}
-void MadsSequenceList::setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot) {
- MadsSequenceEntry &timerEntry = _entries[timerIndex];
- SpriteAsset &sprite = _owner._spriteSlots.getSprite(timerEntry.spriteListIndex);
+void MadsSequenceList::setSpriteSlot(int seqIndex, MadsSpriteSlot &spriteSlot) {
+ MadsSequenceEntry &timerEntry = _entries[seqIndex];
+ SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(timerEntry.spriteListIndex);
- // TODO: Figure out logic for spriteId value based on SPRITE_SLOT.field_0
- spriteSlot.spriteId = (0 /*field 0*/ == 1) ? -4 : 1;
- spriteSlot.timerIndex = timerIndex;
+ spriteSlot.spriteType = spriteSet.isBackground() ? BACKGROUND_SPRITE : FOREGROUND_SPRITE;
+ spriteSlot.seqIndex = seqIndex;
spriteSlot.spriteListIndex = timerEntry.spriteListIndex;
- spriteSlot.frameNumber = ((timerEntry.field_2 == 1) ? 0x8000 : 0) | timerEntry.frameIndex;
+ spriteSlot.frameNumber = (timerEntry.flipped ? 0x8000 : 0) | timerEntry.frameIndex;
spriteSlot.depth = timerEntry.depth;
spriteSlot.scale = timerEntry.scale;
- if (timerEntry.field_12 == 0) {
- spriteSlot.xp = timerEntry.width;
- spriteSlot.yp = timerEntry.height;
+ if (!timerEntry.nonFixed) {
+ spriteSlot.xp = timerEntry.msgPos.x;
+ spriteSlot.yp = timerEntry.msgPos.y;
} else {
- spriteSlot.xp = sprite.getFrame(timerEntry.frameIndex - 1)->x;
- spriteSlot.yp = sprite.getFrame(timerEntry.frameIndex - 1)->y;
+ spriteSlot.xp = spriteSet.getFrame(timerEntry.frameIndex - 1)->x;
+ spriteSlot.yp = spriteSet.getFrame(timerEntry.frameIndex - 1)->y;
}
}
-bool MadsSequenceList::loadSprites(int timerIndex) {
- MadsSequenceEntry &seqEntry = _entries[timerIndex];
+bool MadsSequenceList::loadSprites(int seqIndex) {
+ MadsSequenceEntry &seqEntry = _entries[seqIndex];
int slotIndex;
bool result = false;
int idx = -1;
- _owner._spriteSlots.deleteTimer(timerIndex);
+ _owner._spriteSlots.deleteTimer(seqIndex);
if (seqEntry.doneFlag) {
- remove(timerIndex);
+ remove(seqIndex);
return false;
}
@@ -599,7 +1362,7 @@ bool MadsSequenceList::loadSprites(int timerIndex) {
seqEntry.doneFlag = true;
} else if ((slotIndex = _owner._spriteSlots.getIndex()) >= 0) {
MadsSpriteSlot &spriteSlot = _owner._spriteSlots[slotIndex];
- setSpriteSlot(timerIndex, spriteSlot);
+ setSpriteSlot(seqIndex, spriteSlot);
int x2 = 0, y2 = 0;
@@ -621,7 +1384,7 @@ bool MadsSequenceList::loadSprites(int timerIndex) {
dynHotspot.bounds.top = MAX(y2 - height, 0);
dynHotspot.bounds.bottom = MIN(y2, 155) - dynHotspot.bounds.top;
- _owner._dynamicHotspots._flag = true;
+ _owner._dynamicHotspots._changed = true;
}
}
@@ -727,454 +1490,138 @@ void MadsSequenceList::delay(uint32 v1, uint32 v2) {
}
}
-//--------------------------------------------------------------------------
+void MadsSequenceList::setAnimRange(int seqIndex, int startVal, int endVal) {
+ MadsSequenceEntry &seqEntry = _entries[seqIndex];
+ SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(seqEntry.spriteListIndex);
+ int numSprites = spriteSet.getCount();
+ int tempStart = startVal, tempEnd = endVal;
-MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this),
- _kernelMessages(*this) {
- _textSpacing = -1;
- _ticksAmount = 3;
- _newTimeout = 0;
- _abortTimers = 0;
- _abortTimers2 = 0;
- _abortTimersMode = ABORTMODE_0;
- _abortTimersMode2 = ABORTMODE_0;
-}
-
-void MadsView::refresh() {
- // Draw any sprites
- _spriteSlots.draw(_view);
-
- // Draw text elements onto the view
- _textDisplay.draw(_view);
-
- // Remove any sprite slots that are no longer needed
- _spriteSlots.cleanUp();
-
- // Deactivate any text display entries that are no longer needed
- _textDisplay.cleanUp();
-}
-
-/*--------------------------------------------------------------------------
- * MadsInterfaceView handles the user interface section at the bottom of
- * game screens in MADS games
- *--------------------------------------------------------------------------
- */
-
-MadsInterfaceView::MadsInterfaceView(MadsM4Engine *vm): GameInterfaceView(vm,
- Common::Rect(0, MADS_SURFACE_HEIGHT, vm->_screen->width(), vm->_screen->height())) {
- _screenType = VIEWID_INTERFACE;
- _highlightedElement = -1;
- _topIndex = 0;
- _selectedObject = -1;
- _cheatKeyCtr = 0;
-
- _objectSprites = NULL;
- _objectPalData = NULL;
-
- /* Set up the rect list for screen elements */
- // Actions
- for (int i = 0; i < 10; ++i)
- _screenObjects.addRect((i / 5) * 32 + 1, (i % 5) * 8 + MADS_SURFACE_HEIGHT + 2,
- ((i / 5) + 1) * 32 + 3, ((i % 5) + 1) * 8 + MADS_SURFACE_HEIGHT + 2);
-
- // Scroller elements (up arrow, scroller, down arrow)
- _screenObjects.addRect(73, 160, 82, 167);
- _screenObjects.addRect(73, 168, 82, 190);
- _screenObjects.addRect(73, 191, 82, 198);
-
- // Inventory object names
- for (int i = 0; i < 5; ++i)
- _screenObjects.addRect(89, 158 + i * 8, 160, 166 + i * 8);
-
- // Full rectangle area for all vocab actions
- for (int i = 0; i < 5; ++i)
- _screenObjects.addRect(239, 158 + i * 8, 320, 166 + i * 8);
-}
-
-MadsInterfaceView::~MadsInterfaceView() {
- delete _objectSprites;
-}
-
-void MadsInterfaceView::setFontMode(InterfaceFontMode newMode) {
- switch (newMode) {
- case ITEM_NORMAL:
- _vm->_font->setColors(4, 4, 0xff);
+ switch (startVal) {
+ case -2:
+ tempStart = numSprites;
break;
- case ITEM_HIGHLIGHTED:
- _vm->_font->setColors(5, 5, 0xff);
+ case -1:
+ tempStart = 1;
break;
- case ITEM_SELECTED:
- _vm->_font->setColors(6, 6, 0xff);
+ }
+
+ switch (endVal) {
+ case -2:
+ case 0:
+ tempEnd = numSprites;
+ break;
+ case -1:
+ tempEnd = 1;
+ break;
+ default:
+ tempEnd = numSprites;
break;
}
-}
-
-void MadsInterfaceView::initialise() {
- // Build up the inventory list
- _inventoryList.clear();
- for (uint i = 0; i < _madsVm->globals()->getObjectsSize(); ++i) {
- MadsObject *obj = _madsVm->globals()->getObject(i);
- if (obj->roomNumber == PLAYER_INVENTORY)
- _inventoryList.push_back(i);
- }
+ seqEntry.frameStart = tempStart;
+ seqEntry.numSprites = tempEnd;
- // If the inventory has at least one object, select it
- if (_inventoryList.size() > 0)
- setSelectedObject(_inventoryList[0]);
+ seqEntry.frameIndex = (seqEntry.frameInc < 0) ? tempStart : tempEnd;
}
-void MadsInterfaceView::setSelectedObject(int objectNumber) {
- char resName[80];
-
- // Load inventory resource
- if (_objectSprites) {
- _vm->_palette->deleteRange(_objectPalData);
- delete _objectSprites;
- }
-
- // Check to make sure the object is in the inventory, and also visible on-screen
- int idx = _inventoryList.indexOf(objectNumber);
- if (idx == -1) {
- // Object wasn't found, so return
- _selectedObject = -1;
- return;
+void MadsSequenceList::scan() {
+ for (uint i = 0; i < _entries.size(); ++i) {
+ if (!_entries[i].active && (_entries[i].spriteListIndex != -1)) {
+ int idx = _owner._spriteSlots.getIndex();
+ setSpriteSlot(i, _owner._spriteSlots[idx]);
+ }
}
-
- // Found the object
- if (idx < _topIndex)
- _topIndex = idx;
- else if (idx >= (_topIndex + 5))
- _topIndex = MAX(0, idx - 4);
-
- _selectedObject = objectNumber;
- sprintf(resName, "*OB%.3dI.SS", objectNumber);
-
- Common::SeekableReadStream *data = _vm->res()->get(resName);
- _objectSprites = new SpriteAsset(_vm, data, data->size(), resName);
- _vm->res()->toss(resName);
-
- // Slot it into available palette space
- _objectPalData = _objectSprites->getRgbList();
- _vm->_palette->addRange(_objectPalData);
- _objectSprites->translate(_objectPalData, true);
-
- _objectFrameNumber = 0;
}
-void MadsInterfaceView::addObjectToInventory(int objectNumber) {
- if (_inventoryList.indexOf(objectNumber) == -1) {
- _madsVm->globals()->getObject(objectNumber)->roomNumber = PLAYER_INVENTORY;
- _inventoryList.push_back(objectNumber);
- }
-
- setSelectedObject(objectNumber);
+/**
+ * Sets the depth of the specified entry in the sequence list
+ */
+void MadsSequenceList::setDepth(int seqIndex, int depth) {
+ _entries[seqIndex].depth = depth;
}
-void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
- _vm->_font->setFont(FONT_INTERFACE_MADS);
- char buffer[100];
-
- // Check to see if any dialog is currently active
- bool dialogVisible = _vm->_viewManager->getView(LAYER_DIALOG) != NULL;
-
- // Highlighting logic for action list
- int actionIndex = 0;
- for (int x = 0; x < 2; ++x) {
- for (int y = 0; y < 5; ++y, ++actionIndex) {
- // Determine the font colour depending on whether an item is selected. Note that the first action,
- // 'Look', is always 'selected', even when another action is clicked on
- setFontMode((_highlightedElement == actionIndex) ? ITEM_HIGHLIGHTED :
- ((actionIndex == 0) ? ITEM_SELECTED : ITEM_NORMAL));
-
- // Get the verb action and capitalise it
- const char *verbStr = _madsVm->globals()->getVocab(kVerbLook + actionIndex);
- strcpy(buffer, verbStr);
- if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
-
- // Display the verb
- const Common::Rect r(_screenObjects[actionIndex]);
- _vm->_font->writeString(destSurface, buffer, r.left, r.top, r.width(), 0);
- }
- }
-
- // Check for highlighting of the scrollbar controls
- if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_SCROLLER) || (_highlightedElement == SCROLL_DOWN)) {
- // Highlight the control's borders
- const Common::Rect r(_screenObjects[_highlightedElement]);
- destSurface->frameRect(r, 5);
- }
-
- // Draw the horizontal line in the scroller representing the current top selected
- const Common::Rect scroller(_screenObjects[SCROLL_SCROLLER]);
- int yP = (_inventoryList.size() < 2) ? 0 : (scroller.height() - 5) * _topIndex / (_inventoryList.size() - 1);
- destSurface->setColor(4);
- destSurface->hLine(scroller.left + 2, scroller.right - 3, scroller.top + 2 + yP);
-
- // List inventory items
- for (uint i = 0; i < 5; ++i) {
- if ((_topIndex + i) >= _inventoryList.size())
- break;
-
- const char *descStr = _madsVm->globals()->getVocab(_madsVm->globals()->getObject(
- _inventoryList[_topIndex + i])->descId);
- strcpy(buffer, descStr);
- if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
-
- const Common::Rect r(_screenObjects[INVLIST_START + i]);
-
- // Set the highlighting of the inventory item
- if (_highlightedElement == (int)(INVLIST_START + i)) setFontMode(ITEM_HIGHLIGHTED);
- else if (_selectedObject == _inventoryList[_topIndex + i]) setFontMode(ITEM_SELECTED);
- else setFontMode(ITEM_NORMAL);
-
- // Write out it's description
- _vm->_font->writeString(destSurface, buffer, r.left, r.top, r.width(), 0);
- }
-
- // Handle the display of any currently selected object
- if (_objectSprites) {
- // Display object sprite. Note that the frame number isn't used directly, because it would result
- // in too fast an animation
- M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED);
- spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, 0);
-
- if (!_madsVm->globals()->_config.invObjectsStill && !dialogVisible) {
- // If objects need to be animated, move to the next frame
- if (++_objectFrameNumber >= (_objectSprites->getCount() * INV_ANIM_FRAME_SPEED))
- _objectFrameNumber = 0;
- }
-
- // List the vocab actions for the currently selected object
- MadsObject *obj = _madsVm->globals()->getObject(_selectedObject);
- int yIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1);
-
- for (int i = 0; i < obj->vocabCount; ++i) {
- const Common::Rect r(_screenObjects[VOCAB_START + i]);
-
- // Get the vocab description and capitalise it
- const char *descStr = _madsVm->globals()->getVocab(obj->vocabList[i].vocabId);
- strcpy(buffer, descStr);
- if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
+//--------------------------------------------------------------------------
- // Set the highlighting and display the entry
- setFontMode((i == yIndex) ? ITEM_HIGHLIGHTED : ITEM_NORMAL);
- _vm->_font->writeString(destSurface, buffer, r.left, r.top, r.width(), 0);
- }
- }
+Animation::Animation(MadsM4Engine *vm): _vm(vm) {
}
-bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) {
- MadsAction &act = _madsVm->scene()->getAction();
-
- // If the mouse isn't being held down, then reset the repeated scroll timer
- if (eventType != MEVENT_LEFT_HOLD)
- _nextScrollerTicks = 0;
-
- // Handle various event types
- switch (eventType) {
- case MEVENT_MOVE:
- // If the cursor isn't in "wait mode", don't do any processing
- if (_vm->_mouse->getCursorNum() == CURSOR_WAIT)
- return true;
-
- // Ensure the cursor is the standard arrow
- _vm->_mouse->setCursorNum(CURSOR_ARROW);
-
- // Check if any interface element is currently highlighted
- _highlightedElement = _screenObjects.find(Common::Point(x, y));
-
- return true;
-
- case MEVENT_LEFT_CLICK:
- // Left mouse click
- {
- // Check if an inventory object was selected
- if ((_highlightedElement >= INVLIST_START) && (_highlightedElement < (INVLIST_START + 5))) {
- // Ensure there is an inventory item listed in that cell
- uint idx = _highlightedElement - INVLIST_START;
- if ((_topIndex + idx) < _inventoryList.size()) {
- // Set the selected object
- setSelectedObject(_inventoryList[_topIndex + idx]);
- }
- } else if ((_highlightedElement >= ACTIONS_START) && (_highlightedElement < (ACTIONS_START + 10))) {
- // A standard action was selected
- int verbId = kVerbLook + (_highlightedElement - ACTIONS_START);
- warning("Selected action #%d", verbId);
-
- } else if ((_highlightedElement >= VOCAB_START) && (_highlightedElement < (VOCAB_START + 5))) {
- // A vocab action was selected
- MadsObject *obj = _madsVm->globals()->getObject(_selectedObject);
- int vocabIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1);
- if (vocabIndex >= 0) {
- act._actionMode = ACTMODE_OBJECT;
- act._actionMode2 = ACTMODE2_2;
- act._flags1 = obj->vocabList[1].flags1;
- act._flags2 = obj->vocabList[1].flags2;
-
- act._currentHotspot = _selectedObject;
- act._articleNumber = act._flags2;
- }
- }
- }
- return true;
-
- case MEVENT_LEFT_HOLD:
- // Left mouse hold
- // Handle the scroller - the up/down buttons allow for multiple actions whilst the mouse is held down
- if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_DOWN)) {
- if ((_nextScrollerTicks == 0) || (g_system->getMillis() >= _nextScrollerTicks)) {
- // Handle scroll up/down action
- _nextScrollerTicks = g_system->getMillis() + SCROLLER_DELAY;
-
- if ((_highlightedElement == SCROLL_UP) && (_topIndex > 0))
- --_topIndex;
- if ((_highlightedElement == SCROLL_DOWN) && (_topIndex < (int)(_inventoryList.size() - 1)))
- ++_topIndex;
- }
- }
- return true;
-
- case MEVENT_LEFT_DRAG:
- // Left mouse drag
- // Handle the the the scroller area that can be dragged to adjust the top displayed index
- if (_highlightedElement == SCROLL_SCROLLER) {
- // Calculate the new top index based on the Y position
- const Common::Rect r(_screenObjects[SCROLL_SCROLLER]);
- _topIndex = CLIP((int)(_inventoryList.size() - 1) * (y - r.top - 2) / (r.height() - 5),
- 0, (int)_inventoryList.size() - 1);
- }
- return true;
-
- case KEVENT_KEY:
- if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX)
- handleCheatKey(param1);
- handleKeypress(param1);
- return true;
-
- default:
- break;
- }
-
- return false;
+Animation::~Animation() {
}
-bool MadsInterfaceView::handleCheatKey(int32 keycode) {
- switch (keycode) {
- case Common::KEYCODE_SPACE:
- // TODO: Move player to current destination
- return true;
-
- case Common::KEYCODE_t | (Common::KEYCODE_LALT):
- case Common::KEYCODE_t | (Common::KEYCODE_RALT):
- {
- // Teleport to room
- //Scene *sceneView = (Scene *)vm->_viewManager->getView(VIEWID_SCENE);
-
-
- return true;
- }
+//--------------------------------------------------------------------------
- default:
- break;
- }
+MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this),
+ _kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this),
+ _screenObjects(*this), _action(*this) {
+
+ _textSpacing = -1;
+ _newTimeout = 0;
+ _abortTimers = 0;
+ _abortTimers2 = 0;
+ _abortTimersMode = ABORTMODE_0;
+ _abortTimersMode2 = ABORTMODE_0;
- return false;
+ _depthSurface = NULL;
+ _bgSurface = NULL;
+ _viewport = NULL;
+ _sceneAnimation = new MadsAnimation(_vm, this);
}
-const char *CHEAT_SEQUENCE = "widepipe";
+MadsView::~MadsView() {
+ delete _sceneAnimation;
+ delete _viewport;
+}
-bool MadsInterfaceView::handleKeypress(int32 keycode) {
- int flags = keycode >> 24;
- int kc = keycode & 0xffff;
+void MadsView::refresh() {
+ if (!_viewport)
+ setViewport(_view->bounds());
- // Capitalise the letter if necessary
- if (_cheatKeyCtr < CHEAT_SEQUENCE_MAX) {
- if ((flags & Common::KBD_CTRL) && (kc == CHEAT_SEQUENCE[_cheatKeyCtr])) {
- ++_cheatKeyCtr;
- if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX)
- Dialog::display(_vm, 22, cheatingEnabledDesc);
- return true;
- } else {
- _cheatKeyCtr = 0;
- }
- }
+ // Draw any sprites
+ _dirtyAreas.clear();
+ _spriteSlots.drawBackground();
- // Handle the various keys
- if ((keycode == Common::KEYCODE_ESCAPE) || (keycode == Common::KEYCODE_F1)) {
- // Game menu
- _madsVm->globals()->dialogType = DIALOG_GAME_MENU;
- leaveScene();
- return false;
- } else if (flags & Common::KBD_CTRL) {
- // Handling of the different control key combinations
- switch (kc) {
- case Common::KEYCODE_i:
- // Mouse to inventory
- warning("TODO: Mouse to inventory");
- break;
+ // Process dirty areas
+ _textDisplay.setDirtyAreas();
- case Common::KEYCODE_k:
- // Toggle hotspots
- warning("TODO: Toggle hotspots");
- break;
+ // Merge any identified dirty areas
+ _dirtyAreas.merge(1, DIRTY_AREAS_SIZE);
+
+ // Copy dirty areas to the main display surface
+ _dirtyAreas.copy(_viewport, _bgSurface, _posAdjust);
- case Common::KEYCODE_p:
- // Player stats
- warning("TODO: Player stats");
- break;
+ // Handle dirty areas for foreground objects
+ _spriteSlots.setDirtyAreas();
+ _textDisplay.setDirtyAreas2();
+ _dirtyAreas.merge(1, DIRTY_AREAS_SIZE);
- case Common::KEYCODE_q:
- // Quit game
- break;
+ // Draw foreground sprites
+ _spriteSlots.drawForeground(_viewport);
- case Common::KEYCODE_s:
- // Activate sound
- warning("TODO: Activate sound");
- break;
+ // Draw text elements onto the view
+ _textDisplay.draw(_viewport);
- case Common::KEYCODE_u:
- // Rotate player
- warning("TODO: Rotate player");
- break;
+ // Remove any sprite slots that are no longer needed
+ _spriteSlots.cleanUp();
- case Common::KEYCODE_v: {
- // Release version
- Dialog *dlg = new Dialog(_vm, GameReleaseInfoStr, GameReleaseTitleStr);
- _vm->_viewManager->addView(dlg);
- _vm->_viewManager->moveToFront(dlg);
- return false;
- }
+ // Deactivate any text display entries that are no longer needed
+ _textDisplay.cleanUp();
+}
- default:
- break;
- }
- } else if ((flags & Common::KBD_ALT) && (kc == Common::KEYCODE_q)) {
- // Quit Game
+void MadsView::update() {
+ _sequenceList.tick();
+ _kernelMessages.update();
+}
- } else {
- // Standard keypresses
- switch (kc) {
- case Common::KEYCODE_F2:
- // Save game
- _madsVm->globals()->dialogType = DIALOG_SAVE;
- leaveScene();
- break;
- case Common::KEYCODE_F3:
- // Restore game
- _madsVm->globals()->dialogType = DIALOG_RESTORE;
- leaveScene();
- break;
- }
- }
-//DIALOG_OPTIONS
- return false;
+void MadsView::clearLists() {
+ _textDisplay.clear();
+ _kernelMessages.clear();
+ _spriteSlots.clear();
}
-void MadsInterfaceView::leaveScene() {
- // Close the scene
- View *view = _madsVm->_viewManager->getView(VIEWID_SCENE);
- _madsVm->_viewManager->deleteView(view);
+void MadsView::setViewport(const Common::Rect &bounds) {
+ delete _viewport;
+ _viewport = new M4Surface(bounds.width(), bounds.height(), _view->getBasePtr(bounds.left, bounds.top),
+ _view->getPitch());
}
} // End of namespace M4
diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h
index 926702a80b..c93d0beda3 100644
--- a/engines/m4/mads_views.h
+++ b/engines/m4/mads_views.h
@@ -34,18 +34,87 @@
namespace M4 {
-#define MADS_SURFACE_HEIGHT 156
-#define MADS_SCREEN_HEIGHT 200
-#define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2)
-
class MadsView;
+enum MadsActionMode {ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, ACTMODE_TALK = 6};
+enum MAdsActionMode2 {ACTMODE2_0 = 0, ACTMODE2_2 = 2, ACTMODE2_4 = 4, ACTMODE2_5 = 5};
+
+struct ActionDetails {
+ int verbId;
+ int objectNameId;
+ int indirectObjectId;
+};
+
+struct MadsActionSavedFields {
+ int articleNumber;
+ int actionMode;
+ int actionMode2;
+ bool lookFlag;
+ int selectedRow;
+};
+
+class MadsAction {
+private:
+ MadsView &_owner;
+ char _statusText[100];
+ char _dialogTitle[100];
+
+ void appendVocab(int vocabId, bool capitalise = false);
+public:
+ ActionDetails _action, _activeAction;
+ int _currentAction;
+ int8 _flags1, _flags2;
+ MadsActionMode _actionMode;
+ MAdsActionMode2 _actionMode2;
+ int _articleNumber;
+ bool _lookFlag;
+ int _selectedRow;
+ bool _textChanged;
+ int _selectedAction;
+ bool _startWalkFlag;
+ int _statusTextIndex;
+ int _hotspotId;
+ MadsActionSavedFields _savedFields;
+ bool _walkFlag;
+
+ // Unknown fields
+ int16 _v86F3A;
+ int16 _v86F42;
+ int16 _v86F4E;
+ bool _v86F4A;
+ int16 _v86F4C;
+ int _v83338;
+ bool _inProgress;
+ bool _v8453A;
+
+public:
+ MadsAction(MadsView &owner);
+
+ void clear();
+ void set();
+ const char *statusText() const { return _statusText; }
+ void refresh();
+ void startAction();
+ void checkAction();
+ bool isAction(int verbId, int objectNameId = 0, int indirectObjectId = 0);
+};
+
enum AbortTimerMode {ABORTMODE_0 = 0, ABORTMODE_1 = 1, ABORTMODE_2 = 2};
+class SpriteSlotSubset {
+public:
+ int spriteListIndex;
+ int frameNumber;
+ int xp;
+ int yp;
+ int depth;
+ int scale;
+};
+
class MadsSpriteSlot {
public:
- int spriteId;
- int timerIndex;
+ int spriteType;
+ int seqIndex;
int spriteListIndex;
int frameNumber;
int xp;
@@ -54,20 +123,27 @@ public:
int scale;
MadsSpriteSlot() { }
+
+ bool operator==(const SpriteSlotSubset &other) const;
+ void copy(const SpriteSlotSubset &other);
};
#define SPRITE_SLOTS_SIZE 50
-typedef Common::Array<Common::SharedPtr<SpriteAsset> > SpriteList;
+enum SpriteIdSpecial {
+ BACKGROUND_SPRITE = -4, FULL_SCREEN_REFRESH = -2, EXPIRED_SPRITE = -1, SPRITE_ZERO = 0, FOREGROUND_SPRITE = 1
+};
class MadsSpriteSlots {
private:
+ MadsView &_owner;
Common::Array<MadsSpriteSlot> _entries;
- SpriteList _sprites;
+ Common::Array<SpriteAsset *> _sprites;
public:
int startIndex;
- MadsSpriteSlots();
+ MadsSpriteSlots(MadsView &owner);
+ ~MadsSpriteSlots();
MadsSpriteSlot &operator[](int idx) {
assert(idx < SPRITE_SLOTS_SIZE);
@@ -75,18 +151,20 @@ public:
}
SpriteAsset &getSprite(int idx) {
assert(idx < (int)_sprites.size());
- return *_sprites[idx].get();
+ return *_sprites[idx];
}
int getIndex();
- int addSprites(const char *resName);
- void clear() {
- startIndex = 0;
- _sprites.clear();
- }
- void deleteTimer(int timerIndex);
+ int addSprites(const char *resName, bool suppressErrors = false, int flags = 0);
+ int addSprites(SpriteAsset *spriteSet);
+ void deleteSprites(int listIndex);
+ void clear();
+ void deleteTimer(int seqIndex);
- void draw(View *view);
+ void drawBackground();
+ void drawForeground(M4Surface *viewport);
+ void setDirtyAreas();
+ void fullRefresh();
void cleanUp();
};
@@ -108,9 +186,10 @@ public:
class MadsTextDisplay {
private:
+ MadsView &_owner;
Common::Array<MadsTextDisplayEntry> _entries;
public:
- MadsTextDisplay();
+ MadsTextDisplay(MadsView &owner);
MadsTextDisplayEntry &operator[](int idx) {
assert(idx < TEXT_DISPLAY_SIZE);
@@ -124,16 +203,19 @@ public:
int add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font);
void clear();
- void draw(View *view);
+ void draw(M4Surface *view);
+ void setDirtyAreas();
+ void setDirtyAreas2();
void cleanUp();
};
#define TIMED_TEXT_SIZE 10
-#define TEXT_4A_SIZE 30
+#define INDEFINITE_TIMEOUT 9999999
-enum KernelMessageFlags {KMSG_1 = 1, KMSG_2 = 2, KMSG_4 = 4, KMSG_8 = 8, KMSG_20 = 0x20, KMSG_40 = 0x40, KMSG_ACTIVE = 0x80};
+enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_PLAYER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10,
+ KMSG_CENTER_ALIGN = 0x20, KMSG_EXPIRE = 0x40, KMSG_ACTIVE = 0x80};
-class MadsKernelMessageListEntry {
+class MadsKernelMessageEntry {
public:
uint8 flags;
int sequenceIndex;
@@ -144,31 +226,39 @@ public:
Common::Point position;
int textDisplayIndex;
int msgOffset;
- int field_E;
+ int numTicks;
uint32 frameTimer2;
uint32 frameTimer;
uint32 timeout;
- bool field_1C;
+ int abortTimers;
AbortTimerMode abortMode;
uint16 actionNouns[3];
- const char *msg;
+ char msg[100];
+
+ MadsKernelMessageEntry() {
+ flags = 0;
+ }
};
class MadsKernelMessageList {
private:
MadsView &_owner;
- Common::Array<MadsKernelMessageListEntry> _entries;
+ Common::Array<MadsKernelMessageEntry> _entries;
Font *_talkFont;
public:
+ int word_8469E;
+public:
MadsKernelMessageList(MadsView &owner);
void clear();
- int add(const Common::Point &pt, uint fontColour, uint8 flags, uint8 v2, uint32 timeout, const char *msg);
- int addQuote(int quoteId, int v2, uint32 timeout);
- void unk1(int msgIndex, int v1, int v2);
+ int add(const Common::Point &pt, uint fontColour, uint8 flags, uint8 abortTimers, uint32 timeout, const char *msg);
+ int addQuote(int quoteId, int abortTimers, uint32 timeout);
+ void scrollMessage(int msgIndex, int numTicks, bool quoted);
void setSeqIndex(int msgIndex, int seqIndex);
void remove(int msgIndex);
void reset();
+ void update();
+ void processText(int msgIndex);
};
class ScreenObjectEntry {
@@ -184,10 +274,20 @@ public:
class ScreenObjects {
private:
+ MadsView &_owner;
Common::Array<ScreenObjectEntry> _entries;
public:
- ScreenObjects() {}
+ int _v832EC;
+ int _v7FECA;
+ int _v7FED6;
+ int _v8332A;
+ int _yp;
+ int _v8333C;
+ int _selectedObject;
+ int _category;
+ int _objectIndex;
+ ScreenObjects(MadsView &owner);
ScreenObjectEntry &operator[](uint idx) {
assert(idx <= _entries.size());
return _entries[idx - 1];
@@ -199,12 +299,13 @@ public:
int scan(int xp, int yp, int layer);
int scanBackwards(int xp, int yp, int layer);
void setActive(int category, int idx, bool active);
+ void check(bool scanFlag, bool mouseClick);
};
class DynamicHotspot {
public:
bool active;
- int timerIndex;
+ int seqIndex;
Common::Rect bounds;
Common::Point pos;
int facing;
@@ -224,16 +325,54 @@ private:
Common::Array<DynamicHotspot> _entries;
int _count;
public:
- bool _flag;
+ bool _changed;
public:
MadsDynamicHotspots(MadsView &owner);
DynamicHotspot &operator[](uint idx) { return _entries[idx]; }
- int add(int descId, int field14, int timerIndex, const Common::Rect &bounds);
+ int add(int descId, int field14, int seqIndex, const Common::Rect &bounds);
int setPosition(int index, int xp, int yp, int facing);
int set17(int index, int v);
void remove(int index);
void reset();
+ void refresh() {
+ // TODO
+ }
+};
+
+class MadsDirtyArea {
+public:
+ Common::Rect bounds;
+ Common::Rect bounds2;
+ bool textActive;
+ bool active;
+
+ MadsDirtyArea() { active = false; }
+ void setArea(int width, int height, int maxWidth, int maxHeight);
+};
+
+#define DIRTY_AREAS_SIZE 90
+#define DIRTY_AREAS_TEXT_DISPLAY_IDX 50
+
+class MadsDirtyAreas {
+private:
+ MadsView &_owner;
+ Common::Array<MadsDirtyArea> _entries;
+public:
+ MadsDirtyAreas(MadsView &owner);
+
+ MadsDirtyArea &operator[](uint idx) {
+ assert(idx < _entries.size());
+ return _entries[idx];
+ }
+
+ void setSpriteSlot(int dirtyIdx, const MadsSpriteSlot &spriteSlot);
+ void setTextDisplay(int dirtyIdx, const MadsTextDisplayEntry &textDisplay);
+ void merge(int startIndex, int count);
+ bool intersects(int idx1, int idx2);
+ void mergeAreas(int idx1, int idx2);
+ void copy(M4Surface *dest, M4Surface *src, const Common::Point &posAdjust);
+ void clear();
};
enum SpriteAnimType {ANIMTYPE_CYCLED = 1, ANIMTYPE_REVERSIBLE = 2};
@@ -252,8 +391,7 @@ struct MadsSequenceSubEntries {
struct MadsSequenceEntry {
int8 active;
int8 spriteListIndex;
-
- int field_2;
+ bool flipped;
int frameIndex;
int frameStart;
@@ -266,12 +404,10 @@ struct MadsSequenceEntry {
int scale;
int dynamicHotspotIndex;
- int field_12;
+ bool nonFixed;
int field_13;
- int width;
- int height;
-
+ Common::Point msgPos;
int triggerCountdown;
bool doneFlag;
MadsSequenceSubEntries entries;
@@ -295,88 +431,66 @@ public:
MadsSequenceEntry &operator[](int index) { return _entries[index]; }
void clear();
bool addSubEntry(int index, SequenceSubEntryMode mode, int frameIndex, int abortVal);
- int add(int spriteListIndex, int v0, int v1, int triggerCountdown, int delayTicks, int extraTicks, int numTicks,
- int height, int width, char field_12, char scale, uint8 depth, int frameInc, SpriteAnimType animType,
- int numSprites, int frameStart);
- void remove(int timerIndex);
- void setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot);
- bool loadSprites(int timerIndex);
+ int add(int spriteListIndex, bool flipped, int frameIndex, int triggerCountdown, int delayTicks,
+ int extraTicks, int numTicks, int msgX, int msgY, bool nonFixed, char scale, uint8 depth,
+ int frameInc, SpriteAnimType animType, int numSprites, int frameStart);
+ void remove(int seqIndex);
+ void setSpriteSlot(int seqIndex, MadsSpriteSlot &spriteSlot);
+ bool loadSprites(int seqIndex);
void tick();
void delay(uint32 v1, uint32 v2);
+ void setAnimRange(int seqIndex, int startVal, int endVal);
+ void scan();
+ void setDepth(int seqIndex, int depth);
};
+class Animation {
+protected:
+ MadsM4Engine *_vm;
+public:
+ Animation(MadsM4Engine *vm);
+ virtual ~Animation();
+ virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface) = 0;
+ virtual void load(const Common::String &filename, int v0) = 0;
+ virtual void update() = 0;
+ virtual void setCurrentFrame(int frameNumber) = 0;
+ virtual int getCurrentFrame() = 0;
+};
+
+
class MadsView {
private:
View *_view;
public:
+ Animation *_sceneAnimation;
MadsSpriteSlots _spriteSlots;
MadsTextDisplay _textDisplay;
MadsKernelMessageList _kernelMessages;
ScreenObjects _screenObjects;
MadsDynamicHotspots _dynamicHotspots;
MadsSequenceList _sequenceList;
+ MadsDirtyAreas _dirtyAreas;
+ MadsAction _action;
int _textSpacing;
- int _ticksAmount;
uint32 _newTimeout;
int _abortTimers;
int8 _abortTimers2;
AbortTimerMode _abortTimersMode;
AbortTimerMode _abortTimersMode2;
+ Common::Point _posAdjust;
+
+ M4Surface *_depthSurface;
+ M4Surface *_bgSurface;
+ M4Surface *_viewport;
public:
MadsView(View *view);
+ ~MadsView();
void refresh();
-};
-
-#define CHEAT_SEQUENCE_MAX 8
-
-class IntegerList : public Common::Array<int> {
-public:
- int indexOf(int v) {
- for (uint i = 0; i < size(); ++i)
- if (operator [](i) == v)
- return i;
- return -1;
- }
-};
-
-enum InterfaceFontMode {ITEM_NORMAL, ITEM_HIGHLIGHTED, ITEM_SELECTED};
-
-enum InterfaceObjects {ACTIONS_START = 0, SCROLL_UP = 10, SCROLL_SCROLLER = 11, SCROLL_DOWN = 12,
- INVLIST_START = 13, VOCAB_START = 18};
-
-class MadsInterfaceView : public GameInterfaceView {
-private:
- IntegerList _inventoryList;
- RectList _screenObjects;
- int _highlightedElement;
- int _topIndex;
- uint32 _nextScrollerTicks;
- int _cheatKeyCtr;
-
- // Object display fields
- int _selectedObject;
- SpriteAsset *_objectSprites;
- RGBList *_objectPalData;
- int _objectFrameNumber;
-
- void setFontMode(InterfaceFontMode newMode);
- bool handleCheatKey(int32 keycode);
- bool handleKeypress(int32 keycode);
- void leaveScene();
-public:
- MadsInterfaceView(MadsM4Engine *vm);
- ~MadsInterfaceView();
-
- virtual void initialise();
- virtual void setSelectedObject(int objectNumber);
- virtual void addObjectToInventory(int objectNumber);
- int getSelectedObject() { return _selectedObject; }
- int getInventoryObject(int objectIndex) { return _inventoryList[objectIndex]; }
-
- void onRefresh(RectList *rects, M4Surface *destSurface);
- bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents);
+ void update();
+ void clearLists();
+ void setViewport(const Common::Rect &bounds);
};
}
diff --git a/engines/m4/midi.cpp b/engines/m4/midi.cpp
index 78fe0d6bd6..2c767fdf5a 100644
--- a/engines/m4/midi.cpp
+++ b/engines/m4/midi.cpp
@@ -109,7 +109,7 @@ void MidiPlayer::send(uint32 b) {
else if ((b & 0xFFF0) == 0x007BB0) {
//Only respond to All Notes Off if this channel
//has currently been allocated
- if (_channel[b & 0x0F])
+ if (!_channel[b & 0x0F])
return;
}
diff --git a/engines/m4/module.mk b/engines/m4/module.mk
index 1b08ea2188..f60757ba3b 100644
--- a/engines/m4/module.mk
+++ b/engines/m4/module.mk
@@ -22,6 +22,7 @@ MODULE_OBJS = \
mads_anim.o \
mads_logic.o \
mads_menus.o \
+ mads_player.o \
mads_scene.o \
mads_views.o \
midi.o \
diff --git a/engines/m4/rails.cpp b/engines/m4/rails.cpp
index fbad6995eb..11b9bcdbb9 100644
--- a/engines/m4/rails.cpp
+++ b/engines/m4/rails.cpp
@@ -179,7 +179,7 @@ long SqrtF16(long n) {
uint32 r = 0, s;
uint32 v = (uint32)n;
- for (int i = 15; i <= 0; i--) {
+ for (int i = 15; i >= 0; --i) {
s = r + (1L << i * 2);
r >>= 1;
if (s <= v) {
diff --git a/engines/m4/rails.h b/engines/m4/rails.h
index a7add5a8eb..e3183c243f 100644
--- a/engines/m4/rails.h
+++ b/engines/m4/rails.h
@@ -93,6 +93,8 @@ private:
bool isLineWalkable(int x0, int y0, int x1, int y1);
};
+long SqrtF16(long n);
+
} // End of namespace M4
#endif
diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp
index 15c68f276c..8457f2087a 100644
--- a/engines/m4/scene.cpp
+++ b/engines/m4/scene.cpp
@@ -44,7 +44,7 @@ Scene::Scene(MadsM4Engine *vm, SceneResources *res): View(vm, Common::Rect(0, 0,
_screenType = VIEWID_SCENE;
_sceneResources->hotspots = new HotSpotList();
- _sceneResources->props = new HotSpotList();
+ _sceneResources->dynamicHotspots = new HotSpotList();
_backgroundSurface = new M4Surface();
_walkSurface = new M4Surface();
_palData = NULL;
@@ -55,11 +55,13 @@ Scene::Scene(MadsM4Engine *vm, SceneResources *res): View(vm, Common::Rect(0, 0,
Scene::~Scene() {
leaveScene();
+ _vm->_scene = NULL;
}
void Scene::loadScene(int sceneNumber) {
_previousScene = _currentScene;
_currentScene = sceneNumber;
+ _nextScene = sceneNumber;
}
void Scene::leaveScene() {
@@ -122,14 +124,14 @@ void Scene::showHotSpots() {
HotSpot *currentHotSpot;
// hotspots (green)
- for (i = 0; i < _sceneResources->hotspotCount; i++) {
+ for (i = 0; i < _sceneResources->hotspots->size(); i++) {
currentHotSpot = _sceneResources->hotspots->get(i);
_backgroundSurface->frameRect(currentHotSpot->getRect(), _vm->_palette->GREEN);
}
- // props (red)
- for (i = 0; i < _sceneResources->propsCount; i++) {
- currentHotSpot = _sceneResources->props->get(i);
+ // Dynamic hotspots (red)
+ for (i = 0; i < _sceneResources->dynamicHotspots->size(); i++) {
+ currentHotSpot = _sceneResources->dynamicHotspots->get(i);
_backgroundSurface->frameRect(currentHotSpot->getRect(), _vm->_palette->RED);
}
}
@@ -153,8 +155,21 @@ void Scene::showCodes() {
colors[255 * 4 + 2] = 255;
_vm->_palette->setPalette(colors, 0, 256);
} else {
- // For MADS, simply copy the walk data to the background, in whatever current palette is active
+ // MADS handling
+
+ // copy the walk data to the background, in whatever current palette is active
_walkSurface->copyTo(_backgroundSurface);
+
+ // Show all the scene's walk nodes
+ SceneNodeList &nodeList = _madsVm->scene()->getSceneResources()._nodes;
+ _backgroundSurface->setColour(_madsVm->_palette->WHITE);
+ for (uint i = 0; i < nodeList.size() - 2; ++i) {
+ // Draw a little cross at the node's position
+ _backgroundSurface->hLine(nodeList[i].pt.x - 2, nodeList[i].pt.x + 2, nodeList[i].pt.y);
+ _backgroundSurface->vLine(nodeList[i].pt.x, nodeList[i].pt.y - 2, nodeList[i].pt.y + 2);
+ }
+
+ ((MadsScene *)this)->_spriteSlots.fullRefresh();
}
}
@@ -183,7 +198,7 @@ bool Scene::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &cap
rightClick(x, y);
break;
case MEVENT_MOVE:
- checkHotspotAtMousePos(x, y);
+ mouseMove(x, y);
break;
default:
return false;
diff --git a/engines/m4/scene.h b/engines/m4/scene.h
index 633a34b549..9262a7c828 100644
--- a/engines/m4/scene.h
+++ b/engines/m4/scene.h
@@ -53,17 +53,16 @@ enum MADSVerbs {
kVerbPull = 10,
kVerbClose = 11,
kVerbThrow = 12,
- kVerbWalkTo = 13
+ kVerbWalkTo = 13,
+ kVerbLookAt = 209
};
class SceneResources {
public:
char artBase[MAX_CHK_FILENAME_SIZE];
char pictureBase[MAX_CHK_FILENAME_SIZE];
- int32 hotspotCount;
HotSpotList *hotspots;
- int32 propsCount;
- HotSpotList *props;
+ HotSpotList *dynamicHotspots;
int32 frontY, backY;
int32 frontScale, backScale;
int16 depthTable[16];
@@ -80,6 +79,7 @@ private:
protected:
int _currentScene;
int _previousScene;
+ int _nextScene;
GameInterfaceView *_interfaceSurface;
M4Surface *_backgroundSurface;
M4Surface *_walkSurface;
@@ -95,7 +95,7 @@ public:
virtual void leaveScene();
virtual void loadSceneCodes(int sceneNumber, int index = 0) = 0;
virtual void show();
- virtual void checkHotspotAtMousePos(int x, int y) = 0;
+ virtual void mouseMove(int x, int y) = 0;
virtual void leftClick(int x, int y) = 0;
virtual void rightClick(int x, int y) = 0;
virtual void update() = 0;
diff --git a/engines/m4/sound.cpp b/engines/m4/sound.cpp
index 69ab8c0516..e0fbd2f7a9 100644
--- a/engines/m4/sound.cpp
+++ b/engines/m4/sound.cpp
@@ -197,20 +197,20 @@ void Sound::loadDSRFile(const char *fileName) {
//printf("DSR has %i entries\n", _dsrFile.entryCount);
for (int i = 0; i < _dsrFile.entryCount; i++) {
- DSREntry* newEntry = new DSREntry();
- newEntry->frequency = fileStream->readUint16LE();
- newEntry->channels = fileStream->readUint32LE();
- newEntry->compSize = fileStream->readUint32LE();
- newEntry->uncompSize = fileStream->readUint32LE();
- newEntry->offset = fileStream->readUint32LE();
+ DSREntry newEntry;
+ newEntry.frequency = fileStream->readUint16LE();
+ newEntry.channels = fileStream->readUint32LE();
+ newEntry.compSize = fileStream->readUint32LE();
+ newEntry.uncompSize = fileStream->readUint32LE();
+ newEntry.offset = fileStream->readUint32LE();
_dsrFile.dsrEntries.push_back(newEntry);
/*
printf("%i: ", i);
printf("frequency: %i ", newEntry->frequency);
printf("channels: %i ", newEntry->channels);
- printf("comp: %i ", newEntry->compSize);
- printf("uncomp: %i ", newEntry->uncompSize);
+ printf("comp: %i ", newEntry.compSize);
+ printf("uncomp: %i ", newEntry.uncompSize);
printf("offset: %i ", newEntry->offset);
printf("\n");
*/
@@ -225,9 +225,7 @@ void Sound::unloadDSRFile() {
if (!_dsrFileLoaded)
return;
- for (int i = 0; i < _dsrFile.entryCount; i++) {
- _dsrFile.dsrEntries.remove_at(0);
- }
+ _dsrFile.dsrEntries.clear();
_dsrFile.entryCount = 0;
strcpy(_dsrFile.fileName, "");
@@ -251,28 +249,28 @@ void Sound::playDSRSound(int soundIndex, int volume, bool loop) {
// Get sound data
FabDecompressor fab;
- byte *compData = new byte[_dsrFile.dsrEntries[soundIndex]->compSize];
- byte *buffer = new byte[_dsrFile.dsrEntries[soundIndex]->uncompSize];
+ byte *compData = new byte[_dsrFile.dsrEntries[soundIndex].compSize];
+ byte *buffer = new byte[_dsrFile.dsrEntries[soundIndex].uncompSize];
Common::SeekableReadStream *fileStream = _vm->res()->get(_dsrFile.fileName);
- fileStream->seek(_dsrFile.dsrEntries[soundIndex]->offset, SEEK_SET);
- fileStream->read(compData, _dsrFile.dsrEntries[soundIndex]->compSize);
+ fileStream->seek(_dsrFile.dsrEntries[soundIndex].offset, SEEK_SET);
+ fileStream->read(compData, _dsrFile.dsrEntries[soundIndex].compSize);
_vm->res()->toss(_dsrFile.fileName);
- fab.decompress(compData, _dsrFile.dsrEntries[soundIndex]->compSize,
- buffer, _dsrFile.dsrEntries[soundIndex]->uncompSize);
+ fab.decompress(compData, _dsrFile.dsrEntries[soundIndex].compSize,
+ buffer, _dsrFile.dsrEntries[soundIndex].uncompSize);
// Play sound
Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
Audio::makeRawStream(buffer,
- _dsrFile.dsrEntries[soundIndex]->uncompSize,
- _dsrFile.dsrEntries[soundIndex]->frequency, Audio::FLAG_UNSIGNED),
+ _dsrFile.dsrEntries[soundIndex].uncompSize,
+ _dsrFile.dsrEntries[soundIndex].frequency, Audio::FLAG_UNSIGNED),
loop ? 0 : 1);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &handle->handle, stream, -1, volume);
/*
// Dump the sound file
FILE *destFile = fopen("sound.raw", "wb");
- fwrite(_dsrFile.dsrEntries[soundIndex]->data, _dsrFile.dsrEntries[soundIndex]->uncompSize, 1, destFile);
+ fwrite(_dsrFile.dsrEntries[soundIndex]->data, _dsrFile.dsrEntries[soundIndex].uncompSize, 1, destFile);
fclose(destFile);
*/
}
diff --git a/engines/m4/sound.h b/engines/m4/sound.h
index 7d442a73cc..5587810506 100644
--- a/engines/m4/sound.h
+++ b/engines/m4/sound.h
@@ -65,7 +65,7 @@ struct DSREntry {
struct DSRFile {
char fileName[20];
int entryCount;
- Common::Array<DSREntry *> dsrEntries;
+ Common::Array<DSREntry> dsrEntries;
};
class MadsM4Engine;
diff --git a/engines/m4/sprite.cpp b/engines/m4/sprite.cpp
index 0ff4bec855..641b93baea 100644
--- a/engines/m4/sprite.cpp
+++ b/engines/m4/sprite.cpp
@@ -121,60 +121,89 @@ void M4Sprite::loadDeltaRle(Common::SeekableReadStream* rleData, int destX, int
// TODO: The sprite outlines (pixel value 0xFD) are not shown
void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) {
- byte *outp, *lineStart;
- bool newLine = false;
+ bool spriteEnd = false;
- outp = getBasePtr();
- lineStart = getBasePtr();
+ // Set entire sprite contents to transparent pixels
+ fillRect(bounds(), TRANSPARENT_COLOUR_INDEX);
- while (1) {
- byte cmd1, cmd2, count, pixel;
-
- if (newLine) {
- outp = lineStart + w;
- lineStart = outp;
- newLine = false;
- }
-
- cmd1 = source->readByte();
+ // Major line loop
+ for (int yp = 0; yp < h; ++yp) {
+ byte *destP = getBasePtr(0, yp);
+ bool newLine = false;
+ byte cmd = source->readByte();
+ int x2 = 0;
- if (cmd1 == 0xFC)
+ if (cmd == 0xfc) {
+ // End of entire sprite
+ spriteEnd = true;
break;
- else if (cmd1 == 0xFF)
+ } else if (cmd == 0xff) {
+ // The entire line is empty
newLine = true;
- else if (cmd1 == 0xFD) {
- while (!newLine) {
- count = source->readByte();
- if (count == 0xFF) {
+ } else if (cmd == 0xFD) {
+ // Lines contains only run lenghs of pixels
+ while (x2 < w) {
+ cmd = source->readByte();
+ if (cmd == 0xff) {
+ // End of line reached
newLine = true;
- } else {
- pixel = source->readByte();
- while (count--)
- *outp++ = (pixel == 0xFD) ? 0 : pixel;
+ break;
+ }
+
+ byte v = source->readByte();
+ while (cmd-- > 0) {
+ if (x2 < w)
+ *destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v;
+ ++x2;
}
}
} else {
- while (!newLine) {
- cmd2 = source->readByte();
- if (cmd2 == 0xFF) {
+ // Line intermixes run lengths with individual pixels
+ while (x2 < w) {
+ cmd = source->readByte();
+ if (cmd == 0xff) {
+ // End of line reached
newLine = true;
- } else if (cmd2 == 0xFE) {
- count = source->readByte();
- pixel = source->readByte();
- while (count--)
- *outp++ = (pixel == 0xFD) ? 0 : pixel;
+ break;
+ }
+
+ if (cmd == 0xFE) {
+ // Handle repeated sequence
+ cmd = source->readByte();
+ byte v = source->readByte();
+ while (cmd-- > 0) {
+ if (x2 < w) {
+ *destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v;
+ }
+ ++x2;
+ }
} else {
- *outp++ = (cmd2 == 0xFD) ? 0 : cmd2;
+ // Handle writing out single pixel
+ *destP++ = (cmd == 0xFD) ? TRANSPARENT_COLOUR_INDEX : cmd;
+ ++x2;
}
}
}
+
+ // Check if we need to scan forward to find the end of the line
+ if (!newLine) {
+ do {
+ if (source->eos()) {
+ warning("M4Sprite::loadMadsSprite: unexpected end of data");
+ break;
+ }
+ } while (source->readByte() != 0xff);
+ }
+ }
+
+ if (!spriteEnd) {
+ byte v = source->readByte();
+ assert(v == 0xFC);
}
}
-byte M4Sprite::getTransparentColor() const {
- // FIXME: We assume that the transparent color is the color of the
- // top left pixel.
- return *getBasePtr(0, 0);
+byte M4Sprite::getTransparencyIndex() const {
+ return TRANSPARENT_COLOUR_INDEX;
}
} // End of namespace M4
diff --git a/engines/m4/sprite.h b/engines/m4/sprite.h
index 022f3bbc4f..d4e5502efd 100644
--- a/engines/m4/sprite.h
+++ b/engines/m4/sprite.h
@@ -115,19 +115,7 @@ public:
void loadDeltaRle(Common::SeekableReadStream* rleData, int destX, int destY);
void loadMadsSprite(Common::SeekableReadStream* source);
- void draw1(M4Surface *destSurface, int scale, int depth, int xp, int yp) {
- // TODO: Properly implement drawing
- copyTo(destSurface, xp, yp, 0);
- }
- void draw2(M4Surface *destSurface, int depth, int xp, int yp) {
- // TODO: Properly implement drawing
- copyTo(destSurface, xp, yp, 0);
- }
- void draw3(M4Surface *destSurface, int xp, int yp) {
- // TODO: Properly implement drawing
- copyTo(destSurface, xp, yp, 0);
- }
- byte getTransparentColor() const;
+ byte getTransparencyIndex() const;
protected:
};
diff --git a/engines/m4/viewmgr.h b/engines/m4/viewmgr.h
index 16c3d6ecc3..211e6087f4 100644
--- a/engines/m4/viewmgr.h
+++ b/engines/m4/viewmgr.h
@@ -42,6 +42,19 @@ namespace M4 {
class View;
class ViewManager;
+enum SceneTransition {
+ kTransitionNone = 0,
+ kTransitionFadeIn = 1,
+ kTransitionFadeIn2 = 2,
+ kTransitionBoxInBottomLeft = 3,
+ kTransitionBoxInBottomRight = 4,
+ kTransitionBoxInTopLeft = 5,
+ kTransitionBoxInTopRight = 6,
+ kTransitionPanLeftToRight = 7,
+ kTransitionPanRightToLeft = 8,
+ kTransitionCircleIn = 9
+};
+
enum {SCREEN_DIALOG, SCREEN_BUFFER, SCREEN_TEXT, SCREEN_TRANSPARENT};
enum ScreenEventType {SCREVENT_NONE = 0, SCREVENT_KEY = 1, SCREVENT_MOUSE = 2, SCREVENT_ALL = 3};
enum ScreenLayers {
diff --git a/engines/made/database.cpp b/engines/made/database.cpp
index ae1a08e1b5..51308cb7e5 100644
--- a/engines/made/database.cpp
+++ b/engines/made/database.cpp
@@ -515,6 +515,8 @@ int16 GameDatabaseV2::loadgame(const char *filename, int16 version) {
_objects[i]->load(*in);
}
delete in;
+
+ _objectPropertyCache.clear(); // make sure to clear cache
return result;
}
@@ -644,6 +646,8 @@ void GameDatabaseV3::load(Common::SeekableReadStream &sourceS) {
void GameDatabaseV3::reloadFromStream(Common::SeekableReadStream &sourceS) {
sourceS.seek(_gameStateOffs);
sourceS.read(_gameState, _gameStateSize);
+
+ _objectPropertyCache.clear(); // make sure to clear cache
}
bool GameDatabaseV3::getSavegameDescription(const char *filename, Common::String &description, int16 version) {
@@ -734,6 +738,9 @@ int16 GameDatabaseV3::loadgame(const char *filename, int16 version) {
in->skip(64); // skip savegame description
in->read(_gameState, _gameStateSize);
delete in;
+
+ _objectPropertyCache.clear(); // make sure to clear cache
+
return 0;
}
diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp
index 1dfc0c3f83..6a6a70cb30 100644
--- a/engines/made/detection.cpp
+++ b/engines/made/detection.cpp
@@ -76,7 +76,6 @@ using Common::GUIO_NONE;
using Common::GUIO_NOSPEECH;
static const MadeGameDescription gameDescriptions[] = {
-
{
// NOTE: Return to Zork entries with *.dat are used to detect the game via rtzcd.dat,
// which is packed inside rtzcd.red. Entries with *.red refer to the packed file
@@ -329,6 +328,60 @@ static const MadeGameDescription gameDescriptions[] = {
},
{
+ // Return to Zork - Japanese DOS
+ // This is the RTZCD.DAT in the base directory of the FM-Towns CD
+ {
+ "rtz",
+ "",
+ AD_ENTRY1("rtzcd.dat", "c4fccf67ad247f09b94c3c808b138576"),
+ Common::JA_JPN,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_RTZ,
+ 0,
+ GF_CD,
+ 3,
+ },
+
+ {
+ // Return to Zork - Japanese FM-Towns
+ // This is in the RTZFM folder of the FM-Towns CD
+ {
+ "rtz",
+ "",
+ AD_ENTRY1("rtzcd.dat", "e949a6a42d82daabfa7d4dc0a87a9843"),
+ Common::JA_JPN,
+ Common::kPlatformFMTowns,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_RTZ,
+ 0,
+ GF_CD,
+ 3,
+ },
+
+ {
+ // Return to Zork - Japanese PC-98
+ // This is in the RTZ9821 folder of the FM-Towns CD
+ {
+ "rtz",
+ "",
+ AD_ENTRY1("rtzcd.dat", "0c0117e98530c736a141c2aad6834dc5"),
+ Common::JA_JPN,
+ Common::kPlatformPC98,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_RTZ,
+ 0,
+ GF_CD,
+ 3,
+ },
+
+ {
// The Manhole: New and Enhanced
{
"manhole",
@@ -493,7 +546,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class MadeMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/made/made.cpp b/engines/made/made.cpp
index 54e2189471..94926014d3 100644
--- a/engines/made/made.cpp
+++ b/engines/made/made.cpp
@@ -97,11 +97,11 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng
_script = new ScriptInterpreter(this);
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
- //bool adlib = (midiDriver == MD_ADLIB);
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+ //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
- MidiDriver *driver = MidiDriver::createMidi(midiDriver);
+ MidiDriver *driver = MidiDriver::createMidi(dev);
if (native_mt32)
driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp
index 28d46cf4ec..cdcb49f9f9 100644
--- a/engines/made/resource.cpp
+++ b/engines/made/resource.cpp
@@ -50,10 +50,9 @@ PictureResource::~PictureResource() {
delete _picture;
_picture = 0;
}
- if (_picturePalette) {
- delete[] _picturePalette;
- _picturePalette = 0;
- }
+
+ delete[] _picturePalette;
+ _picturePalette = 0;
}
void PictureResource::load(byte *source, int size) {
diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp
index cd4081ea52..8d01ec70f3 100644
--- a/engines/made/scriptfuncs.cpp
+++ b/engines/made/scriptfuncs.cpp
@@ -28,6 +28,7 @@
#include "common/events.h"
#include "graphics/cursorman.h"
#include "sound/audiocd.h"
+#include "sound/softsynth/pcspk.h"
#include "made/made.h"
#include "made/resource.h"
@@ -41,6 +42,22 @@
namespace Made {
+ScriptFunctions::ScriptFunctions(MadeEngine *vm) : _vm(vm), _soundStarted(false) {
+ // Initialize the two tone generators
+ _pcSpeaker1 = new Audio::PCSpeaker();
+ _pcSpeaker2 = new Audio::PCSpeaker();
+ _vm->_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_pcSpeakerHandle1, _pcSpeaker1);
+ _vm->_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_pcSpeakerHandle2, _pcSpeaker2);
+}
+
+ScriptFunctions::~ScriptFunctions() {
+ for (uint i = 0; i < _externalFuncs.size(); ++i)
+ delete _externalFuncs[i];
+
+ _vm->_system->getMixer()->stopHandle(_pcSpeakerHandle1);
+ _vm->_system->getMixer()->stopHandle(_pcSpeakerHandle2);
+}
+
typedef Common::Functor2Mem<int16, int16*, int16, ScriptFunctions> ExternalScriptFunc;
#define External(x) \
_externalFuncs.push_back(new ExternalScriptFunc(this, &ScriptFunctions::x)); \
@@ -308,36 +325,78 @@ int16 ScriptFunctions::sfFlashScreen(int16 argc, int16 *argv) {
}
int16 ScriptFunctions::sfPlayNote(int16 argc, int16 *argv) {
- // TODO: Used in Manhole:NE, Manhole EGA
- // This is used when using the piano in the desk screen inside the ship.
+ // This is used when using the piano in the desk screen inside the ship
+ // in The Manhole (EGA/NE).
+
// It takes 2 parameters:
- // The first parameter is the key pressed
+ // The first parameter is the note number of the key pressed + 1
// The second parameter is some sort of modifier (volume, perhaps?),
- // depending on which of the 3 keys on the right has been pressed (12 - 14)
- warning("Unimplemented opcode: sfPlayNote");
+ // depending on which of the 3 keys on the right has been pressed.
+ // This value seems to be [12, 14] in NE and [1, 3] in EGA.
+
+ // Note frequencies based on http://www.phy.mtu.edu/~suits/notefreqs.html
+ static const int freqTable[] = {
+ 16, 17, 18, 19, 21, 22, 23, 24, 26, 28, 29,
+ 30, 32, 35, 37, 39, 41, 44, 46, 49, 52, 55,
+ 58, 62, 65, 69, 73, 77, 82, 87, 93, 98, 104,
+ 110, 117, 123, 131, 139, 147, 156, 165, 175, 195,
+ 196, 208, 220, 233, 247, 262, 277, 294, 311, 330,
+ 349, 370, 392, 415, 440, 466, 494, 523, 554, 587,
+ 622, 659, 698, 740, 784, 831, 880, 932, 988, 1047,
+ 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760,
+ 1865, 1976, 2093, 2217, 2349, 2489, 2637, 2794, 2960,
+ 3136, 3322, 3529, 3729, 3951, 4186, 4435, 4697, 4978
+ };
+
+ debug(4, "sfPlayNote: Note = %d, Volume(?) = %d", argv[0] - 1, argv[1]);
+
+ _pcSpeaker1->play(Audio::PCSpeaker::kWaveFormSine, freqTable[argv[0] - 1], -1);
+
+ // TODO: Figure out what to do with the second parameter
+ //_pcSpeaker1->setVolume(argv[1]);
+
return 0;
}
int16 ScriptFunctions::sfStopNote(int16 argc, int16 *argv) {
- // TODO: Used in Manhole:NE, Manhole EGA
// Used in the same place as sfPlayNote, with the same parameters
- warning("Unimplemented opcode: sfStopNote");
+ // We just stop the wave generator here
+ _pcSpeaker1->stop();
return 0;
}
int16 ScriptFunctions::sfPlayTele(int16 argc, int16 *argv) {
- // TODO: Used in Manhole:NE, Manhole EGA
// This is used when pressing the phone keys while using the phone in
- // the desk screen inside the ship.
+ // the desk screen inside the ship in The Manhole (EGA/NE).
// It takes 1 parameter, the key pressed (0-9, 10 for asterisk, 11 for hash)
- warning("Unimplemented opcode: sfPlayTele");
+
+ // A telephone keypad uses a two tones for each key.
+ // See http://en.wikipedia.org/wiki/Telephone_keypad for more info
+
+ static const int freqTable1[] = {
+ 1336, 1209, 1336, 1477,
+ 1209, 1336, 1477, 1209,
+ 1336, 1477, 1209, 1477
+ };
+
+ static const int freqTable2[] = {
+ 941, 697, 697, 697,
+ 770, 770, 770, 852,
+ 852, 852, 941, 941
+ };
+
+ debug(4, "sfPlayTele: Button = %d", argv[0]);
+
+ _pcSpeaker1->play(Audio::PCSpeaker::kWaveFormSine, freqTable1[argv[0]], -1);
+ _pcSpeaker2->play(Audio::PCSpeaker::kWaveFormSine, freqTable2[argv[0]], -1);
return 0;
}
int16 ScriptFunctions::sfStopTele(int16 argc, int16 *argv) {
- // TODO: Used in Manhole:NE, Manhole EGA
// Used in the same place as sfPlayTele, with the same parameters
- warning("Unimplemented opcode: sfStopTele");
+ // We just stop both wave generators here
+ _pcSpeaker1->stop();
+ _pcSpeaker2->stop();
return 0;
}
diff --git a/engines/made/scriptfuncs.h b/engines/made/scriptfuncs.h
index 5fdfb77f45..3bed27c5c8 100644
--- a/engines/made/scriptfuncs.h
+++ b/engines/made/scriptfuncs.h
@@ -33,6 +33,10 @@
#include "made/resource.h"
+namespace Audio {
+ class PCSpeaker;
+}
+
namespace Made {
class MadeEngine;
@@ -41,17 +45,16 @@ typedef Common::Functor2<int16, int16*, int16> ExternalFunc;
class ScriptFunctions {
public:
- ScriptFunctions(MadeEngine *vm) : _vm(vm), _soundStarted(false) {}
- virtual ~ScriptFunctions() {
- for (uint i = 0; i < _externalFuncs.size(); ++i)
- delete _externalFuncs[i];
- }
+ ScriptFunctions(MadeEngine *vm);
+ virtual ~ScriptFunctions();
+
int16 callFunction(uint16 index, int16 argc, int16 *argv) {
if (index >= _externalFuncs.size())
error("ScriptFunctions::callFunction() Invalid function index %d", index);
debug(4, "%s", _externalFuncNames[index]);
return (*_externalFuncs[index])(argc, argv);
}
+
void setupExternalsTable();
const char* getFuncName(int index) { return _externalFuncNames[index]; }
int getCount() const { return _externalFuncs.size(); }
@@ -64,6 +67,10 @@ protected:
SoundResource* _soundResource;
bool _soundStarted;
+ // PlayNote/StopNote and PlayTele/StopTele wave generators
+ Audio::SoundHandle _pcSpeakerHandle1, _pcSpeakerHandle2;
+ Audio::PCSpeaker *_pcSpeaker1, *_pcSpeaker2;
+
Common::Array<const ExternalFunc*> _externalFuncs;
Common::Array<const char *> _externalFuncNames;
GenericResource *_musicRes;
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index 389665db39..5dcfff4f90 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -28,9 +28,10 @@
#include "mohawk/myst_scripts.h"
#include "mohawk/graphics.h"
#include "mohawk/riven.h"
+#include "mohawk/riven_external.h"
#include "mohawk/livingbooks.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
namespace Mohawk {
@@ -307,6 +308,7 @@ RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript));
DCmd_Register("listZipCards", WRAP_METHOD(RivenConsole, Cmd_ListZipCards));
DCmd_Register("getRMAP", WRAP_METHOD(RivenConsole, Cmd_GetRMAP));
+ DCmd_Register("combos", WRAP_METHOD(RivenConsole, Cmd_Combos));
}
RivenConsole::~RivenConsole() {
@@ -556,9 +558,11 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
printf ("==================================\n\n");
Common::SeekableReadStream *cardStream = _vm->getRawData(MKID_BE('CARD'), (uint16)atoi(argv[3]));
cardStream->seek(4);
- RivenScriptList scriptList = RivenScript::readScripts(_vm, cardStream);
- for (uint32 i = 0; i < scriptList.size(); i++)
+ RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream, false);
+ for (uint32 i = 0; i < scriptList.size(); i++) {
scriptList[i]->dumpScript(varNames, xNames, 0);
+ delete scriptList[i];
+ }
delete cardStream;
} else if (!scumm_stricmp(argv[2], "HSPT")) {
printf ("\n\nDumping scripts for %s\'s card %d hotspots!\n", argv[1], (uint16)atoi(argv[3]));
@@ -571,9 +575,11 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
for (uint16 i = 0; i < hotspotCount; i++) {
printf ("Hotspot %d:\n", i);
hsptStream->seek(22, SEEK_CUR); // Skip non-script related stuff
- RivenScriptList scriptList = RivenScript::readScripts(_vm, hsptStream);
- for (uint32 j = 0; j < scriptList.size(); j++)
+ RivenScriptList scriptList = _vm->_scriptMan->readScripts(hsptStream, false);
+ for (uint32 j = 0; j < scriptList.size(); j++) {
scriptList[j]->dumpScript(varNames, xNames, 1);
+ delete scriptList[j];
+ }
}
delete hsptStream;
@@ -608,6 +614,33 @@ bool RivenConsole::Cmd_GetRMAP(int argc, const char **argv) {
return true;
}
+bool RivenConsole::Cmd_Combos(int argc, const char **argv) {
+ // In the vain of SCUMM's 'drafts' command, this command will list
+ // out all combinations needed in Riven, decoded from the variables.
+ // You'll need to look up the Rebel Tunnel puzzle on your own; the
+ // solution is constant.
+
+ uint32 teleCombo = *_vm->matchVarToString("tcorrectorder");
+ uint32 prisonCombo = *_vm->matchVarToString("pcorrectorder");
+ uint32 domeCombo = *_vm->matchVarToString("adomecombo");
+
+ DebugPrintf("Telescope Combo:\n ");
+ for (int i = 0; i < 5; i++)
+ DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(teleCombo, i));
+
+ DebugPrintf("\nPrison Combo:\n ");
+ for (int i = 0; i < 5; i++)
+ DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(prisonCombo, i));
+
+ DebugPrintf("\nDome Combo:\n ");
+ for (int i = 1; i <= 25; i++)
+ if (domeCombo & (1 << (25 - i)))
+ DebugPrintf("%d ", i);
+
+ DebugPrintf("\n");
+ return true;
+}
+
LivingBooksConsole::LivingBooksConsole(MohawkEngine_LivingBooks *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound));
DCmd_Register("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound));
diff --git a/engines/mohawk/console.h b/engines/mohawk/console.h
index 9a30d46225..1806c61027 100644
--- a/engines/mohawk/console.h
+++ b/engines/mohawk/console.h
@@ -88,6 +88,7 @@ private:
bool Cmd_DumpScript(int argc, const char **argv);
bool Cmd_ListZipCards(int argc, const char **argv);
bool Cmd_GetRMAP(int argc, const char **argv);
+ bool Cmd_Combos(int argc, const char **argv);
};
class LivingBooksConsole : public GUI::Debugger {
diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index a7b1fe7fae..f04338239f 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -117,846 +117,21 @@ static const PlainGameDescriptor mohawkGames[] = {
{"ruff", "Ruff's Bone"},
{"newkid", "The New Kid on the Block"},
{"arthurrace", "Arthur's Reading Race"},
+ {"arthurbday", "Arthur's Birthday"},
+ {"lilmonster", "Little Monster at School"},
#endif
{0, 0}
};
+#include "mohawk/detection_tables.h"
-namespace Mohawk {
-
-static const MohawkGameDescription gameDescriptions[] = {
- // Myst
- // English Windows 3.11
- // From clone2727
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "ae3258c9c90128d274aa6a790b3ad181"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Myst Demo
- // English Windows 3.11
- // From CD-ROM Today July, 1994
- {
- {
- "myst",
- "Demo",
- AD_ENTRY1("DEMO.DAT", "c39303dd53fb5c4e7f3c23231c606cd0"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_MYST,
- GF_DEMO,
- 0,
- },
-
- // Myst
- // German Windows 3.11
- // From clone2727
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "4beb3366ed3f3b9bfb6e81a14a43bdcc"),
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Myst
- // German Windows 3.11
- // From LordHoto
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "e0937cca1ab125e48e30dc3cd5046ddf"),
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Myst
- // Spanish Windows ?
- // From jvprat
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "f7e7d7ca69934f1351b5acd4fe4d44c2"),
- Common::ES_ESP,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Myst
- // Japanese Windows 3.11
- // From clone2727
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "032c88e3b7e8db4ca475e7b7db9a66bb"),
- Common::JA_JPN,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Myst
- // French Windows 3.11
- // From Strangerke
- {
- {
- "myst",
- "",
- AD_ENTRY1("MYST.DAT", "d631d42567a941c67c78f2e491f4ea58"),
- Common::FR_FRA,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0,
- },
-
- // Making of Myst
- // English Windows 3.11
- // From clone2727
- {
- {
- "MakingOfMyst",
- "",
- AD_ENTRY1("MAKING.DAT", "f6387e8f0f7b8a3e42c95294315d6a0e"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MAKINGOF,
- 0,
- 0,
- },
-
- // Making of Myst
- // Japanese Windows 3.11
- // From clone2727
- {
- {
- "MakingOfMyst",
- "",
- AD_ENTRY1("MAKING.DAT", "03ff62607e64419ab2b6ebf7b7bcdf63"),
- Common::JA_JPN,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MAKINGOF,
- 0,
- 0,
- },
-
- // Myst Masterpiece Edition
- // English Windows
- // From clone2727
- {
- {
- "myst",
- "Masterpiece Edition",
- AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- GF_ME,
- 0,
- },
-
- // Myst Masterpiece Edition
- // English Windows
- // From clone2727
- {
- {
- "myst",
- "Masterpiece Edition",
- AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"),
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- GF_ME,
- 0,
- },
-
- // Myst Masterpiece Edition
- // German Windows
- // From DrMcCoy (Included in "Myst: Die Trilogie")
- {
- {
- "myst",
- "Masterpiece Edition",
- AD_ENTRY1("MYST.DAT", "f88e0ace66dbca78eebdaaa1d3314ceb"),
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- GF_ME,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version 1.0 (5CD)
- // From clone2727
- {
- {
- "riven",
- "",
- AD_ENTRY1("a_Data.MHK", "71145fdecbd68a0cfc292c2fbddf8e08"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- 0,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version 1.03 (5CD)
- // From ST
- {
- {
- "riven",
- "",
- AD_ENTRY1("a_Data.MHK", "d8ccae34a0e3c709135a73f449b783be"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- 0,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version 1.? (5CD)
- // From jvprat
- {
- {
- "riven",
- "",
- AD_ENTRY1("a_Data.MHK", "249e8c995d191b03ee94c892c0eac775"),
- Common::ES_ESP,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- 0,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version 1.? (DVD, From "Myst 10th Anniversary Edition")
- // From Clone2727
- {
- {
- "riven",
- "DVD",
- AD_ENTRY1("a_Data.MHK", "08fcaa5d5a2a01d7a5a6960f497212fe"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- GF_DVD,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version 1.0 (DVD, From "Myst: Die Trilogie")
- // From DrMcCoy
- {
- {
- "riven",
- "",
- AD_ENTRY1("a_Data.MHK", "a5fe1c91a6033eb6ee54b287578b74b9"),
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- GF_DVD,
- 0,
- },
-
- // Riven: The Sequel to Myst
- // Version ? (Demo, From "Prince of Persia Collector's Edition")
- // From Clone2727
- {
- {
- "riven",
- "Demo",
- AD_ENTRY1("a_Data.MHK", "bae6b03bd8d6eb350d35fd13f0e3139f"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- GF_DEMO,
- 0,
- },
-
-#ifdef DETECT_BRODERBUND_TITLES
- {
- {
- "zoombini",
- "",
- AD_ENTRY1("ZOOMBINI.MHK", "98b758fec55104c096cfd129048be9a6"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_ZOOMBINI,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "csworld",
- "v3.0",
- AD_ENTRY1("C2K.MHK", "605fe88380848031bbd0ff84ade6fe40"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_CSWORLD,
- 0,
- 0
- },
-
- {
- {
- "csworld",
- "v3.5",
- AD_ENTRY1("C2K.MHK", "d4857aeb0f5e2e0c4ac556aa74f38c23"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_CSWORLD,
- 0,
- 0
- },
-
- {
- {
- "csamtrak",
- "",
- AD_ENTRY1("AMTRAK.MHK", "2f95301f0bb950d555bb7b0e3b1b7eb1"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_CSAMTRAK,
- 0,
- 0
- },
-
- {
- {
- "maggiess",
- "",
- AD_ENTRY1("MAGGIESS.MHK", "08f75fc8c0390e68fdada5ddb35d0355"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MAGGIESS,
- 0,
- 0
- },
-
- {
- {
- "jamesmath",
- "",
- AD_ENTRY1("BRODER.MHK", "007299da8b2c6e8ec1cde9598c243024"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_JAMESMATH,
- GF_HASMIDI,
- 0
- },
-
- // This is in the NEWDATA folder, so I assume it's a newer version ;)
- {
- {
- "jamesmath",
- "",
- AD_ENTRY1("BRODER.MHK", "53c000938a50dca92860fd9b546dd276"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_JAMESMATH,
- GF_HASMIDI,
- 1
- },
-
- {
- {
- "treehouse",
- "",
- AD_ENTRY1("MAINROOM.MHK", "12f51894d7f838af639ea9bf1bc8f45b"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_TREEHOUSE,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "greeneggs",
- "",
- AD_ENTRY1("GREEN.LB", "5df8438138186f89e71299d7b4f88d06"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV3,
- 0,
- 0
- },
-
- // 32-bit version of the previous entry
- {
- {
- "greeneggs",
- "",
- AD_ENTRY1("GREEN32.LB", "5df8438138186f89e71299d7b4f88d06"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV3,
- 0,
- 0
- },
-
- {
- {
- "1stdegree",
- "",
- AD_ENTRY1("AL236_1.MHK", "3ba145492a7b8b4dee0ef4222c5639c3"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_1STDEGREE,
- GF_HASMIDI,
- 0
- },
-
- // In The 1st Degree
- // French Windows
- // From Strangerke
- {
- {
- "1stdegree",
- "",
- AD_ENTRY1("AL236_1.MHK", "0e0c70b1b702b6ddca61a1192ada1282"),
- Common::FR_FRA,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_1STDEGREE,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "csusa",
- "",
- AD_ENTRY1("USAC2K.MHK", "b8c9d3a2586f62bce3a48b50d7a700e9"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_CSUSA,
- 0,
- 0
- },
-
- {
- {
- "tortoise",
- "Demo v1.0",
- AD_ENTRY1("TORTOISE.512", "75d9a2f8339e423604a0c6e8177600a6"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "tortoise",
- "Demo v1.1",
- AD_ENTRY1("TORTOISE.512", "a38c99360e2bea3bfdec418469aef022"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "arthur",
- "",
- AD_ENTRY1("PAGES.512", "1550a361454ec452fe7d2328aac2003c"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- 0,
- 0
- },
-
- {
- {
- "arthur",
- "Demo",
- AD_ENTRY1("PAGES.512", "a4d68cef197af1416921ca5b2e0c1e31"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "arthur",
- "Demo",
- AD_ENTRY1("Bookoutline", "7e2691611ff4c7b89c05221736628059"),
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "grandma",
- "Demo v1.0",
- AD_ENTRY1("PAGES.512", "95d9f4b035bf5d15c57a9189f231b0f8"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "grandma",
- "Demo v1.1",
- AD_ENTRY1("GRANDMA.512", "72a4d5fb1b3f06b5f75425635d42ce2e"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "grandma",
- "Demo",
- AD_ENTRY1("Bookoutline", "553c93891b9631d1e1d269599e1efa6c"),
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "ruff",
- "Demo",
- AD_ENTRY1("RUFF.512", "2ba1aa65177c816e156db648c398d362"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "ruff",
- "Demo",
- AD_ENTRY1("Ruff's Bone Demo", "22553ac2ceb2a166bdf1def6ad348532"),
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "newkid",
- "Demo v1.0",
- AD_ENTRY1("NEWKID.512", "2b9d94763a50d514c04a3af488934f73"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "newkid",
- "Demo v1.1",
- AD_ENTRY1("NEWKID.512", "41e975b7390c626f8d1058a34f9d9b2e"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_DEMO,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV1,
- GF_DEMO,
- 0
- },
-
- {
- {
- "arthurrace",
- "",
- AD_ENTRY1("RACE.LB", "1645f36bcb36e440d928e920aa48c373"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV3,
- 0,
- 0
- },
-
- // 32-bit version of the previous entry
- {
- {
- "arthurrace",
- "",
- AD_ENTRY1("RACE32.LB", "292a05bc48c1dd9583821a4181a02ef2"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_LIVINGBOOKSV3,
- 0,
- 0
- },
-#endif
-
- { AD_TABLE_END_MARKER, 0, 0, 0 }
+static const char *directoryGlobs[] = {
+ "all",
+ "assets1",
+ "data",
+ 0
};
-//////////////////////////////
-//Fallback detection
-//////////////////////////////
-
-static const MohawkGameDescription fallbackDescs[] = {
- {
- {
- "myst",
- "unknown",
- AD_ENTRY1(0, 0),
- Common::UNK_LANG,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- 0,
- 0
- },
-
- {
- {
- "MakingOfMyst",
- "unknown",
- AD_ENTRY1(0, 0),
- Common::UNK_LANG,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MAKINGOF,
- 0,
- 0
- },
-
- {
- {
- "myst",
- "unknown (Masterpiece Edition)",
- AD_ENTRY1(0, 0),
- Common::UNK_LANG,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_MYST,
- GF_ME,
- 0
- },
-
- {
- {
- "riven",
- "unknown",
- AD_ENTRY1(0, 0),
- Common::UNK_LANG,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- 0,
- 0
- },
-
- {
- {
- "riven",
- "unknown (DVD)",
- AD_ENTRY1(0, 0),
- Common::UNK_LANG,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- Common::GUIO_NONE
- },
- GType_RIVEN,
- GF_DVD,
- 0
- }
-};
-
-static const ADFileBasedFallback fileBased[] = {
- { &fallbackDescs[0], { "MYST.DAT", 0 } },
- { &fallbackDescs[1], { "MAKING.DAT", 0 } },
- { &fallbackDescs[2], { "MYST.DAT", "Help.dat", 0 } }, // Help system doesn't exist in original
- { &fallbackDescs[3], { "a_Data.MHK", 0 } },
- { &fallbackDescs[4], { "a_Data.MHK", "t_Data1.MHK" , 0 } },
- { 0, { 0 } }
-};
-
-} // End of namespace Mohawk
-
static const ADParams detectionParams = {
// Pointer to ADGameDescription or its superset structure
(const byte *)Mohawk::gameDescriptions,
@@ -975,7 +150,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game)
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ // Maximum directory depth
+ 2,
+ // List of directory globs
+ directoryGlobs
};
class MohawkMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h
new file mode 100644
index 0000000000..7470dbf1dd
--- /dev/null
+++ b/engines/mohawk/detection_tables.h
@@ -0,0 +1,1030 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Mohawk {
+
+static const MohawkGameDescription gameDescriptions[] = {
+ // Myst
+ // English Windows 3.11
+ // From clone2727
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "ae3258c9c90128d274aa6a790b3ad181"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Myst Demo
+ // English Windows 3.11
+ // From CD-ROM Today July, 1994
+ {
+ {
+ "myst",
+ "Demo",
+ AD_ENTRY1("DEMO.DAT", "c39303dd53fb5c4e7f3c23231c606cd0"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_DEMO,
+ 0,
+ },
+
+ // Myst
+ // German Windows 3.11
+ // From clone2727
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "4beb3366ed3f3b9bfb6e81a14a43bdcc"),
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Myst
+ // German Windows 3.11
+ // From LordHoto
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "e0937cca1ab125e48e30dc3cd5046ddf"),
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Myst
+ // Spanish Windows ?
+ // From jvprat
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "f7e7d7ca69934f1351b5acd4fe4d44c2"),
+ Common::ES_ESP,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Myst
+ // Japanese Windows 3.11
+ // From clone2727
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "032c88e3b7e8db4ca475e7b7db9a66bb"),
+ Common::JA_JPN,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Myst
+ // French Windows 3.11
+ // From Strangerke
+ {
+ {
+ "myst",
+ "",
+ AD_ENTRY1("MYST.DAT", "d631d42567a941c67c78f2e491f4ea58"),
+ Common::FR_FRA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0,
+ },
+
+ // Making of Myst
+ // English Windows 3.11
+ // From clone2727
+ {
+ {
+ "MakingOfMyst",
+ "",
+ AD_ENTRY1("MAKING.DAT", "f6387e8f0f7b8a3e42c95294315d6a0e"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MAKINGOF,
+ 0,
+ 0,
+ },
+
+ // Making of Myst
+ // Japanese Windows 3.11
+ // From clone2727
+ {
+ {
+ "MakingOfMyst",
+ "",
+ AD_ENTRY1("MAKING.DAT", "03ff62607e64419ab2b6ebf7b7bcdf63"),
+ Common::JA_JPN,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MAKINGOF,
+ 0,
+ 0,
+ },
+
+ // Myst Masterpiece Edition
+ // English Windows
+ // From clone2727
+ {
+ {
+ "myst",
+ "Masterpiece Edition",
+ AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_ME,
+ 0,
+ },
+
+ // Myst Masterpiece Edition
+ // English Windows
+ // From clone2727
+ {
+ {
+ "myst",
+ "Masterpiece Edition",
+ AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_ME,
+ 0,
+ },
+
+ // Myst Masterpiece Edition
+ // German Windows
+ // From DrMcCoy (Included in "Myst: Die Trilogie")
+ {
+ {
+ "myst",
+ "Masterpiece Edition",
+ AD_ENTRY1("MYST.DAT", "f88e0ace66dbca78eebdaaa1d3314ceb"),
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_ME,
+ 0,
+ },
+
+ // Myst Masterpiece Edition
+ // French Windows
+ // From gamin (Included in "Myst: La Trilogie")
+ {
+ {
+ "myst",
+ "Masterpiece Edition",
+ AD_ENTRY1("MYST.DAT", "aea81633b2d2ae498f09072fb87263b6"),
+ Common::FR_FRA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_ME,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version 1.0 (5CD)
+ // From clone2727
+ {
+ {
+ "riven",
+ "",
+ AD_ENTRY1("a_Data.MHK", "71145fdecbd68a0cfc292c2fbddf8e08"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ 0,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version 1.03 (5CD)
+ // From ST
+ {
+ {
+ "riven",
+ "",
+ AD_ENTRY1("a_Data.MHK", "d8ccae34a0e3c709135a73f449b783be"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ 0,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version 1.? (5CD)
+ // From jvprat
+ {
+ {
+ "riven",
+ "",
+ AD_ENTRY1("a_Data.MHK", "249e8c995d191b03ee94c892c0eac775"),
+ Common::ES_ESP,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ 0,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version 1.? (DVD, From "Myst 10th Anniversary Edition")
+ // From Clone2727
+ {
+ {
+ "riven",
+ "DVD",
+ AD_ENTRY1("a_Data.MHK", "08fcaa5d5a2a01d7a5a6960f497212fe"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ GF_DVD,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version 1.0 (DVD, From "Myst: Die Trilogie")
+ // From DrMcCoy
+ {
+ {
+ "riven",
+ "",
+ AD_ENTRY1("a_Data.MHK", "a5fe1c91a6033eb6ee54b287578b74b9"),
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ GF_DVD,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version ? (DVD, From "Myst: La Trilogie")
+ // From gamin
+ {
+ {
+ "riven",
+ "",
+ AD_ENTRY1("a_Data.MHK", "aff2a384aaa9a0e0ec51010f708c5c04"),
+ Common::FR_FRA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ GF_DVD,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
+ // Version ? (Demo, From "Prince of Persia Collector's Edition")
+ // From Clone2727
+ {
+ {
+ "riven",
+ "Demo",
+ AD_ENTRY1("a_Data.MHK", "bae6b03bd8d6eb350d35fd13f0e3139f"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ GF_DEMO,
+ 0,
+ },
+
+#ifdef DETECT_BRODERBUND_TITLES
+ {
+ {
+ "zoombini",
+ "",
+ AD_ENTRY1("ZOOMBINI.MHK", "98b758fec55104c096cfd129048be9a6"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_ZOOMBINI,
+ GF_HASMIDI,
+ 0
+ },
+
+ {
+ {
+ "csworld",
+ "v3.0",
+ AD_ENTRY1("C2K.MHK", "605fe88380848031bbd0ff84ade6fe40"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_CSWORLD,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "csworld",
+ "v3.5",
+ AD_ENTRY1("C2K.MHK", "d4857aeb0f5e2e0c4ac556aa74f38c23"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_CSWORLD,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "csamtrak",
+ "",
+ AD_ENTRY1("AMTRAK.MHK", "2f95301f0bb950d555bb7b0e3b1b7eb1"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_CSAMTRAK,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "maggiess",
+ "",
+ AD_ENTRY1("MAGGIESS.MHK", "08f75fc8c0390e68fdada5ddb35d0355"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MAGGIESS,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "jamesmath",
+ "",
+ AD_ENTRY1("BRODER.MHK", "007299da8b2c6e8ec1cde9598c243024"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_JAMESMATH,
+ GF_HASMIDI,
+ 0
+ },
+
+ // This is in the NEWDATA folder, so I assume it's a newer version ;)
+ {
+ {
+ "jamesmath",
+ "",
+ AD_ENTRY1("BRODER.MHK", "53c000938a50dca92860fd9b546dd276"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_JAMESMATH,
+ GF_HASMIDI,
+ 1
+ },
+
+ {
+ {
+ "treehouse",
+ "",
+ AD_ENTRY1("MAINROOM.MHK", "12f51894d7f838af639ea9bf1bc8f45b"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_TREEHOUSE,
+ GF_HASMIDI,
+ 0
+ },
+
+ {
+ {
+ "greeneggs",
+ "",
+ AD_ENTRY1("GREEN.LB", "5df8438138186f89e71299d7b4f88d06"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
+ // 32-bit version of the previous entry
+ {
+ {
+ "greeneggs",
+ "",
+ AD_ENTRY1("GREEN32.LB", "5df8438138186f89e71299d7b4f88d06"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "1stdegree",
+ "",
+ AD_ENTRY1("AL236_1.MHK", "3ba145492a7b8b4dee0ef4222c5639c3"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_1STDEGREE,
+ GF_HASMIDI,
+ 0
+ },
+
+ // In The 1st Degree
+ // French Windows
+ // From Strangerke
+ {
+ {
+ "1stdegree",
+ "",
+ AD_ENTRY1("AL236_1.MHK", "0e0c70b1b702b6ddca61a1192ada1282"),
+ Common::FR_FRA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_1STDEGREE,
+ GF_HASMIDI,
+ 0
+ },
+
+ {
+ {
+ "csusa",
+ "",
+ AD_ENTRY1("USAC2K.MHK", "b8c9d3a2586f62bce3a48b50d7a700e9"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_CSUSA,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "tortoise",
+ "Demo v1.0",
+ AD_ENTRY1("TORTOISE.512", "75d9a2f8339e423604a0c6e8177600a6"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "tortoise",
+ "Demo v1.1",
+ AD_ENTRY1("TORTOISE.512", "a38c99360e2bea3bfdec418469aef022"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "tortoise",
+ "Demo",
+ AD_ENTRY1("The Tortoise and the Hare Demo", "35d571806838667743c7c15a133e9335"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthur",
+ "",
+ AD_ENTRY1("PAGES.512", "1550a361454ec452fe7d2328aac2003c"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "arthur",
+ "Demo",
+ AD_ENTRY1("PAGES.512", "a4d68cef197af1416921ca5b2e0c1e31"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthur",
+ "Demo v1.1",
+ AD_ENTRY1("ARTHUR.512", "f19e824e0a2f2745ed698e6aaf44f838"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthur",
+ "Demo",
+ AD_ENTRY1("Bookoutline", "7e2691611ff4c7b89c05221736628059"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthur",
+ "Demo",
+ AD_ENTRY1("Arthur's Teacher Trouble Demo", "dcbd8af6bf25854df8ad36fd13665d08"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "grandma",
+ "Demo v1.0",
+ AD_ENTRY1("PAGES.512", "95d9f4b035bf5d15c57a9189f231b0f8"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "grandma",
+ "Demo v1.1",
+ AD_ENTRY1("GRANDMA.512", "72a4d5fb1b3f06b5f75425635d42ce2e"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "grandma",
+ "Demo",
+ AD_ENTRY1("Bookoutline", "553c93891b9631d1e1d269599e1efa6c"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "grandma",
+ "Demo",
+ AD_ENTRY1("Just Grandma and Me Demo", "552d8729fa77a4a83c88283c7d79bd31"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "ruff",
+ "Demo",
+ AD_ENTRY1("RUFF.512", "2ba1aa65177c816e156db648c398d362"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "ruff",
+ "Demo",
+ AD_ENTRY1("Ruff's Bone Demo", "22553ac2ceb2a166bdf1def6ad348532"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "newkid",
+ "Demo v1.0",
+ AD_ENTRY1("NEWKID.512", "2b9d94763a50d514c04a3af488934f73"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "newkid",
+ "Demo v1.1",
+ AD_ENTRY1("NEWKID.512", "41e975b7390c626f8d1058a34f9d9b2e"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "newkid",
+ "Demo",
+ AD_ENTRY1("The New Kid on the Block Demo", "7d33237e0ea452a97f2a3acdfb9e1286"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthurrace",
+ "",
+ AD_ENTRY1("RACE.LB", "1645f36bcb36e440d928e920aa48c373"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
+ // 32-bit version of the previous entry
+ {
+ {
+ "arthurrace",
+ "",
+ AD_ENTRY1("RACE32.LB", "292a05bc48c1dd9583821a4181a02ef2"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "arthurbday",
+ "Demo",
+ AD_ENTRY1("BIRTHDAY.512", "fb73e387cfec65c5c930db068a8f468a"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "arthurbday",
+ "Demo",
+ AD_ENTRY1("Arthur's Birthday Demo", "0d974ec635eea615475368e865f1b1c8"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
+ "lilmonster",
+ "",
+ AD_ENTRY1("MONSTER.512", "e7b24bf8f59106b5c4df51b39eb8c0ef"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "lilmonster",
+ "",
+ AD_ENTRY1("BookOutline", "970409f9d967d63c05e63113f8e78fe2"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ 0
+ },
+#endif
+
+ { AD_TABLE_END_MARKER, 0, 0, 0 }
+};
+
+//////////////////////////////
+//Fallback detection
+//////////////////////////////
+
+static const MohawkGameDescription fallbackDescs[] = {
+ {
+ {
+ "myst",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "MakingOfMyst",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MAKINGOF,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "myst",
+ "unknown (Masterpiece Edition)",
+ AD_ENTRY1(0, 0),
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_MYST,
+ GF_ME,
+ 0
+ },
+
+ {
+ {
+ "riven",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ 0,
+ 0
+ },
+
+ {
+ {
+ "riven",
+ "unknown (DVD)",
+ AD_ENTRY1(0, 0),
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_RIVEN,
+ GF_DVD,
+ 0
+ }
+};
+
+static const ADFileBasedFallback fileBased[] = {
+ { &fallbackDescs[0], { "MYST.DAT", 0 } },
+ { &fallbackDescs[1], { "MAKING.DAT", 0 } },
+ { &fallbackDescs[2], { "MYST.DAT", "Help.dat", 0 } }, // Help system doesn't exist in original
+ { &fallbackDescs[3], { "a_Data.MHK", 0 } },
+ { &fallbackDescs[4], { "a_Data.MHK", "t_Data1.MHK" , 0 } },
+ { 0, { 0 } }
+};
+
+} // End of Namespace Mohawk
diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index c5327dbeea..c09763cbb3 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -30,6 +30,7 @@
#include "gui/GuiManager.h"
#include "common/savefile.h"
+#include "common/translation.h"
namespace Mohawk {
@@ -77,11 +78,11 @@ enum {
};
MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) {
- _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, "Zip Mode Activated", kZipCmd, 'Z');
- _transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, "Transitions Enabled", kTransCmd, 'T');
+ _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
+ _transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~T~ransitions Enabled"), 0, kTransCmd);
- new GUI::ButtonWidget(this, 95, 160, 120, 25, "OK", GUI::kOKCmd, 'O');
- new GUI::ButtonWidget(this, 225, 160, 120, 25, "Cancel", GUI::kCloseCmd, 'C');
+ new GUI::ButtonWidget(this, 95, 160, 120, 25, _("~O~K"), 0, GUI::kOKCmd);
+ new GUI::ButtonWidget(this, 225, 160, 120, 25, _("~C~ancel"), 0, GUI::kCloseCmd);
}
MystOptionsDialog::~MystOptionsDialog() {
@@ -111,11 +112,11 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui
}
RivenOptionsDialog::RivenOptionsDialog(MohawkEngine_Riven* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) {
- _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, "Zip Mode Activated", kZipCmd, 'Z');
- _waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, "Water Effect Enabled", kWaterCmd, 'W');
+ _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
+ _waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~W~ater Effect Enabled"), 0, kWaterCmd);
- new GUI::ButtonWidget(this, 95, 160, 120, 25, "OK", GUI::kOKCmd, 'O');
- new GUI::ButtonWidget(this, 225, 160, 120, 25, "Cancel", GUI::kCloseCmd, 'C');
+ new GUI::ButtonWidget(this, 95, 160, 120, 25, _("~O~K"), 0, GUI::kOKCmd);
+ new GUI::ButtonWidget(this, 225, 160, 120, 25, _("~C~ancel"), 0, GUI::kCloseCmd);
}
RivenOptionsDialog::~RivenOptionsDialog() {
diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp
index 35691c36aa..1974aec9c2 100644
--- a/engines/mohawk/graphics.cpp
+++ b/engines/mohawk/graphics.cpp
@@ -78,9 +78,8 @@ MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : _vm(vm) {
error("Myst requires greater than 256 colors to run");
if (_vm->getFeatures() & GF_ME) {
- // We want to delete our own JPEG surfaces, so don't free after use.
- _jpegDecoder = new JPEGDecoder(false);
- _pictDecoder = new MystPICT(_jpegDecoder);
+ _jpegDecoder = new Graphics::JPEGDecoder();
+ _pictDecoder = new Graphics::PictDecoder(_pixelFormat);
} else {
_jpegDecoder = NULL;
_pictDecoder = NULL;
@@ -152,9 +151,10 @@ void MystGraphics::copyImageSectionToScreen(uint16 image, Common::Rect src, Comm
if (_vm->getFeatures() & GF_ME && _vm->getPlatform() == Common::kPlatformMacintosh && _pictureFile.picFile.isOpen()) {
for (uint32 i = 0; i < _pictureFile.pictureCount; i++)
if (_pictureFile.entries[i].id == image) {
- if (_pictureFile.entries[i].type == 0)
- surface = _jpegDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size));
- else if (_pictureFile.entries[i].type == 1)
+ if (_pictureFile.entries[i].type == 0) {
+ Graphics::Surface *jpegSurface = _jpegDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size));
+ surface->copyFrom(*jpegSurface);
+ } else if (_pictureFile.entries[i].type == 1)
surface = _pictDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size));
else
error ("Unknown Picture File type %d", _pictureFile.entries[i].type);
@@ -466,27 +466,22 @@ void RivenGraphics::runScheduledTransition() {
// transitions were found by hacking scripts.
switch (_scheduledTransition) {
+ case 0: // Swipe Left
+ case 1: // Swipe Right
+ case 2: // Swipe Up
+ case 3: // Swipe Down
case 12: // Pan Left
- warning ("STUB: Pan left");
- break;
case 13: // Pan Right
- warning ("STUB: Pan right");
- break;
case 14: // Pan Up
- warning ("STUB: Pan up");
- break;
case 15: // Pan Down
- warning ("STUB: Pan down");
- break;
case 16: // Dissolve
case 17: // Dissolve (tspit CARD 155)
- warning ("STUB: Dissolve");
break;
default:
- if (_scheduledTransition < 12)
- error ("Found unused transition %d", _scheduledTransition);
+ if (_scheduledTransition >= 4 && _scheduledTransition <= 11)
+ error("Found unused transition %d", _scheduledTransition);
else
- error ("Found unknown transition %d", _scheduledTransition);
+ error("Found unknown transition %d", _scheduledTransition);
}
// For now, just copy the image to screen without doing any transition.
@@ -607,19 +602,23 @@ void RivenGraphics::showInventory() {
if (_vm->getFeatures() & GF_DEMO || _vm->getCurStack() == aspit)
return;
- // There are three books and three vars. However, there's only
- // a possible two combinations. Either you have only Atrus'
- // journal or you have all three books.
- // bool hasAtrusBook = *_vm->matchVarToString("aatrusbook") != 0;
+ // There are three books and three vars. We have three different
+ // combinations. At the start you have just Atrus' journal. Later,
+ // you get Catherine's journal and the trap book. Near the end,
+ // you lose the trap book and have just the two journals.
+
bool hasCathBook = *_vm->matchVarToString("acathbook") != 0;
- // bool hasTrapBook = *_vm->matchVarToString("atrapbook") != 0;
+ bool hasTrapBook = *_vm->matchVarToString("atrapbook") != 0;
if (!hasCathBook) {
- drawInventoryImage(101, g_atrusJournalRectSolo);
+ drawInventoryImage(101, g_atrusJournalRect1);
+ } else if (!hasTrapBook) {
+ drawInventoryImage(101, g_atrusJournalRect2);
+ drawInventoryImage(102, g_cathJournalRect2);
} else {
- drawInventoryImage(101, g_atrusJournalRect);
- drawInventoryImage(102, g_cathJournalRect);
- drawInventoryImage(100, g_trapBookRect);
+ drawInventoryImage(101, g_atrusJournalRect3);
+ drawInventoryImage(102, g_cathJournalRect3);
+ drawInventoryImage(100, g_trapBookRect3);
}
_vm->_system->updateScreen();
diff --git a/engines/mohawk/graphics.h b/engines/mohawk/graphics.h
index 8d28e1ff4b..dd1764e6d6 100644
--- a/engines/mohawk/graphics.h
+++ b/engines/mohawk/graphics.h
@@ -27,11 +27,11 @@
#define MOHAWK_GRAPHICS_H
#include "mohawk/bitmap.h"
-#include "mohawk/jpeg.h"
#include "mohawk/livingbooks.h"
-#include "mohawk/myst_pict.h"
#include "common/file.h"
+#include "graphics/pict.h"
+#include "graphics/video/codecs/mjpeg.h"
namespace Mohawk {
@@ -96,16 +96,16 @@ public:
void loadExternalPictureFile(uint16 stack);
void copyImageSectionToScreen(uint16 image, Common::Rect src, Common::Rect dest);
void copyImageToScreen(uint16 image, Common::Rect dest);
- void showCursor(void);
- void hideCursor(void);
+ void showCursor();
+ void hideCursor();
void changeCursor(uint16);
void drawRect(Common::Rect rect, bool active);
private:
MohawkEngine_Myst *_vm;
MystBitmap *_bmpDecoder;
- MystPICT *_pictDecoder;
- JPEGDecoder *_jpegDecoder;
+ Graphics::PictDecoder *_pictDecoder;
+ Graphics::JPEGDecoder *_jpegDecoder;
Graphics::PixelFormat _pixelFormat;
struct PictureFile {
diff --git a/engines/mohawk/jpeg.cpp b/engines/mohawk/jpeg.cpp
deleted file mode 100644
index 07ec54dfea..0000000000
--- a/engines/mohawk/jpeg.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/system.h"
-#include "graphics/conversion.h" // For YUV2RGB
-
-#include "mohawk/jpeg.h"
-
-namespace Mohawk {
-
-JPEGDecoder::JPEGDecoder(bool freeSurfaceAfterUse) : Graphics::Codec(), _freeSurfaceAfterUse(freeSurfaceAfterUse) {
- _jpeg = new Graphics::JPEG();
- _pixelFormat = g_system->getScreenFormat();
- _surface = NULL;
-}
-
-JPEGDecoder::~JPEGDecoder() {
- delete _jpeg;
-
- if (_surface) {
- _surface->free();
- delete _surface;
- }
-}
-
-Graphics::Surface *JPEGDecoder::decodeImage(Common::SeekableReadStream* stream) {
- _jpeg->read(stream);
- Graphics::Surface *ySurface = _jpeg->getComponent(1);
- Graphics::Surface *uSurface = _jpeg->getComponent(2);
- Graphics::Surface *vSurface = _jpeg->getComponent(3);
-
- Graphics::Surface *destSurface = NULL;
-
- // If we should free the surface after use, use the internal _surface storage
- // (this should be used when using as a Codec, as the Codecs should free their
- // surfaces when deleting the Codec object). Otherwise, create a new Surface
- // as the destination.
- if (_freeSurfaceAfterUse) {
- if (!_surface) {
- _surface = new Graphics::Surface();
- _surface->create(ySurface->w, ySurface->h, _pixelFormat.bytesPerPixel);
- }
- destSurface = _surface;
- } else {
- destSurface = new Graphics::Surface();
- destSurface->create(ySurface->w, ySurface->h, _pixelFormat.bytesPerPixel);
- }
-
- assert(destSurface);
-
- for (uint16 i = 0; i < destSurface->h; i++) {
- for (uint16 j = 0; j < destSurface->w; j++) {
- byte r = 0, g = 0, b = 0;
- Graphics::YUV2RGB(*((byte *)ySurface->getBasePtr(j, i)), *((byte *)uSurface->getBasePtr(j, i)), *((byte *)vSurface->getBasePtr(j, i)), r, g, b);
- if (_pixelFormat.bytesPerPixel == 2)
- *((uint16 *)destSurface->getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
- else
- *((uint32 *)destSurface->getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
- }
- }
-
- return destSurface;
-}
-
-} // End of namespace Mohawk
diff --git a/engines/mohawk/module.mk b/engines/mohawk/module.mk
index b224a8b143..bb79d4abac 100644
--- a/engines/mohawk/module.mk
+++ b/engines/mohawk/module.mk
@@ -6,11 +6,9 @@ MODULE_OBJS = \
detection.o \
dialogs.o \
graphics.o \
- jpeg.o \
livingbooks.o \
mohawk.o \
myst.o \
- myst_pict.o \
myst_vars.o \
myst_saveload.o \
myst_scripts.o \
@@ -22,13 +20,7 @@ MODULE_OBJS = \
riven_scripts.o \
riven_vars.o \
sound.o \
- video/cinepak.o \
- video/qdm2.o \
- video/qtrle.o \
- video/qt_player.o \
- video/rpza.o \
- video/smc.o \
- video/video.o
+ video.o
# This module can be built as a plugin
diff --git a/engines/mohawk/mohawk.cpp b/engines/mohawk/mohawk.cpp
index 5bde6bbeec..6b4d8bb2d2 100644
--- a/engines/mohawk/mohawk.cpp
+++ b/engines/mohawk/mohawk.cpp
@@ -35,7 +35,7 @@
#include "mohawk/mohawk.h"
#include "mohawk/dialogs.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "sound/mixer.h"
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index d1ef3b2137..9ff301c129 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -33,7 +33,7 @@
#include "mohawk/dialogs.h"
#include "mohawk/resource.h"
#include "mohawk/resource_cache.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
namespace Mohawk {
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index a453bb0985..2f6d178da8 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -27,7 +27,7 @@
#include "mohawk/graphics.h"
#include "mohawk/myst_scripts.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "gui/message.h"
diff --git a/engines/mohawk/resource.cpp b/engines/mohawk/resource.cpp
index 62a857b90b..74efd6770f 100644
--- a/engines/mohawk/resource.cpp
+++ b/engines/mohawk/resource.cpp
@@ -103,7 +103,7 @@ void MohawkArchive::open(Common::SeekableReadStream *stream) {
else
debug (3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x NameTable Offset = %04x", i, tag2str(_types[i].tag), _types[i].resource_table_offset, _types[i].name_table_offset);
- //Resource Table
+ // Resource Table
_mhk->seek(_rsrc.abs_offset + _types[i].resource_table_offset);
_types[i].resTable.resources = _mhk->readUint16BE();
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 0412144034..07b08dc220 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -29,39 +29,50 @@
#include "common/keyboard.h"
#include "mohawk/graphics.h"
+#include "mohawk/resource.h"
#include "mohawk/riven.h"
#include "mohawk/riven_external.h"
#include "mohawk/riven_saveload.h"
#include "mohawk/dialogs.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
namespace Mohawk {
-Common::Rect *g_atrusJournalRectSolo;
-Common::Rect *g_atrusJournalRect;
-Common::Rect *g_cathJournalRect;
-Common::Rect *g_trapBookRect;
+Common::Rect *g_atrusJournalRect1;
+Common::Rect *g_atrusJournalRect2;
+Common::Rect *g_cathJournalRect2;
+Common::Rect *g_atrusJournalRect3;
+Common::Rect *g_cathJournalRect3;
+Common::Rect *g_trapBookRect3;
MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescription *gamedesc) : MohawkEngine(syst, gamedesc) {
_showHotspots = false;
_cardData.hasData = false;
_gameOver = false;
_activatedSLST = false;
+ _ignoreNextMouseUp = false;
_extrasFile = NULL;
+ _curStack = aspit;
+ _hotspots = NULL;
- // Attempt to let game run from the CDs
- // NOTE: assets2 contains higher quality audio than assets1
- const Common::FSNode gameDataDir(ConfMan.get("path"));
+ // NOTE: We can never really support CD swapping. All of the music files
+ // (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive
+ // during install and used from there. The same goes for the extras.mhk
+ // file. The following directories allow Riven to be played directly
+ // from the DVD.
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
SearchMan.addSubDirectoryMatching(gameDataDir, "all");
SearchMan.addSubDirectoryMatching(gameDataDir, "data");
SearchMan.addSubDirectoryMatching(gameDataDir, "exe");
- SearchMan.addSubDirectoryMatching(gameDataDir, "assets2");
-
- g_atrusJournalRectSolo = new Common::Rect(295, 402, 313, 426);
- g_atrusJournalRect = new Common::Rect(222, 402, 240, 426);
- g_cathJournalRect = new Common::Rect(291, 408, 311, 419);
- g_trapBookRect = new Common::Rect(363, 396, 386, 432);
+ SearchMan.addSubDirectoryMatching(gameDataDir, "assets1");
+
+ g_atrusJournalRect1 = new Common::Rect(295, 402, 313, 426);
+ g_atrusJournalRect2 = new Common::Rect(259, 402, 278, 426);
+ g_cathJournalRect2 = new Common::Rect(328, 408, 348, 419);
+ g_atrusJournalRect3 = new Common::Rect(222, 402, 240, 426);
+ g_cathJournalRect3 = new Common::Rect(291, 408, 311, 419);
+ g_trapBookRect3 = new Common::Rect(363, 396, 386, 432);
}
MohawkEngine_Riven::~MohawkEngine_Riven() {
@@ -70,15 +81,17 @@ MohawkEngine_Riven::~MohawkEngine_Riven() {
delete _externalScriptHandler;
delete _extrasFile;
delete _saveLoad;
+ delete _scriptMan;
delete[] _vars;
- delete _loadDialog;
delete _optionsDialog;
delete _rnd;
- delete g_atrusJournalRectSolo;
- delete g_atrusJournalRect;
- delete g_cathJournalRect;
- delete g_trapBookRect;
- _cardData.scripts.clear();
+ delete[] _hotspots;
+ delete g_atrusJournalRect1;
+ delete g_atrusJournalRect2;
+ delete g_cathJournalRect2;
+ delete g_atrusJournalRect3;
+ delete g_cathJournalRect3;
+ delete g_trapBookRect3;
}
GUI::Debugger *MohawkEngine_Riven::getDebugger() {
@@ -93,9 +106,8 @@ Common::Error MohawkEngine_Riven::run() {
_console = new RivenConsole(this);
_saveLoad = new RivenSaveLoad(this, _saveFileMan);
_externalScriptHandler = new RivenExternal(this);
- _loadDialog = new GUI::SaveLoadChooser("Load Game:", "Load");
- _loadDialog->setSaveMode(false);
_optionsDialog = new RivenOptionsDialog(this);
+ _scriptMan = new RivenScriptManager(this);
_rnd = new Common::RandomSource();
g_eventRec.registerRandomSource(*_rnd, "riven");
@@ -147,10 +159,15 @@ Common::Error MohawkEngine_Riven::run() {
runHotspotScript(_curHotspot, kMouseDownScript);
break;
case Common::EVENT_LBUTTONUP:
- if (_curHotspot >= 0)
- runHotspotScript(_curHotspot, kMouseUpScript);
- else
- checkInventoryClick();
+ // See RivenScript::switchCard() for more information on why we sometimes
+ // disable the next up event.
+ if (!_ignoreNextMouseUp) {
+ if (_curHotspot >= 0)
+ runHotspotScript(_curHotspot, kMouseUpScript);
+ else
+ checkInventoryClick();
+ }
+ _ignoreNextMouseUp = false;
break;
case Common::EVENT_KEYDOWN:
switch (event.kbd.keycode) {
@@ -233,6 +250,7 @@ void MohawkEngine_Riven::changeToStack(uint16 n) {
// Stop any videos playing
_video->stopVideos();
+ _video->clearMLST();
// Clear the old stack files out
for (uint32 i = 0; i < _mhk.size(); i++)
@@ -310,7 +328,6 @@ void MohawkEngine_Riven::refreshCard() {
_gfx->clearWaterEffects();
_gfx->_activatedPLSTs.clear();
_video->stopVideos();
- _video->_mlstRecords.clear();
_gfx->drawPLST(1);
_activatedSLST = false;
@@ -333,13 +350,13 @@ void MohawkEngine_Riven::refreshCard() {
}
void MohawkEngine_Riven::loadCard(uint16 id) {
- // NOTE: Do not clear the card scripts because it may delete a currently running script!
+ // NOTE: The card scripts are cleared by the RivenScriptManager automatically.
Common::SeekableReadStream* inStream = getRawData(ID_CARD, id);
_cardData.name = inStream->readSint16BE();
_cardData.zipModePlace = inStream->readUint16BE();
- _cardData.scripts = RivenScript::readScripts(this, inStream);
+ _cardData.scripts = _scriptMan->readScripts(inStream);
_cardData.hasData = true;
delete inStream;
@@ -357,7 +374,10 @@ void MohawkEngine_Riven::loadCard(uint16 id) {
}
void MohawkEngine_Riven::loadHotspots(uint16 id) {
- // NOTE: Do not clear the hotspots because it may delete a currently running script!
+ // Clear old hotspots
+ delete[] _hotspots;
+
+ // NOTE: The hotspot scripts are cleared by the RivenScriptManager automatically.
Common::SeekableReadStream* inStream = getRawData(ID_HSPT, id);
@@ -399,7 +419,7 @@ void MohawkEngine_Riven::loadHotspots(uint16 id) {
_hotspots[i].zipModeHotspot = inStream->readUint16BE();
// Read in the scripts now
- _hotspots[i].scripts = RivenScript::readScripts(this, inStream);
+ _hotspots[i].scripts = _scriptMan->readScripts(inStream);
}
delete inStream;
@@ -474,26 +494,37 @@ void MohawkEngine_Riven::checkInventoryClick() {
*matchVarToString("returncardid") = _curCard;
// See RivenGraphics::showInventory() for an explanation
- // of why only this variable is used.
+ // of the variables' meanings.
bool hasCathBook = *matchVarToString("acathbook") != 0;
+ bool hasTrapBook = *matchVarToString("atrapbook") != 0;
// Go to the book if a hotspot contains the mouse
if (!hasCathBook) {
- if (g_atrusJournalRectSolo->contains(_mousePos)) {
+ if (g_atrusJournalRect1->contains(_mousePos)) {
+ _gfx->hideInventory();
+ changeToStack(aspit);
+ changeToCard(5);
+ }
+ } else if (!hasTrapBook) {
+ if (g_atrusJournalRect2->contains(_mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(5);
+ } else if (g_cathJournalRect2->contains(_mousePos)) {
+ _gfx->hideInventory();
+ changeToStack(aspit);
+ changeToCard(6);
}
} else {
- if (g_atrusJournalRect->contains(_mousePos)) {
+ if (g_atrusJournalRect3->contains(_mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(5);
- } else if (g_cathJournalRect->contains(_mousePos)) {
+ } else if (g_cathJournalRect3->contains(_mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(6);
- } else if (g_trapBookRect->contains(_mousePos)) {
+ } else if (g_trapBookRect3->contains(_mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(7);
@@ -577,7 +608,19 @@ void MohawkEngine_Riven::runHotspotScript(uint16 hotspot, uint16 scriptType) {
}
void MohawkEngine_Riven::runLoadDialog() {
- runDialog(*_loadDialog);
+ GUI::SaveLoadChooser slc("Load Game:", "Load");
+ slc.setSaveMode(false);
+
+ Common::String gameId = ConfMan.get("gameid");
+
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
+
+ int slot = slc.runModal(plugin, ConfMan.getActiveDomainName());
+ if (slot >= 0)
+ loadGameState(slot);
+
+ slc.close();
}
Common::Error MohawkEngine_Riven::loadGameState(int slot) {
@@ -612,4 +655,4 @@ bool ZipMode::operator== (const ZipMode &z) const {
return z.name == name && z.id == id;
}
-}
+} // End of namespace Mohawk
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index f014b76fb8..631285455e 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -68,10 +68,12 @@ enum {
// Rects for the inventory object positions (initialized in
// MohawkEngine_Riven's constructor).
-extern Common::Rect *g_atrusJournalRectSolo;
-extern Common::Rect *g_atrusJournalRect;
-extern Common::Rect *g_cathJournalRect;
-extern Common::Rect *g_trapBookRect;
+extern Common::Rect *g_atrusJournalRect1;
+extern Common::Rect *g_atrusJournalRect2;
+extern Common::Rect *g_cathJournalRect2;
+extern Common::Rect *g_atrusJournalRect3;
+extern Common::Rect *g_cathJournalRect3;
+extern Common::Rect *g_trapBookRect3;
struct RivenHotspot {
uint16 blstID;
@@ -111,9 +113,9 @@ public:
RivenGraphics *_gfx;
RivenExternal *_externalScriptHandler;
Common::RandomSource *_rnd;
+ RivenScriptManager *_scriptMan;
Card _cardData;
- bool _gameOver;
GUI::Debugger *getDebugger();
@@ -127,7 +129,6 @@ private:
MohawkArchive *_extrasFile; // We need a separate handle for the extra data
RivenConsole *_console;
RivenSaveLoad *_saveLoad;
- GUI::SaveLoadChooser *_loadDialog;
RivenOptionsDialog *_optionsDialog;
// Stack/Card-related functions and variables
@@ -147,6 +148,10 @@ private:
uint32 *_vars;
uint32 _varCount;
+ // Miscellaneous
+ bool _gameOver;
+ bool _ignoreNextMouseUp;
+
public:
Common::SeekableReadStream *getExtrasResource(uint32 tag, uint16 id);
bool _activatedSLST;
@@ -180,6 +185,9 @@ public:
uint32 *getLocalVar(uint32 index);
uint32 *matchVarToString(Common::String varName);
uint32 *matchVarToString(const char *varName);
+
+ void setGameOver() { _gameOver = true; }
+ void ignoreNextMouseUp() { _ignoreNextMouseUp = true; }
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp
index 99afacc5ce..67d621a54c 100644
--- a/engines/mohawk/riven_external.cpp
+++ b/engines/mohawk/riven_external.cpp
@@ -27,7 +27,7 @@
#include "mohawk/riven.h"
#include "mohawk/riven_external.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "gui/message.h"
#include "common/events.h"
@@ -210,7 +210,28 @@ void RivenExternal::runEndGame(uint16 video) {
_vm->_video->playMovieBlocking(video);
// TODO: Play until the last frame and then run the credits
- _vm->_gameOver = true;
+ _vm->setGameOver();
+}
+
+void RivenExternal::runDomeButtonMovie() {
+ // This command just plays the video of the button moving down and up.
+ _vm->_video->playMovieBlocking(2);
+}
+
+void RivenExternal::runDomeCheck() {
+ // Check if we clicked while the golden frame was showing
+
+ VideoHandle video = _vm->_video->findVideoHandle(1);
+ assert(video != NULL_VID_HANDLE);
+
+ int32 curFrame = _vm->_video->getCurFrame(video);
+ int32 frameCount = _vm->_video->getFrameCount(video);
+
+ // The final frame of the video is the 'golden' frame (double meaning: the
+ // frame that is the magic one is the one with the golden symbol) but we
+ // give a 3 frame leeway in either direction.
+ if (frameCount - curFrame < 3 || curFrame < 3)
+ *_vm->matchVarToString("domecheck") = 1;
}
// ------------------------------------------------------------------------------------
@@ -218,11 +239,13 @@ void RivenExternal::runEndGame(uint16 video) {
// ------------------------------------------------------------------------------------
void RivenExternal::xastartupbtnhide(uint16 argc, uint16 *argv) {
- // The original game hides the start/setup buttons depending on an ini entry. It's safe to ignore this command.
+ // The original game hides the start/setup buttons depending on an ini entry.
+ // It's safe to ignore this command.
}
void RivenExternal::xasetupcomplete(uint16 argc, uint16 *argv) {
- // The original game sets an ini entry to disable the setup button and use the start button only. It's safe to ignore this part of the command.
+ // The original game sets an ini entry to disable the setup button and use the
+ // start button only. It's safe to ignore this part of the command.
_vm->_sound->stopSound();
_vm->changeToCard(1);
}
@@ -261,9 +284,14 @@ void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) {
return;
(*page)--;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ if (_vm->getFeatures() & GF_DEMO)
+ _vm->_sound->playSound(4, false);
+ else
+ _vm->_sound->playSound(3, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(1);
_vm->_gfx->updateScreen();
}
@@ -276,9 +304,14 @@ void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) {
return;
(*page)++;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ if (_vm->getFeatures() & GF_DEMO)
+ _vm->_sound->playSound(5, false);
+ else
+ _vm->_sound->playSound(4, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(0);
_vm->_gfx->updateScreen();
}
@@ -326,9 +359,11 @@ void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) {
return;
(*page)--;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ _vm->_sound->playSound(5, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(3);
_vm->_gfx->updateScreen();
}
@@ -341,9 +376,11 @@ void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) {
return;
(*page)++;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ _vm->_sound->playSound(6, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(2);
_vm->_gfx->updateScreen();
}
@@ -357,12 +394,20 @@ void RivenExternal::xtrapbookback(uint16 argc, uint16 *argv) {
void RivenExternal::xatrapbookclose(uint16 argc, uint16 *argv) {
// Close the trap book
*_vm->matchVarToString("atrap") = 0;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(8, false);
+
_vm->refreshCard();
}
void RivenExternal::xatrapbookopen(uint16 argc, uint16 *argv) {
// Open the trap book
*_vm->matchVarToString("atrap") = 1;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(9, false);
+
_vm->refreshCard();
}
@@ -414,7 +459,11 @@ void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) {
return;
(*page)--;
+ // Play the page turning sound
+ _vm->_sound->playSound(22, false);
+
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(1);
_vm->_gfx->updateScreen();
}
@@ -427,7 +476,11 @@ void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) {
return;
(*page)++;
+ // Play the page turning sound
+ _vm->_sound->playSound(23, false);
+
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(0);
_vm->_gfx->updateScreen();
}
@@ -514,13 +567,14 @@ void RivenExternal::xbupdateboiler(uint16 argc, uint16 *argv) {
if (heat) {
if (platform == 0) {
_vm->_video->activateMLST(7, _vm->getCurCard());
- // TODO: Play video (non-blocking)
+ _vm->_video->playMovie(7);
} else {
_vm->_video->activateMLST(8, _vm->getCurCard());
- // TODO: Play video (non-blocking)
+ _vm->_video->playMovie(8);
}
} else {
- // TODO: Stop MLST's 7 and 8
+ _vm->_video->stopMovie(7);
+ _vm->_video->stopMovie(8);
}
_vm->refreshCard();
@@ -627,26 +681,28 @@ void RivenExternal::xbisland190_slidermw(uint16 argc, uint16 *argv) {
}
void RivenExternal::xbscpbtn(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeButtonMovie();
}
void RivenExternal::xbisland_domecheck(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeCheck();
}
void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
// Get the variable for the valve
uint32 *valve = _vm->matchVarToString("bvalve");
- Common::Event event;
int changeX = 0;
int changeY = 0;
+ bool done = false;
// Set the cursor to the closed position
_vm->_gfx->changeCursor(2004);
_vm->_system->updateScreen();
- for (;;) {
+ while (!done) {
+ Common::Event event;
+
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
@@ -658,30 +714,53 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
// FIXME: These values for changes in x/y could be tweaked.
if (*valve == 0 && changeY <= -10) {
*valve = 1;
- // TODO: Play movie
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_video->playMovieBlocking(2);
_vm->refreshCard();
} else if (*valve == 1) {
if (changeX >= 0 && changeY >= 10) {
*valve = 0;
- // TODO: Play movie
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_video->playMovieBlocking(3);
_vm->refreshCard();
} else if (changeX <= -10 && changeY <= 10) {
*valve = 2;
- // TODO: Play movie
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_video->playMovieBlocking(1);
_vm->refreshCard();
}
} else if (*valve == 2 && changeX >= 10) {
*valve = 1;
- // TODO: Play movie
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_video->playMovieBlocking(4);
_vm->refreshCard();
}
- return;
+ done = true;
default:
break;
}
}
_vm->_system->delayMillis(10);
}
+
+ // If we changed state and the new state is that the valve is flowing to
+ // the boiler, we need to update the boiler state.
+ if (*valve == 1) {
+ if (*_vm->matchVarToString("bidvlv") == 1) { // Check which way the water is going at the boiler
+ if (*_vm->matchVarToString("bblrarm") == 1) {
+ // If the pipe is open, make sure the water is drained out
+ *_vm->matchVarToString("bheat") = 0;
+ *_vm->matchVarToString("bblrwtr") = 0;
+ } else {
+ // If the pipe is closed, fill the boiler again
+ *_vm->matchVarToString("bheat") = *_vm->matchVarToString("bblrvalve");
+ *_vm->matchVarToString("bblrwtr") = 1;
+ }
+ } else {
+ // Have the grating inside the boiler match the switch outside
+ *_vm->matchVarToString("bblrgrt") = (*_vm->matchVarToString("bblrsw") == 1) ? 0 : 1;
+ }
+ }
}
void RivenExternal::xbchipper(uint16 argc, uint16 *argv) {
@@ -723,11 +802,11 @@ void RivenExternal::xgisland25_slidermw(uint16 argc, uint16 *argv) {
}
void RivenExternal::xgscpbtn(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeButtonMovie();
}
void RivenExternal::xgisland1490_domecheck(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeCheck();
}
void RivenExternal::xgplateau3160_dopools(uint16 argc, uint16 *argv) {
@@ -936,33 +1015,60 @@ void RivenExternal::xjtunnel106_pictfix(uint16 argc, uint16 *argv) {
}
void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) {
- // TODO: This function is supposed to do a lot more, something like this (pseudocode):
-
- // Show level pull movie
- // Set transition up
- // Change to up card
- // Show movie of carriage coming down
- // Set transition down
- // Change back to card 276
- // Show movie of carriage coming down
- // if jgallows == 0
- // Set up timer
- // Enter new input loop
- // if you click within the time
- // move forward
- // set transition right
- // change to card right
- // show movie of ascending
- // change to card 263
- // else
- // show movie of carriage ascending only
- // else
- // show movie of carriage ascending only
-
-
- // For now, if the gallows base is closed, assume ascension and move to that card.
- if (*_vm->matchVarToString("jgallows") == 0)
- _vm->changeToCard(_vm->matchRMAPToCard(0x17167));
+ // Run the gallows's carriage
+
+ _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_video->playMovieBlocking(1); // Play handle movie
+ _vm->_gfx->scheduleTransition(15); // Set pan down transition
+ _vm->changeToCard(_vm->matchRMAPToCard(0x18e77)); // Change to card facing up
+ _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor (again)
+ _vm->_video->playMovieBlocking(4); // Play carriage beginning to drop
+ _vm->_gfx->scheduleTransition(14); // Set pan up transition
+ _vm->changeToCard(_vm->matchRMAPToCard(0x183a9)); // Change to card looking straight again
+ _vm->_video->playMovieBlocking(2);
+
+ uint32 *gallows = _vm->matchVarToString("jgallows");
+ if (*gallows == 1) {
+ // If the gallows is open, play the up movie and return
+ _vm->_video->playMovieBlocking(3);
+ return;
+ }
+
+ // Give the player 5 seconds to click (anywhere)
+ uint32 startTime = _vm->_system->getMillis();
+ bool gotClick = false;
+ while (_vm->_system->getMillis() - startTime <= 5000 && !gotClick) {
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ _vm->_system->updateScreen();
+ break;
+ case Common::EVENT_LBUTTONUP:
+ gotClick = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ _vm->_system->delayMillis(10);
+ }
+
+ _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor
+
+ if (gotClick) {
+ _vm->_gfx->scheduleTransition(16); // Schedule dissolve transition
+ _vm->changeToCard(_vm->matchRMAPToCard(0x18d4d)); // Move forward
+ _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_system->delayMillis(500); // Delay a half second before changing again
+ _vm->_gfx->scheduleTransition(12); // Schedule pan left transition
+ _vm->changeToCard(_vm->matchRMAPToCard(0x18ab5)); // Turn right
+ _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_video->playMovieBlocking(1); // Play carriage ride movie
+ _vm->changeToCard(_vm->matchRMAPToCard(0x17167)); // We have arrived at the top
+ } else
+ _vm->_video->playMovieBlocking(3); // Too slow!
}
void RivenExternal::xjdome25_resetsliders(uint16 argc, uint16 *argv) {
@@ -978,11 +1084,11 @@ void RivenExternal::xjdome25_slidermw(uint16 argc, uint16 *argv) {
}
void RivenExternal::xjscpbtn(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeButtonMovie();
}
void RivenExternal::xjisland3500_domecheck(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeCheck();
}
int RivenExternal::jspitElevatorLoop() {
@@ -1019,8 +1125,10 @@ int RivenExternal::jspitElevatorLoop() {
void RivenExternal::xhandlecontrolup(uint16 argc, uint16 *argv) {
int changeLevel = jspitElevatorLoop();
+ // If we've moved the handle down, go down a floor
if (changeLevel == -1) {
- // TODO: Run movie
+ _vm->_video->playMovieBlocking(1);
+ _vm->_video->playMovieBlocking(2);
_vm->changeToCard(_vm->matchRMAPToCard(0x1e374));
}
}
@@ -1028,8 +1136,10 @@ void RivenExternal::xhandlecontrolup(uint16 argc, uint16 *argv) {
void RivenExternal::xhandlecontroldown(uint16 argc, uint16 *argv) {
int changeLevel = jspitElevatorLoop();
+ // If we've moved the handle up, go up a floor
if (changeLevel == 1) {
- // TODO: Run movie
+ _vm->_video->playMovieBlocking(1);
+ _vm->_video->playMovieBlocking(2);
_vm->changeToCard(_vm->matchRMAPToCard(0x1e374));
}
}
@@ -1037,11 +1147,29 @@ void RivenExternal::xhandlecontroldown(uint16 argc, uint16 *argv) {
void RivenExternal::xhandlecontrolmid(uint16 argc, uint16 *argv) {
int changeLevel = jspitElevatorLoop();
+ if (changeLevel == 0)
+ return;
+
+ // Play the handle moving video
+ if (changeLevel == 1)
+ _vm->_video->playMovieBlocking(7);
+ else
+ _vm->_video->playMovieBlocking(6);
+
+ // If the whark's mouth is open, close it
+ uint32 *mouthVar = _vm->matchVarToString("jwmouth");
+ if (*mouthVar == 1) {
+ _vm->_video->playMovieBlocking(3);
+ _vm->_video->playMovieBlocking(8);
+ *mouthVar = 0;
+ }
+
+ // Play the elevator video and then change the card
if (changeLevel == 1) {
- // TODO: Run movie
+ _vm->_video->playMovieBlocking(5);
_vm->changeToCard(_vm->matchRMAPToCard(0x1e597));
- } else if (changeLevel == -1) {
- // TODO: Run movie
+ } else {
+ _vm->_video->playMovieBlocking(4);
_vm->changeToCard(_vm->matchRMAPToCard(0x1e29c));
}
}
@@ -1172,9 +1300,11 @@ void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) {
return;
(*page)--;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ _vm->_sound->playSound(12, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(1);
_vm->_gfx->updateScreen();
}
@@ -1187,13 +1317,15 @@ void RivenExternal::xogehnbooknextpage(uint16 argc, uint16 *argv) {
return;
(*page)++;
- // TODO: Play the page turning sound
+ // Play the page turning sound
+ _vm->_sound->playSound(13, false);
// Now update the screen :)
+ _vm->_gfx->scheduleTransition(0);
_vm->_gfx->updateScreen();
}
-static uint16 getComboDigit(uint32 correctCombo, uint32 digit) {
+uint16 RivenExternal::getComboDigit(uint32 correctCombo, uint32 digit) {
static const uint32 powers[] = { 100000, 10000, 1000, 100, 10, 1 };
return (correctCombo % powers[digit]) / powers[digit + 1];
}
@@ -1258,11 +1390,11 @@ void RivenExternal::xpisland990_elevcombo(uint16 argc, uint16 *argv) {
}
void RivenExternal::xpscpbtn(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeButtonMovie();
}
void RivenExternal::xpisland290_domecheck(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeCheck();
}
void RivenExternal::xpisland25_opencard(uint16 argc, uint16 *argv) {
@@ -1457,11 +1589,11 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
}
void RivenExternal::xtscpbtn(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeButtonMovie();
}
void RivenExternal::xtisland4990_domecheck(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ runDomeCheck();
}
void RivenExternal::xtisland5056_opencard(uint16 argc, uint16 *argv) {
diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h
index 8270a00854..bdf3fa01bc 100644
--- a/engines/mohawk/riven_external.h
+++ b/engines/mohawk/riven_external.h
@@ -38,6 +38,7 @@ public:
~RivenExternal();
void runCommand(uint16 argc, uint16 *argv);
+ uint16 getComboDigit(uint32 correctCombo, uint32 digit);
private:
MohawkEngine_Riven *_vm;
@@ -57,6 +58,8 @@ private:
int jspitElevatorLoop();
void runDemoBoundaryDialog();
void runEndGame(uint16 video);
+ void runDomeCheck();
+ void runDomeButtonMovie();
// -----------------------------------------------------
// aspit (Main Menu, Books, Setup) external commands
diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp
index 3c989838da..d73b4ec0dc 100644
--- a/engines/mohawk/riven_saveload.cpp
+++ b/engines/mohawk/riven_saveload.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "mohawk/resource.h"
#include "mohawk/riven.h"
#include "mohawk/riven_saveload.h"
@@ -31,11 +32,9 @@
namespace Mohawk {
RivenSaveLoad::RivenSaveLoad(MohawkEngine_Riven *vm, Common::SaveFileManager *saveFileMan) : _vm(vm), _saveFileMan(saveFileMan) {
- _loadFile = new MohawkArchive();
}
RivenSaveLoad::~RivenSaveLoad() {
- delete _loadFile;
}
Common::StringArray RivenSaveLoad::generateSaveGameList() {
@@ -63,7 +62,8 @@ static uint16 mapOldStackIDToNew(uint16 oldID) {
case 8:
return aspit;
}
- error ("Unknown old stack ID %d", oldID);
+
+ error("Unknown old stack ID %d", oldID);
return 0;
}
@@ -86,7 +86,8 @@ static uint16 mapNewStackIDToOld(uint16 newID) {
case tspit:
return 4;
}
- error ("Unknown new stack ID %d", newID);
+
+ error("Unknown new stack ID %d", newID);
return 0;
}
@@ -94,26 +95,28 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
if (_vm->getFeatures() & GF_DEMO) // Don't load games in the demo
return false;
- Common::InSaveFile *loadFile;
- if (!(loadFile = _saveFileMan->openForLoading(filename.c_str())))
+ Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filename);
+ if (!loadFile)
return false;
- debug (0, "Loading game from \'%s\'", filename.c_str());
- _loadFile->open(loadFile);
+ debug(0, "Loading game from \'%s\'", filename.c_str());
+
+ MohawkArchive *mhk = new MohawkArchive();
+ mhk->open(loadFile);
// First, let's make sure we're using a saved game file from this version of Riven by checking the VERS resource
- Common::SeekableReadStream *vers = _loadFile->getRawData(ID_VERS, 1);
+ Common::SeekableReadStream *vers = mhk->getRawData(ID_VERS, 1);
uint32 saveGameVersion = vers->readUint32BE();
delete vers;
if ((saveGameVersion == kCDSaveGameVersion && (_vm->getFeatures() & GF_DVD))
|| (saveGameVersion == kDVDSaveGameVersion && !(_vm->getFeatures() & GF_DVD))) {
- warning ("Incompatible saved game versions. No support for this yet.");
- delete _loadFile;
+ warning("Incompatible saved game versions. No support for this yet.");
+ delete mhk;
return false;
}
// Now, we'll read in the variable values.
- Common::SeekableReadStream *vars = _loadFile->getRawData(ID_VARS, 1);
+ Common::SeekableReadStream *vars = mhk->getRawData(ID_VARS, 1);
Common::Array<uint32> rawVariables;
while (!vars->eos()) {
@@ -126,7 +129,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
// Next, we set the variables based on the name found by the index in the VARS resource.
// TODO: Merge with code in mohawk.cpp for loading names?
- Common::SeekableReadStream *names = _loadFile->getRawData(ID_NAME, 1);
+ Common::SeekableReadStream *names = mhk->getRawData(ID_NAME, 1);
uint16 namesCount = names->readUint16BE();
uint16 *stringOffsets = new uint16[namesCount];
@@ -151,9 +154,10 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
c = (char)names->readByte();
}
- // WORKAROUND: Some versions have two extra variables. However, the saves are
- // still compatible with other saves of the same version. Are these used in the
- // original interpreter anywhere? (They come from DVD v1.1)
+ // TODO: Some versions have two extra variables. However, the saves are
+ // still compatible with other saves of the same version (they come from DVD v1.1).
+ // There are used in the whark number puzzle. I thought jleftpos and jrightpos were
+ // for this purpose.
if (name == "dropLeftStart" || name == "dropRightStart")
continue;
@@ -161,11 +165,11 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
*var = rawVariables[i];
- if (!scumm_stricmp(name.c_str(), "CurrentStackID"))
+ if (name.equalsIgnoreCase("CurrentStackID"))
stackID = mapOldStackIDToNew(rawVariables[i]);
- else if (!scumm_stricmp(name.c_str(), "CurrentCardID"))
+ else if (name.equalsIgnoreCase("CurrentCardID"))
cardID = rawVariables[i];
- else if (!scumm_stricmp(name.c_str(), "ReturnStackID"))
+ else if (name.equalsIgnoreCase("ReturnStackID"))
*var = mapOldStackIDToNew(rawVariables[i]);
}
@@ -179,7 +183,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
_vm->_zipModeData.clear();
// Finally, we load in zip mode data.
- Common::SeekableReadStream *zips = _loadFile->getRawData(ID_ZIPS, 1);
+ Common::SeekableReadStream *zips = mhk->getRawData(ID_ZIPS, 1);
uint16 zipsRecordCount = zips->readUint16BE();
for (uint16 i = 0; i < zipsRecordCount; i++) {
ZipMode zip;
@@ -189,10 +193,10 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
zip.id = zips->readUint16BE();
_vm->_zipModeData.push_back(zip);
}
+
delete zips;
+ delete mhk;
- delete _loadFile;
- _loadFile = NULL;
return true;
}
@@ -211,7 +215,14 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() {
for (uint32 i = 0; i < _vm->getVarCount(); i++) {
stream->writeUint32BE(0); // Unknown
stream->writeUint32BE(0); // Unknown
- stream->writeUint32BE(_vm->getGlobalVar(i));
+
+ // Remap returnstackid here because we don't actually want to change
+ // our internal returnstackid.
+ uint32 variable = _vm->getGlobalVar(i);
+ if (_vm->getGlobalVarName(i) == "returnstackid")
+ variable = mapNewStackIDToOld(variable);
+
+ stream->writeUint32BE(variable);
}
return stream;
@@ -257,17 +268,17 @@ bool RivenSaveLoad::saveGame(Common::String filename) {
// Note, this code is still WIP. It works quite well for now.
// Make sure we have the right extension
- if (!filename.hasSuffix(".rvn") && !filename.hasSuffix(".RVN"))
+ if (!filename.matchString("*.rvn", true))
filename += ".rvn";
// Convert class variables to variable numbers
*_vm->matchVarToString("currentstackid") = mapNewStackIDToOld(_vm->getCurStack());
*_vm->matchVarToString("currentcardid") = _vm->getCurCard();
- *_vm->matchVarToString("returnstackid") = mapNewStackIDToOld(*_vm->matchVarToString("returnstackid"));
- Common::OutSaveFile *saveFile;
- if (!(saveFile = _saveFileMan->openForSaving(filename.c_str())))
+ Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename);
+ if (!saveFile)
return false;
+
debug (0, "Saving game to \'%s\'", filename.c_str());
Common::MemoryWriteStreamDynamic *versSection = genVERSSection();
@@ -392,7 +403,7 @@ bool RivenSaveLoad::saveGame(Common::String filename) {
void RivenSaveLoad::deleteSave(Common::String saveName) {
debug (0, "Deleting save file \'%s\'", saveName.c_str());
- _saveFileMan->removeSavefile(saveName.c_str());
+ _saveFileMan->removeSavefile(saveName);
}
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_saveload.h b/engines/mohawk/riven_saveload.h
index c708f9d35d..9cc9bc3737 100644
--- a/engines/mohawk/riven_saveload.h
+++ b/engines/mohawk/riven_saveload.h
@@ -29,8 +29,6 @@
#include "common/savefile.h"
#include "common/str.h"
-#include "mohawk/resource.h"
-
namespace Mohawk {
class MohawkEngine_Riven;
@@ -53,7 +51,6 @@ public:
private:
MohawkEngine_Riven *_vm;
Common::SaveFileManager *_saveFileMan;
- MohawkArchive *_loadFile;
Common::MemoryWriteStreamDynamic *genVERSSection();
Common::MemoryWriteStreamDynamic *genNAMESection();
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index e809ad9642..1fcaba8ac0 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -28,40 +28,28 @@
#include "mohawk/riven_external.h"
#include "mohawk/riven_scripts.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "common/stream.h"
#include "graphics/cursorman.h"
namespace Mohawk {
-RivenScript::RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType)
- : _vm(vm), _stream(stream), _scriptType(scriptType) {
+RivenScript::RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard)
+ : _vm(vm), _stream(stream), _scriptType(scriptType), _parentStack(parentStack), _parentCard(parentCard) {
setupOpcodes();
+ _isRunning = false;
}
RivenScript::~RivenScript() {
delete _stream;
}
-RivenScriptList RivenScript::readScripts(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream) {
- RivenScriptList scriptList;
-
- uint16 scriptCount = stream->readUint16BE();
- for (uint16 i = 0; i < scriptCount; i++) {
- uint16 scriptType = stream->readUint16BE();
- uint32 scriptSize = calculateScriptSize(stream);
- scriptList.push_back(Common::SharedPtr<RivenScript>(new RivenScript(vm, stream->readStream(scriptSize), scriptType)));
- }
-
- return scriptList;
-}
-
uint32 RivenScript::calculateCommandSize(Common::SeekableReadStream* script) {
uint16 command = script->readUint16BE();
uint32 commandSize = 2;
if (command == 8) {
- if (script->readUint16BE() != 2)
+ if (script->readUint16BE() != 2) // Arg count?
warning ("if-then-else unknown value is not 2");
script->readUint16BE(); // variable to check against
uint16 logicBlockCount = script->readUint16BE(); // number of logic blocks
@@ -161,7 +149,7 @@ void RivenScript::setupOpcodes() {
OPCODE(activateFLST),
OPCODE(zipMode),
OPCODE(activateMLST),
- OPCODE(activateSLSTWithVolume)
+ OPCODE(empty) // Activate an SLST with a volume parameter (not used)
};
_opcodes = riven_opcodes;
@@ -239,10 +227,13 @@ void RivenScript::dumpCommands(Common::StringArray varNames, Common::StringArray
}
void RivenScript::runScript() {
+ _isRunning = true;
+
if (_stream->pos() != 0)
_stream->seek(0);
processCommands(true);
+ _isRunning = false;
}
void RivenScript::processCommands(bool runCommands) {
@@ -298,13 +289,10 @@ void RivenScript::processCommands(bool runCommands) {
// Command 1: draw tBMP resource (tbmp_id, left, top, right, bottom, u0, u1, u2, u3)
void RivenScript::drawBitmap(uint16 op, uint16 argc, uint16 *argv) {
- if (argc < 5) {
- // Copy the image to the whole screen, ignoring the rest of the parameters
+ if (argc < 5) // Copy the image to the whole screen, ignoring the rest of the parameters
_vm->_gfx->copyImageToScreen(argv[0], 0, 0, 608, 392);
- } else {
- // Copy the image to a certain part of the screen
+ else // Copy the image to a certain part of the screen
_vm->_gfx->copyImageToScreen(argv[0], argv[1], argv[2], argv[3], argv[4]);
- }
// Now, update the screen
_vm->_gfx->updateScreen();
@@ -313,6 +301,12 @@ void RivenScript::drawBitmap(uint16 op, uint16 argc, uint16 *argv) {
// Command 2: go to card (card id)
void RivenScript::switchCard(uint16 op, uint16 argc, uint16 *argv) {
_vm->changeToCard(argv[0]);
+
+ // WORKAROUND: If we changed card on a mouse down event,
+ // we want to ignore the next mouse up event so we don't
+ // change card when lifting the mouse on the next card.
+ if (_scriptType == kMouseDownScript)
+ _vm->ignoreNextMouseUp();
}
// Command 3: play an SLST from the script
@@ -547,9 +541,8 @@ void RivenScript::activateSLST(uint16 op, uint16 argc, uint16 *argv) {
// Command 41: activate MLST record and play
void RivenScript::activateMLSTAndPlay(uint16 op, uint16 argc, uint16 *argv) {
- _vm->_video->enableMovie(argv[0] - 1);
_vm->_video->activateMLST(argv[0], _vm->getCurCard());
- // TODO: Play movie (blocking?)
+ _vm->_video->playMovie(argv[0]);
}
// Command 43: activate BLST record (card hotspot enabling lists)
@@ -608,9 +601,46 @@ void RivenScript::activateMLST(uint16 op, uint16 argc, uint16 *argv) {
_vm->_video->activateMLST(argv[0], _vm->getCurCard());
}
-// Command 47: activate SLST record with a volume argument
-void RivenScript::activateSLSTWithVolume(uint16 op, uint16 argc, uint16 *argv) {
- warning("STUB: activateSLSTWithVolume()");
+RivenScriptManager::RivenScriptManager(MohawkEngine_Riven *vm) {
+ _vm = vm;
+}
+
+RivenScriptManager::~RivenScriptManager() {
+ for (uint32 i = 0; i < _currentScripts.size(); i++)
+ delete _currentScripts[i];
+}
+
+RivenScriptList RivenScriptManager::readScripts(Common::SeekableReadStream *stream, bool garbageCollect) {
+ if (garbageCollect)
+ unloadUnusedScripts(); // Garbage collect!
+
+ RivenScriptList scriptList;
+
+ uint16 scriptCount = stream->readUint16BE();
+ for (uint16 i = 0; i < scriptCount; i++) {
+ uint16 scriptType = stream->readUint16BE();
+ uint32 scriptSize = RivenScript::calculateScriptSize(stream);
+ RivenScript *script = new RivenScript(_vm, stream->readStream(scriptSize), scriptType, _vm->getCurStack(), _vm->getCurCard());
+ scriptList.push_back(script);
+
+ // Only add it to the scripts that we will free later if it is requested.
+ // (ie. we don't want to store scripts from the dumpScript console command)
+ if (garbageCollect)
+ _currentScripts.push_back(script);
+ }
+
+ return scriptList;
+}
+
+void RivenScriptManager::unloadUnusedScripts() {
+ // Free any scripts that aren't part of the current card and aren't running
+ for (uint32 i = 0; i < _currentScripts.size(); i++) {
+ if ((_vm->getCurStack() != _currentScripts[i]->getParentStack() || _vm->getCurCard() != _currentScripts[i]->getParentCard()) && !_currentScripts[i]->isRunning()) {
+ delete _currentScripts[i];
+ _currentScripts.remove_at(i);
+ i--;
+ }
+ }
}
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h
index a1512af697..5187bbde08 100644
--- a/engines/mohawk/riven_scripts.h
+++ b/engines/mohawk/riven_scripts.h
@@ -50,19 +50,20 @@ enum {
};
class RivenScript;
-typedef Common::Array<Common::SharedPtr<RivenScript> > RivenScriptList;
class RivenScript {
public:
- RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType);
+ RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard);
~RivenScript();
void runScript();
void dumpScript(Common::StringArray varNames, Common::StringArray xNames, byte tabs);
uint16 getScriptType() { return _scriptType; }
+ uint16 getParentStack() { return _parentStack; }
+ uint16 getParentCard() { return _parentCard; }
+ bool isRunning() { return _isRunning; }
- // Read in an array of script objects from a stream
- static RivenScriptList readScripts(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream);
+ static uint32 calculateScriptSize(Common::SeekableReadStream *script);
private:
typedef void (RivenScript::*OpcodeProcRiven)(uint16 op, uint16 argc, uint16 *argv);
@@ -70,18 +71,18 @@ private:
OpcodeProcRiven proc;
const char *desc;
};
- const RivenOpcode* _opcodes;
+ const RivenOpcode *_opcodes;
void setupOpcodes();
MohawkEngine_Riven *_vm;
Common::SeekableReadStream *_stream;
- uint16 _scriptType;
+ uint16 _scriptType, _parentStack, _parentCard, _parentHotspot;
+ bool _isRunning;
void dumpCommands(Common::StringArray varNames, Common::StringArray xNames, byte tabs);
void processCommands(bool runCommands);
- static uint32 calculateCommandSize(Common::SeekableReadStream* script);
- static uint32 calculateScriptSize(Common::SeekableReadStream* script);
+ static uint32 calculateCommandSize(Common::SeekableReadStream *script);
DECLARE_OPCODE(empty) { warning ("Unknown Opcode %04x", op); }
@@ -120,7 +121,21 @@ private:
DECLARE_OPCODE(activateFLST);
DECLARE_OPCODE(zipMode);
DECLARE_OPCODE(activateMLST);
- DECLARE_OPCODE(activateSLSTWithVolume);
+};
+
+typedef Common::Array<RivenScript*> RivenScriptList;
+
+class RivenScriptManager {
+public:
+ RivenScriptManager(MohawkEngine_Riven *vm);
+ ~RivenScriptManager();
+
+ RivenScriptList readScripts(Common::SeekableReadStream *stream, bool garbageCollect = true);
+
+private:
+ void unloadUnusedScripts();
+ RivenScriptList _currentScripts;
+ MohawkEngine_Riven *_vm;
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp
index 3f7cd5a8b6..b6d2dff315 100644
--- a/engines/mohawk/riven_vars.cpp
+++ b/engines/mohawk/riven_vars.cpp
@@ -319,6 +319,8 @@ void MohawkEngine_Riven::initVars() {
*matchVarToString("bheat") = 1;
*matchVarToString("waterenabled") = 1;
*matchVarToString("ogehnpage") = 1;
+ *matchVarToString("bblrsw") = 1;
+ *matchVarToString("ocage") = 1;
// Randomize the telescope combination
uint32 *teleCombo = matchVarToString("tcorrectorder");
diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index b84573f011..091bd68021 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -27,12 +27,12 @@
#include "common/util.h"
+#include "sound/musicplugin.h"
#include "sound/audiostream.h"
#include "sound/decoders/mp3.h"
#include "sound/decoders/raw.h"
#include "sound/decoders/wave.h"
-
namespace Mohawk {
Sound::Sound(MohawkEngine* vm) : _vm(vm) {
@@ -79,7 +79,7 @@ void Sound::initMidi() {
// Let's get our MIDI parser/driver
_midiParser = MidiParser::createParser_SMF();
- _midiDriver = MidiDriver::createMidi(MidiDriver::detectMusicDriver(MDT_ADLIB|MDT_MIDI));
+ _midiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_ADLIB|MDT_MIDI));
// Set up everything!
_midiDriver->open();
@@ -233,6 +233,10 @@ void Sound::playSLST(uint16 index, uint16 card) {
if (slstRecord.index == index) {
playSLST(slstRecord);
+ delete[] slstRecord.sound_ids;
+ delete[] slstRecord.volumes;
+ delete[] slstRecord.balances;
+ delete[] slstRecord.u2;
delete slstStream;
return;
}
@@ -244,6 +248,7 @@ void Sound::playSLST(uint16 index, uint16 card) {
}
delete slstStream;
+
// No matching records, assume we need to stop all SLST's
stopAllSLST();
}
@@ -277,8 +282,11 @@ void Sound::playSLST(SLSTRecord slstRecord) {
}
void Sound::stopAllSLST() {
- for (uint16 i = 0; i < _currentSLSTSounds.size(); i++)
+ for (uint16 i = 0; i < _currentSLSTSounds.size(); i++) {
_vm->_mixer->stopHandle(*_currentSLSTSounds[i].handle);
+ delete _currentSLSTSounds[i].handle;
+ }
+
_currentSLSTSounds.clear();
}
@@ -314,6 +322,7 @@ void Sound::playSLSTSound(uint16 id, bool fade, bool loop, uint16 volume, int16
void Sound::stopSLSTSound(uint16 index, bool fade) {
// TODO: Fade out, mixer needs to be extended to get volume on a handle
_vm->_mixer->stopHandle(*_currentSLSTSounds[index].handle);
+ delete _currentSLSTSounds[index].handle;
_currentSLSTSounds.remove_at(index);
}
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
new file mode 100644
index 0000000000..17456b8ec3
--- /dev/null
+++ b/engines/mohawk/video.cpp
@@ -0,0 +1,415 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "mohawk/resource.h"
+#include "mohawk/video.h"
+
+#include "common/events.h"
+#include "graphics/video/qt_decoder.h"
+
+namespace Mohawk {
+
+VideoManager::VideoManager(MohawkEngine* vm) : _vm(vm) {
+}
+
+VideoManager::~VideoManager() {
+ stopVideos();
+}
+
+void VideoManager::pauseVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ if (_videoStreams[i].video)
+ _videoStreams[i]->pauseVideo(true);
+}
+
+void VideoManager::resumeVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ if (_videoStreams[i].video)
+ _videoStreams[i]->pauseVideo(false);
+}
+
+void VideoManager::stopVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ delete _videoStreams[i].video;
+ _videoStreams.clear();
+}
+
+void VideoManager::playMovie(Common::String filename, uint16 x, uint16 y, bool clearScreen) {
+ VideoHandle videoHandle = createVideoHandle(filename, x, y, false);
+ if (videoHandle == NULL_VID_HANDLE)
+ return;
+
+ // Clear screen if requested
+ if (clearScreen) {
+ _vm->_system->fillScreen(_vm->_system->getScreenFormat().RGBToColor(0, 0, 0));
+ _vm->_system->updateScreen();
+ }
+
+ waitUntilMovieEnds(videoHandle);
+}
+
+void VideoManager::playMovieCentered(Common::String filename, bool clearScreen) {
+ VideoHandle videoHandle = createVideoHandle(filename, 0, 0, false);
+ if (videoHandle == NULL_VID_HANDLE)
+ return;
+
+ // Clear screen if requested
+ if (clearScreen) {
+ _vm->_system->fillScreen(_vm->_system->getScreenFormat().RGBToColor(0, 0, 0));
+ _vm->_system->updateScreen();
+ }
+
+ _videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2;
+ _videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2;
+
+ waitUntilMovieEnds(videoHandle);
+}
+
+void VideoManager::waitUntilMovieEnds(VideoHandle videoHandle) {
+ bool continuePlaying = true;
+
+ while (_videoStreams[videoHandle].video && !_videoStreams[videoHandle]->endOfVideo() && !_vm->shouldQuit() && continuePlaying) {
+ if (updateBackgroundMovies())
+ _vm->_system->updateScreen();
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_RTL:
+ case Common::EVENT_QUIT:
+ continuePlaying = false;
+ break;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_SPACE:
+ _vm->pauseGame();
+ break;
+ case Common::KEYCODE_ESCAPE:
+ continuePlaying = false;
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ // Cut down on CPU usage
+ _vm->_system->delayMillis(10);
+ }
+
+ delete _videoStreams[videoHandle].video;
+ _videoStreams[videoHandle].video = 0;
+ _videoStreams[videoHandle].id = 0;
+ _videoStreams[videoHandle].filename.clear();
+}
+
+void VideoManager::playBackgroundMovie(Common::String filename, int16 x, int16 y, bool loop) {
+ VideoHandle videoHandle = createVideoHandle(filename, x, y, loop);
+ if (videoHandle == NULL_VID_HANDLE)
+ return;
+
+ // Center x if requested
+ if (x < 0)
+ _videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2;
+
+ // Center y if requested
+ if (y < 0)
+ _videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2;
+}
+
+bool VideoManager::updateBackgroundMovies() {
+ bool updateScreen = false;
+
+ for (uint32 i = 0; i < _videoStreams.size() && !_vm->shouldQuit(); i++) {
+ // Skip deleted videos
+ if (!_videoStreams[i].video)
+ continue;
+
+ // Remove any videos that are over
+ if (_videoStreams[i]->endOfVideo()) {
+ if (_videoStreams[i].loop) {
+ _videoStreams[i]->rewind();
+ } else {
+ delete _videoStreams[i].video;
+ _videoStreams[i].video = 0;
+ _videoStreams[i].id = 0;
+ _videoStreams[i].filename.clear();
+ continue;
+ }
+ }
+
+ // Check if we need to draw a frame
+ if (_videoStreams[i]->needsUpdate()) {
+ Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame();
+ bool deleteFrame = false;
+
+ if (frame && _videoStreams[i].enabled) {
+ // Convert from 8bpp to the current screen format if necessary
+ if (frame->bytesPerPixel == 1) {
+ Graphics::Surface *newFrame = new Graphics::Surface();
+ Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();
+ byte *palette = _videoStreams[i]->getPalette();
+ assert(palette);
+
+ newFrame->create(frame->w, frame->h, pixelFormat.bytesPerPixel);
+
+ for (uint16 j = 0; j < frame->h; j++) {
+ for (uint16 k = 0; k < frame->w; k++) {
+ byte palIndex = *((byte *)frame->getBasePtr(k, j));
+ byte r = palette[palIndex * 3];
+ byte g = palette[palIndex * 3 + 1];
+ byte b = palette[palIndex * 3 + 2];
+ if (pixelFormat.bytesPerPixel == 2)
+ *((uint16 *)newFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
+ else
+ *((uint32 *)newFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
+ }
+ }
+
+ frame = newFrame;
+ deleteFrame = true;
+ }
+
+ // Clip the width/height to make sure we stay on the screen (Myst does this a few times)
+ uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x);
+ uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y);
+ _vm->_system->copyRectToScreen((byte*)frame->pixels, frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height);
+
+ // We've drawn something to the screen, make sure we update it
+ updateScreen = true;
+
+ // Delete the frame if we're using the buffer from the 8bpp conversion
+ if (deleteFrame) {
+ frame->free();
+ delete frame;
+ }
+ }
+ }
+
+ // Update the audio buffer too
+ _videoStreams[i]->updateAudioBuffer();
+ }
+
+ // Return true if we need to update the screen
+ return updateScreen;
+}
+
+void VideoManager::activateMLST(uint16 mlstId, uint16 card) {
+ Common::SeekableReadStream *mlstStream = _vm->getRawData(ID_MLST, card);
+ uint16 recordCount = mlstStream->readUint16BE();
+
+ for (uint16 i = 0; i < recordCount; i++) {
+ MLSTRecord mlstRecord;
+ mlstRecord.index = mlstStream->readUint16BE();
+ mlstRecord.movieID = mlstStream->readUint16BE();
+ mlstRecord.code = mlstStream->readUint16BE();
+ mlstRecord.left = mlstStream->readUint16BE();
+ mlstRecord.top = mlstStream->readUint16BE();
+
+ for (byte j = 0; j < 2; j++)
+ if (mlstStream->readUint16BE() != 0)
+ warning("u0[%d] in MLST non-zero", j);
+
+ if (mlstStream->readUint16BE() != 0xFFFF)
+ warning("u0[2] in MLST not 0xFFFF");
+
+ mlstRecord.loop = mlstStream->readUint16BE();
+ mlstRecord.volume = mlstStream->readUint16BE();
+ mlstRecord.u1 = mlstStream->readUint16BE();
+
+ if (mlstRecord.u1 != 1)
+ warning("mlstRecord.u1 not 1");
+
+ // We've found a match, add it
+ if (mlstRecord.index == mlstId) {
+ // Make sure we don't have any duplicates
+ for (uint32 j = 0; j < _mlstRecords.size(); j++)
+ if (_mlstRecords[j].index == mlstRecord.index || _mlstRecords[j].code == mlstRecord.code) {
+ _mlstRecords.remove_at(j);
+ j--;
+ }
+
+ _mlstRecords.push_back(mlstRecord);
+ break;
+ }
+ }
+
+ delete mlstStream;
+}
+
+void VideoManager::clearMLST() {
+ _mlstRecords.clear();
+}
+
+void VideoManager::playMovie(uint16 id) {
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id) {
+ debug(1, "Play tMOV %d (non-blocking) at (%d, %d) %s", _mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, _mlstRecords[i].loop != 0 ? "looping" : "non-looping");
+ createVideoHandle(_mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, _mlstRecords[i].loop != 0);
+ return;
+ }
+}
+
+void VideoManager::playMovieBlocking(uint16 id) {
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id) {
+ debug(1, "Play tMOV %d (blocking) at (%d, %d)", _mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top);
+ VideoHandle videoHandle = createVideoHandle(_mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, false);
+ waitUntilMovieEnds(videoHandle);
+ return;
+ }
+}
+
+void VideoManager::stopMovie(uint16 id) {
+ debug(2, "Stopping movie %d", id);
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id)
+ for (uint16 j = 0; j < _videoStreams.size(); j++)
+ if (_mlstRecords[i].movieID == _videoStreams[j].id) {
+ delete _videoStreams[j].video;
+ _videoStreams[j].video = 0;
+ _videoStreams[j].id = 0;
+ _videoStreams[j].filename.clear();
+ return;
+ }
+}
+
+void VideoManager::enableMovie(uint16 id) {
+ debug(2, "Enabling movie %d", id);
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id)
+ for (uint16 j = 0; j < _videoStreams.size(); j++)
+ if (_mlstRecords[i].movieID == _videoStreams[j].id) {
+ _videoStreams[j].enabled = true;
+ return;
+ }
+}
+
+void VideoManager::disableMovie(uint16 id) {
+ debug(2, "Disabling movie %d", id);
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id)
+ for (uint16 j = 0; j < _videoStreams.size(); j++)
+ if (_mlstRecords[i].movieID == _videoStreams[j].id) {
+ _videoStreams[j].enabled = false;
+ return;
+ }
+}
+
+void VideoManager::disableAllMovies() {
+ debug(2, "Disabling all movies");
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ _videoStreams[i].enabled = false;
+}
+
+VideoHandle VideoManager::createVideoHandle(uint16 id, uint16 x, uint16 y, bool loop) {
+ // First, check to see if that video is already playing
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (_videoStreams[i].id == id)
+ return i;
+
+ // Otherwise, create a new entry
+ VideoEntry entry;
+ entry.video = new Graphics::QuickTimeDecoder();
+ entry.x = x;
+ entry.y = y;
+ entry.filename = "";
+ entry.id = id;
+ entry.loop = loop;
+ entry.enabled = true;
+ entry->setChunkBeginOffset(_vm->getResourceOffset(ID_TMOV, id));
+ entry->load(_vm->getRawData(ID_TMOV, id));
+
+ // Search for any deleted videos so we can take a formerly used slot
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (!_videoStreams[i].video) {
+ _videoStreams[i] = entry;
+ return i;
+ }
+
+ // Otherwise, just add it to the list
+ _videoStreams.push_back(entry);
+ return _videoStreams.size() - 1;
+}
+
+VideoHandle VideoManager::createVideoHandle(Common::String filename, uint16 x, uint16 y, bool loop) {
+ // First, check to see if that video is already playing
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (_videoStreams[i].filename == filename)
+ return i;
+
+ // Otherwise, create a new entry
+ VideoEntry entry;
+ entry.video = new Graphics::QuickTimeDecoder();
+ entry.x = x;
+ entry.y = y;
+ entry.filename = filename;
+ entry.id = 0;
+ entry.loop = loop;
+ entry.enabled = true;
+
+ Common::File *file = new Common::File();
+ if (!file->open(filename)) {
+ delete file;
+ return NULL_VID_HANDLE;
+ }
+
+ entry->load(file);
+
+ // Search for any deleted videos so we can take a formerly used slot
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (!_videoStreams[i].video) {
+ _videoStreams[i] = entry;
+ return i;
+ }
+
+ // Otherwise, just add it to the list
+ _videoStreams.push_back(entry);
+ return _videoStreams.size() - 1;
+}
+
+VideoHandle VideoManager::findVideoHandle(uint16 id) {
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id)
+ for (uint16 j = 0; j < _videoStreams.size(); j++)
+ if (_videoStreams[j].video && _mlstRecords[i].movieID == _videoStreams[j].id)
+ return j;
+
+ return NULL_VID_HANDLE;
+}
+
+int32 VideoManager::getCurFrame(const VideoHandle &handle) {
+ assert(handle != NULL_VID_HANDLE);
+ return _videoStreams[handle]->getCurFrame();
+}
+
+uint32 VideoManager::getFrameCount(const VideoHandle &handle) {
+ assert(handle != NULL_VID_HANDLE);
+ return _videoStreams[handle]->getFrameCount();
+}
+
+} // End of namespace Mohawk
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
new file mode 100644
index 0000000000..6aa553e26b
--- /dev/null
+++ b/engines/mohawk/video.h
@@ -0,0 +1,114 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MOHAWK_VIDEO_H
+#define MOHAWK_VIDEO_H
+
+#include "graphics/pixelformat.h"
+
+namespace Graphics {
+ class QuickTimeDecoder;
+}
+
+namespace Mohawk {
+
+class MohawkEngine;
+
+struct MLSTRecord {
+ uint16 index;
+ uint16 movieID;
+ uint16 code;
+ uint16 left;
+ uint16 top;
+ uint16 u0[3];
+ uint16 loop;
+ uint16 volume;
+ uint16 u1;
+};
+
+struct VideoEntry {
+ Graphics::QuickTimeDecoder *video;
+ uint16 x;
+ uint16 y;
+ bool loop;
+ Common::String filename;
+ uint16 id; // Riven only
+ bool enabled;
+
+ Graphics::QuickTimeDecoder *operator->() const { assert(video); return video; }
+};
+
+typedef int32 VideoHandle;
+
+enum {
+ NULL_VID_HANDLE = -1
+};
+
+class VideoManager {
+public:
+ VideoManager(MohawkEngine *vm);
+ ~VideoManager();
+
+ // Generic movie functions
+ void playMovie(Common::String filename, uint16 x = 0, uint16 y = 0, bool clearScreen = false);
+ void playMovieCentered(Common::String filename, bool clearScreen = true);
+ void playBackgroundMovie(Common::String filename, int16 x = -1, int16 y = -1, bool loop = false);
+ bool updateBackgroundMovies();
+ void pauseVideos();
+ void resumeVideos();
+ void stopVideos();
+
+ // Riven-related functions
+ void activateMLST(uint16 mlstId, uint16 card);
+ void clearMLST();
+ void enableMovie(uint16 id);
+ void disableMovie(uint16 id);
+ void disableAllMovies();
+ void playMovie(uint16 id);
+ void stopMovie(uint16 id);
+ void playMovieBlocking(uint16 id);
+
+ // Handle functions
+ VideoHandle findVideoHandle(uint16 id);
+ int32 getCurFrame(const VideoHandle &handle);
+ uint32 getFrameCount(const VideoHandle &handle);
+
+private:
+ MohawkEngine *_vm;
+
+ // Riven-related variables
+ Common::Array<MLSTRecord> _mlstRecords;
+
+ // Keep tabs on any videos playing
+ Common::Array<VideoEntry> _videoStreams;
+
+ VideoHandle createVideoHandle(uint16 id, uint16 x, uint16 y, bool loop);
+ VideoHandle createVideoHandle(Common::String filename, uint16 x, uint16 y, bool loop);
+ void waitUntilMovieEnds(VideoHandle videoHandle);
+};
+
+} // End of namespace Mohawk
+
+#endif
diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp
index a493523301..cfe6ad8954 100644
--- a/engines/parallaction/callables_ns.cpp
+++ b/engines/parallaction/callables_ns.cpp
@@ -453,14 +453,15 @@ void Parallaction_ns::_c_startIntro(void *parm) {
}
void Parallaction_ns::_c_endIntro(void *parm) {
- // NOTE: suspend command execution queue, to
- // avoid running the QUIT command before
- // credits are displayed. This solves bug
- // #2619824.
- // Execution of the command list will resume
- // as soon as runGameFrame is run.
- _cmdExec->suspend();
-
+ if (getFeatures() & GF_DEMO) {
+ // NOTE: suspend command execution queue, to
+ // avoid running the QUIT command before
+ // credits are displayed. This solves bug
+ // #2619824.
+ // Execution of the command list will resume
+ // as soon as runGameFrame is run.
+ _cmdExec->suspend();
+ }
startCreditSequence();
_intro = false;
}
diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp
index e5e2b22644..e00a087923 100644
--- a/engines/parallaction/detection.cpp
+++ b/engines/parallaction/detection.cpp
@@ -240,7 +240,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NOLAUNCHLOAD
+ Common::GUIO_NOLAUNCHLOAD,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class ParallactionMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/parallaction/exec.cpp b/engines/parallaction/exec.cpp
index 24579286e6..434c4f6ae6 100644
--- a/engines/parallaction/exec.cpp
+++ b/engines/parallaction/exec.cpp
@@ -193,8 +193,10 @@ void CommandExec::runSuspended() {
debugC(3, kDebugExec, "CommandExec::runSuspended()");
_execZone = _suspendedCtxt._zone;
- runList(_suspendedCtxt._first, _suspendedCtxt._last);
+ CommandList::iterator first = _suspendedCtxt._first;
+ CommandList::iterator last = _suspendedCtxt._last;
cleanSuspendedList();
+ runList(first, last);
}
}
diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp
index d5d89616d2..13c1318123 100644
--- a/engines/parallaction/exec_br.cpp
+++ b/engines/parallaction/exec_br.cpp
@@ -293,7 +293,7 @@ DECLARE_COMMAND_OPCODE(text) {
DECLARE_COMMAND_OPCODE(part) {
- warning("Parallaction_br::cmdOp_part not yet implemented");
+ _vm->_nextPart = ctxt._cmd->_counterValue;
}
@@ -527,6 +527,11 @@ DECLARE_INSTRUCTION_OPCODE(endif) {
DECLARE_INSTRUCTION_OPCODE(stop) {
ZonePtr z = ctxt._inst->_z;
+
+ // Prevent execution if zone is missing. The known case is "PART2/insegui.scr", which has
+ // "STOP insegui", which doesn't exist (see ticket #3021744 for the gory details)
+ if (!z) return;
+
if (ACTIONTYPE(z) == kZoneHear) {
warning("Parallaction_br::instOp_stop not yet implemented for HEAR zones");
// TODO: stop music or sound effects generated by a zone.
diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp
index fc6cb28d9e..a1926fc197 100644
--- a/engines/parallaction/gfxbase.cpp
+++ b/engines/parallaction/gfxbase.cpp
@@ -222,10 +222,12 @@ void Gfx::drawGfxObject(GfxObj *obj, Graphics::Surface &surf) {
obj->getRect(obj->frame, rect);
int x = obj->x;
+ int y = obj->y;
if (_overlayMode) {
x += _scrollPosX;
+ y += _scrollPosY;
}
- rect.translate(x, obj->y);
+ rect.translate(x, y);
data = obj->getData(obj->frame);
if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) {
@@ -281,30 +283,54 @@ void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *sur
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;
+ // unscaled rectangle size
+ uint width = r.width();
+ uint height = r.height();
+
+ // scaled rectangle size
+ uint scaledWidth = r.width() * scale / 100;
+ uint scaledHeight = r.height() * scale / 100;
+
+ // scaled rectangle origin
+ uint scaledLeft = r.left + (width - scaledWidth) / 2;
+ uint scaledTop = r.top + (height - scaledHeight);
+
+ // clipped scaled destination rectangle
+ Common::Rect dstRect(scaledWidth, scaledHeight);
+ dstRect.moveTo(scaledLeft, scaledTop);
+
+ Common::Rect clipper(surf->w, surf->h);
+ dstRect.clip(clipper);
+ if (!dstRect.isValidRect()) return;
+
+
+ // clipped source rectangle
+ Common::Rect srcRect;
+ srcRect.left = (dstRect.left - scaledLeft) * 100 / scale;
+ srcRect.top = (dstRect.top - scaledTop) * 100 / scale;
+ srcRect.setWidth(dstRect.width() * 100 / scale);
+ srcRect.setHeight(dstRect.height() * 100 / scale);
+ if (!srcRect.isValidRect()) return;
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();
+ dp.x = dstRect.left;
+ dp.y = dstRect.top;
+
+ byte *s = data + srcRect.left + srcRect.top * width;
byte *d = (byte*)surf->getBasePtr(dp.x, dp.y);
uint line = 0, col = 0;
- for (uint16 i = 0; i < q.height(); i++) {
+ uint xAccum = 0, yAccum = 0;
+ uint inc = width * (100 - scale);
+ uint thr = width * 100;
+
+ for (uint16 i = 0; i < srcRect.height(); i++) {
yAccum += inc;
if (yAccum >= thr) {
yAccum -= thr;
- s += r.width();
+ s += width;
continue;
}
@@ -312,7 +338,7 @@ void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *sur
byte *d2 = d;
col = 0;
- for (uint16 j = 0; j < q.width(); j++) {
+ for (uint16 j = 0; j < srcRect.width(); j++) {
xAccum += inc;
if (xAccum >= thr) {
@@ -335,7 +361,7 @@ void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *sur
col++;
}
- s += r.width() - q.width();
+ s += width - srcRect.width();
d += surf->w;
line++;
}
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index a7b1f6fe32..326ae2c519 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -317,8 +317,10 @@ void Gfx::drawList(Graphics::Surface &surface, GfxObjArray &list) {
void Gfx::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
if (_doubleBuffering) {
- if (_overlayMode)
+ if (_overlayMode) {
x += _scrollPosX;
+ y += _scrollPosY;
+ }
byte *dst = (byte*)_backBuffer.getBasePtr(x, y);
for (int i = 0; i < h; i++) {
@@ -358,7 +360,7 @@ void Gfx::unlockScreen() {
void Gfx::updateScreenIntern() {
if (_doubleBuffering) {
- byte *data = (byte*)_backBuffer.getBasePtr(_scrollPosX, 0);
+ byte *data = (byte*)_backBuffer.getBasePtr(_scrollPosX, _scrollPosY);
_vm->_system->copyRectToScreen(data, _backBuffer.pitch, 0, 0, _vm->_screenWidth, _vm->_screenHeight);
}
@@ -863,6 +865,8 @@ void Gfx::setBackground(uint type, BackgroundInfo *info) {
_minScrollX = 0;
_maxScrollX = MAX<int>(0, _backgroundInfo->width - _vm->_screenWidth);
+ _minScrollY = 0;
+ _maxScrollY = MAX<int>(0, _backgroundInfo->height - _vm->_screenHeight);
}
diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp
index 7096bbe569..21cb2d8b00 100644
--- a/engines/parallaction/gui_br.cpp
+++ b/engines/parallaction/gui_br.cpp
@@ -98,6 +98,12 @@ public:
}
};
+
+struct LocationPart {
+ int part;
+ const char *location;
+};
+
class MainMenuInputState_BR : public MenuInputState {
Parallaction_br *_vm;
@@ -158,7 +164,7 @@ class MainMenuInputState_BR : public MenuInputState {
const char **_menuStrings;
const MenuOptions *_options;
- static const char *_firstLocation[];
+ static LocationPart _firstLocation[];
int _availItems;
int _selection;
@@ -205,7 +211,8 @@ public:
return this;
}
- switch (_options[_selection]) {
+ int selection = _options[_selection];
+ switch (selection) {
case kMenuQuit: {
_vm->quitGame();
break;
@@ -218,8 +225,10 @@ public:
}
break;
- default:
- _vm->scheduleLocationSwitch(_firstLocation[_options[_selection]]);
+ default:
+ _vm->_nextPart = _firstLocation[selection].part;
+ _vm->scheduleLocationSwitch(_firstLocation[selection].location);
+
}
_vm->_system->showMouse(false);
@@ -262,14 +271,15 @@ public:
};
-const char *MainMenuInputState_BR::_firstLocation[] = {
- "intro.0",
- "museo.1",
- "start.2",
- "bolscoi.3",
- "treno.4"
+LocationPart MainMenuInputState_BR::_firstLocation[] = {
+ { 0, "intro" },
+ { 1, "museo" },
+ { 2, "start" },
+ { 3, "bolscoi" },
+ { 4, "treno" }
};
+
const char *MainMenuInputState_BR::_menuStringsAmiga[NUM_MENULINES] = {
"See the introduction",
"Load a Saved Game",
diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp
index 60cc867226..7ad1be8681 100644
--- a/engines/parallaction/input.cpp
+++ b/engines/parallaction/input.cpp
@@ -148,8 +148,7 @@ void Input::readInput() {
setCursorPos(e.mouse);
}
- if (_vm->_debugger->isAttached())
- _vm->_debugger->onFrame();
+ _vm->_debugger->onFrame();
return;
@@ -390,7 +389,7 @@ void Input::exitInventoryMode() {
_vm->dropItem(z->u._mergeObj1);
_vm->dropItem(z->u._mergeObj2);
_vm->addInventoryItem(z->u._mergeObj3);
- _vm->_cmdExec->run(z->_commands);
+ _vm->_cmdExec->run(z->_commands); // commands might set a new _inputMode
}
}
@@ -407,7 +406,11 @@ void Input::exitInventoryMode() {
}
_vm->resumeJobs();
- _inputMode = kInputModeGame;
+ // in case the input mode was not changed by the code above (especially by the commands
+ // executed in case of a merge), then assume we are going back to game mode
+ if (_inputMode == kInputModeInventory) {
+ _inputMode = kInputModeGame;
+ }
}
bool Input::updateInventoryInput() {
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index a5769350bd..3a84aa215e 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -546,6 +546,9 @@ public:
const char **_audioCommandsNamesRes;
static const char *_partNames[];
int _part;
+ int _nextPart;
+
+
#if 0 // disabled since I couldn't find any references to lip sync in the scripts
int16 _lipSyncVal;
uint _subtitleLipSync;
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index 9fd46cc9af..ee718189b5 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -61,8 +61,8 @@ Common::Error Parallaction_br::init() {
_disk = new DosDisk_br(this);
}
_disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters.
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- MidiDriver *driver = MidiDriver::createMidi(midiDriver);
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ MidiDriver *driver = MidiDriver::createMidi(dev);
_soundManI = new DosSoundMan_br(this, driver);
} else {
_disk = new AmigaDisk_br(this);
@@ -86,6 +86,7 @@ Common::Error Parallaction_br::init() {
_walker = new PathWalker_BR;
_part = -1;
+ _nextPart = -1;
_subtitle[0] = 0;
_subtitle[1] = 0;
@@ -260,6 +261,12 @@ void Parallaction_br::cleanupGame() {
_globalFlagsNames = 0;
_objectsNames = 0;
_countersNames = 0;
+
+ _numLocations = 0;
+ _globalFlags = 0;
+ memset(_localFlags, 0, sizeof(_localFlags));
+ memset(_locationNames, 0, sizeof(_locationNames));
+ memset(_zoneFlags, 0, sizeof(_zoneFlags));
}
@@ -268,17 +275,16 @@ void Parallaction_br::changeLocation() {
return;
}
- char location[200];
- strcpy(location, _newLocationName.c_str());
-
- char *partStr = strrchr(location, '.');
- if (partStr) {
+ if (_nextPart != -1) {
cleanupGame();
- int n = partStr - location;
- location[n] = '\0';
+ // more cleanup needed for part changes (see also saveload)
+ _globalFlags = 0;
+ cleanInventory(true);
+ strcpy(_characterName1, "null");
+
+ _part = _nextPart;
- _part = atoi(++partStr);
if (getFeatures() & GF_DEMO) {
assert(_part == 1);
} else {
@@ -305,8 +311,8 @@ void Parallaction_br::changeLocation() {
freeLocation(false);
// load new location
- strcpy(_location._name, location);
- parseLocation(location);
+ strcpy(_location._name, _newLocationName.c_str());
+ parseLocation(_location._name);
if (_location._startPosition.x != -1000) {
_char._ani->setFoot(_location._startPosition);
@@ -357,6 +363,7 @@ void Parallaction_br::changeLocation() {
_engineFlags &= ~kEngineChangeLocation;
_newLocationName.clear();
+ _nextPart = -1;
}
// FIXME: Parallaction_br::parseLocation() is now a verbatim copy of the same routine from Parallaction_ns.
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index c1d6c9367a..f1e7b14583 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -24,7 +24,6 @@
*/
#include "common/system.h"
-
#include "common/config-manager.h"
#include "parallaction/parallaction.h"
@@ -167,8 +166,8 @@ Common::Error Parallaction_ns::init() {
_disk->init();
if (getPlatform() == Common::kPlatformPC) {
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- MidiDriver *driver = MidiDriver::createMidi(midiDriver);
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ MidiDriver *driver = MidiDriver::createMidi(dev);
_soundManI = new DosSoundMan_ns(this, driver);
_soundManI->setMusicVolume(ConfMan.getInt("music_volume"));
} else {
diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h
index 3e46e99180..5eb26e9fa1 100644
--- a/engines/parallaction/parser.h
+++ b/engines/parallaction/parser.h
@@ -294,6 +294,7 @@ public:
virtual void parseGetData(ZonePtr z);
virtual void parseDoorData(ZonePtr z);
virtual void parseHearData(ZonePtr z);
+ virtual void parseNoneData(ZonePtr z);
protected:
void parseAnswerCounter(Answer *answer);
virtual Answer *parseAnswer();
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index d3ce1235c1..57259fd637 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -825,6 +825,16 @@ void LocationParser_br::parseHearData(ZonePtr z) {
}
}
+void LocationParser_br::parseNoneData(ZonePtr z) {
+ /* the only case we have to handle here is that of "scende2", which is the only Animation with
+ a command list following the type marker.
+ */
+ if (!scumm_stricmp(_tokens[0], "commands")) {
+ parseCommands(z->_commands);
+ }
+}
+
+
typedef void (LocationParser_br::*ZoneTypeParser)(ZonePtr);
static ZoneTypeParser parsers[] = {
0, // no type
@@ -836,7 +846,7 @@ static ZoneTypeParser parsers[] = {
&LocationParser_br::parseHearData,
0, // feel
&LocationParser_br::parseSpeakData,
- 0, // none
+ &LocationParser_br::parseNoneData,
0, // trap
0, // you
0, // command
@@ -882,7 +892,6 @@ DECLARE_ANIM_PARSER(moveto) {
// ctxt.a->_moveTo.z = atoi(_tokens[3]);
}
-
DECLARE_ANIM_PARSER(endanimation) {
debugC(7, kDebugParser, "ANIM_PARSER(endanimation) ");
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index 8fc916e490..d6df23d415 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -450,7 +450,7 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) {
Common::Point foot;
s._a->getFoot(foot);
- debugC(1, kDebugWalk, "buildPath: from (%i, %i) to (%i, %i)", foot.x, foot.y, x, y);
+ debugC(1, kDebugWalk, "buildPath: try to build path from (%i, %i) to (%i, %i)", foot.x, foot.y, x, y);
s._walkPath.clear();
// look for easy path first
@@ -465,13 +465,13 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) {
ZonePtr z0 = _vm->hitZone(kZonePath, x, y);
if (!z0) {
s._walkPath.push_back(dest);
- debugC(3, kDebugWalk, "buildPath: corner case 0");
+ debugC(3, kDebugWalk, "buildPath: corner case 0 (%i nodes)", s._walkPath.size());
return;
}
ZonePtr z1 = _vm->hitZone(kZonePath, foot.x, foot.y);
if (!z1 || z1 == z0) {
s._walkPath.push_back(dest);
- debugC(3, kDebugWalk, "buildPath: corner case 1");
+ debugC(3, kDebugWalk, "buildPath: corner case 1 (%i nodes)", s._walkPath.size());
return;
}
@@ -480,7 +480,7 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) {
if (z1->u._pathLists[id].empty()) {
s._walkPath.clear();
- debugC(3, kDebugWalk, "buildPath: no path");
+ debugC(3, kDebugWalk, "buildPath: no path found");
return;
}
@@ -490,7 +490,7 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) {
s._walkPath.push_front(*b);
}
s._walkPath.push_back(dest);
- debugC(3, kDebugWalk, "buildPath: complex path");
+ debugC(3, kDebugWalk, "buildPath: complex path (%i nodes)", s._walkPath.size());
}
@@ -541,8 +541,6 @@ void PathWalker_BR::walk() {
return;
}
- debugC(3, kDebugWalk, "PathWalker_BR::walk()");
-
doWalk(_character);
doWalk(_follower);
@@ -566,8 +564,6 @@ void PathWalker_BR::walk() {
}
_vm->_gfx->initiateScroll(dx, dy);
-
- debugC(3, kDebugWalk, "PathWalker_BR::walk() -> done");
}
void PathWalker_BR::checkTrap(const Common::Point &p) {
@@ -601,8 +597,6 @@ void PathWalker_BR::doWalk(State &s) {
return;
}
- debugC(3, kDebugWalk, "PathWalker_BR::doWalk(%s)", s._a->_name);
-
if (s._walkDelay > 0) {
s._walkDelay--;
if (s._walkDelay == 0 && s._a->_scriptName) {
@@ -619,10 +613,10 @@ void PathWalker_BR::doWalk(State &s) {
if (s._walkPath.empty()) {
finalizeWalk(s);
- debugC(3, kDebugWalk, "PathWalker_BR::doWalk, case 0");
+ debugC(3, kDebugWalk, "PathWalker_BR::doWalk, walk completed (no more nodes)");
return;
} else {
- debugC(3, kDebugWalk, "PathWalker_BR::doWalk, moving to next node");
+ debugC(3, kDebugWalk, "PathWalker_BR::doWalk, reached a walkpath node, %i left", s._walkPath.size());
}
}
@@ -632,6 +626,19 @@ void PathWalker_BR::doWalk(State &s) {
int xStep = (scale * 16) / 100 + 1;
int yStep = (scale * 10) / 100 + 1;
+
+ /* WORKAROUND: in the balloon scene, the position of the balloon (which is implemented as a
+ Character) is controlled by the user (for movement, via this walking code) and by the scripts
+ (to simulate the balloon floating in the air, in a neverending loop that alters the position
+ coordinates).
+ When the two step sizes are equal in magnitude and opposite in direction, then the walk code
+ enters an infinite loop without giving control back to the user (this happens quite frequently
+ when navigating the balloon near the borders of the screen, where the calculated step is
+ forcibly small because of clipping). Since the "floating" script (part1/scripts/mongolo.scr)
+ uses increments of 3 for both x and y, we tweak the calculated steps accordingly here. */
+ if (xStep == 3) xStep--;
+ if (yStep == 3) yStep--;
+
debugC(9, kDebugWalk, "calculated step: (%i, %i)", xStep, yStep);
s._fieldC = 0;
@@ -714,7 +721,7 @@ void PathWalker_BR::doWalk(State &s) {
Common::Point p2;
s._a->getFoot(p2);
checkTrap(p2);
- debugC(3, kDebugWalk, "PathWalker_BR::doWalk, case 1");
+ debugC(3, kDebugWalk, "PathWalker_BR::doWalk, stepped to (%i, %i)", p2.x, p2.y);
return;
}
diff --git a/engines/queen/music.cpp b/engines/queen/music.cpp
index b4b9210616..3d859c8335 100644
--- a/engines/queen/music.cpp
+++ b/engines/queen/music.cpp
@@ -34,6 +34,7 @@
#include "sound/midiparser.h"
+
namespace Queen {
extern MidiDriver *C_Player_CreateAdLibMidiDriver(Audio::Mixer *);
@@ -45,9 +46,9 @@ MidiMusic::MidiMusic(QueenEngine *vm)
_queuePos = _lastSong = _currentSong = 0;
queueClear();
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- _adlib = (midiDriver == MD_ADLIB);
- _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32);
+ _adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
+ _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
const char *musicDataFile;
if (vm->resource()->isDemo()) {
@@ -72,7 +73,7 @@ MidiMusic::MidiMusic(QueenEngine *vm)
// }
_driver = C_Player_CreateAdLibMidiDriver(vm->_mixer);
} else {
- _driver = MidiDriver::createMidi(midiDriver);
+ _driver = MidiDriver::createMidi(dev);
if (_nativeMT32) {
_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
}
diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp
index 10c3d56cb4..74bb52f574 100644
--- a/engines/queen/queen.cpp
+++ b/engines/queen/queen.cpp
@@ -264,9 +264,7 @@ void QueenEngine::writeOptionSettings() {
}
void QueenEngine::update(bool checkPlayerInput) {
- if (_debugger->isAttached()) {
- _debugger->onFrame();
- }
+ _debugger->onFrame();
_graphics->update(_logic->currentRoom());
_logic->update();
@@ -424,7 +422,7 @@ void QueenEngine::makeGameStateName(int slot, char *buf) const {
int QueenEngine::getGameStateSlot(const char *filename) const {
int i = -1;
const char *slot = strrchr(filename, '.');
- if (slot && slot[1] == 's') {
+ if (slot && (slot[1] == 's' || slot[1] == 'S')) {
i = atoi(slot + 2);
}
return i;
diff --git a/engines/queen/resource.cpp b/engines/queen/resource.cpp
index a43141ef56..1e2eff8458 100644
--- a/engines/queen/resource.cpp
+++ b/engines/queen/resource.cpp
@@ -96,18 +96,7 @@ ResourceEntry *Resource::resourceEntry(const char *filename) const {
entryName.toUppercase();
ResourceEntry *re = NULL;
-#ifndef PALMOS_MODE
re = (ResourceEntry *)bsearch(entryName.c_str(), _resourceTable, _resourceEntries, sizeof(ResourceEntry), compareResourceEntry);
-#else
- // PALMOS FIXME (?) : still doesn't work for me (????) use this instead
- uint32 cur = 0;
- do {
- if (!strcmp(entryName.c_str(), _resourceTable[cur].filename)) {
- re = &_resourceTable[cur];
- break;
- }
- } while (++cur < _resourceEntries);
-#endif
return re;
}
diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp
index c3f5fec83a..8bc8025032 100644
--- a/engines/saga/actor.cpp
+++ b/engines/saga/actor.cpp
@@ -1173,7 +1173,9 @@ void Actor::drawActors() {
return;
}
- if (_vm->_anim->hasCutaway()) {
+ // WORKAROUND
+ // Bug #2928923: 'ITE: Graphic Glitches during racoon death "Cut Scene"'
+ if (_vm->_anim->hasCutaway() || _vm->_scene->currentSceneNumber() == 287 || _vm->_scene->currentSceneNumber() == 286) {
drawSpeech();
return;
}
diff --git a/engines/saga/console.cpp b/engines/saga/console.cpp
index 2c201ac57d..228febfe9c 100644
--- a/engines/saga/console.cpp
+++ b/engines/saga/console.cpp
@@ -40,9 +40,6 @@ Console::Console(SagaEngine *vm) : GUI::Debugger() {
DCmd_Register("continue", WRAP_METHOD(Console, Cmd_Exit));
- // CVAR_Register_I(&_soundEnabled, "sound", NULL, CVAR_CFG, 0, 1);
- // CVAR_Register_I(&_musicEnabled, "music", NULL, CVAR_CFG, 0, 1);
-
// Actor commands
DCmd_Register("actor_walk_to", WRAP_METHOD(Console, cmdActorWalkTo));
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index 1c2c6bacff..7913291527 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -122,7 +122,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class SagaMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp
index d15f0b2af3..1f4091d07c 100644
--- a/engines/saga/events.cpp
+++ b/engines/saga/events.cpp
@@ -306,7 +306,6 @@ int Events::handleOneShot(Event *event) {
_vm->_sndRes->playVoice(event->param);
break;
case kMusicEvent:
- _vm->_music->stop();
if (event->op == kEventPlay)
_vm->_music->play(event->param, (MusicFlags)event->param2);
break;
diff --git a/engines/saga/font.h b/engines/saga/font.h
index f290384e87..d8b1da30b9 100644
--- a/engines/saga/font.h
+++ b/engines/saga/font.h
@@ -190,7 +190,7 @@ class Font {
}
}
bool valid(FontId fontId) {
- return ((fontId >= 0) && (fontId < _loadedFonts));
+ return (fontId < _loadedFonts);
}
int getByteLen(int numBits) const {
int byteLength = numBits / 8;
diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp
index c0d3cee465..c4b4688785 100644
--- a/engines/saga/interface.cpp
+++ b/engines/saga/interface.cpp
@@ -544,8 +544,10 @@ bool Interface::processAscii(Common::KeyState keystate) {
return true;
}
+#ifdef ENABLE_IHNM
if (_vm->_scene->isNonInteractiveIHNMDemoPart())
_vm->_scene->showIHNMDemoSpecialScreen();
+#endif
break;
case kPanelCutaway:
if (keystate.keycode == Common::KEYCODE_ESCAPE) {
@@ -555,8 +557,10 @@ bool Interface::processAscii(Common::KeyState keystate) {
return true;
}
+#ifdef ENABLE_INHM
if (_vm->_scene->isNonInteractiveIHNMDemoPart())
_vm->_scene->showIHNMDemoSpecialScreen();
+#endif
break;
case kPanelVideo:
if (keystate.keycode == Common::KEYCODE_ESCAPE) {
@@ -570,8 +574,10 @@ bool Interface::processAscii(Common::KeyState keystate) {
return true;
}
+#ifdef ENABLE_IHNM
if (_vm->_scene->isNonInteractiveIHNMDemoPart())
_vm->_scene->showIHNMDemoSpecialScreen();
+#endif
break;
case kPanelOption:
// TODO: check input dialog keys
@@ -1855,6 +1861,7 @@ void Interface::update(const Point& mousePoint, int updateFlag) {
if (updateFlag & UPDATE_MOUSECLICK) {
if (!_vm->isIHNMDemo()) {
_vm->_scene->clearPsychicProfile();
+ _vm->_script->wakeUpThreads(kWaitTypeDelay);
} else {
setMode(kPanelConverse);
_vm->_scene->_textList.clear();
@@ -1866,8 +1873,10 @@ void Interface::update(const Point& mousePoint, int updateFlag) {
break;
case kPanelNull:
+#ifdef ENABLE_IHNM
if (_vm->_scene->isNonInteractiveIHNMDemoPart() && (updateFlag & UPDATE_MOUSECLICK))
_vm->_scene->showIHNMDemoSpecialScreen();
+#endif
break;
}
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 75c5cdffd7..e4a16e27da 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -42,19 +42,25 @@ namespace Saga {
#define BUFFER_SIZE 4096
#define MUSIC_SUNSPOT 26
-MusicPlayer::MusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) {
+MusicDriver::MusicDriver() : _isGM(false) {
memset(_channel, 0, sizeof(_channel));
_masterVolume = 0;
+ _nativeMT32 = ConfMan.getBool("native_mt32");
+
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _driver = MidiDriver::createMidi(dev);
+ if (isMT32())
+ _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+
this->open();
}
-MusicPlayer::~MusicPlayer() {
- _driver->setTimerCallback(NULL, NULL);
- stopMusic();
+MusicDriver::~MusicDriver() {
this->close();
+ delete _driver;
}
-void MusicPlayer::setVolume(int volume) {
+void MusicDriver::setVolume(int volume) {
volume = CLIP(volume, 0, 255);
if (_masterVolume == volume)
@@ -71,32 +77,7 @@ void MusicPlayer::setVolume(int volume) {
}
}
-int MusicPlayer::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
-
- int ret = _driver->open();
- if (ret)
- return ret;
-
- _driver->setTimerCallback(this, &onTimer);
- return 0;
-}
-
-void MusicPlayer::close() {
- stopMusic();
- if (_driver)
- _driver->close();
- _driver = 0;
-}
-
-void MusicPlayer::send(uint32 b) {
- if (_passThrough) {
- _driver->send(b);
- return;
- }
-
+void MusicDriver::send(uint32 b) {
byte channel = (byte)(b & 0x0F);
if ((b & 0xFFF0) == 0x07B0) {
// Adjust volume changes by master volume
@@ -104,71 +85,88 @@ void MusicPlayer::send(uint32 b) {
_channelVolume[channel] = volume;
volume = volume * _masterVolume / 255;
b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ } else if ((b & 0xF0) == 0xC0 && !_isGM && !isMT32()) {
+ // Remap MT32 instruments to General Midi
b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
- }
- else if ((b & 0xFFF0) == 0x007BB0) {
- //Only respond to All Notes Off if this channel
- //has currently been allocated
- if (_channel[b & 0x0F])
+ } else if ((b & 0xFFF0) == 0x007BB0) {
+ // Only respond to All Notes Off if this channel
+ // has currently been allocated
+ if (!_channel[channel])
return;
}
if (!_channel[channel])
_channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
-
- if (_channel[channel])
+ else
_channel[channel]->send(b);
}
-void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
- // FIXME: The "elkfanfare" is played much too quickly. There are some
- // meta events that we don't handle. Perhaps there is a
- // connection...?
-
- switch (type) {
- case 0x2F: // End of Track
- if (_looping)
- _parser->jumpToTick(0);
- else
- stopMusic();
- break;
- default:
- //warning("Unhandled meta event: %02x", type);
- break;
- }
-}
-
-void MusicPlayer::onTimer(void *refCon) {
- MusicPlayer *music = (MusicPlayer *)refCon;
- Common::StackLock lock(music->_mutex);
-
- if (music->_isPlaying)
- music->_parser->onTimer();
-}
-
-void MusicPlayer::playMusic() {
- _isPlaying = true;
-}
+Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
+ _currentVolume = 0;
+ _driver = new MusicDriver();
-void MusicPlayer::stopMusic() {
- Common::StackLock lock(_mutex);
+ _digitalMusicContext = _vm->_resource->getContext(GAME_DIGITALMUSICFILE);
+ if (!_driver->isAdlib())
+ _musicContext = _vm->_resource->getContext(GAME_MUSICFILE_GM);
+ else
+ _musicContext = _vm->_resource->getContext(GAME_MUSICFILE_FM);
- _isPlaying = false;
- if (_parser) {
- _parser->unloadMusic();
- _parser = NULL;
+ if (!_musicContext) {
+ if (_vm->getGameId() == GID_ITE) {
+ _musicContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
+ } else {
+ // I've listened to music from both the FM and the GM
+ // file, and I've tentatively reached the conclusion
+ // that they are both General MIDI. My guess is that
+ // the FM file has been reorchestrated to sound better
+ // on AdLib and other FM synths.
+ //
+ // Sev says the AdLib music does not sound like in the
+ // original, but I still think assuming General MIDI is
+ // the right thing to do. Some music, like the End
+ // Title (song 0) sound absolutely atrocious when piped
+ // through our MT-32 to GM mapping.
+ //
+ // It is, however, quite possible that the original
+ // used a different GM to FM mapping. If the original
+ // sounded markedly better, perhaps we should add some
+ // way of replacing our stock mapping in adlib.cpp?
+ //
+ // For the composer's own recording of the End Title,
+ // see http://www.johnottman.com/
+
+ // Oddly enough, the intro music (song 1) is very
+ // different in the two files. I have no idea why.
+ // Note that the IHNM demo has only got one music file
+ // (music.rsc). It is assumed that it contains FM music
+ _musicContext = _vm->_resource->getContext(GAME_MUSICFILE_FM);
+ }
}
-}
-Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver) : _vm(vm), _mixer(mixer), _adlib(false) {
- _player = new MusicPlayer(driver);
- _currentVolume = 0;
-
- xmidiParser = MidiParser::createParser_XMIDI();
- smfParser = MidiParser::createParser_SMF();
+ // Check if the game is using XMIDI or SMF music
+ if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
+ // Just set an XMIDI parser for Mac IHNM for now
+ _parser = MidiParser::createParser_XMIDI();
+ } else {
+ byte *resourceData;
+ size_t resourceSize;
+ int resourceId = (_vm->getGameId() == GID_ITE ? 9 : 0);
+ _vm->_resource->loadResource(_musicContext, resourceId, resourceData, resourceSize);
+ if (!memcmp(resourceData, "FORM", 4)) {
+ _parser = MidiParser::createParser_XMIDI();
+ // ITE had MT32 mapped instruments
+ _driver->setGM(_vm->getGameId() != GID_ITE);
+ } else {
+ _parser = MidiParser::createParser_SMF();
+ // ITE with standalone MIDI files is General MIDI
+ _driver->setGM(_vm->getGameId() == GID_ITE);
+ }
+ free(resourceData);
+ }
- _digitalMusicContext = _vm->_resource->getContext(GAME_DIGITALMUSICFILE);
+ _parser->setMidiDriver(_driver);
+ _parser->setTimerRate(_driver->getBaseTempo());
+ _parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
_songTableLen = 0;
_songTable = 0;
@@ -180,11 +178,10 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver) : _vm(vm),
Music::~Music() {
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
_mixer->stopHandle(_musicHandle);
- delete _player;
- xmidiParser->setMidiDriver(NULL);
- smfParser->setMidiDriver(NULL);
- delete xmidiParser;
- delete smfParser;
+ _driver->setTimerCallback(NULL, NULL);
+ delete _driver;
+ _parser->setMidiDriver(NULL);
+ delete _parser;
free(_songTable);
free(_midiMusicData);
@@ -194,6 +191,12 @@ void Music::musicVolumeGaugeCallback(void *refCon) {
((Music *)refCon)->musicVolumeGauge();
}
+void Music::onTimer(void *refCon) {
+ Music *music = (Music *)refCon;
+ Common::StackLock lock(music->_driver->_mutex);
+ music->_parser->onTimer();
+}
+
void Music::musicVolumeGauge() {
int volume;
@@ -209,7 +212,7 @@ void Music::musicVolumeGauge() {
volume = 1;
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
- _player->setVolume(volume);
+ _driver->setVolume(volume);
if (_currentVolumePercent == 100) {
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
@@ -226,23 +229,21 @@ void Music::setVolume(int volume, int time) {
if (time == 1) {
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
- _player->setVolume(volume);
+ _driver->setVolume(volume);
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
_currentVolume = volume;
return;
}
- _vm->getTimerManager()->installTimerProc(&musicVolumeGaugeCallback, time * 100L, this);
+ _vm->getTimerManager()->installTimerProc(&musicVolumeGaugeCallback, time * 3000L, this);
}
bool Music::isPlaying() {
- return _mixer->isSoundHandleActive(_musicHandle) || _player->isPlaying();
+ return _mixer->isSoundHandleActive(_musicHandle) || _parser->isPlaying();
}
void Music::play(uint32 resourceId, MusicFlags flags) {
Audio::SeekableAudioStream *audioStream = NULL;
- MidiParser *parser;
- ResourceContext *context = NULL;
byte *resourceData;
size_t resourceSize;
uint32 loopStart;
@@ -254,8 +255,8 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
}
_trackNumber = resourceId;
- _player->stopMusic();
_mixer->stopHandle(_musicHandle);
+ _parser->unloadMusic();
int realTrackNumber;
@@ -356,55 +357,10 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
return;
}
- if (flags == MUSIC_DEFAULT) {
+ if (flags == MUSIC_DEFAULT)
flags = MUSIC_NORMAL;
- }
// Load MIDI/XMI resource data
-
- if (_vm->getGameId() == GID_ITE) {
- context = _vm->_resource->getContext(GAME_MUSICFILE_GM);
- if (context == NULL) {
- context = _vm->_resource->getContext(GAME_RESOURCEFILE);
- }
- } else if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
- // The music of the Mac version of IHNM is loaded from its
- // associated external file later on
- } else {
- // I've listened to music from both the FM and the GM
- // file, and I've tentatively reached the conclusion
- // that they are both General MIDI. My guess is that
- // the FM file has been reorchestrated to sound better
- // on AdLib and other FM synths.
- //
- // Sev says the AdLib music does not sound like in the
- // original, but I still think assuming General MIDI is
- // the right thing to do. Some music, like the End
- // Title (song 0) sound absolutely atrocious when piped
- // through our MT-32 to GM mapping.
- //
- // It is, however, quite possible that the original
- // used a different GM to FM mapping. If the original
- // sounded markedly better, perhaps we should add some
- // way of replacing our stock mapping in adlib.cpp?
- //
- // For the composer's own recording of the End Title,
- // see http://www.johnottman.com/
-
- // Oddly enough, the intro music (song 1) is very
- // different in the two files. I have no idea why.
- // Note that the IHNM demo has only got one music file
- // (music.rsc). It is assumed that it contains FM music
-
- if (hasAdLib() || _vm->isIHNMDemo()) {
- context = _vm->_resource->getContext(GAME_MUSICFILE_FM);
- } else {
- context = _vm->_resource->getContext(GAME_MUSICFILE_GM);
- }
- }
-
- _player->setGM(true);
-
if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
// Load the external music file for Mac IHNM
#if 0
@@ -422,56 +378,39 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
#endif
return;
} else {
- _vm->_resource->loadResource(context, resourceId, resourceData, resourceSize);
+ _vm->_resource->loadResource(_musicContext, resourceId, resourceData, resourceSize);
}
if (resourceSize < 4) {
error("Music::play() wrong music resource size");
}
- if (xmidiParser->loadMusic(resourceData, resourceSize)) {
- if (_vm->getGameId() == GID_ITE)
- _player->setGM(false);
+ if (!_parser->loadMusic(resourceData, resourceSize))
+ error("Music::play() wrong music resource");
- parser = xmidiParser;
- } else {
- if (smfParser->loadMusic(resourceData, resourceSize)) {
- parser = smfParser;
- } else {
- error("Music::play() wrong music resource");
- }
- }
-
- parser->setTrack(0);
- parser->setMidiDriver(_player);
- parser->setTimerRate(_player->getBaseTempo());
- parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+ _parser->setTrack(0);
+ _driver->setTimerCallback(this, &onTimer);
- _player->_parser = parser;
setVolume(_vm->_musicVolume);
- if (flags & MUSIC_LOOP)
- _player->setLoop(true);
- else
- _player->setLoop(false);
+ // Handle music looping
+ _parser->property(MidiParser::mpAutoLoop, (flags & MUSIC_LOOP) ? 1 : 0);
- _player->playMusic();
free(_midiMusicData);
_midiMusicData = resourceData;
}
void Music::pause() {
- _player->setVolume(-1);
- _player->setPlaying(false);
+ _driver->setTimerCallback(NULL, NULL);
}
void Music::resume() {
- _player->setVolume(_vm->_musicVolume);
- _player->setPlaying(true);
+ _driver->setTimerCallback(this, &onTimer);
}
void Music::stop() {
- _player->stopMusic();
+ _driver->setTimerCallback(NULL, NULL);
+ _parser->unloadMusic();
}
} // End of namespace Saga
diff --git a/engines/saga/music.h b/engines/saga/music.h
index 22711ba167..5cce3d4c04 100644
--- a/engines/saga/music.h
+++ b/engines/saga/music.h
@@ -44,41 +44,32 @@ enum MusicFlags {
MUSIC_DEFAULT = 0xffff
};
-class MusicPlayer : public MidiDriver {
+class MusicDriver : public MidiDriver {
public:
- MusicPlayer(MidiDriver *driver);
- ~MusicPlayer();
-
- bool isPlaying() { return _isPlaying; }
- void setPlaying(bool playing) { _isPlaying = playing; }
+ MusicDriver();
+ ~MusicDriver();
void setVolume(int volume);
int getVolume() { return _masterVolume; }
- void setNativeMT32(bool b) { _nativeMT32 = b; }
- bool hasNativeMT32() { return _nativeMT32; }
- void playMusic();
- void stopMusic();
- void setLoop(bool loop) { _looping = loop; }
- void setPassThrough(bool b) { _passThrough = b; }
-
+ bool isAdlib() { return _driverType == MT_ADLIB; }
+ bool isMT32() { return _driverType == MT_MT32 || _nativeMT32; }
void setGM(bool isGM) { _isGM = isGM; }
//MidiDriver interface implementation
- int open();
- void close();
+ int open() { return _driver->open(); }
+ void close() { _driver->close(); }
void send(uint32 b);
- void metaEvent(byte type, byte *data, uint16 length);
+ void metaEvent(byte type, byte *data, uint16 length) {}
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
+ void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { _driver->setTimerCallback(timerParam, timerProc); }
+ uint32 getBaseTempo() { return _driver->getBaseTempo(); }
//Channel allocation functions
MidiChannel *allocateChannel() { return 0; }
MidiChannel *getPercussionChannel() { return 0; }
- MidiParser *_parser;
Common::Mutex _mutex;
protected:
@@ -87,14 +78,11 @@ protected:
MidiChannel *_channel[16];
MidiDriver *_driver;
+ MusicType _driverType;
byte _channelVolume[16];
- bool _nativeMT32;
bool _isGM;
- bool _passThrough;
+ bool _nativeMT32;
- bool _isPlaying;
- bool _looping;
- bool _randomLoop;
byte _masterVolume;
byte *_musicData;
@@ -105,13 +93,8 @@ protected:
class Music {
public:
- Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver);
+ Music(SagaEngine *vm, Audio::Mixer *mixer);
~Music();
- void setNativeMT32(bool b) { _player->setNativeMT32(b); }
- bool hasNativeMT32() { return _player->hasNativeMT32(); }
- void setAdLib(bool b) { _adlib = b; }
- bool hasAdLib() { return _adlib; }
- void setPassThrough(bool b) { _player->setPassThrough(b); }
bool isPlaying();
bool hasDigitalMusic() { return _digitalMusic; }
@@ -130,24 +113,23 @@ private:
SagaEngine *_vm;
Audio::Mixer *_mixer;
- MusicPlayer *_player;
+ MusicDriver *_driver;
Audio::SoundHandle _musicHandle;
uint32 _trackNumber;
- bool _adlib;
-
int _targetVolume;
int _currentVolume;
int _currentVolumePercent;
bool _digitalMusic;
+ ResourceContext *_musicContext;
ResourceContext *_digitalMusicContext;
- MidiParser *xmidiParser;
- MidiParser *smfParser;
+ MidiParser *_parser;
byte *_midiMusicData;
static void musicVolumeGaugeCallback(void *refCon);
+ static void onTimer(void *refCon);
void musicVolumeGauge();
};
diff --git a/engines/saga/puzzle.cpp b/engines/saga/puzzle.cpp
index 957ab3c8b6..5b13473d77 100644
--- a/engines/saga/puzzle.cpp
+++ b/engines/saga/puzzle.cpp
@@ -411,12 +411,12 @@ void Puzzle::solicitHint() {
switch (_hintRqState) {
case kRQSpeaking:
if (_vm->_actor->isSpeaking()) {
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50000, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50 * 1000000, this);
break;
}
_hintRqState = _hintNextRqState;
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 333333, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 100*1000000/3, this);
break;
case kRQNoHint:
@@ -439,11 +439,11 @@ void Puzzle::solicitHint() {
// Roll to see if Sakka scolds
if (_vm->_rnd.getRandomNumber(1)) {
_hintRqState = kRQSakkaDenies;
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 200000, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 200*1000000, this);
} else {
_hintRqState = kRQSpeaking;
_hintNextRqState = kRQHintRequested;
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50000, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50*1000000, this);
}
break;
@@ -456,7 +456,7 @@ void Puzzle::solicitHint() {
_hintRqState = kRQSpeaking;
_hintNextRqState = kRQHintRequestedStage2;
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50000, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50*1000000, this);
_vm->_interface->converseClear();
_vm->_interface->converseAddText(optionsStr[_lang][kROAccept], 0, 1, 0, 0 );
diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp
index ec168d296e..dc9334b037 100644
--- a/engines/saga/render.cpp
+++ b/engines/saga/render.cpp
@@ -110,6 +110,12 @@ void Render::drawScene() {
_vm->_actor->drawActors();
}
+ // WORKAROUND
+ // Bug #2886130: "ITE: Graphic Glitches during Cat Tribe Celebration"
+ if (_vm->_scene->currentSceneNumber() == 274) {
+ _vm->_interface->drawStatusBar();
+ }
+
#ifdef SAGA_DEBUG
if (getFlags() & RF_OBJECTMAP_TEST) {
if (_vm->_scene->_objectMap)
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index 2911d9c451..025462c558 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -83,7 +83,6 @@ SagaEngine::SagaEngine(OSystem *syst, const SAGAGameDescription *gameDesc)
_sndRes = NULL;
_sound = NULL;
_music = NULL;
- _driver = NULL;
_anim = NULL;
_render = NULL;
_isoMap = NULL;
@@ -198,9 +197,6 @@ SagaEngine::~SagaEngine() {
delete _sound;
_sound = NULL;
- delete _driver;
- _driver = NULL;
-
delete _gfx;
_gfx = NULL;
@@ -285,17 +281,7 @@ Common::Error SagaEngine::run() {
_console = new Console(this);
// Graphics should be initialized before music
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
- bool adlib = (midiDriver == MD_ADLIB);
-
- _driver = MidiDriver::createMidi(midiDriver);
- if (native_mt32)
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
- _music = new Music(this, _mixer, _driver);
- _music->setNativeMT32(native_mt32);
- _music->setAdLib(adlib);
+ _music = new Music(this, _mixer);
_render = new Render(this, _system);
if (!_render->initialized()) {
return Common::kUnknownError;
@@ -380,8 +366,7 @@ Common::Error SagaEngine::run() {
uint32 currentTicks;
while (!shouldQuit()) {
- if (_console->isAttached())
- _console->onFrame();
+ _console->onFrame();
if (_render->getFlags() & RF_RENDERPAUSE) {
// Freeze time while paused
@@ -447,7 +432,7 @@ void SagaEngine::loadStrings(StringsTable &stringsTable, const byte *stringsPoin
offset = scriptS.readUint16();
// In some rooms in IHNM, string offsets can be greater than the maximum value than a 16-bit integer can hold
// We detect this by checking the previous offset, and if it was bigger than the current one, an overflow
- // occured (since the string offsets are sequential), so we're adding the missing part of the number
+ // occurred (since the string offsets are sequential), so we're adding the missing part of the number
// Fixes bug #1895205 - "IHNM: end game text/caption error"
if (prevOffset > offset)
offset += 65536;
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 2bef489e05..102d1e5c82 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -525,7 +525,6 @@ public:
SndRes *_sndRes;
Sound *_sound;
Music *_music;
- MidiDriver *_driver;
Anim *_anim;
Render *_render;
IsoMap *_isoMap;
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index 40ee1fb720..d7ee037c50 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -1201,6 +1201,12 @@ void Scene::endScene() {
_vm->_script->abortAllThreads();
_vm->_script->_skipSpeeches = false;
+ // WORKAROUND: Bug #2886151: "ITE: Mouse stops responding at Boar Castle"
+ // This is bug in original engine
+ if (_sceneNumber == 50) {
+ _vm->_interface->activate();
+ }
+
// Copy current screen to render buffer so inset rooms will get proper background
if (!(_sceneDescription.flags & kSceneFlagISO) && !_vm->_scene->isInIntro()) {
BGInfo bgInfo;
@@ -1425,6 +1431,8 @@ void Scene::clearPlacard() {
q_event = _vm->_events->chain(q_event, &event);
}
+#ifdef ENABLE_IHNM
+
void Scene::showPsychicProfile(const char *text) {
int textHeight;
static PalEntry cur_pal[PAL_ENTRIES];
@@ -1440,6 +1448,8 @@ void Scene::showPsychicProfile(const char *text) {
_vm->_interface->setMode(kPanelPlacard);
_vm->_gfx->savePalette();
+ _vm->_events->clearList();
+
event.type = kEvTOneshot;
event.code = kCursorEvent;
event.op = kEventHide;
@@ -1531,4 +1541,6 @@ void Scene::showIHNMDemoSpecialScreen() {
_vm->_scene->changeScene(150, 0, kTransitionFade);
}
+#endif // IHNM
+
} // End of namespace Saga
diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp
index 18bbca2425..5fd120ac33 100644
--- a/engines/saga/script.cpp
+++ b/engines/saga/script.cpp
@@ -571,9 +571,7 @@ void Script::opCall(SCRIPTOP_PARAMS) {
if (iparam1 != kAddressModule) {
error("Script::runThread iparam1 != kAddressModule");
}
- byte *addr = thread->baseAddress(iparam1);
iparam1 = scriptS->readSint16LE();
- addr += iparam1;
thread->push(argumentsCount);
// NOTE: The original pushes the program
diff --git a/engines/saga/script.h b/engines/saga/script.h
index f31af7b2ea..21afeb5c44 100644
--- a/engines/saga/script.h
+++ b/engines/saga/script.h
@@ -246,16 +246,19 @@ public:
}
void waitWalk(void *threadObj) {
+ debug(3, "waitWalk()");
wait(kWaitTypeWalk);
_threadObj = threadObj;
}
void waitDelay(int sleepTime) {
+ debug(3, "waitDelay(%d)", sleepTime);
wait(kWaitTypeDelay);
_sleepTime = sleepTime;
}
void waitFrames(int frames) {
+ debug(3, "waitFrames(%d)", frames);
wait(kWaitTypeWaitFrames);
_frameWait = frames;
}
diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp
index f98a80acd8..328d4040af 100644
--- a/engines/saga/sfuncs.cpp
+++ b/engines/saga/sfuncs.cpp
@@ -370,12 +370,15 @@ void Script::sfStopBgdAnim(SCRIPTFUNC_PARAMS) {
// reenabled.
// Param1: boolean
void Script::sfLockUser(SCRIPTFUNC_PARAMS) {
- if (thread->pop()) {
+ int16 param = thread->pop();
+
+ if (param != 0) {
_vm->_interface->deactivate();
} else {
_vm->_interface->activate();
}
+ debug(1, "sfLockUser(%d)", param);
}
// Script function #12 (0x0C)
@@ -1153,18 +1156,6 @@ void Script::sfPlacardOff(SCRIPTFUNC_PARAMS) {
_vm->_scene->clearPlacard();
}
-void Script::sfPsychicProfile(SCRIPTFUNC_PARAMS) {
- thread->wait(kWaitTypePlacard);
-
- _vm->_scene->showPsychicProfile(thread->_strings->getString(thread->pop()));
-}
-
-void Script::sfPsychicProfileOff(SCRIPTFUNC_PARAMS) {
- // This is called a while after the psychic profile is
- // opened, to close it automatically
- _vm->_scene->clearPsychicProfile();
-}
-
// Script function #50 (0x32)
void Script::sfSetProtagState(SCRIPTFUNC_PARAMS) {
_vm->_actor->setProtagState(thread->pop());
@@ -1473,6 +1464,8 @@ void Script::sfPlayLoopedSound(SCRIPTFUNC_PARAMS) {
} else {
_vm->_sound->stopSound();
}
+
+ debug(1, "sfPlayLoopedSound(%d)", param);
}
// Script function #72 (0x48)
diff --git a/engines/saga/sfuncs_ihnm.cpp b/engines/saga/sfuncs_ihnm.cpp
index fe586b54ae..b98c1cb852 100644
--- a/engines/saga/sfuncs_ihnm.cpp
+++ b/engines/saga/sfuncs_ihnm.cpp
@@ -440,6 +440,18 @@ void Script::sfDisableAbortSpeeches(SCRIPTFUNC_PARAMS) {
_vm->_interface->disableAbortSpeeches(thread->pop() != 0);
}
+void Script::sfPsychicProfile(SCRIPTFUNC_PARAMS) {
+ thread->wait(kWaitTypePlacard);
+
+ _vm->_scene->showPsychicProfile(thread->_strings->getString(thread->pop()));
+}
+
+void Script::sfPsychicProfileOff(SCRIPTFUNC_PARAMS) {
+ // This is called a while after the psychic profile is
+ // opened, to close it automatically
+ _vm->_scene->clearPsychicProfile();
+}
+
} // End of namespace Saga
#endif
diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp
index 8ea3fc4003..a27608dcf5 100644
--- a/engines/saga/sndres.cpp
+++ b/engines/saga/sndres.cpp
@@ -159,7 +159,7 @@ void SndRes::playSound(uint32 resourceId, int volume, bool loop) {
return;
}
- _vm->_sound->playSound(buffer, volume, loop);
+ _vm->_sound->playSound(buffer, volume, loop, resourceId);
}
void SndRes::playVoice(uint32 resourceId) {
diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp
index 811ee709f7..db979e8104 100644
--- a/engines/saga/sound.cpp
+++ b/engines/saga/sound.cpp
@@ -105,10 +105,20 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundBuffer &buffe
_mixer->playStream(soundType, handle, Audio::makeLoopingAudioStream(stream, loop ? 0 : 1), -1, volume);
}
-void Sound::playSound(SoundBuffer &buffer, int volume, bool loop) {
+void Sound::playSound(SoundBuffer &buffer, int volume, bool loop, int resId) {
+ // WORKAROUND
+ // Prevent playing same looped sound for several times
+ // Fixes bug #2886141: "ITE: Cumulative Snoring sounds in Prince's Bedroom"
+ for (int i = 0; i < SOUND_HANDLES; i++)
+ if (_handles[i].type == kEffectHandle && _handles[i].resId == resId) {
+ debug(1, "Skipped playing SFX #%d", resId);
+ return;
+ }
+
SndHandle *handle = getHandle();
handle->type = kEffectHandle;
+ handle->resId = resId;
playSoundBuffer(&handle->handle, buffer, 2 * volume, handle->type, loop);
}
@@ -129,6 +139,7 @@ void Sound::stopSound() {
if (_handles[i].type == kEffectHandle) {
_mixer->stopHandle(_handles[i].handle);
_handles[i].type = kFreeHandle;
+ _handles[i].resId = -1;
}
}
diff --git a/engines/saga/sound.h b/engines/saga/sound.h
index 9cf8f29767..7ee2765a0f 100644
--- a/engines/saga/sound.h
+++ b/engines/saga/sound.h
@@ -63,6 +63,7 @@ enum sndHandleType {
struct SndHandle {
Audio::SoundHandle handle;
sndHandleType type;
+ int resId;
};
class Sound {
@@ -71,7 +72,7 @@ public:
Sound(SagaEngine *vm, Audio::Mixer *mixer);
~Sound();
- void playSound(SoundBuffer &buffer, int volume, bool loop);
+ void playSound(SoundBuffer &buffer, int volume, bool loop, int resId);
void pauseSound();
void resumeSound();
void stopSound();
diff --git a/engines/saga/sthread.cpp b/engines/saga/sthread.cpp
index c133f8de88..be674e5acd 100644
--- a/engines/saga/sthread.cpp
+++ b/engines/saga/sthread.cpp
@@ -58,6 +58,8 @@ ScriptThread &Script::createThread(uint16 scriptModuleNumber, uint16 scriptEntry
_threadList.push_front(newThread);
+ debug(3, "createThread(). Total threads: %d", _threadList.size());
+
ScriptThread &tmp = *_threadList.begin();
tmp._stackBuf = (int16 *)malloc(ScriptThread::THREAD_STACK_SIZE * sizeof(int16));
tmp._stackTopIndex = ScriptThread::THREAD_STACK_SIZE - 2;
@@ -78,6 +80,8 @@ void Script::wakeUpActorThread(int waitType, void *threadObj) {
void Script::wakeUpThreads(int waitType) {
ScriptThreadList::iterator threadIterator;
+ debug(3, "wakeUpThreads(%d)", waitType);
+
for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
ScriptThread &thread = *threadIterator;
if ((thread._flags & kTFlagWaiting) && (thread._waitType == waitType)) {
@@ -89,6 +93,8 @@ void Script::wakeUpThreads(int waitType) {
void Script::wakeUpThreadsDelayed(int waitType, int sleepTime) {
ScriptThreadList::iterator threadIterator;
+ debug(3, "wakeUpThreads(%d, %d)", waitType, sleepTime);
+
for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
ScriptThread &thread = *threadIterator;
if ((thread._flags & kTFlagWaiting) && (thread._waitType == waitType)) {
@@ -169,6 +175,8 @@ void Script::executeThreads(uint msec) {
void Script::abortAllThreads() {
ScriptThreadList::iterator threadIterator;
+ debug(3, "abortAllThreads()");
+
threadIterator = _threadList.begin();
while (threadIterator != _threadList.end()) {
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 16bc69115f..fac819167b 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -31,22 +31,19 @@
#include "sci/event.h"
#include "sci/resource.h"
#include "sci/engine/state.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/selector.h"
#include "sci/engine/savegame.h"
#include "sci/engine/gc.h"
#include "sci/engine/features.h"
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-#include "sci/sound/iterator/songlib.h" // for SongLibrary
-#include "sci/sound/iterator/iterator.h" // for SCI_SONG_ITERATOR_TYPE_SCI0
-#else
+#include "sci/sound/midiparser_sci.h"
#include "sci/sound/music.h"
-#endif
#include "sci/sound/drivers/mididriver.h"
-#include "sci/graphics/gui.h"
-#include "sci/graphics/gui32.h"
#include "sci/graphics/cursor.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/paint.h"
+#include "sci/graphics/paint16.h"
+#include "sci/graphics/paint32.h"
#include "sci/graphics/palette.h"
#include "sci/parser/vocabulary.h"
@@ -54,7 +51,7 @@
#include "graphics/video/avi_decoder.h"
#include "sci/video/seq_decoder.h"
#ifdef ENABLE_SCI32
-#include "sci/video/vmd_decoder.h"
+#include "graphics/video/coktel_decoder.h"
#endif
#include "common/file.h"
@@ -69,15 +66,15 @@ bool g_debug_track_mouse_clicks = false;
// Refer to the "addresses" command on how to pass address parameters
static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeValue);
-Console::Console(SciEngine *engine) : GUI::Debugger() {
- _engine = engine;
+Console::Console(SciEngine *engine) : GUI::Debugger(),
+ _engine(engine), _debugState(engine->_debugState), _enterTime(0) {
// Variables
DVar_Register("sleeptime_factor", &g_debug_sleeptime_factor, DVAR_INT, 0);
- DVar_Register("gc_interval", &script_gc_interval, DVAR_INT, 0);
+ DVar_Register("gc_interval", &engine->_gamestate->scriptGCInterval, DVAR_INT, 0);
DVar_Register("simulated_key", &g_debug_simulated_key, DVAR_INT, 0);
DVar_Register("track_mouse_clicks", &g_debug_track_mouse_clicks, DVAR_BOOL, 0);
- DVar_Register("script_abort_flag", &script_abort_flag, DVAR_INT, 0);
+ DVar_Register("script_abort_flag", &_engine->_gamestate->abortScriptProcessing, DVAR_INT, 0);
// General
DCmd_Register("help", WRAP_METHOD(Console, cmdHelp));
@@ -96,6 +93,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger() {
DCmd_Register("sentence_fragments", WRAP_METHOD(Console, cmdSentenceFragments));
DCmd_Register("parse", WRAP_METHOD(Console, cmdParse));
DCmd_Register("set_parse_nodes", WRAP_METHOD(Console, cmdSetParseNodes));
+ DCmd_Register("said", WRAP_METHOD(Console, cmdSaid));
// Resources
DCmd_Register("diskdump", WRAP_METHOD(Console, cmdDiskDump));
DCmd_Register("hexdump", WRAP_METHOD(Console, cmdHexDump));
@@ -104,6 +102,8 @@ Console::Console(SciEngine *engine) : GUI::Debugger() {
DCmd_Register("resource_types", WRAP_METHOD(Console, cmdResourceTypes));
DCmd_Register("list", WRAP_METHOD(Console, cmdList));
DCmd_Register("hexgrep", WRAP_METHOD(Console, cmdHexgrep));
+ DCmd_Register("verify_scripts", WRAP_METHOD(Console, cmdVerifyScripts));
+ DCmd_Register("show_instruments", WRAP_METHOD(Console, cmdShowInstruments));
// Game
DCmd_Register("save_game", WRAP_METHOD(Console, cmdSaveGame));
DCmd_Register("restore_game", WRAP_METHOD(Console, cmdRestoreGame));
@@ -149,15 +149,17 @@ Console::Console(SciEngine *engine) : GUI::Debugger() {
DCmd_Register("addresses", WRAP_METHOD(Console, cmdAddresses));
DCmd_Register("registers", WRAP_METHOD(Console, cmdRegisters));
DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript));
- DCmd_Register("set_acc", WRAP_METHOD(Console, cmdSetAccumulator));
DCmd_Register("backtrace", WRAP_METHOD(Console, cmdBacktrace));
DCmd_Register("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias
- DCmd_Register("step", WRAP_METHOD(Console, cmdStep));
- DCmd_Register("s", WRAP_METHOD(Console, cmdStep)); // alias
+ DCmd_Register("trace", WRAP_METHOD(Console, cmdTrace));
+ DCmd_Register("t", WRAP_METHOD(Console, cmdTrace)); // alias
+ DCmd_Register("s", WRAP_METHOD(Console, cmdTrace)); // alias
+ DCmd_Register("stepover", WRAP_METHOD(Console, cmdStepOver));
+ DCmd_Register("p", WRAP_METHOD(Console, cmdStepOver)); // alias
+ DCmd_Register("step_ret", WRAP_METHOD(Console, cmdStepRet));
+ DCmd_Register("pret", WRAP_METHOD(Console, cmdStepRet)); // alias
DCmd_Register("step_event", WRAP_METHOD(Console, cmdStepEvent));
DCmd_Register("se", WRAP_METHOD(Console, cmdStepEvent)); // alias
- DCmd_Register("step_ret", WRAP_METHOD(Console, cmdStepRet));
- DCmd_Register("sret", WRAP_METHOD(Console, cmdStepRet)); // alias
DCmd_Register("step_global", WRAP_METHOD(Console, cmdStepGlobal));
DCmd_Register("sg", WRAP_METHOD(Console, cmdStepGlobal)); // alias
DCmd_Register("step_callk", WRAP_METHOD(Console, cmdStepCallk));
@@ -166,60 +168,60 @@ Console::Console(SciEngine *engine) : GUI::Debugger() {
DCmd_Register("disasm_addr", WRAP_METHOD(Console, cmdDisassembleAddress));
DCmd_Register("send", WRAP_METHOD(Console, cmdSend));
DCmd_Register("go", WRAP_METHOD(Console, cmdGo));
+ DCmd_Register("logkernel", WRAP_METHOD(Console, cmdLogKernel));
// Breakpoints
DCmd_Register("bp_list", WRAP_METHOD(Console, cmdBreakpointList));
DCmd_Register("bplist", WRAP_METHOD(Console, cmdBreakpointList)); // alias
+ DCmd_Register("bl", WRAP_METHOD(Console, cmdBreakpointList)); // alias
DCmd_Register("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete));
DCmd_Register("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias
- DCmd_Register("bp_exec_method", WRAP_METHOD(Console, cmdBreakpointExecMethod));
- DCmd_Register("bpx", WRAP_METHOD(Console, cmdBreakpointExecMethod)); // alias
- DCmd_Register("bp_exec_function", WRAP_METHOD(Console, cmdBreakpointExecFunction));
- DCmd_Register("bpe", WRAP_METHOD(Console, cmdBreakpointExecFunction)); // alias
+ DCmd_Register("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias
+ DCmd_Register("bp_method", WRAP_METHOD(Console, cmdBreakpointMethod));
+ DCmd_Register("bpx", WRAP_METHOD(Console, cmdBreakpointMethod)); // alias
+ DCmd_Register("bp_kernel", WRAP_METHOD(Console, cmdBreakpointKernel));
+ DCmd_Register("bpk", WRAP_METHOD(Console, cmdBreakpointKernel)); // alias
+ DCmd_Register("bp_function", WRAP_METHOD(Console, cmdBreakpointFunction));
+ DCmd_Register("bpe", WRAP_METHOD(Console, cmdBreakpointFunction)); // alias
// VM
DCmd_Register("script_steps", WRAP_METHOD(Console, cmdScriptSteps));
DCmd_Register("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist));
- DCmd_Register("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias
+ DCmd_Register("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias
+ DCmd_Register("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias
DCmd_Register("vm_vars", WRAP_METHOD(Console, cmdVMVars));
- DCmd_Register("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias
+ DCmd_Register("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias
+ DCmd_Register("vv", WRAP_METHOD(Console, cmdVMVars)); // alias
DCmd_Register("stack", WRAP_METHOD(Console, cmdStack));
DCmd_Register("value_type", WRAP_METHOD(Console, cmdValueType));
DCmd_Register("view_listnode", WRAP_METHOD(Console, cmdViewListNode));
DCmd_Register("view_reference", WRAP_METHOD(Console, cmdViewReference));
- DCmd_Register("vr", WRAP_METHOD(Console, cmdViewReference)); // alias
+ DCmd_Register("vr", WRAP_METHOD(Console, cmdViewReference)); // alias
DCmd_Register("view_object", WRAP_METHOD(Console, cmdViewObject));
- DCmd_Register("vo", WRAP_METHOD(Console, cmdViewObject)); // alias
+ DCmd_Register("vo", WRAP_METHOD(Console, cmdViewObject)); // alias
DCmd_Register("active_object", WRAP_METHOD(Console, cmdViewActiveObject));
DCmd_Register("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject));
- g_debugState.seeking = kDebugSeekNothing;
- g_debugState.seekLevel = 0;
- g_debugState.runningStep = 0;
- g_debugState.stopOnEvent = false;
- g_debugState.debugging = false;
- g_debugState.breakpointWasHit = false;
- g_debugState._breakpoints.clear(); // No breakpoints defined
- g_debugState._activeBreakpointTypes = 0;
+ _debugState.seeking = kDebugSeekNothing;
+ _debugState.seekLevel = 0;
+ _debugState.runningStep = 0;
+ _debugState.stopOnEvent = false;
+ _debugState.debugging = false;
+ _debugState.breakpointWasHit = false;
+ _debugState._breakpoints.clear(); // No breakpoints defined
+ _debugState._activeBreakpointTypes = 0;
}
Console::~Console() {
}
void Console::preEnter() {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- if (_engine->_gamestate)
- _engine->_gamestate->_sound.sfx_suspend(true);
-#endif
- if (_engine->_gamestate && _engine->_gamestate->_soundCmd)
- _engine->_gamestate->_soundCmd->pauseAll(true);
+ if (g_sci && g_sci->_soundCmd)
+ g_sci->_soundCmd->pauseAll(true);
+ _enterTime = g_system->getMillis();
}
void Console::postEnter() {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- if (_engine->_gamestate)
- _engine->_gamestate->_sound.sfx_suspend(false);
-#endif
- if (_engine->_gamestate && _engine->_gamestate->_soundCmd)
- _engine->_gamestate->_soundCmd->pauseAll(false);
+ if (g_sci && g_sci->_soundCmd)
+ g_sci->_soundCmd->pauseAll(false);
if (!_videoFile.empty()) {
_engine->_gfxCursor->kernelHide();
@@ -232,7 +234,7 @@ void Console::postEnter() {
videoDecoder = seqDecoder;
#ifdef ENABLE_SCI32
} else if (_videoFile.hasSuffix(".vmd")) {
- videoDecoder = new VMDDecoder(g_system->getMixer());
+ videoDecoder = new Graphics::VMDDecoder(g_system->getMixer());
#endif
} else if (_videoFile.hasSuffix(".avi")) {
videoDecoder = new Graphics::AviDecoder(g_system->getMixer());
@@ -241,8 +243,12 @@ void Console::postEnter() {
if (videoDecoder && videoDecoder->loadFile(_videoFile)) {
uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2;
uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2;
+ bool skipVideo = false;
+
+ if (videoDecoder->hasDirtyPalette())
+ videoDecoder->setSystemPalette();
- while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo()) {
+ while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) {
if (videoDecoder->needsUpdate()) {
Graphics::Surface *frame = videoDecoder->decodeNextFrame();
if (frame) {
@@ -256,8 +262,10 @@ void Console::postEnter() {
}
Common::Event event;
- while (g_system->getEventManager()->pollEvent(event))
- ;
+ while (g_system->getEventManager()->pollEvent(event)) {
+ if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
+ skipVideo = true;
+ }
g_system->delayMillis(10);
}
@@ -270,15 +278,10 @@ void Console::postEnter() {
_videoFile.clear();
_videoFrameDelay = 0;
}
-}
-
-#if 0
-// Unused
-#define LOOKUP_SPECIES(species) (\
- (species >= 1000) ? species : *(s->_classtable[species].scriptposp) \
- + s->_classtable[species].class_offset)
-#endif
+ // Subtract the time we were running the debugger from the game running time
+ _engine->_gamestate->gameStartTime += g_system->getMillis() - _enterTime;
+}
bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf("\n");
@@ -314,6 +317,7 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf(" sentence_fragments - Shows the sentence fragments (used to build Parse trees)\n");
DebugPrintf(" parse - Parses a sequence of words and prints the resulting parse tree\n");
DebugPrintf(" set_parse_nodes - Sets the contents of all parse nodes\n");
+ DebugPrintf(" said - Match a string against a said spec\n");
DebugPrintf("\n");
DebugPrintf("Resources:\n");
DebugPrintf(" diskdump - Dumps the specified resource to disk as a patch file\n");
@@ -323,6 +327,8 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf(" resource_types - Shows the valid resource types\n");
DebugPrintf(" list - Lists all the resources of a given type\n");
DebugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n");
+ DebugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n");
+ DebugPrintf(" show_instruments - Shows the instruments of a specific song, or all songs\n");
DebugPrintf("\n");
DebugPrintf("Game:\n");
DebugPrintf(" save_game - Saves the current game state to the hard disk\n");
@@ -367,28 +373,30 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf(" addresses - Provides information on how to pass addresses\n");
DebugPrintf(" registers - Shows the current register values\n");
DebugPrintf(" dissect_script - Examines a script\n");
- DebugPrintf(" set_acc - Sets the accumulator\n");
DebugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n");
- DebugPrintf(" step / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n");
+ DebugPrintf(" trace / t / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n");
+ DebugPrintf(" stepover / p - Executes one operation, skips over call/send\n");
+ DebugPrintf(" step_ret / pret - Steps forward until ret is called on the current execution stack level.\n");
DebugPrintf(" step_event / se - Steps forward until a SCI event is received.\n");
- DebugPrintf(" step_ret / sret - Steps forward until ret is called on the current execution stack level.\n");
DebugPrintf(" step_global / sg - Steps until the global variable with the specified index is modified.\n");
DebugPrintf(" step_callk / snk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n");
DebugPrintf(" disasm - Disassembles a method by name\n");
DebugPrintf(" disasm_addr - Disassembles one or more commands\n");
DebugPrintf(" send - Sends a message to an object\n");
DebugPrintf(" go - Executes the script\n");
+ DebugPrintf(" logkernel - Logs kernel calls\n");
DebugPrintf("\n");
DebugPrintf("Breakpoints:\n");
- DebugPrintf(" bp_list / bplist - Lists the current breakpoints\n");
- DebugPrintf(" bp_del / bpdel - Deletes a breakpoint with the specified index\n");
- DebugPrintf(" bp_exec_method / bpx - Sets a breakpoint on the execution of the specified method\n");
- DebugPrintf(" bp_exec_function / bpe - Sets a breakpoint on the execution of the specified exported function\n");
+ DebugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n");
+ DebugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n");
+ DebugPrintf(" bp_method / bpx - Sets a breakpoint on the execution or access of a specified method/selector\n");
+ DebugPrintf(" bp_kernel / bpk - Sets a breakpoint on execution of a kernel function\n");
+ DebugPrintf(" bp_function / bpe - Sets a breakpoint on the execution of the specified exported function\n");
DebugPrintf("\n");
DebugPrintf("VM:\n");
DebugPrintf(" script_steps - Shows the number of executed SCI operations\n");
- DebugPrintf(" vm_varlist / vmvarlist - Shows the addresses of variables in the VM\n");
- DebugPrintf(" vm_vars / vmvars - Displays or changes variables in the VM\n");
+ DebugPrintf(" vm_varlist / vmvarlist / vl - Shows the addresses of variables in the VM\n");
+ DebugPrintf(" vm_vars / vmvars / vv - Displays or changes variables in the VM\n");
DebugPrintf(" stack - Lists the specified number of stack elements\n");
DebugPrintf(" value_type - Determines the type of a value\n");
DebugPrintf(" view_listnode - Examines the list node at the given address\n");
@@ -411,20 +419,19 @@ ResourceType parseResourceType(const char *resid) {
return res;
}
-const char *selector_name(EngineState *s, int selector) {
- if (selector >= 0 && selector < (int)g_sci->getKernel()->getSelectorNamesSize())
- return g_sci->getKernel()->getSelectorName(selector).c_str();
- else
- return "--INVALID--";
-}
-
bool Console::cmdGetVersion(int argc, const char **argv) {
const char *viewTypeDesc[] = { "Unknown", "EGA", "VGA", "VGA SCI1.1", "Amiga" };
- EngineState *s = _engine->_gamestate;
bool hasVocab997 = g_sci->getResMan()->testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS)) ? true : false;
+ Common::String gameVersion = "N/A";
- DebugPrintf("Game ID: %s\n", s->_gameId.c_str());
+ Common::File versionFile;
+ if (versionFile.open("VERSION")) {
+ gameVersion = versionFile.readLine();
+ versionFile.close();
+ }
+
+ DebugPrintf("Game ID: %s\n", _engine->getGameIdStr());
DebugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion()));
DebugPrintf("\n");
DebugPrintf("Detected features:\n");
@@ -432,12 +439,14 @@ bool Console::cmdGetVersion(int argc, const char **argv) {
DebugPrintf("Sound type: %s\n", getSciVersionDesc(_engine->_features->detectDoSoundType()));
DebugPrintf("Graphics functions type: %s\n", getSciVersionDesc(_engine->_features->detectGfxFunctionsType()));
DebugPrintf("Lofs type: %s\n", getSciVersionDesc(_engine->_features->detectLofsType()));
- DebugPrintf("Move count type: %s\n", (_engine->_features->detectMoveCountType() == kIncrementMoveCount) ? "increment" : "ignore");
+ DebugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore");
DebugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType()));
DebugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]);
+ DebugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no");
DebugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc());
DebugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc());
DebugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no");
+ DebugPrintf("Game version (VERSION file): %s\n", gameVersion.c_str());
DebugPrintf("\n");
return true;
@@ -480,14 +489,14 @@ bool Console::cmdSelector(int argc, const char **argv) {
return true;
}
- for (uint seeker = 0; seeker < _engine->getKernel()->getSelectorNamesSize(); seeker++) {
- if (!scumm_stricmp(_engine->getKernel()->getSelectorName(seeker).c_str(), argv[1])) {
- DebugPrintf("Selector %s found at %03x (%d)\n", _engine->getKernel()->getSelectorName(seeker).c_str(), seeker, seeker);
- return true;
- }
+ Common::String name = argv[1];
+ int seeker = _engine->getKernel()->findSelector(name.c_str());
+ if (seeker >= 0) {
+ DebugPrintf("Selector %s found at %03x (%d)\n", name.c_str(), seeker, seeker);
+ return true;
}
- DebugPrintf("Selector %s wasn't found\n", argv[1]);
+ DebugPrintf("Selector %s wasn't found\n", name.c_str());
return true;
}
@@ -593,14 +602,14 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) {
}
bool Console::cmdRegisters(int argc, const char **argv) {
+ EngineState *s = _engine->_gamestate;
DebugPrintf("Current register values:\n");
- DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(_engine->_gamestate->r_acc), PRINT_REG(_engine->_gamestate->r_prev), scriptState.restAdjust);
+ DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->restAdjust);
- if (!_engine->_gamestate->_executionStack.empty()) {
- EngineState *s = _engine->_gamestate; // for PRINT_STK
+ if (!s->_executionStack.empty()) {
DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n",
- PRINT_REG(scriptState.xs->addr.pc), PRINT_REG(scriptState.xs->objp),
- (unsigned)(scriptState.xs->fp - s->stack_base), (unsigned)(scriptState.xs->sp - s->stack_base));
+ PRINT_REG(s->xs->addr.pc), PRINT_REG(s->xs->objp),
+ (unsigned)(s->xs->fp - s->stack_base), (unsigned)(s->xs->sp - s->stack_base));
} else
DebugPrintf("<no execution stack: pc,obj,fp omitted>\n");
@@ -811,6 +820,203 @@ bool Console::cmdHexgrep(int argc, const char **argv) {
return true;
}
+bool Console::cmdVerifyScripts(int argc, const char **argv) {
+ if (getSciVersion() < SCI_VERSION_1_1) {
+ DebugPrintf("This script check is only meant for SCI1.1-SCI2.1 games\n");
+ return true;
+ }
+
+ Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeScript);
+ Common::sort(resources->begin(), resources->end());
+ Common::List<ResourceId>::iterator itr = resources->begin();
+
+ DebugPrintf("%d SCI1.1-SCI2.1 scripts found, performing sanity checks...\n", resources->size());
+
+ Resource *script, *heap;
+ while (itr != resources->end()) {
+ script = _engine->getResMan()->findResource(*itr, false);
+ if (!script)
+ DebugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber());
+
+ heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->getNumber()), false);
+ if (!heap)
+ DebugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->getNumber());
+
+ if (script && heap && (script->size + heap->size > 65535))
+ DebugPrintf("Error: script and heap %d together are larger than 64KB (%d bytes)\n",
+ itr->getNumber(), script->size + heap->size);
+
+ ++itr;
+ }
+
+ DebugPrintf("SCI1.1-SCI2.1 script check finished\n");
+ delete resources;
+
+ return true;
+}
+
+bool Console::cmdShowInstruments(int argc, const char **argv) {
+ int songNumber = -1;
+
+ if (argc == 2)
+ songNumber = atoi(argv[1]);
+
+ SciVersion doSoundVersion = _engine->_features->detectDoSoundType();
+ MidiPlayer *player = MidiPlayer_Midi_create(doSoundVersion);
+ MidiParser_SCI *parser = new MidiParser_SCI(doSoundVersion, 0);
+ parser->setMidiDriver(player);
+
+ Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeSound);
+ Common::sort(resources->begin(), resources->end());
+ Common::List<ResourceId>::iterator itr = resources->begin();
+ int instruments[128];
+ bool instrumentsSongs[128][1000];
+
+ for (int i = 0; i < 128; i++)
+ instruments[i] = 0;
+
+ for (int i = 0; i < 128; i++)
+ for (int j = 0; j < 1000; j++)
+ instrumentsSongs[i][j] = false;
+
+ if (songNumber == -1) {
+ DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources->size());
+ DebugPrintf("Instruments:\n");
+ DebugPrintf("============\n");
+ }
+
+ SoundResource *sound;
+
+ while (itr != resources->end()) {
+ if (songNumber >= 0 && itr->getNumber() != songNumber) {
+ ++itr;
+ continue;
+ }
+
+ sound = new SoundResource(itr->getNumber(), _engine->getResMan(), doSoundVersion);
+ int channelFilterMask = sound->getChannelFilterMask(player->getPlayId(), player->hasRhythmChannel());
+ SoundResource::Track *track = sound->getTrackByType(player->getPlayId());
+ if (track->digitalChannelNr != -1) {
+ // Skip digitized sound effects
+ delete sound;
+ ++itr;
+ continue;
+ }
+
+ parser->loadMusic(track, NULL, channelFilterMask, doSoundVersion);
+ const byte *channelData = parser->getMixedData();
+
+ byte curEvent = 0, prevEvent = 0, command = 0;
+ bool endOfTrack = false;
+ bool firstOneShown = false;
+
+ DebugPrintf("Song %d: ", itr->getNumber());
+
+ do {
+ while (*channelData == 0xF8)
+ channelData++;
+
+ channelData++; // delta
+
+ if ((*channelData & 0xF0) >= 0x80)
+ curEvent = *(channelData++);
+ else
+ curEvent = prevEvent;
+ if (curEvent < 0x80)
+ continue;
+
+ prevEvent = curEvent;
+ command = curEvent >> 4;
+
+ byte channel;
+
+ switch (command) {
+ case 0xC: // program change
+ channel = curEvent & 0x0F;
+ if (channel != 15) { // SCI special
+ byte instrument = *channelData++;
+ if (!firstOneShown)
+ firstOneShown = true;
+ else
+ DebugPrintf(",");
+
+ DebugPrintf(" %d", instrument);
+ instruments[instrument]++;
+ instrumentsSongs[instrument][itr->getNumber()] = true;
+ }
+ break;
+ case 0xD:
+ channelData++; // param1
+ break;
+ case 0xB:
+ channelData++; // param1
+ channelData++; // param2
+ break;
+ case 0x8:
+ case 0x9:
+ case 0xA:
+ case 0xE:
+ channelData++; // param1
+ channelData++; // param2
+ break;
+ case 0xF:
+ if ((curEvent & 0x0F) == 0x2) {
+ channelData++; // param1
+ channelData++; // param2
+ } else if ((curEvent & 0x0F) == 0x3) {
+ channelData++; // param1
+ } else if ((curEvent & 0x0F) == 0xF) { // META
+ byte type = *channelData++;
+ if (type == 0x2F) {// end of track reached
+ endOfTrack = true;
+ } else {
+ // no further processing necessary
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ } while (!endOfTrack);
+
+ DebugPrintf("\n");
+
+ delete sound;
+ ++itr;
+ }
+
+ delete parser;
+ delete player;
+
+ DebugPrintf("\n");
+
+ if (songNumber == -1) {
+ DebugPrintf("Used instruments: ");
+ for (int i = 0; i < 128; i++) {
+ if (instruments[i] > 0)
+ DebugPrintf("%d, ", i);
+ }
+ DebugPrintf("\n\n");
+
+ DebugPrintf("Used instruments in songs:\n");
+ for (int i = 0; i < 128; i++) {
+ if (instruments[i] > 0) {
+ DebugPrintf("Instrument %d: ", i);
+ for (int j = 0; j < 1000; j++) {
+ if (instrumentsSongs[i][j])
+ DebugPrintf("%d, ", j);
+ }
+ DebugPrintf("\n");
+ }
+ }
+
+ DebugPrintf("\n\n");
+ }
+
+ delete resources;
+ return true;
+}
+
bool Console::cmdList(int argc, const char **argv) {
if (argc < 2) {
DebugPrintf("Lists all the resources of a given type\n");
@@ -834,26 +1040,25 @@ bool Console::cmdList(int argc, const char **argv) {
}
Common::List<ResourceId> *resources = _engine->getResMan()->listResources(res, number);
- sort(resources->begin(), resources->end(), ResourceIdLess());
+ Common::sort(resources->begin(), resources->end());
Common::List<ResourceId>::iterator itr = resources->begin();
int cnt = 0;
while (itr != resources->end()) {
if (number == -1) {
- DebugPrintf("%8i", itr->number);
+ DebugPrintf("%8i", itr->getNumber());
if (++cnt % 10 == 0)
DebugPrintf("\n");
- }
- else if (number == (int)itr->number) {
- DebugPrintf("(%3i, %3i, %3i, %3i) ", (itr->tuple >> 24) & 0xff, (itr->tuple >> 16) & 0xff,
- (itr->tuple >> 8) & 0xff, itr->tuple & 0xff);
+ } else if (number == (int)itr->getNumber()) {
+ const uint32 tuple = itr->getTuple();
+ DebugPrintf("(%3i, %3i, %3i, %3i) ", (tuple >> 24) & 0xff, (tuple >> 16) & 0xff,
+ (tuple >> 8) & 0xff, tuple & 0xff);
if (++cnt % 4 == 0)
DebugPrintf("\n");
}
++itr;
}
DebugPrintf("\n");
-
delete resources;
}
@@ -884,7 +1089,7 @@ bool Console::cmdSaveGame(int argc, const char **argv) {
}
// TODO: enable custom descriptions? force filename into a specific format?
- if (gamestate_save(_engine->_gamestate, out, "debugging", version)) {
+ if (!gamestate_save(_engine->_gamestate, out, "debugging", version)) {
DebugPrintf("Saving the game state to '%s' failed\n", argv[1]);
} else {
out->finalize();
@@ -917,39 +1122,22 @@ bool Console::cmdRestoreGame(int argc, const char **argv) {
return true;
}
- return false;
+ return Cmd_Exit(0, 0);
}
bool Console::cmdRestartGame(int argc, const char **argv) {
- if (argc != 2) {
- DebugPrintf("Restarts the game. There are two ways to restart a SCI game:\n");
- DebugPrintf("%s play - calls the game object's play() method\n", argv[0]);
- DebugPrintf("%s replay - calls the replay() methody\n", argv[0]);
- return true;
- }
-
- if (!scumm_stricmp(argv[1], "play")) {
- _engine->_gamestate->restarting_flags |= SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE;
- } else if (!scumm_stricmp(argv[1], "replay")) {
- _engine->_gamestate->restarting_flags &= ~SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE;
- } else {
- DebugPrintf("Invalid usage of %s\n", argv[0]);
- return true;
- }
+ _engine->_gamestate->abortScriptProcessing = kAbortRestartGame;;
- _engine->_gamestate->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW;
- script_abort_flag = 1;
-
- return false;
+ return Cmd_Exit(0, 0);
}
bool Console::cmdClassTable(int argc, const char **argv) {
DebugPrintf("Available classes:\n");
- for (uint i = 0; i < _engine->_gamestate->_segMan->_classtable.size(); i++) {
- if (_engine->_gamestate->_segMan->_classtable[i].reg.segment) {
+ for (uint i = 0; i < _engine->_gamestate->_segMan->classTableSize(); i++) {
+ if (_engine->_gamestate->_segMan->_classTable[i].reg.segment) {
DebugPrintf(" Class 0x%x at %04x:%04x (script 0x%x)\n", i,
- PRINT_REG(_engine->_gamestate->_segMan->_classtable[i].reg),
- _engine->_gamestate->_segMan->_classtable[i].script);
+ PRINT_REG(_engine->_gamestate->_segMan->_classTable[i].reg),
+ _engine->_gamestate->_segMan->_classTable[i].script);
}
}
@@ -1011,8 +1199,9 @@ bool Console::cmdParse(int argc, const char **argv) {
char string[1000];
// Construct the string
- strcpy(string, argv[2]);
+ strcpy(string, argv[1]);
for (int i = 2; i < argc; i++) {
+ strcat(string, " ");
strcat(string, argv[i]);
}
@@ -1044,6 +1233,122 @@ bool Console::cmdParse(int argc, const char **argv) {
return true;
}
+bool Console::cmdSaid(int argc, const char **argv) {
+ if (argc < 2) {
+ DebugPrintf("Matches a string against a said spec\n");
+ DebugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]);
+ DebugPrintf("<string> is a sequence of actual words.\n");
+ DebugPrintf("<said spec> is a sequence of hex tokens.\n");
+ return true;
+ }
+
+ ResultWordList words;
+ char *error;
+ char string[1000];
+ byte spec[1000];
+
+ int p;
+ // Construct the string
+ strcpy(string, argv[1]);
+ for (p = 2; p < argc && strcmp(argv[p],"&") != 0; p++) {
+ strcat(string, " ");
+ strcat(string, argv[p]);
+ }
+
+ if (p >= argc-1) {
+ DebugPrintf("Matches a string against a said spec\n");
+ DebugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]);
+ DebugPrintf("<string> is a sequence of actual words.\n");
+ DebugPrintf("<said spec> is a sequence of hex tokens.\n");
+ return true;
+ }
+
+ // TODO: Maybe turn this into a proper said spec compiler
+ unsigned int len = 0;
+ for (p++; p < argc; p++) {
+ if (strcmp(argv[p], ",") == 0) {
+ spec[len++] = 0xf0;
+ } else if (strcmp(argv[p], "&") == 0) {
+ spec[len++] = 0xf1;
+ } else if (strcmp(argv[p], "/") == 0) {
+ spec[len++] = 0xf2;
+ } else if (strcmp(argv[p], "(") == 0) {
+ spec[len++] = 0xf3;
+ } else if (strcmp(argv[p], ")") == 0) {
+ spec[len++] = 0xf4;
+ } else if (strcmp(argv[p], "[") == 0) {
+ spec[len++] = 0xf5;
+ } else if (strcmp(argv[p], "]") == 0) {
+ spec[len++] = 0xf6;
+ } else if (strcmp(argv[p], "#") == 0) {
+ spec[len++] = 0xf7;
+ } else if (strcmp(argv[p], "<") == 0) {
+ spec[len++] = 0xf8;
+ } else if (strcmp(argv[p], ">") == 0) {
+ spec[len++] = 0xf9;
+ } else if (strcmp(argv[p], "[<") == 0) {
+ spec[len++] = 0xf5;
+ spec[len++] = 0xf8;
+ } else if (strcmp(argv[p], "[/") == 0) {
+ spec[len++] = 0xf5;
+ spec[len++] = 0xf2;
+ } else if (strcmp(argv[p], "!*") == 0) {
+ spec[len++] = 0x0f;
+ spec[len++] = 0xfe;
+ } else if (strcmp(argv[p], "[!*]") == 0) {
+ spec[len++] = 0xf5;
+ spec[len++] = 0x0f;
+ spec[len++] = 0xfe;
+ spec[len++] = 0xf6;
+ } else {
+ unsigned int s = strtol(argv[p], 0, 16);
+ if (s >= 0xf0 && s <= 0xff) {
+ spec[len++] = s;
+ } else {
+ spec[len++] = s >> 8;
+ spec[len++] = s & 0xFF;
+ }
+ }
+ }
+ spec[len++] = 0xFF;
+
+ printf("Matching '%s' against:", string);
+ _engine->getVocabulary()->debugDecipherSaidBlock(spec);
+ printf("\n");
+
+ bool res = _engine->getVocabulary()->tokenizeString(words, string, &error);
+ if (res && !words.empty()) {
+ int syntax_fail = 0;
+
+ _engine->getVocabulary()->synonymizeTokens(words);
+
+ DebugPrintf("Parsed to the following blocks:\n");
+
+ for (ResultWordList::const_iterator i = words.begin(); i != words.end(); ++i)
+ DebugPrintf(" Type[%04x] Group[%04x]\n", i->_class, i->_group);
+
+ if (_engine->getVocabulary()->parseGNF(words, true))
+ syntax_fail = 1; // Building a tree failed
+
+ if (syntax_fail)
+ DebugPrintf("Building a tree failed.\n");
+ else {
+ _engine->getVocabulary()->dumpParseTree();
+ _engine->getVocabulary()->parserIsValid = true;
+
+ int ret = said(_engine->_gamestate, (byte*)spec, true);
+ DebugPrintf("kSaid: %s\n", (ret == SAID_NO_MATCH ? "No match" : "Match"));
+ }
+
+ } else {
+ DebugPrintf("Unknown word: '%s'\n", error);
+ free(error);
+ }
+
+ return true;
+}
+
+
bool Console::cmdParserNodes(int argc, const char **argv) {
if (argc != 2) {
DebugPrintf("Shows the specified number of nodes from the parse node tree\n");
@@ -1115,7 +1420,11 @@ bool Console::cmdDrawRobot(int argc, const char **argv) {
uint16 resourceId = atoi(argv[1]);
- _engine->_gui32->drawRobot(resourceId);
+ if (_engine->_gfxPaint32) {
+ _engine->_gfxPaint32->debugDrawRobot(resourceId);
+ } else {
+ DebugPrintf("command not available in non-sci32 games");
+ }
return true;
}
#endif
@@ -1129,7 +1438,11 @@ bool Console::cmdUndither(int argc, const char **argv) {
bool flag = atoi(argv[1]) ? true : false;
_engine->_gfxScreen->debugUnditherSetState(flag);
- return false;
+ if (flag)
+ DebugPrintf("undithering ENABLED\n");
+ else
+ DebugPrintf("undithering DISABLED\n");
+ return true;
}
bool Console::cmdPicVisualize(int argc, const char **argv) {
@@ -1141,7 +1454,16 @@ bool Console::cmdPicVisualize(int argc, const char **argv) {
bool state = atoi(argv[1]) ? true : false;
- return _engine->_gui->debugEGAdrawingVisualize(state);
+ if (_engine->_resMan->getViewType() == kViewEga) {
+ _engine->_gfxPaint16->debugSetEGAdrawingVisualize(state);
+ if (state)
+ DebugPrintf("picture visualization ENABLED\n");
+ else
+ DebugPrintf("picture visualization DISABLED\n");
+ } else {
+ DebugPrintf("picture visualization only available for EGA games\n");
+ }
+ return true;
}
bool Console::cmdPlayVideo(int argc, const char **argv) {
@@ -1159,7 +1481,7 @@ bool Console::cmdPlayVideo(int argc, const char **argv) {
if (filename.hasSuffix(".seq") || filename.hasSuffix(".avi") || filename.hasSuffix(".vmd")) {
_videoFile = filename;
_videoFrameDelay = (argc == 2) ? 10 : atoi(argv[2]);
- return false;
+ return Cmd_Exit(0, 0);
} else {
DebugPrintf("Unknown video file type\n");
return true;
@@ -1184,7 +1506,7 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) {
switch (mobj->getType()) {
case SEG_TYPE_SCRIPT:
- DebugPrintf("S script.%03d l:%d ", (*(Script *)mobj)._nr, (*(Script *)mobj).getLockers());
+ DebugPrintf("S script.%03d l:%d ", (*(Script *)mobj).getScriptNumber(), (*(Script *)mobj).getLockers());
break;
case SEG_TYPE_CLONES:
@@ -1219,9 +1541,15 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) {
DebugPrintf("M dynmem: %d bytes", (*(DynMem *)mobj)._size);
break;
- case SEG_TYPE_STRING_FRAG:
- DebugPrintf("F string fragments");
+#ifdef ENABLE_SCI32
+ case SEG_TYPE_ARRAY:
+ DebugPrintf("A SCI32 arrays (%d)", (*(ArrayTable *)mobj).entries_used);
+ break;
+
+ case SEG_TYPE_STRING:
+ DebugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used);
break;
+#endif
default:
DebugPrintf("I Invalid (type = %x)", mobj->getType());
@@ -1248,13 +1576,13 @@ bool Console::segmentInfo(int nr) {
case SEG_TYPE_SCRIPT: {
Script *scr = (Script *)mobj;
- DebugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->_nr, scr->getLockers(), (uint)scr->_bufSize, (uint)scr->_bufSize);
- if (scr->_exportTable)
- DebugPrintf(" Exports: %4d at %d\n", scr->_numExports, (int)(((byte *)scr->_exportTable) - ((byte *)scr->_buf)));
+ DebugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->getScriptNumber(), scr->getLockers(), (uint)scr->getBufSize(), (uint)scr->getBufSize());
+ if (scr->getExportTable())
+ DebugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->getBuf())));
else
DebugPrintf(" Exports: none\n");
- DebugPrintf(" Synonyms: %4d\n", scr->_numSynonyms);
+ DebugPrintf(" Synonyms: %4d\n", scr->getSynonymsNr());
if (scr->_localsBlock)
DebugPrintf(" Locals : %4d in segment 0x%x\n", scr->_localsBlock->_locals.size(), scr->_localsSegment);
@@ -1268,7 +1596,7 @@ bool Console::segmentInfo(int nr) {
for (it = scr->_objects.begin(); it != end; ++it) {
DebugPrintf(" ");
// Object header
- Object *obj = _engine->_gamestate->_segMan->getObject(it->_value.getPos());
+ const Object *obj = _engine->_gamestate->_segMan->getObject(it->_value.getPos());
if (obj)
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(it->_value.getPos()),
_engine->_gamestate->_segMan->getObjectName(it->_value.getPos()),
@@ -1315,7 +1643,7 @@ bool Console::segmentInfo(int nr) {
objpos.segment = nr;
DebugPrintf(" [%04x] %s; copy of ", i, _engine->_gamestate->_segMan->getObjectName(objpos));
// Object header
- Object *obj = _engine->_gamestate->_segMan->getObject(ct->_table[i].getPos());
+ const Object *obj = _engine->_gamestate->_segMan->getObject(ct->_table[i].getPos());
if (obj)
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].getPos()),
_engine->_gamestate->_segMan->getObjectName(ct->_table[i].getPos()),
@@ -1361,10 +1689,14 @@ bool Console::segmentInfo(int nr) {
}
break;
- case SEG_TYPE_STRING_FRAG: {
- DebugPrintf("string frags\n");
+#ifdef ENABLE_SCI32
+ case SEG_TYPE_STRING:
+ DebugPrintf("SCI32 strings\n");
break;
- }
+ case SEG_TYPE_ARRAY:
+ DebugPrintf("SCI32 arrays\n");
+ break;
+#endif
default :
DebugPrintf("Invalid type %d\n", mobj->getType());
@@ -1380,7 +1712,7 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) {
DebugPrintf("Provides information on the specified segment(s)\n");
DebugPrintf("Usage: %s <segment number>\n", argv[0]);
DebugPrintf("<segment number> can be a number, which shows the information of the segment with\n");
- DebugPrintf("the specified number, or \"all\" to show information on all active segments");
+ DebugPrintf("the specified number, or \"all\" to show information on all active segments\n");
return true;
}
@@ -1388,9 +1720,11 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) {
for (uint i = 0; i < _engine->_gamestate->_segMan->_heap.size(); i++)
segmentInfo(i);
} else {
- int nr = atoi(argv[1]);
- if (!segmentInfo(nr))
- DebugPrintf("Segment %04x does not exist\n", nr);
+ int segmentNr;
+ if (!parseInteger(argv[1], segmentNr))
+ return true;
+ if (!segmentInfo(segmentNr))
+ DebugPrintf("Segment %04xh does not exist\n", segmentNr);
}
return true;
@@ -1403,21 +1737,23 @@ bool Console::cmdKillSegment(int argc, const char **argv) {
DebugPrintf("Usage: %s <segment number>\n", argv[0]);
return true;
}
-
- _engine->_gamestate->_segMan->getScript(atoi(argv[1]))->setLockers(0);
+ int segmentNumber;
+ if (!parseInteger(argv[1], segmentNumber))
+ return true;
+ _engine->_gamestate->_segMan->getScript(segmentNumber)->setLockers(0);
return true;
}
bool Console::cmdShowMap(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Shows one of the screen maps\n");
+ DebugPrintf("Switches to one of the following screen maps\n");
DebugPrintf("Usage: %s <screen map>\n", argv[0]);
DebugPrintf("Screen maps:\n");
- DebugPrintf("- 0: visual map (back buffer)\n");
- DebugPrintf("- 1: priority map (back buffer)\n");
- DebugPrintf("- 2: control map (static buffer)\n");
- DebugPrintf("- 3: display screen (newgui only)\n");
+ DebugPrintf("- 0: visual map\n");
+ DebugPrintf("- 1: priority map\n");
+ DebugPrintf("- 2: control map\n");
+ DebugPrintf("- 3: display screen\n");
return true;
}
@@ -1435,28 +1771,12 @@ bool Console::cmdShowMap(int argc, const char **argv) {
DebugPrintf("Map %d is not available.\n", map);
return true;
}
- return false;
+ return Cmd_Exit(0, 0);
}
bool Console::cmdSongLib(int argc, const char **argv) {
DebugPrintf("Song library:\n");
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- Song *seeker = _engine->_gamestate->_sound._songlib._lib;
-
- do {
- DebugPrintf(" %p", (void *)seeker);
-
- if (seeker) {
- DebugPrintf("[%04lx,p=%d,s=%d]->", seeker->_handle, seeker->_priority, seeker->_status);
- seeker = seeker->_next;
- }
- DebugPrintf("\n");
- } while (seeker);
- DebugPrintf("\n");
-#else
- _engine->_gamestate->_soundCmd->printPlayList(this);
-#endif
+ g_sci->_soundCmd->printPlayList(this);
return true;
}
@@ -1476,7 +1796,7 @@ bool Console::cmdSongInfo(int argc, const char **argv) {
return true;
}
- _engine->_gamestate->_soundCmd->printSongInfo(addr, this);
+ g_sci->_soundCmd->printSongInfo(addr, this);
return true;
}
@@ -1495,9 +1815,8 @@ bool Console::cmdStartSound(int argc, const char **argv) {
return true;
}
- _engine->_gamestate->_soundCmd->startNewSound(number);
-
- return false;
+ g_sci->_soundCmd->startNewSound(number);
+ return Cmd_Exit(0, 0);
}
bool Console::cmdToggleSound(int argc, const char **argv) {
@@ -1519,37 +1838,21 @@ bool Console::cmdToggleSound(int argc, const char **argv) {
return true;
}
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- int handle = id.segment << 16 | id.offset; // frobnicate handle
-
- if (id.segment) {
- SegManager *segMan = _engine->_gamestate->_segMan; // for PUT_SEL32V
- _engine->_gamestate->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
- _engine->_gamestate->_sound.sfx_remove_song(handle);
- PUT_SEL32V(segMan, id, SELECTOR(signal), SIGNAL_OFFSET);
- PUT_SEL32V(segMan, id, SELECTOR(nodePtr), 0);
- PUT_SEL32V(segMan, id, SELECTOR(handle), 0);
- }
-#else
-
Common::String newState = argv[2];
newState.toLowercase();
if (newState == "play")
- _engine->_gamestate->_soundCmd->playSound(id);
+ g_sci->_soundCmd->processPlaySound(id);
else if (newState == "stop")
- _engine->_gamestate->_soundCmd->stopSound(id);
+ g_sci->_soundCmd->processStopSound(id, false);
else
DebugPrintf("New state can either be 'play' or 'stop'");
-#endif
return true;
}
bool Console::cmdStopAllSounds(int argc, const char **argv) {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
- _engine->_gamestate->_soundCmd->stopAllSounds();
-#endif
+ g_sci->_soundCmd->stopAllSounds();
DebugPrintf("All sounds have been stopped\n");
return true;
@@ -1563,36 +1866,6 @@ bool Console::cmdIsSample(int argc, const char **argv) {
return true;
}
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- Resource *song = _engine->getResMan()->findResource(ResourceId(kResourceTypeSound, atoi(argv[1])), 0);
- SongIterator *songit;
- Audio::AudioStream *data;
-
- if (!song) {
- DebugPrintf("Not a sound resource!\n");
- return true;
- }
-
- songit = songit_new(song->data, song->size, SCI_SONG_ITERATOR_TYPE_SCI0, 0xcaffe /* What do I care about the ID? */);
-
- if (!songit) {
- DebugPrintf("Could not convert to song iterator!\n");
- return true;
- }
-
- data = songit->getAudioStream();
- if (data) {
- // TODO
-/*
- DebugPrintf("\nIs sample (encoding %dHz/%s/%04x)", data->conf.rate, (data->conf.stereo) ?
- ((data->conf.stereo == SFX_PCM_STEREO_LR) ? "stereo-LR" : "stereo-RL") : "mono", data->conf.format);
-*/
- delete data;
- } else
- DebugPrintf("Valid song, but not a sample.\n");
-
- delete songit;
-#else
int16 number = atoi(argv[1]);
if (!_engine->getResMan()->testResource(ResourceId(kResourceTypeSound, number))) {
@@ -1616,7 +1889,6 @@ bool Console::cmdIsSample(int argc, const char **argv) {
DebugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n",
track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr);
-#endif
return true;
}
@@ -1628,10 +1900,10 @@ bool Console::cmdGCInvoke(int argc, const char **argv) {
}
bool Console::cmdGCObjects(int argc, const char **argv) {
- reg_t_hash_map *use_map = find_all_used_references(_engine->_gamestate);
+ AddrSet *use_map = findAllActiveReferences(_engine->_gamestate);
DebugPrintf("Reachable object references (normalised):\n");
- for (reg_t_hash_map::iterator i = use_map->begin(); i != use_map->end(); ++i) {
+ for (AddrSet::iterator i = use_map->begin(); i != use_map->end(); ++i) {
DebugPrintf(" - %04x:%04x\n", PRINT_REG(i->_key));
}
@@ -1640,11 +1912,6 @@ bool Console::cmdGCObjects(int argc, const char **argv) {
return true;
}
-void _print_address(void * _, reg_t addr) {
- if (addr.segment)
- g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(addr));
-}
-
bool Console::cmdGCShowReachable(int argc, const char **argv) {
if (argc != 2) {
DebugPrintf("Prints all addresses directly reachable from the memory object specified as parameter.\n");
@@ -1668,7 +1935,10 @@ bool Console::cmdGCShowReachable(int argc, const char **argv) {
}
DebugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr));
- mobj->listAllOutgoingReferences(addr, NULL, _print_address);
+ const Common::Array<reg_t> tmp = mobj->listAllOutgoingReferences(addr);
+ for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
+ if (it->segment)
+ g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it));
return true;
}
@@ -1697,7 +1967,10 @@ bool Console::cmdGCShowFreeable(int argc, const char **argv) {
}
DebugPrintf("Freeable in segment %04x:\n", addr.segment);
- mobj->listAllDeallocatable(addr.segment, NULL, _print_address);
+ const Common::Array<reg_t> tmp = mobj->listAllDeallocatable(addr.segment);
+ for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
+ if (it->segment)
+ g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it));
return true;
}
@@ -1733,14 +2006,15 @@ bool Console::cmdGCNormalize(int argc, const char **argv) {
}
bool Console::cmdVMVarlist(int argc, const char **argv) {
+ EngineState *s = _engine->_gamestate;
const char *varnames[] = {"global", "local", "temp", "param"};
DebugPrintf("Addresses of variables in the VM:\n");
for (int i = 0; i < 4; i++) {
- DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(scriptState.variables_seg[i], scriptState.variables[i] - scriptState.variables_base[i])));
- if (scriptState.variables_max)
- DebugPrintf(" total %d", scriptState.variables_max[i]);
+ DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(s->variablesSegment[i], s->variables[i] - s->variablesBase[i])));
+ if (s->variablesMax)
+ DebugPrintf(" total %d", s->variablesMax[i]);
DebugPrintf("\n");
}
@@ -1748,55 +2022,95 @@ bool Console::cmdVMVarlist(int argc, const char **argv) {
}
bool Console::cmdVMVars(int argc, const char **argv) {
- if (argc < 3) {
+ if (argc < 2) {
DebugPrintf("Displays or changes variables in the VM\n");
DebugPrintf("Usage: %s <type> <varnum> [<value>]\n", argv[0]);
- DebugPrintf("First parameter is either g(lobal), l(ocal), t(emp) or p(aram).\n");
- DebugPrintf("Second parameter is the var number\n");
+ DebugPrintf("First parameter is either g(lobal), l(ocal), t(emp), p(aram) or a(cc).\n");
+ DebugPrintf("Second parameter is the var number (not specified on acc)\n");
DebugPrintf("Third parameter (if specified) is the value to set the variable to, in address form\n");
DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
- const char *varnames[] = {"global", "local", "temp", "param"};
- const char *varabbrev = "gltp";
- const char *vartype_pre = strchr(varabbrev, *argv[1]);
- int vartype;
- int idx = atoi(argv[2]);
-
- if (!vartype_pre) {
+ EngineState *s = _engine->_gamestate;
+ const char *varNames[] = {"global", "local", "temp", "param", "acc"};
+ const char *varAbbrev = "gltpa";
+ const char *varType_pre = strchr(varAbbrev, *argv[1]);
+ int varType;
+ int varIndex = 0;
+ reg_t *curValue = NULL;
+ const char *setValue = NULL;
+
+ if (!varType_pre) {
DebugPrintf("Invalid variable type '%c'\n", *argv[1]);
return true;
}
- vartype = vartype_pre - varabbrev;
+ varType = varType_pre - varAbbrev;
- if (idx < 0) {
- DebugPrintf("Invalid: negative index\n");
- return true;
- }
+ switch (varType) {
+ case 0:
+ case 1:
+ case 2:
+ case 3: {
+ // for global, local, temp and param, we need an index
+ if (argc < 3) {
+ DebugPrintf("Variable number must be specified for requested type\n");
+ return true;
+ }
+ if (argc > 4) {
+ DebugPrintf("Too many arguments\n");
+ return true;
+ }
- if ((scriptState.variables_max) && (scriptState.variables_max[vartype] <= idx)) {
- DebugPrintf("Max. index is %d (0x%x)\n", scriptState.variables_max[vartype], scriptState.variables_max[vartype]);
- return true;
- }
+ if (!parseInteger(argv[2], varIndex))
+ return true;
- switch (argc) {
- case 3:
- DebugPrintf("%s var %d == %04x:%04x\n", varnames[vartype], idx, PRINT_REG(scriptState.variables[vartype][idx]));
+ if (varIndex < 0) {
+ DebugPrintf("Variable number may not be negative\n");
+ return true;
+ }
+
+ if ((s->variablesMax) && (s->variablesMax[varType] <= varIndex)) {
+ DebugPrintf("Maximum variable number for this type is %d (0x%x)\n", s->variablesMax[varType], s->variablesMax[varType]);
+ return true;
+ }
+ curValue = &s->variables[varType][varIndex];
+ if (argc == 4)
+ setValue = argv[3];
break;
+ }
+
case 4:
- if (parse_reg_t(_engine->_gamestate, argv[3], &scriptState.variables[vartype][idx], true)) {
- DebugPrintf("Invalid value/address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
- DebugPrintf("Or pass a decimal or hexadecimal value directly (e.g. 12, 1Ah)\n");
+ // acc
+ if (argc > 3) {
+ DebugPrintf("Too many arguments\n");
return true;
}
+ curValue = &s->r_acc;
+ if (argc == 3)
+ setValue = argv[2];
break;
+
default:
- DebugPrintf("Too many arguments\n");
+ break;
}
+ if (!setValue) {
+ if (varType == 4)
+ DebugPrintf("%s == %04x:%04x", varNames[varType], PRINT_REG(*curValue));
+ else
+ DebugPrintf("%s var %d == %04x:%04x", varNames[varType], varIndex, PRINT_REG(*curValue));
+ printBasicVarInfo(*curValue);
+ DebugPrintf("\n");
+ } else {
+ if (parse_reg_t(s, setValue, curValue, true)) {
+ DebugPrintf("Invalid value/address passed.\n");
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ DebugPrintf("Or pass a decimal or hexadecimal value directly (e.g. 12, 1Ah)\n");
+ return true;
+ }
+ }
return true;
}
@@ -1846,20 +2160,22 @@ bool Console::cmdValueType(int argc, const char **argv) {
int t = g_sci->getKernel()->findRegType(val);
switch (t) {
- case KSIG_LIST:
+ case SIG_TYPE_LIST:
DebugPrintf("List");
break;
- case KSIG_OBJECT:
+ case SIG_TYPE_OBJECT:
DebugPrintf("Object");
break;
- case KSIG_REF:
+ case SIG_TYPE_REFERENCE:
DebugPrintf("Reference");
break;
- case KSIG_ARITHMETIC:
- DebugPrintf("Arithmetic");
+ case SIG_TYPE_INTEGER:
+ DebugPrintf("Integer");
+ case SIG_TYPE_INTEGER | SIG_TYPE_NULL:
+ DebugPrintf("Null");
break;
default:
- DebugPrintf("Erroneous unknown type %02x(%d decimal)\n", t, t);
+ DebugPrintf("Erroneous unknown type 0x%02x (%d decimal)\n", t, t);
}
return true;
@@ -1923,7 +2239,7 @@ bool Console::cmdViewReference(int argc, const char **argv) {
return true;
}
- if (reg_end.segment != reg.segment) {
+ if (reg_end.segment != reg.segment && reg_end != NULL_REG) {
DebugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n");
reg_end = NULL_REG;
}
@@ -1939,47 +2255,68 @@ bool Console::cmdViewReference(int argc, const char **argv) {
switch (type) {
case 0:
break;
- case KSIG_LIST: {
- List *l = _engine->_gamestate->_segMan->lookupList(reg);
+ case SIG_TYPE_LIST: {
+ List *list = _engine->_gamestate->_segMan->lookupList(reg);
DebugPrintf("list\n");
- if (l)
- printList(l);
+ if (list)
+ printList(list);
else
DebugPrintf("Invalid list.\n");
}
break;
- case KSIG_NODE:
+ case SIG_TYPE_NODE:
DebugPrintf("list node\n");
printNode(reg);
break;
- case KSIG_OBJECT:
+ case SIG_TYPE_OBJECT:
DebugPrintf("object\n");
printObject(reg);
break;
- case KSIG_REF: {
- int size;
- const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg);
- size = block.maxSize;
+ case SIG_TYPE_REFERENCE: {
+ switch (_engine->_gamestate->_segMan->getSegmentType(reg.segment)) {
+#ifdef ENABLE_SCI32
+ case SEG_TYPE_STRING: {
+ DebugPrintf("SCI32 string\n");
+ const SciString *str = _engine->_gamestate->_segMan->lookupString(reg);
+ Common::hexdump((const byte *) str->getRawData(), str->getSize(), 16, 0);
+ break;
+ }
+ case SEG_TYPE_ARRAY: {
+ DebugPrintf("SCI32 array:\n");
+ const SciArray<reg_t> *array = _engine->_gamestate->_segMan->lookupArray(reg);
+ hexDumpReg(array->getRawData(), array->getSize(), 4, 0, true);
+ break;
+ }
+#endif
+ default: {
+ int size;
+ const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg);
+ size = block.maxSize;
- DebugPrintf("raw data\n");
+ DebugPrintf("raw data\n");
- if (reg_end.segment != 0 && size < reg_end.offset - reg.offset) {
- DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size);
- reg_end = NULL_REG;
- }
+ if (reg_end.segment != 0 && size < reg_end.offset - reg.offset) {
+ DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size);
+ reg_end = NULL_REG;
+ }
- if (reg_end.segment != 0 && (size >= reg_end.offset - reg.offset))
- size = reg_end.offset - reg.offset;
+ if (reg_end.segment != 0 && (size >= reg_end.offset - reg.offset))
+ size = reg_end.offset - reg.offset;
- if (reg_end.segment != 0)
- DebugPrintf("Block size less than or equal to %d\n", size);
+ if (reg_end.segment != 0)
+ DebugPrintf("Block size less than or equal to %d\n", size);
- Common::hexdump(block.raw, size, 16, 0);
+ if (block.isRaw)
+ Common::hexdump(block.raw, size, 16, 0);
+ else
+ hexDumpReg(block.reg, size / 2, 4, 0);
+ }
}
break;
- case KSIG_ARITHMETIC:
+ }
+ case SIG_TYPE_INTEGER:
DebugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.offset, reg.offset);
break;
default:
@@ -2019,7 +2356,7 @@ bool Console::cmdViewObject(int argc, const char **argv) {
bool Console::cmdViewActiveObject(int argc, const char **argv) {
DebugPrintf("Information on the currently active object or class:\n");
- printObject(scriptState.xs->objp);
+ printObject(_engine->_gamestate->xs->objp);
return true;
}
@@ -2032,35 +2369,12 @@ bool Console::cmdViewAccumulatorObject(int argc, const char **argv) {
}
bool Console::cmdScriptSteps(int argc, const char **argv) {
- DebugPrintf("Number of executed SCI operations: %d\n", script_step_counter);
- return true;
-}
-
-bool Console::cmdSetAccumulator(int argc, const char **argv) {
- if (argc != 2) {
- DebugPrintf("Sets the accumulator.\n");
- DebugPrintf("Usage: %s <address>\n", argv[0]);
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
- return true;
- }
-
- reg_t val;
-
- if (parse_reg_t(_engine->_gamestate, argv[1], &val, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
- return true;
- }
-
- _engine->_gamestate->r_acc = val;
-
+ DebugPrintf("Number of executed SCI operations: %d\n", _engine->_gamestate->scriptStepCounter);
return true;
}
bool Console::cmdBacktrace(int argc, const char **argv) {
- DebugPrintf("Dumping the send/self/super/call/calle/callb stack:\n");
-
- DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->execution_stack_base);
+ DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase);
Common::List<ExecStack>::iterator iter;
uint i = 0;
@@ -2071,20 +2385,25 @@ bool Console::cmdBacktrace(int argc, const char **argv) {
int paramc, totalparamc;
switch (call.type) {
-
- case EXEC_STACK_TYPE_CALL: {// Normal function
- DebugPrintf(" %x:[%x] %s::%s(", i, call.origin, objname, (call.selector == -1) ? "<call[be]?>" :
- selector_name(_engine->_gamestate, call.selector));
- }
- break;
+ case EXEC_STACK_TYPE_CALL: // Normal function
+ if (call.type == EXEC_STACK_TYPE_CALL)
+ DebugPrintf(" %x: script %d - ", i, (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.segment]).getScriptNumber());
+ if (call.debugSelector != -1) {
+ DebugPrintf("%s::%s(", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str());
+ } else if (call.debugExportId != -1) {
+ DebugPrintf("export %d (", call.debugExportId);
+ } else if (call.debugLocalCallOffset != -1) {
+ DebugPrintf("call %x (", call.debugLocalCallOffset);
+ }
+ break;
case EXEC_STACK_TYPE_KERNEL: // Kernel function
- DebugPrintf(" %x:[%x] k%s(", i, call.origin, _engine->getKernel()->getKernelName(call.selector).c_str());
+ DebugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugSelector).c_str());
break;
case EXEC_STACK_TYPE_VARSELECTOR:
- DebugPrintf(" %x:[%x] vs%s %s::%s (", i, call.origin, (call.argc) ? "write" : "read",
- objname, _engine->getKernel()->getSelectorName(call.selector).c_str());
+ DebugPrintf(" %x:[%x] vs%s %s::%s (", i, call.debugOrigin, (call.argc) ? "write" : "read",
+ objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str());
break;
}
@@ -2103,7 +2422,10 @@ bool Console::cmdBacktrace(int argc, const char **argv) {
if (call.argc > 16)
DebugPrintf("...");
- DebugPrintf(")\n obj@%04x:%04x", PRINT_REG(call.objp));
+ DebugPrintf(")\n ");
+ if (call.debugOrigin != -1)
+ DebugPrintf("by %x ", call.debugOrigin);
+ DebugPrintf("obj@%04x:%04x", PRINT_REG(call.objp));
if (call.type == EXEC_STACK_TYPE_CALL) {
DebugPrintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc));
if (call.sp == CALL_SP_CARRY)
@@ -2116,35 +2438,41 @@ bool Console::cmdBacktrace(int argc, const char **argv) {
DebugPrintf(" pc:none");
DebugPrintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _engine->_gamestate->stack_base));
- if (call.type == EXEC_STACK_TYPE_CALL)
- DebugPrintf(" script: %d", (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.segment])._nr);
DebugPrintf("\n");
}
return true;
}
-bool Console::cmdStep(int argc, const char **argv) {
+bool Console::cmdTrace(int argc, const char **argv) {
if (argc == 2 && atoi(argv[1]) > 0)
- g_debugState.runningStep = atoi(argv[1]) - 1;
- g_debugState.debugging = true;
+ _debugState.runningStep = atoi(argv[1]) - 1;
+ _debugState.debugging = true;
+
+ return Cmd_Exit(0, 0);
+}
+
+bool Console::cmdStepOver(int argc, const char **argv) {
+ _debugState.seeking = kDebugSeekStepOver;
+ _debugState.seekLevel = _engine->_gamestate->_executionStack.size();
+ _debugState.debugging = true;
- return false;
+ return Cmd_Exit(0, 0);
}
bool Console::cmdStepEvent(int argc, const char **argv) {
- g_debugState.stopOnEvent = true;
- g_debugState.debugging = true;
+ _debugState.stopOnEvent = true;
+ _debugState.debugging = true;
- return false;
+ return Cmd_Exit(0, 0);
}
bool Console::cmdStepRet(int argc, const char **argv) {
- g_debugState.seeking = kDebugSeekLevelRet;
- g_debugState.seekLevel = _engine->_gamestate->_executionStack.size() - 1;
- g_debugState.debugging = true;
+ _debugState.seeking = kDebugSeekLevelRet;
+ _debugState.seekLevel = _engine->_gamestate->_executionStack.size() - 1;
+ _debugState.debugging = true;
- return false;
+ return Cmd_Exit(0, 0);
}
bool Console::cmdStepGlobal(int argc, const char **argv) {
@@ -2154,11 +2482,11 @@ bool Console::cmdStepGlobal(int argc, const char **argv) {
return true;
}
- g_debugState.seeking = kDebugSeekGlobal;
- g_debugState.seekSpecial = atoi(argv[1]);
- g_debugState.debugging = true;
+ _debugState.seeking = kDebugSeekGlobal;
+ _debugState.seekSpecial = atoi(argv[1]);
+ _debugState.debugging = true;
- return false;
+ return Cmd_Exit(0, 0);
}
bool Console::cmdStepCallk(int argc, const char **argv) {
@@ -2184,14 +2512,14 @@ bool Console::cmdStepCallk(int argc, const char **argv) {
}
}
- g_debugState.seeking = kDebugSeekSpecialCallk;
- g_debugState.seekSpecial = callk_index;
+ _debugState.seeking = kDebugSeekSpecialCallk;
+ _debugState.seekSpecial = callk_index;
} else {
- g_debugState.seeking = kDebugSeekCallk;
+ _debugState.seeking = kDebugSeekCallk;
}
- g_debugState.debugging = true;
+ _debugState.debugging = true;
- return false;
+ return Cmd_Exit(0, 0);
}
bool Console::cmdDisassemble(int argc, const char **argv) {
@@ -2209,8 +2537,8 @@ bool Console::cmdDisassemble(int argc, const char **argv) {
return true;
}
- Object *obj = _engine->_gamestate->_segMan->getObject(objAddr);
- int selector_id = _engine->getKernel()->findSelector(argv[2]);
+ const Object *obj = _engine->_gamestate->_segMan->getObject(objAddr);
+ int selectorId = _engine->getKernel()->findSelector(argv[2]);
reg_t addr;
if (!obj) {
@@ -2218,12 +2546,12 @@ bool Console::cmdDisassemble(int argc, const char **argv) {
return true;
}
- if (selector_id < 0) {
+ if (selectorId < 0) {
DebugPrintf("Not a valid selector name.");
return true;
}
- if (lookup_selector(_engine->_gamestate->_segMan, objAddr, selector_id, NULL, &addr) != kSelectorMethod) {
+ if (lookupSelector(_engine->_gamestate->_segMan, objAddr, selectorId, NULL, &addr) != kSelectorMethod) {
DebugPrintf("Not a method.");
return true;
}
@@ -2302,24 +2630,24 @@ bool Console::cmdSend(int argc, const char **argv) {
return true;
}
- const char *selector_name = argv[2];
- int selector_id = _engine->getKernel()->findSelector(selector_name);
+ const char *selectorName = argv[2];
+ int selectorId = _engine->getKernel()->findSelector(selectorName);
- if (selector_id < 0) {
- DebugPrintf("Unknown selector: \"%s\"\n", selector_name);
+ if (selectorId < 0) {
+ DebugPrintf("Unknown selector: \"%s\"\n", selectorName);
return true;
}
- Object *o = _engine->_gamestate->_segMan->getObject(object);
+ const Object *o = _engine->_gamestate->_segMan->getObject(object);
if (o == NULL) {
DebugPrintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object));
return true;
}
- SelectorType selector_type = lookup_selector(_engine->_gamestate->_segMan, object, selector_id, 0, 0);
+ SelectorType selector_type = lookupSelector(_engine->_gamestate->_segMan, object, selectorId, NULL, NULL);
if (selector_type == kSelectorNone) {
- DebugPrintf("Object does not support selector: \"%s\"\n", selector_name);
+ DebugPrintf("Object does not support selector: \"%s\"\n", selectorName);
return true;
}
@@ -2329,7 +2657,7 @@ bool Console::cmdSend(int argc, const char **argv) {
// Create the data block for send_selecor() at the top of the stack:
// [selector_number][argument_counter][arguments...]
StackPtr stackframe = _engine->_gamestate->_executionStack.back().sp;
- stackframe[0] = make_reg(0, selector_id);
+ stackframe[0] = make_reg(0, selectorId);
stackframe[1] = make_reg(0, send_argc);
for (int i = 0; i < send_argc; i++) {
if (parse_reg_t(_engine->_gamestate, argv[3+i], &stackframe[2+i], false)) {
@@ -2356,7 +2684,7 @@ bool Console::cmdSend(int argc, const char **argv) {
// We call run_engine explictly so we can restore the value of r_acc
// after execution.
- run_vm(_engine->_gamestate, 0);
+ run_vm(_engine->_gamestate);
}
@@ -2371,19 +2699,44 @@ bool Console::cmdSend(int argc, const char **argv) {
bool Console::cmdGo(int argc, const char **argv) {
// CHECKME: is this necessary?
- g_debugState.seeking = kDebugSeekNothing;
+ _debugState.seeking = kDebugSeekNothing;
return Cmd_Exit(argc, argv);
}
+bool Console::cmdLogKernel(int argc, const char **argv) {
+ if (argc < 3) {
+ DebugPrintf("Logs calls to specified kernel function.\n");
+ DebugPrintf("Usage: %s <kernel-function/*> <on/off>\n", argv[0]);
+ DebugPrintf("Example: %s StrCpy on\n", argv[0]);
+ return true;
+ }
+
+ bool logging;
+ if (strcmp(argv[2], "on") == 0)
+ logging = true;
+ else if (strcmp(argv[2], "off") == 0)
+ logging = false;
+ else {
+ DebugPrintf("2nd parameter must be either on or off\n");
+ return true;
+ }
+
+ if (g_sci->getKernel()->debugSetFunction(argv[1], logging, -1))
+ DebugPrintf("Logging %s for k%s\n", logging ? "enabled" : "disabled", argv[1]);
+ else
+ DebugPrintf("Unknown kernel function %s\n", argv[1]);
+ return true;
+}
+
bool Console::cmdBreakpointList(int argc, const char **argv) {
int i = 0;
int bpdata;
DebugPrintf("Breakpoint list:\n");
- Common::List<Breakpoint>::const_iterator bp = g_debugState._breakpoints.begin();
- Common::List<Breakpoint>::const_iterator end = g_debugState._breakpoints.end();
+ Common::List<Breakpoint>::const_iterator bp = _debugState._breakpoints.begin();
+ Common::List<Breakpoint>::const_iterator end = _debugState._breakpoints.end();
for (; bp != end; ++bp) {
DebugPrintf(" #%i: ", i);
switch (bp->type) {
@@ -2399,6 +2752,9 @@ bool Console::cmdBreakpointList(int argc, const char **argv) {
i++;
}
+ if (!i)
+ DebugPrintf(" No breakpoints defined.\n");
+
return true;
}
@@ -2406,14 +2762,21 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) {
if (argc != 2) {
DebugPrintf("Deletes a breakpoint with the specified index.\n");
DebugPrintf("Usage: %s <breakpoint index>\n", argv[0]);
+ DebugPrintf("<index> * will remove all breakpoints\n");
+ return true;
+ }
+
+ if (strcmp(argv[1], "*") == 0) {
+ _debugState._breakpoints.clear();
+ _debugState._activeBreakpointTypes = 0;
return true;
}
const int idx = atoi(argv[1]);
// Find the breakpoint at index idx.
- Common::List<Breakpoint>::iterator bp = g_debugState._breakpoints.begin();
- const Common::List<Breakpoint>::iterator end = g_debugState._breakpoints.end();
+ Common::List<Breakpoint>::iterator bp = _debugState._breakpoints.begin();
+ const Common::List<Breakpoint>::iterator end = _debugState._breakpoints.end();
for (int i = 0; bp != end && i < idx; ++bp, ++i) {
// do nothing
}
@@ -2424,23 +2787,23 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) {
}
// Delete it
- g_debugState._breakpoints.erase(bp);
+ _debugState._breakpoints.erase(bp);
// Update EngineState::_activeBreakpointTypes.
int type = 0;
- for (bp = g_debugState._breakpoints.begin(); bp != end; ++bp) {
+ for (bp = _debugState._breakpoints.begin(); bp != end; ++bp) {
type |= bp->type;
}
- g_debugState._activeBreakpointTypes = type;
+ _debugState._activeBreakpointTypes = type;
return true;
}
-bool Console::cmdBreakpointExecMethod(int argc, const char **argv) {
+bool Console::cmdBreakpointMethod(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Sets a breakpoint on the execution of the specified method.\n");
- DebugPrintf("Usage: %s <method name>\n", argv[0]);
+ DebugPrintf("Sets a breakpoint on execution/access of a specified method/selector.\n");
+ DebugPrintf("Usage: %s <name>\n", argv[0]);
DebugPrintf("Example: %s ego::doit\n", argv[0]);
DebugPrintf("May also be used to set a breakpoint that applies whenever an object\n");
DebugPrintf("of a specific type is touched: %s foo::\n", argv[0]);
@@ -2454,13 +2817,29 @@ bool Console::cmdBreakpointExecMethod(int argc, const char **argv) {
bp.type = BREAK_SELECTOR;
bp.name = argv[1];
- g_debugState._breakpoints.push_back(bp);
- g_debugState._activeBreakpointTypes |= BREAK_SELECTOR;
+ _debugState._breakpoints.push_back(bp);
+ _debugState._activeBreakpointTypes |= BREAK_SELECTOR;
return true;
}
-bool Console::cmdBreakpointExecFunction(int argc, const char **argv) {
+bool Console::cmdBreakpointKernel(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Sets a breakpoint on execution of a kernel function.\n");
+ DebugPrintf("Usage: %s <name>\n", argv[0]);
+ DebugPrintf("Example: %s DrawPic\n", argv[0]);
+ return true;
+ }
+
+ if (g_sci->getKernel()->debugSetFunction(argv[1], -1, true))
+ DebugPrintf("Breakpoint enabled for k%s\n", argv[1]);
+ else
+ DebugPrintf("Unknown kernel function %s\n", argv[1]);
+
+ return true;
+}
+
+bool Console::cmdBreakpointFunction(int argc, const char **argv) {
// TODO/FIXME: Why does this accept 2 parameters (the high and the low part of the address)?"
if (argc != 3) {
DebugPrintf("Sets a breakpoint on the execution of the specified exported function.\n");
@@ -2475,8 +2854,8 @@ bool Console::cmdBreakpointExecFunction(int argc, const char **argv) {
bp.type = BREAK_EXPORT;
bp.address = (atoi(argv[1]) << 16 | atoi(argv[2]));
- g_debugState._breakpoints.push_back(bp);
- g_debugState._activeBreakpointTypes |= BREAK_EXPORT;
+ _debugState._breakpoints.push_back(bp);
+ _debugState._activeBreakpointTypes |= BREAK_EXPORT;
return true;
}
@@ -2676,16 +3055,16 @@ bool Console::cmdQuit(int argc, const char **argv) {
if (!scumm_stricmp(argv[1], "game")) {
// Quit gracefully
- script_abort_flag = 1; // Terminate VM
- g_debugState.seeking = kDebugSeekNothing;
- g_debugState.runningStep = 0;
+ _engine->_gamestate->abortScriptProcessing = kAbortQuitGame; // Terminate VM
+ _debugState.seeking = kDebugSeekNothing;
+ _debugState.runningStep = 0;
} else if (!scumm_stricmp(argv[1], "now")) {
// Quit ungracefully
exit(0);
}
- return false;
+ return Cmd_Exit(0, 0);
}
bool Console::cmdAddresses(int argc, const char **argv) {
@@ -2925,8 +3304,71 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV
return 0;
}
-void Console::printList(List *l) {
- reg_t pos = l->first;
+bool Console::parseInteger(const char *argument, int &result) {
+ char *endPtr = 0;
+ int idxLen = strlen(argument);
+ const char *lastChar = argument + idxLen - (idxLen == 0 ? 0 : 1);
+
+ if ((strncmp(argument, "0x", 2) == 0) || (*lastChar == 'h')) {
+ // hexadecimal number
+ result = strtol(argument, &endPtr, 16);
+ if ((*endPtr != 0) && (*endPtr != 'h')) {
+ DebugPrintf("Invalid hexadecimal number '%s'\n", argument);
+ return false;
+ }
+ } else {
+ // decimal number
+ result = strtol(argument, &endPtr, 10);
+ if (*endPtr != 0) {
+ DebugPrintf("Invalid decimal number '%s'\n", argument);
+ return false;
+ }
+ }
+ return true;
+}
+
+void Console::printBasicVarInfo(reg_t variable) {
+ int regType = g_sci->getKernel()->findRegType(variable);
+ int segType = regType;
+ SegManager *segMan = g_sci->getEngineState()->_segMan;
+
+ segType &= SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_NODE | SIG_TYPE_LIST | SIG_TYPE_UNINITIALIZED | SIG_TYPE_ERROR;
+
+ switch (segType) {
+ case SIG_TYPE_INTEGER: {
+ uint16 content = variable.toUint16();
+ if (content >= 10)
+ DebugPrintf(" (%dd)", content);
+ break;
+ }
+ case SIG_TYPE_OBJECT:
+ DebugPrintf(" (object '%s')", segMan->getObjectName(variable));
+ break;
+ case SIG_TYPE_REFERENCE:
+ DebugPrintf(" (reference)");
+ break;
+ case SIG_TYPE_NODE:
+ DebugPrintf(" (node)");
+ break;
+ case SIG_TYPE_LIST:
+ DebugPrintf(" (list)");
+ break;
+ case SIG_TYPE_UNINITIALIZED:
+ DebugPrintf(" (uninitialized)");
+ break;
+ case SIG_TYPE_ERROR:
+ DebugPrintf(" (error)");
+ break;
+ default:
+ DebugPrintf(" (??\?)");
+ }
+
+ if (regType & SIG_IS_INVALID)
+ DebugPrintf(" IS INVALID!");
+}
+
+void Console::printList(List *list) {
+ reg_t pos = list->first;
reg_t my_prev = NULL_REG;
DebugPrintf("\t<\n");
@@ -2953,9 +3395,9 @@ void Console::printList(List *l) {
pos = node->succ;
}
- if (my_prev != l->last)
+ if (my_prev != list->last)
DebugPrintf(" WARNING: Last node was expected to be %04x:%04x, was %04x:%04x!\n",
- PRINT_REG(l->last), PRINT_REG(my_prev));
+ PRINT_REG(list->last), PRINT_REG(my_prev));
DebugPrintf("\t>\n");
}
@@ -3001,8 +3443,8 @@ int Console::printNode(reg_t addr) {
int Console::printObject(reg_t pos) {
EngineState *s = _engine->_gamestate; // for the several defines in this function
- Object *obj = s->_segMan->getObject(pos);
- Object *var_container = obj;
+ const Object *obj = s->_segMan->getObject(pos);
+ const Object *var_container = obj;
uint i;
if (!obj) {
@@ -3014,14 +3456,14 @@ int Console::printObject(reg_t pos) {
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), s->_segMan->getObjectName(pos),
obj->getVarCount(), obj->getMethodCount());
- if (!(obj->getInfoSelector().offset & SCRIPT_INFO_CLASS))
+ if (!obj->isClass())
var_container = s->_segMan->getObject(obj->getSuperClassSelector());
DebugPrintf(" -- member variables:\n");
for (i = 0; (uint)i < obj->getVarCount(); i++) {
DebugPrintf(" ");
if (i < var_container->getVarCount()) {
uint16 varSelector = var_container->getVarSelector(i);
- DebugPrintf("[%03x] %s = ", varSelector, selector_name(s, varSelector));
+ DebugPrintf("[%03x] %s = ", varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str());
} else
DebugPrintf("p#%x = ", i);
@@ -3031,7 +3473,7 @@ int Console::printObject(reg_t pos) {
if (!val.segment)
DebugPrintf(" (%d)", val.offset);
- Object *ref = s->_segMan->getObject(val);
+ const Object *ref = s->_segMan->getObject(val);
if (ref)
DebugPrintf(" (%s)", s->_segMan->getObjectName(val));
@@ -3040,12 +3482,66 @@ int Console::printObject(reg_t pos) {
DebugPrintf(" -- methods:\n");
for (i = 0; i < obj->getMethodCount(); i++) {
reg_t fptr = obj->getFunction(i);
- DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), selector_name(s, obj->getFuncSelector(i)), PRINT_REG(fptr));
+ DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), PRINT_REG(fptr));
}
if (s->_segMan->_heap[pos.segment]->getType() == SEG_TYPE_SCRIPT)
- DebugPrintf("\nOwner script:\t%d\n", s->_segMan->getScript(pos.segment)->_nr);
+ DebugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.segment)->getScriptNumber());
return 0;
}
+void Console::hexDumpReg(const reg_t *data, int len, int regsPerLine, int startOffset, bool isArray) {
+ // reg_t version of Common::hexdump
+ assert(1 <= regsPerLine && regsPerLine <= 8);
+ int i;
+ byte c;
+ int offset = startOffset;
+ while (len >= regsPerLine) {
+ printf("%06x: ", offset);
+ for (i = 0; i < regsPerLine; i++) {
+ printf("%04x:%04x ", PRINT_REG(data[i]));
+ }
+ printf(" |");
+ for (i = 0; i < regsPerLine; i++) {
+ c = data[i].toUint16() & 0xff;
+ if (c < 32 || c >= 127)
+ c = '.';
+ printf("%c", c);
+ c = data[i].toUint16() >> 8;
+ if (c < 32 || c >= 127)
+ c = '.';
+ printf("%c", c);
+ }
+ printf("|\n");
+ data += regsPerLine;
+ len -= regsPerLine;
+ offset += regsPerLine * (isArray ? 1 : 2);
+ }
+
+ if (len <= 0)
+ return;
+
+ printf("%06x: ", offset);
+ for (i = 0; i < regsPerLine; i++) {
+ if (i < len)
+ printf("%04x:%04x ", PRINT_REG(data[i]));
+ else
+ printf(" ");
+ }
+ printf(" |");
+ for (i = 0; i < len; i++) {
+ c = data[i].toUint16() & 0xff;
+ if (c < 32 || c >= 127)
+ c = '.';
+ printf("%c", c);
+ c = data[i].toUint16() >> 8;
+ if (c < 32 || c >= 127)
+ c = '.';
+ printf("%c", c);
+ }
+ for (; i < regsPerLine; i++)
+ printf(" ");
+ printf("|\n");
+}
+
} // End of namespace Sci
diff --git a/engines/sci/console.h b/engines/sci/console.h
index c88795ae26..60599ea783 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -65,6 +65,7 @@ private:
bool cmdSentenceFragments(int argc, const char **argv);
bool cmdParse(int argc, const char **argv);
bool cmdSetParseNodes(int argc, const char **argv);
+ bool cmdSaid(int argc, const char **argv);
// Resources
bool cmdDiskDump(int argc, const char **argv);
bool cmdHexDump(int argc, const char **argv);
@@ -73,6 +74,8 @@ private:
bool cmdResourceTypes(int argc, const char **argv);
bool cmdList(int argc, const char **argv);
bool cmdHexgrep(int argc, const char **argv);
+ bool cmdVerifyScripts(int argc, const char **argv);
+ bool cmdShowInstruments(int argc, const char **argv);
// Game
bool cmdSaveGame(int argc, const char **argv);
bool cmdRestoreGame(int argc, const char **argv);
@@ -116,9 +119,9 @@ private:
bool cmdAddresses(int argc, const char **argv);
bool cmdRegisters(int argc, const char **argv);
bool cmdDissectScript(int argc, const char **argv);
- bool cmdSetAccumulator(int argc, const char **argv);
bool cmdBacktrace(int argc, const char **argv);
- bool cmdStep(int argc, const char **argv);
+ bool cmdTrace(int argc, const char **argv);
+ bool cmdStepOver(int argc, const char **argv);
bool cmdStepEvent(int argc, const char **argv);
bool cmdStepRet(int argc, const char **argv);
bool cmdStepGlobal(int argc, const char **argv);
@@ -127,11 +130,13 @@ private:
bool cmdDisassembleAddress(int argc, const char **argv);
bool cmdSend(int argc, const char **argv);
bool cmdGo(int argc, const char **argv);
+ bool cmdLogKernel(int argc, const char **argv);
// Breakpoints
bool cmdBreakpointList(int argc, const char **argv);
bool cmdBreakpointDelete(int argc, const char **argv);
- bool cmdBreakpointExecMethod(int argc, const char **argv);
- bool cmdBreakpointExecFunction(int argc, const char **argv);
+ bool cmdBreakpointMethod(int argc, const char **argv);
+ bool cmdBreakpointKernel(int argc, const char **argv);
+ bool cmdBreakpointFunction(int argc, const char **argv);
// VM
bool cmdScriptSteps(int argc, const char **argv);
bool cmdVMVarlist(int argc, const char **argv);
@@ -144,15 +149,22 @@ private:
bool cmdViewActiveObject(int argc, const char **argv);
bool cmdViewAccumulatorObject(int argc, const char **argv);
+ bool parseInteger(const char *argument, int &result);
+
+ void printBasicVarInfo(reg_t variable);
+
bool segmentInfo(int nr);
- void printList(List *l);
+ void printList(List *list);
int printNode(reg_t addr);
+ void hexDumpReg(const reg_t *data, int len, int regsPerLine = 4, int startOffset = 0, bool isArray = false);
private:
SciEngine *_engine;
+ DebugState &_debugState;
bool _mouseVisible;
Common::String _videoFile;
int _videoFrameDelay;
+ uint32 _enterTime;
};
} // End of namespace Sci
diff --git a/engines/sci/debug.h b/engines/sci/debug.h
index 8383722956..5cf0e38fbc 100644
--- a/engines/sci/debug.h
+++ b/engines/sci/debug.h
@@ -26,8 +26,8 @@
#ifndef SCI_DEBUG_H
#define SCI_DEBUG_H
+#include "common/list.h"
#include "sci/engine/vm_types.h" // for StackPtr
-#include "sci/engine/vm.h" // for ExecStack
namespace Sci {
@@ -57,8 +57,8 @@ enum DebugSeeking {
kDebugSeekCallk = 1, // Step forward until callk is found
kDebugSeekLevelRet = 2, // Step forward until returned from this level
kDebugSeekSpecialCallk = 3, // Step forward until a /special/ callk is found
- kDebugSeekSO = 4, // Step forward until specified PC (after the send command) and stack depth
- kDebugSeekGlobal = 5 // Step forward until one specified global variable is modified
+ kDebugSeekGlobal = 4, // Step forward until one specified global variable is modified
+ kDebugSeekStepOver = 5 // Step forward until we reach same stack-level again
};
struct DebugState {
@@ -79,7 +79,6 @@ struct DebugState {
extern int g_debug_sleeptime_factor;
extern int g_debug_simulated_key;
extern bool g_debug_track_mouse_clicks;
-extern DebugState g_debugState;
} // End of namespace Sci
diff --git a/engines/sci/decompressor.cpp b/engines/sci/decompressor.cpp
index 84af50b596..96c7f24ef6 100644
--- a/engines/sci/decompressor.cpp
+++ b/engines/sci/decompressor.cpp
@@ -574,15 +574,17 @@ void DecompressorLZW::reorderView(byte *src, byte *dest) {
for (c = 0; c < cel_total; c++)
decodeRLE(&rle_ptr, &pix_ptr, cc_pos[c] + 8, cc_lengths[c]);
- *writer++ = 'P';
- *writer++ = 'A';
- *writer++ = 'L';
+ if (pal_offset) {
+ *writer++ = 'P';
+ *writer++ = 'A';
+ *writer++ = 'L';
- for (c = 0; c < 256; c++)
- *writer++ = c;
+ for (c = 0; c < 256; c++)
+ *writer++ = c;
- seeker -= 4; /* The missing four. Don't ask why. */
- memcpy(writer, seeker, 4*256 + 4);
+ seeker -= 4; /* The missing four. Don't ask why. */
+ memcpy(writer, seeker, 4*256 + 4);
+ }
free(cc_pos);
free(cc_lengths);
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 2a83c8e32a..e330bd5f30 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -36,12 +36,11 @@
#include "sci/engine/script.h"
#include "sci/engine/seg_manager.h"
#include "sci/engine/state.h"
-#include "sci/engine/vm.h" // for convertSierraGameId
namespace Sci {
// Titles of the games
-static const PlainGameDescriptor SciGameTitles[] = {
+static const PlainGameDescriptor s_sciGameTitles[] = {
{"sci", "Sierra SCI Game"},
{"sci-fanmade", "Fanmade SCI Game"},
// === SCI0 games =========================================================
@@ -57,7 +56,7 @@ static const PlainGameDescriptor SciGameTitles[] = {
{"lsl2", "Leisure Suit Larry 2: Goes Looking for Love (in Several Wrong Places)"},
{"lsl3", "Leisure Suit Larry 3: Passionate Patti in Pursuit of the Pulsating Pectorals"},
{"pq2", "Police Quest II: The Vengeance"},
- {"qfg1", "Quest for Glory I: So You Want to Be a Hero"}, // EGA is SCI0, VGA SCI1.1
+ {"qfg1", "Quest for Glory I: So You Want to Be a Hero"},
{"sq3", "Space Quest III: The Pirates of Pestulon"},
// === SCI01 games ========================================================
{"qfg2", "Quest for Glory II: Trial by Fire"},
@@ -90,11 +89,12 @@ static const PlainGameDescriptor SciGameTitles[] = {
{"hoyle4", "Hoyle Classic Card Games"},
{"kq6", "King's Quest VI: Heir Today, Gone Tomorrow"},
{"laurabow2", "Laura Bow 2: The Dagger of Amon Ra"},
+ {"qfg1vga", "Quest for Glory I: So You Want to Be a Hero"},
{"qfg3", "Quest for Glory III: Wages of War"},
{"sq5", "Space Quest V: The Next Mutation"},
{"islandbrain", "The Island of Dr. Brain"},
{"lsl6", "Leisure Suit Larry 6: Shape Up or Slip Out!"},
- {"mothergoose", "Mixed-Up Mother Goose"}, // floppy is SCI1.1, CD SCI2.1
+ {"mothergoose", "Mixed-Up Mother Goose"},
{"pepper", "Pepper's Adventure in Time"},
{"slater", "Slater & Charlie Go Camping"},
// === SCI2 games =========================================================
@@ -106,6 +106,8 @@ static const PlainGameDescriptor SciGameTitles[] = {
// TODO: Inside The Chest/Behind the Developer's Shield
{"kq7", "King's Quest VII: The Princeless Bride"},
// TODO: King's Questions
+ {"lsl6hires", "Leisure Suit Larry 6: Shape Up or Slip Out!"},
+ {"mothergoosehires","Mixed-Up Mother Goose"},
{"phantasmagoria", "Phantasmagoria"},
{"pqswat", "Police Quest: SWAT"},
{"shivers", "Shivers"},
@@ -120,6 +122,237 @@ static const PlainGameDescriptor SciGameTitles[] = {
{0, 0}
};
+struct GameIdStrToEnum {
+ const char *gameidStr;
+ SciGameId gameidEnum;
+};
+
+static const GameIdStrToEnum s_gameIdStrToEnum[] = {
+ { "astrochicken", GID_ASTROCHICKEN },
+ { "camelot", GID_CAMELOT },
+ { "castlebrain", GID_CASTLEBRAIN },
+ { "christmas1988", GID_CHRISTMAS1988 },
+ { "christmas1990", GID_CHRISTMAS1990 },
+ { "christmas1992", GID_CHRISTMAS1992 },
+ { "cnick-kq", GID_CNICK_KQ },
+ { "cnick-laurabow", GID_CNICK_LAURABOW },
+ { "cnick-longbow", GID_CNICK_LONGBOW },
+ { "cnick-lsl", GID_CNICK_LSL },
+ { "cnick-sq", GID_CNICK_SQ },
+ { "ecoquest", GID_ECOQUEST },
+ { "ecoquest2", GID_ECOQUEST2 },
+ { "fairytales", GID_FAIRYTALES },
+ { "freddypharkas", GID_FREDDYPHARKAS },
+ { "funseeker", GID_FUNSEEKER },
+ { "gk1", GID_GK1 },
+ { "gk2", GID_GK2 },
+ { "hoyle1", GID_HOYLE1 },
+ { "hoyle2", GID_HOYLE2 },
+ { "hoyle3", GID_HOYLE3 },
+ { "hoyle4", GID_HOYLE4 },
+ { "iceman", GID_ICEMAN },
+ { "islandbrain", GID_ISLANDBRAIN },
+ { "jones", GID_JONES },
+ { "kq1sci", GID_KQ1 },
+ { "kq4sci", GID_KQ4 },
+ { "kq5", GID_KQ5 },
+ { "kq6", GID_KQ6 },
+ { "kq7", GID_KQ7 },
+ { "laurabow", GID_LAURABOW },
+ { "laurabow2", GID_LAURABOW2 },
+ { "lighthouse", GID_LIGHTHOUSE },
+ { "longbow", GID_LONGBOW },
+ { "lsl1sci", GID_LSL1 },
+ { "lsl2", GID_LSL2 },
+ { "lsl3", GID_LSL3 },
+ { "lsl5", GID_LSL5 },
+ { "lsl6", GID_LSL6 },
+ { "lsl6hires", GID_LSL6HIRES },
+ { "lsl7", GID_LSL7 },
+ { "mothergoose", GID_MOTHERGOOSE },
+ { "mothergoosehires",GID_MOTHERGOOSEHIRES },
+ { "msastrochicken", GID_MSASTROCHICKEN },
+ { "pepper", GID_PEPPER },
+ { "phantasmagoria", GID_PHANTASMAGORIA },
+ { "phantasmagoria2", GID_PHANTASMAGORIA2 },
+ { "pq1sci", GID_PQ1 },
+ { "pq2", GID_PQ2 },
+ { "pq3", GID_PQ3 },
+ { "pq4", GID_PQ4 },
+ { "pqswat", GID_PQSWAT },
+ { "qfg1", GID_QFG1 },
+ { "qfg1vga", GID_QFG1VGA },
+ { "qfg2", GID_QFG2 },
+ { "qfg3", GID_QFG3 },
+ { "qfg4", GID_QFG4 },
+ { "rama", GID_RAMA },
+ { "sci-fanmade", GID_FANMADE }, // FIXME: Do we really need/want this?
+ { "shivers", GID_SHIVERS },
+ { "shivers2", GID_SHIVERS2 },
+ { "slater", GID_SLATER },
+ { "sq1sci", GID_SQ1 },
+ { "sq3", GID_SQ3 },
+ { "sq4", GID_SQ4 },
+ { "sq5", GID_SQ5 },
+ { "sq6", GID_SQ6 },
+ { "torin", GID_TORIN },
+ { NULL, (SciGameId)-1 }
+};
+
+struct OldNewIdTableEntry {
+ const char *oldId;
+ const char *newId;
+ SciVersion version;
+};
+
+static const OldNewIdTableEntry s_oldNewTable[] = {
+ { "arthur", "camelot", SCI_VERSION_NONE },
+ { "brain", "castlebrain", SCI_VERSION_1_MIDDLE }, // Amiga
+ { "brain", "castlebrain", SCI_VERSION_1_LATE },
+ { "demo", "christmas1988", SCI_VERSION_NONE },
+ { "card", "christmas1990", SCI_VERSION_1_EARLY, },
+ { "card", "christmas1992", SCI_VERSION_1_1 },
+ { "RH Budget", "cnick-longbow", SCI_VERSION_NONE },
+ // iceman is the same
+ { "icedemo", "iceman", SCI_VERSION_NONE },
+ // longbow is the same
+ { "eco", "ecoquest", SCI_VERSION_NONE },
+ { "eco2", "ecoquest2", SCI_VERSION_NONE }, // EcoQuest 2 demo
+ { "rain", "ecoquest2", SCI_VERSION_NONE }, // EcoQuest 2 full
+ { "tales", "fairytales", SCI_VERSION_NONE },
+ { "fp", "freddypharkas", SCI_VERSION_NONE },
+ { "emc", "funseeker", SCI_VERSION_NONE },
+ { "gk", "gk1", SCI_VERSION_NONE },
+ // gk2 is the same
+ { "hoyledemo", "hoyle1", SCI_VERSION_NONE },
+ { "cardgames", "hoyle1", SCI_VERSION_NONE },
+ { "solitare", "hoyle2", SCI_VERSION_NONE },
+ // hoyle3 is the same
+ // hoyle4 is the same
+ { "brain", "islandbrain", SCI_VERSION_1_1 },
+ { "demo000", "kq1sci", SCI_VERSION_NONE },
+ { "kq1", "kq1sci", SCI_VERSION_NONE },
+ { "kq4", "kq4sci", SCI_VERSION_NONE },
+ // kq5 is the same
+ // kq6 is the same
+ // kq7 is the same
+ { "mm1", "laurabow", SCI_VERSION_NONE },
+ { "cb1", "laurabow", SCI_VERSION_NONE },
+ { "lb2", "laurabow2", SCI_VERSION_NONE },
+ { "rh", "longbow", SCI_VERSION_NONE },
+ { "ll1", "lsl1sci", SCI_VERSION_NONE },
+ { "lsl1", "lsl1sci", SCI_VERSION_NONE },
+ // lsl2 is the same
+ { "lsl3", "lsl3", SCI_VERSION_NONE },
+ { "ll5", "lsl5", SCI_VERSION_NONE },
+ // lsl5 is the same
+ // lsl6 is the same
+ { "mg", "mothergoose", SCI_VERSION_NONE },
+ { "twisty", "pepper", SCI_VERSION_NONE },
+ { "scary", "phantasmagoria", SCI_VERSION_NONE },
+ // TODO: distinguish the full version of Phantasmagoria from the demo
+ { "pq1", "pq1sci", SCI_VERSION_NONE },
+ { "pq", "pq2", SCI_VERSION_NONE },
+ // pq3 is the same
+ // pq4 is the same
+ { "hq", "qfg1", SCI_VERSION_NONE }, // QFG1 SCI0/EGA
+ { "glory", "qfg1", SCI_VERSION_0_LATE }, // QFG1 SCI0/EGA
+ { "trial", "qfg2", SCI_VERSION_NONE },
+ { "hq2demo", "qfg2", SCI_VERSION_NONE },
+ // rama is the same
+ // TODO: distinguish the full version of rama from the demo
+ { "thegame", "slater", SCI_VERSION_NONE },
+ { "sq1demo", "sq1sci", SCI_VERSION_NONE },
+ { "sq1", "sq1sci", SCI_VERSION_NONE },
+ // sq3 is the same
+ // sq4 is the same
+ // sq5 is the same
+ // sq6 is the same
+ // TODO: distinguish the full version of SQ6 from the demo
+ // torin is the same
+
+
+ // TODO: SCI3 IDs
+
+ { "", "", SCI_VERSION_NONE }
+};
+
+/**
+ * Converts the builtin Sierra game IDs to the ones we use in ScummVM
+ * @param[in] gameId The internal game ID
+ * @param[in] gameFlags The game's flags, which are adjusted accordingly for demos
+ * @return The equivalent ScummVM game id
+ */
+Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, ResourceManager *resMan) {
+ // Convert the id to lower case, so that we match all upper/lower case variants.
+ sierraId.toLowercase();
+
+ // If the game has less than the expected scripts, it's a demo
+ uint32 demoThreshold = 100;
+ // ...but there are some exceptions
+ if (sierraId == "brain" || sierraId == "lsl1" ||
+ sierraId == "mg" || sierraId == "pq" ||
+ sierraId == "jones" ||
+ sierraId == "cardgames" || sierraId == "solitare" ||
+ sierraId == "hoyle3" || sierraId == "hoyle4")
+ demoThreshold = 40;
+ if (sierraId == "fp" || sierraId == "gk" || sierraId == "pq4")
+ demoThreshold = 150;
+
+ Common::ScopedPtr<Common::List<ResourceId> > resources(resMan->listResources(kResourceTypeScript, -1));
+ if (resources->size() < demoThreshold) {
+ *gameFlags |= ADGF_DEMO;
+
+ // Crazy Nick's Picks
+ if (sierraId == "lsl1" && resources->size() == 34)
+ return "cnick-lsl";
+ if (sierraId == "sq4" && resources->size() == 34)
+ return "cnick-sq";
+
+ // TODO: cnick-kq, cnick-laurabow and cnick-longbow (their resources can't be read)
+
+ // Handle Astrochicken 1 (SQ3) and 2 (SQ4)
+ if (sierraId == "sq3" && resources->size() == 20)
+ return "astrochicken";
+ if (sierraId == "sq4")
+ return "msastrochicken";
+ }
+
+ if (sierraId == "torin" && resources->size() == 226) // Torin's Passage demo
+ *gameFlags |= ADGF_DEMO;
+
+ for (const OldNewIdTableEntry *cur = s_oldNewTable; cur->oldId[0]; ++cur) {
+ if (sierraId == cur->oldId) {
+ // Distinguish same IDs from the SCI version
+ if (cur->version != SCI_VERSION_NONE && cur->version != getSciVersion())
+ continue;
+
+ return cur->newId;
+ }
+ }
+
+ if (sierraId == "glory") {
+ // This could either be qfg1 VGA, qfg3 or qfg4 demo (all SCI1.1),
+ // or qfg4 full (SCI2)
+ // qfg1 VGA doesn't have view 1
+ if (!resMan->testResource(ResourceId(kResourceTypeView, 1)))
+ return "qfg1vga";
+
+ // qfg4 full is SCI2
+ if (getSciVersion() == SCI_VERSION_2)
+ return "qfg4";
+
+ // qfg4 demo has less than 50 scripts
+ if (resources->size() < 50)
+ return "qfg4";
+
+ // Otherwise it's qfg3
+ return "qfg3";
+ }
+
+ return sierraId;
+}
+
#include "sci/detection_tables.h"
/**
@@ -147,7 +380,7 @@ static const ADParams detectionParams = {
// Number of bytes to compute MD5 sum for
5000,
// List of all engine targets
- SciGameTitles,
+ s_sciGameTitles,
// Structure for autoupgrading obsolete targets
0,
// Name of single gameid (optional)
@@ -157,7 +390,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class SciMetaEngine : public AdvancedMetaEngine {
@@ -205,50 +442,6 @@ Common::Language charToScummVMLanguage(const char c) {
}
}
-#define READ_UINT16(buf) (!resMan->isSci11Mac() ? READ_LE_UINT16(buf) : READ_BE_UINT16(buf))
-
-// Finds the internal ID of the current game from script 0
-Common::String getSierraGameId(ResourceManager *resMan) {
- Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, 0), false);
- Script *script000 = new Script();
- script000->init(0, resMan);
- script000->mcpyInOut(0, script->data, script->size);
- uint16 curOffset = (getSciVersion() == SCI_VERSION_0_EARLY) ? 2 : 0;
- uint16 objLength = 0;
- int objType = 0;
- int16 exportsOffset = 0;
- Common::String sierraId;
-
- // Now find the export table of the script
- do {
- objType = READ_UINT16(script000->_buf + curOffset);
- if (!objType)
- break;
-
- objLength = READ_UINT16(script000->_buf + curOffset + 2);
- curOffset += 4; // skip header
-
- if (objType == SCI_OBJ_EXPORTS) {
- exportsOffset = READ_UINT16(script000->_buf + curOffset + 2);
- break;
- }
- curOffset += objLength - 4;
- } while (objType != 0 && curOffset < script->size - 2);
-
- // The game object is the first export. Script 0 is always at segment 1
- reg_t gameObj = make_reg(1, exportsOffset);
-
- // TODO: stop using the segment manager and read the object name here
- SegManager *segMan = new SegManager(resMan);
- script_instantiate(resMan, segMan, 0);
- sierraId = segMan->getObjectName(gameObj);
- delete segMan;
-
- delete script000;
-
- return sierraId;
-}
-
const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fslist) const {
bool foundResMap = false;
bool foundRes000 = false;
@@ -269,19 +462,6 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
filename.toLowercase();
if (filename.contains("resource.map") || filename.contains("resmap.00") || filename.contains("Data1")) {
- // HACK: resource.map is located in the same directory as the other resource files,
- // therefore add the directory here, so that the game files can be opened later on
- // We now add the parent directory temporary to our SearchMan so the engine code
- // used in the detection can access all files via Common::File without any problems.
- // In all branches returning from this function, we need to have a call to
- // SearchMan.remove to remove it from the default directory pool again.
- //
- // A proper solution to remove this hack would be to have the code, which is needed
- // for detection, to operate on Stream objects, so they can be easily called from
- // the detection code. This might be easily to achieve through refactoring the
- // code needed for detection.
- assert(!SearchMan.hasArchive("SCI_detection"));
- SearchMan.addDirectory("SCI_detection", file->getParent());
foundResMap = true;
}
@@ -316,8 +496,8 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
filename.contains("patch.005") || filename.contains("bank.001"))
s_fallbackDesc.platform = Common::kPlatformAmiga;
- // The existence of 7.pat indicates a Mac game
- if (filename.contains("7.pat"))
+ // The existence of 7.pat or patch.200 indicates a Mac game
+ if (filename.contains("7.pat") || filename.contains("patch.200"))
s_fallbackDesc.platform = Common::kPlatformMacintosh;
// The data files for Atari ST versions are the same as their DOS counterparts
@@ -325,19 +505,22 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
// If these files aren't found, it can't be SCI
if (!foundResMap && !foundRes000) {
- SearchMan.remove("SCI_detection");
return 0;
}
- ResourceManager *resMan = new ResourceManager(fslist);
+ ResourceManager *resMan = new ResourceManager();
+ assert(resMan);
+ resMan->addAppropriateSources(fslist);
+ resMan->init();
+ // TODO: Add error handling.
+
ViewType gameViews = resMan->getViewType();
// Have we identified the game views? If not, stop here
+ // Can't be SCI (or unsupported SCI views). Pinball Creep by sierra also uses resource.map/resource.000 files
+ // but doesnt share sci format at all, if we dont return 0 here we will detect this game as SCI
if (gameViews == kViewUnknown) {
- SearchMan.remove("SCI_detection");
delete resMan;
- // Can't be SCI (or unsupported SCI views). Pinball Creep by sierra also uses resource.map/resource.000 files
- // but doesnt share sci format at all, if we dont return 0 here we will detect this game as SCI
return 0;
}
@@ -345,7 +528,6 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
// Is SCI32 compiled in? If not, and this is a SCI32 game,
// stop here
if (getSciVersion() >= SCI_VERSION_2) {
- SearchMan.remove("SCI_detection");
delete resMan;
return (const ADGameDescription *)&s_fallbackDesc;
}
@@ -360,7 +542,15 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
s_fallbackDesc.platform = Common::kPlatformAmiga;
// Determine the game id
- Common::String gameId = convertSierraGameId(getSierraGameId(resMan).c_str(), &s_fallbackDesc.flags, resMan);
+ Common::String sierraGameId = resMan->findSierraGameId();
+
+ // If we don't have a game id, the game is not SCI
+ if (sierraGameId.empty()) {
+ delete resMan;
+ return 0;
+ }
+
+ Common::String gameId = convertSierraGameId(sierraGameId, &s_fallbackDesc.flags, resMan);
strncpy(s_fallbackGameIdBuf, gameId.c_str(), sizeof(s_fallbackGameIdBuf) - 1);
s_fallbackGameIdBuf[sizeof(s_fallbackGameIdBuf) - 1] = 0; // Make sure string is NULL terminated
s_fallbackDesc.gameid = s_fallbackGameIdBuf;
@@ -394,7 +584,6 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
}
}
- delete resMan;
// Fill in extras field
if (!strcmp(s_fallbackDesc.gameid, "lsl1sci") ||
@@ -402,24 +591,28 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
!strcmp(s_fallbackDesc.gameid, "sq1sci"))
s_fallbackDesc.extra = "VGA Remake";
- if (!strcmp(s_fallbackDesc.gameid, "qfg1") && !Common::File::exists("resource.001"))
+ if (!strcmp(s_fallbackDesc.gameid, "qfg1vga") && getSciVersion() == SCI_VERSION_1_1)
s_fallbackDesc.extra = "VGA Remake";
// Add "demo" to the description for demos
if (s_fallbackDesc.flags & ADGF_DEMO)
s_fallbackDesc.extra = "demo";
- SearchMan.remove("SCI_detection");
+ delete resMan;
return (const ADGameDescription *)&s_fallbackDesc;
}
-bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
- const ADGameDescription *desc = (const ADGameDescription *)gd;
-
- *engine = new SciEngine(syst, desc);
+bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const GameIdStrToEnum *g = s_gameIdStrToEnum;
+ for (; g->gameidStr; ++g) {
+ if (0 == strcmp(desc->gameid, g->gameidStr)) {
+ *engine = new SciEngine(syst, desc, g->gameidEnum);
+ return true;
+ }
+ }
- return true;
+ return false;
}
bool SciMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -434,9 +627,16 @@ bool SciMetaEngine::hasFeature(MetaEngineFeature f) const {
bool SciEngine::hasFeature(EngineFeature f) const {
return
- //(f == kSupportsRTL) ||
- (f == kSupportsLoadingDuringRuntime);
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime); // ||
//(f == kSupportsSavingDuringRuntime);
+ // We can't allow saving through ScummVM menu, because
+ // a) lots of games don't like saving everywhere (e.g. castle of dr. brain)
+ // b) some games even dont allow saving in certain rooms (e.g. lsl6)
+ // c) somehow some games even get mad when doing this (execstackbase was 1 all of a sudden in lsl3)
+ // d) for sci0/sci01 games we should at least wait till status bar got drawn, although this may not be enough
+ // we can't make sure that the scripts are fine with us saving at a specific location, doing so may work sometimes
+ // and some other times it won't work.
}
SaveStateList SciMetaEngine::listSaves(const char *target) const {
@@ -557,7 +757,7 @@ Common::Error SciEngine::saveGameState(int slot, const char *desc) {
return Common::kWritingFailed;
}
- if (gamestate_save(_gamestate, out, desc, version)) {
+ if (!gamestate_save(_gamestate, out, desc, version)) {
warning("Saving the game state to '%s' failed", fileName.c_str());
return Common::kWritingFailed;
} else {
@@ -573,11 +773,11 @@ Common::Error SciEngine::saveGameState(int slot, const char *desc) {
}
bool SciEngine::canLoadGameStateCurrently() {
- return !_gamestate->execution_stack_base;
+ return !_gamestate->executionStackBase;
}
bool SciEngine::canSaveGameStateCurrently() {
- return !_gamestate->execution_stack_base;
+ return !_gamestate->executionStackBase;
}
} // End of namespace Sci
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index dba4d879aa..0614eff6e6 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -32,7 +32,7 @@ namespace Sci {
{"sci-fanmade", name, { \
{"resource.map", 0, resMapMd5, resMapSize}, \
{"resource.001", 0, resMd5, resSize}, \
- {NULL, 0, NULL, 0}}, lang, Common::kPlatformPC, 0, GUIO_NOSPEECH \
+ AD_LISTEND}, lang, Common::kPlatformPC, 0, GUIO_NOSPEECH \
}
#define FANMADE(name, resMapMd5, resMapSize, resMd5, resSize) FANMADE_L(name, resMapMd5, resMapSize, resMd5, resSize, Common::EN_ANY)
@@ -47,7 +47,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"astrochicken", "", {
{"resource.map", 0, "f3d1be7752d30ba60614533d531e2e98", 474},
{"resource.001", 0, "6fd05926c2199af0af6f72f90d0d7260", 126895},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Castle of Dr. Brain - English Amiga (from www.back2roots.org)
@@ -59,10 +59,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "3fb02ce493f6eacdcc3713851024f80e", 559540},
{"resource.002", 0, "d226d7d3b4f77c4a566913fc310487fc", 792380},
{"resource.003", 0, "d226d7d3b4f77c4a566913fc310487fc", 464348},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
- // Castle of Dr. Brain - German Amiga (from www.back2roots.org)
+ // Castle of Dr. Brain - German Amiga (from www.back2roots.org, also includes english language)
// Executable scanning reports "1.005.001"
// SCI interpreter version 1.000.510
{"castlebrain", "", {
@@ -71,8 +71,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "4e0836fadc324316c1a418125709ba45", 569057},
{"resource.002", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 826309},
{"resource.003", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 493638},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Castle of Dr. Brain - English DOS Non-Interactive Demo
// SCI interpreter version 1.000.005
@@ -80,9 +80,22 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "467bb5e3224bb54640c3280032aebff5", 633},
{"resource.000", 0, "9780f040d58182994e22d2e34fab85b0", 67367},
{"resource.001", 0, "2af49dbd8f2e1db4ab09f9310dc91259", 570553},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
+ // Castle of Dr. Brain - English DOS Floppy EGA (from omer_mor, bug report #3035349)
+ {"castlebrain", "EGA", {
+ {"resource.map", 0, "88d106f945f7fd9d1aeda961cfec38a9", 2646},
+ {"resource.000", 0, "6e125f4ce3f4f5c35f2617c7b66c6e21", 25325},
+ {"resource.001", 0, "1d806162f6d3cfbe3c0135414efe6f88", 99931},
+ {"resource.002", 0, "6a41a0eb5237778427dddf92ae07cf9b", 294772},
+ {"resource.003", 0, "0c6ab4efb3be4d991ae9762e19f17c92", 306378},
+ {"resource.004", 0, "5e7b90949422de005f80285979972e43", 292423},
+ {"resource.005", 0, "8a5ed3ba96e2eaf18e36fedfaab89419", 297838},
+ {"resource.006", 0, "dceed92e709cad1bd9582809a235b0a0", 266682},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
// Castle of Dr. Brain - English DOS Floppy (from jvprat)
// Executable scanning reports "1.000.044", Floppy label reports "1.0, 10.30.91", VERSION file reports "1.000"
// SCI interpreter version 1.000.510
@@ -91,7 +104,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 346731},
{"resource.001", 0, "d2f5a1be74ed963fa849a76892be5290", 794832},
{"resource.002", 0, "c0c29c51af66d65cb53f49e785a2d978", 1280907},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Castle of Dr. Brain - English DOS Floppy 1.1
@@ -100,24 +113,39 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 347071},
{"resource.001", 0, "13e81e1839cd7b216d2bb5615c1ca160", 796776},
{"resource.002", 0, "930e416bec196b9703a331d81b3d66f2", 1283812},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Castle of Dr. Brain - Spanish DOS
+ // Castle of Dr. Brain - English DOS Floppy 1.000
+ // Reported by graxer in bug report #3037942
+ {"castlebrain", "", {
+ {"resource.map", 0, "453daa935535cef68d19704c2b1b78a2", 2649},
+ {"resource.000", 0, "6e125f4ce3f4f5c35f2617c7b66c6e21", 25929},
+ {"resource.001", 0, "4891faa2f6594c622e482f0ddce24fb4", 99404},
+ {"resource.002", 0, "aebb56d5d005557ca0d122a03aa85386", 322459},
+ {"resource.003", 0, "278ec1e6132c7be844d433dd23beb318", 335156},
+ {"resource.004", 0, "fca1c3f2be660185206f004bda09f4fb", 333549},
+ {"resource.005", 0, "9294e55da1e83708ad3104b2a3963e18", 327537},
+ {"resource.006", 0, "1d778a0c65cac9ddbab65495e50a94ee", 335281},
+ {"resource.007", 0, "063bb8ce4157c778cf30d1c912c006f1", 335631},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
+ // Castle of Dr. Brain - Spanish DOS (also includes english language)
// SCI interpreter version 1.000.510
{"castlebrain", "", {
{"resource.map", 0, "5738c163e014bbe046474de009020b82", 2727},
{"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 1197694},
{"resource.001", 0, "735be4e58957180cfc807d5e18fdffcd", 1433302},
- {NULL, 0, NULL, 0}},
- Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Christmas Card 1988 - English DOS
// SCI interpreter version 0.000.294
{"christmas1988", "", {
{"resource.map", 0, "39485580d34a72997f3d5b3aba4d24f1", 426},
{"resource.001", 0, "11391434f41c834090d7a1e9488ce936", 129739},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Christmas Card 1990: The Seasoned Professional - English DOS (16 Colors)
@@ -125,7 +153,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"christmas1990", "16 Colors", {
{"resource.map", 0, "8f656714a05b94423ac6eb10ee8797d0", 600},
{"resource.001", 0, "acde93e58fca4f7a2a5a220558a94aa8", 272629},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Christmas Card 1990: The Seasoned Professional - English DOS (256 Colors)
@@ -133,7 +161,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"christmas1990", "256 Colors", {
{"resource.map", 0, "44b8f45b841b9b5e17e939a35e443988", 600},
{"resource.001", 0, "acde93e58fca4f7a2a5a220558a94aa8", 335362},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Christmas Card 1992 - English DOS
@@ -141,7 +169,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"christmas1992", "", {
{"resource.map", 0, "f1f8c8a8443f523422af70b4ec85b71c", 318},
{"resource.000", 0, "62fb9256f8e7e6e65a6875efdb7939ac", 203396},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Codename: Iceman - English Amiga (from www.back2roots.org)
@@ -155,7 +183,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "d97a96f1ab91b41cf46a02cc89b0a04e", 619219},
{"resource.004", 0, "8613c45fc771d658e5a505b9a4a54f31", 713382},
{"resource.005", 0, "605b67a9ef199a9bb015745e7c004cf4", 478384},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Codename: Iceman - English DOS Non-Interactive Demo
@@ -163,7 +191,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"iceman", "Demo", {
{"resource.map", 0, "782974f29d8a824782d2d4aea39964e3", 1056},
{"resource.001", 0, "d4b75e280d1c3a97cfef1b0bebff387c", 573647},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Codename: Iceman - English DOS (from jvprat)
@@ -176,7 +204,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "36670a917550757d57df84c96cf9e6d9", 566549},
{"resource.003", 0, "d97a96f1ab91b41cf46a02cc89b0a04e", 624303},
{"resource.004", 0, "8613c45fc771d658e5a505b9a4a54f31", 670883},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Codename: Iceman - English DOS (from FRG)
@@ -188,7 +216,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "250b859381ebf2bf8922bd99683b0cc1", 566464},
{"resource.003", 0, "dc7c5280e7acfaffe6ef2a6c963c5f94", 622118},
{"resource.004", 0, "64f342463f6f35ba71b3509ef696ae3f", 669188},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Codename: Iceman - English DOS 1.023 (from abevi, bug report #2612718)
@@ -202,7 +230,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "dc7c5280e7acfaffe6ef2a6c963c5f94", 330653},
{"resource.006", 0, "08050329aa113a9f14ed99cbfe3536ec", 232942},
{"resource.007", 0, "64f342463f6f35ba71b3509ef696ae3f", 267702},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Conquests of Camelot - English Amiga (from www.back2roots.org)
@@ -217,7 +245,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "6821dc97cf643ba521a4e840dda3c58b", 647410},
{"resource.005", 0, "c6e551bdc24f0acc193159038d4ca767", 605882},
{"resource.006", 0, "8f880a536908ab496bbc552f7f5c3738", 585255},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Conquests of Camelot - English DOS Non-Interactive Demo
@@ -225,7 +253,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"camelot", "Demo", {
{"resource.map", 0, "f4cd75c15be75e04cdca3acda2c0b0ea", 468},
{"resource.001", 0, "4930708722f34bfbaa4945fb08f55f61", 232523},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Conquests of Camelot - English DOS (from jvprat)
@@ -237,7 +265,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "8e1a3a8c588007404b532b8dfacc1460", 722250},
{"resource.003", 0, "8e1a3a8c588007404b532b8dfacc1460", 723712},
{"resource.004", 0, "8e1a3a8c588007404b532b8dfacc1460", 729143},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Conquests of Camelot - English DOS
@@ -251,7 +279,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "8e1a3a8c588007404b532b8dfacc1460", 345734},
{"resource.006", 0, "8e1a3a8c588007404b532b8dfacc1460", 332446},
{"resource.007", 0, "8e1a3a8c588007404b532b8dfacc1460", 358182},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Conquests of the Longbow - English Amiga (from www.back2roots.org)
@@ -266,7 +294,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "d1038c75d85a6650d48e07d174a6a913", 838175},
{"resource.005", 0, "1c3804e56b114028c5873a35c2f06d13", 653002},
{"resource.006", 0, "f9487732289a4f4966b4e34eea413325", 842817},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Conquests of the Longbow - English DOS
@@ -280,7 +308,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1064637},
{"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1154950},
{"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1042966},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Conquests of the Longbow - English DOS Floppy (from jvprat)
@@ -294,7 +322,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "1867136d01ece57b531032d466910522", 823686},
{"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1261462},
{"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284720},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Conquests of the Longbow - English DOS
@@ -307,7 +335,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "1867136d01ece57b531032d466910522", 823610},
{"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1260237},
{"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284609},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Conquests of the Longbow EGA - English DOS
@@ -321,18 +349,17 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "b7bb35c027bb424ecefcd122768e5e60", 705631},
{"resource.005", 0, "58942b1aa6d6ffeb66e9f8897fd4435f", 469243},
{"resource.006", 0, "8c767b3939add63d11274065e46aad04", 713158},
- {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Conquests of the Longbow - English DOS Non-Interactive Demo
// SCI interpreter version 1.000.510
{"longbow", "Demo", {
{"resource.map", 0, "cbc5cb73341de1bff1b1e20a640af220", 588},
{"resource.001", 0, "f05a20cc07eee85da8e999d0ac0f596b", 869916},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
- // Conquests of the Longbow - German DOS (suplied by markcoolio in bug report #2727681)
+ // Conquests of the Longbow - German DOS (suplied by markcoolio in bug report #2727681, also includes english language)
// SCI interpreter version 1.000.510
{"longbow", "", {
{"resource.map", 0, "7376b7a07f8bd3a8ab8d67595d3f5b51", 6285},
@@ -343,8 +370,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1101869},
{"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1176914},
{"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1123585},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Eco Quest - English DOS Non-Interactive Demo (from FRG)
// Executable scanning reports "x.yyy.zzz"
@@ -352,16 +379,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ecoquest", "Demo", {
{"resource.map", 0, "c819e171359b7c95f4c13b846d5c034e", 873},
{"resource.001", 0, "baf9393a9bfa73098adb501e5bc5487b", 657518},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Eco Quest - English DOS CD 1.1
// SCI interpreter version 1.001.064
{"ecoquest", "CD", {
{"resource.map", 0, "a4b73d5d2b55bdb6e44345e99c8fbdd0", 4804},
{"resource.000", 0, "d908dbef56816ac6c60dd145fdeafb2b", 3536046},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// Eco Quest - English DOS Floppy
@@ -372,7 +398,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "96d4435d24c01f1c1675e46457604c5f", 1413719},
{"resource.002", 0, "28fe9b4f0567e71feb198bc9f3a2c605", 1241816},
{"resource.003", 0, "f3146df0ad4297f5ce35aa8c4753bf6c", 586832},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Eco Quest - English DOS Floppy
@@ -383,10 +409,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "2fed7451bca81b0c891eed1a956f2263", 1212161},
{"resource.002", 0, "323b3b12f43d53f27d259beb225f0aa7", 1129316},
{"resource.003", 0, "83ac03e4bddb2c1ac2d36d2a587d0536", 1145616},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Eco Quest - German DOS Floppy (supplied by markcoolio in bug report #2723744)
+ // Eco Quest - German DOS Floppy (supplied by markcoolio in bug report #2723744, also includes english language)
// SCI interpreter version 1.000.510
{"ecoquest", "Floppy", {
{"resource.map", 0, "7a9b43bf27dc000ac8559ecbe824b659", 4395},
@@ -394,10 +420,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "2fed7451bca81b0c891eed1a956f2263", 1212060},
{"resource.002", 0, "02d7d0411f7903aacb3bc8b0f8ca8a9a", 1202581},
{"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1175835},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Eco Quest - Spanish DOS Floppy (from jvprat)
+ // Eco Quest - Spanish DOS Floppy (from jvprat, also includes english language)
// Executable scanning reports "1.ECO.013", VERSION file reports "1.000, 11.12.92"
// SCI interpreter version 1.000.510
{"ecoquest", "Floppy", {
@@ -406,10 +432,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "2fed7451bca81b0c891eed1a956f2263", 1212060},
{"resource.002", 0, "2d21a1d2dcbffa551552e3e0725d2284", 1186033},
{"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1174993},
- {NULL, 0, NULL, 0}},
- Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Eco Quest - French DOS Floppy (from Strangerke)
+ // Eco Quest - French DOS Floppy (from Strangerke, also includes english language)
// SCI interpreter version 1.ECO.013
{"ecoquest", "Floppy", {
{"resource.map", 0, "67742945cd59b896d9f22a549f605217", 4407},
@@ -417,15 +443,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "fc7fba54b6bb88fd7e9c229636599aa9", 1205841},
{"resource.002", 0, "b836c6ee9de67d814ac5d1b05f5b9858", 1173872},
{"resource.003", 0, "f8f767f9d6351432621c6e54c1b2ba8c", 1141520},
- {NULL, 0, NULL, 0}},
- Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Eco Quest 2 - English DOS Non-Interactive Demo
// SCI interpreter version 1.001.055
{"ecoquest2", "Demo", {
{"resource.map", 0, "607cfa0d8a03b7d348c06ee727e3d939", 1321},
{"resource.000", 0, "dd6f614c43c029f063e93cd243af90a4", 525992},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Eco Quest 2 - English DOS Floppy (supplied by markcoolio in bug report #2723761)
@@ -433,7 +459,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ecoquest2", "Floppy", {
{"resource.map", 0, "28fb7b6abb9fc1cb8882d7c2e701b63f", 5658},
{"resource.000", 0, "cc1d17e5637528dbe4a812699e1cbfc6", 4208192},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Eco Quest 2 - French DOS Floppy (from Strangerke)
@@ -441,7 +467,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ecoquest2", "Floppy", {
{"resource.map", 0, "c22ab8b33c339c138b6b1697b77b9e79", 5588},
{"resource.000", 0, "1c4093f7248240329121fdf8c0d59152", 4231946},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Freddy Pharkas - English DOS demo (from FRG)
@@ -449,7 +475,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"freddypharkas", "Demo", {
{"resource.map", 0, "97aa9fcfe84c9993a64debd28c32393a", 1909},
{"resource.000", 0, "5ea8e7a3ea10cce6efd5c106dc62fd8c", 867724},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Freddy Pharkas - English CD (from FRG)
@@ -457,7 +483,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"freddypharkas", "CD", {
{"resource.map", 0, "d46b282f228a67ba13bd4b4009e95f8f", 6058},
{"resource.000", 0, "ee3c64ffff0ba9fb08bea2624631c598", 5490246},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// Freddy Pharkas - English DOS Floppy (updated information from markcoolio in bug reports #2723773 and #2724720)
@@ -467,7 +493,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a32674e7fbf7b213b4a066c8037f16b6", 5816},
{"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230},
{"resource.msg", 0, "554f65315d851184f6e38211489fdd8f", -1},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Freddy Pharkas - Windows (supplied by abevi in bug report #2612718)
@@ -476,7 +502,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"freddypharkas", "Floppy", {
{"resource.map", 0, "a32674e7fbf7b213b4a066c8037f16b6", 5816},
{"resource.000", 0, "fed4808fdb72486908ac7ad0044b14d8", 5233230},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
// Freddy Pharkas - German DOS Floppy (from Tobis87, updated information from markcoolio in bug reports #2723772 and #2724720)
@@ -486,7 +512,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a32674e7fbf7b213b4a066c8037f16b6", 5816},
{"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230},
{"resource.msg", 0, "304b5a5781800affd2235152a5794fa8", -1},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Freddy Pharkas - Spanish DOS (from jvprat)
@@ -499,7 +525,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "419dbd5366f702b4123dedbbb0cffaae", 1456640},
{"resource.003", 0, "05acdc256c742e79c50b9fe7ec2cc898", 863310},
{"resource.msg", 0, "45b5bf74933ac3727e4cc844446dc052", 796156},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE },
// Freddy Pharkas - Spanish DOS (from jvprat)
@@ -509,7 +535,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a32674e7fbf7b213b4a066c8037f16b6", 5816},
{"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230},
{"resource.msg", 0, "45b5bf74933ac3727e4cc844446dc052", 796156},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Freddy Pharkas - English DOS CD Demo
@@ -517,7 +543,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"freddypharkas", "CD Demo", {
{"resource.map", 0, "a62a7eae85dd1e6b07f39662b278437e", 1918},
{"resource.000", 0, "4962a3c4dd44e36e78ea4a7a374c2220", 957382},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE },
// Fun Seeker's Guide - English DOS
@@ -525,7 +551,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"funseeker", "", {
{"resource.map", 0, "7ee6859ef74314f6d91938c3595348a9", 282},
{"resource.001", 0, "f1e680095424e31f7fae1255d36bacba", 40692},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Gabriel Knight - English DOS CD Demo
@@ -533,7 +559,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"gk1", "CD Demo", {
{"resource.map", 0, "39645952ae0ed8072c7e838f31b75464", 2490},
{"resource.000", 0, "eb3ed7477ca4110813fe1fcf35928561", 1718450},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE },
#ifdef ENABLE_SCI32
@@ -542,16 +568,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"gk1", "", {
{"resource.map", 0, "372d059f75856afa6d73dd84cbb8913d", 10783},
{"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Gabriel Knight - English DOS Floppy (supplied my markcoolio in bug report #2723777)
// SCI interpreter version 2.000.000
{"gk1", "", {
{"resource.map", 0, "65e8c14092e4c9b3b3538b7602c8c5ec", 10783},
{"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Gabriel Knight - German DOS Floppy (supplied my markcoolio in bug report #2723775)
@@ -559,7 +584,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"gk1", "", {
{"resource.map", 0, "ad6508b0296b25c07b1f58828dc33696", 10789},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13077029},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Gabriel Knight - English DOS CD (from jvprat)
@@ -567,7 +592,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"gk1", "CD", {
{"resource.map", 0, "372d059f75856afa6d73dd84cbb8913d", 10996},
{"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 12581736},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// Gabriel Knight - German DOS CD (from Tobis87)
@@ -575,7 +600,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"gk1", "CD", {
{"resource.map", 0, "a7d3e55114c65647310373cb390815ba", 11392},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13400497},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NONE },
// Gabriel Knight - Spanish DOS CD (from jvprat)
@@ -583,7 +608,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"gk1", "CD", {
{"resource.map", 0, "7cb6e9bba15b544ec7a635c45bde9953", 11404},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13381599},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE },
// Gabriel Knight - French DOS CD (from Hkz)
@@ -591,7 +616,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"gk1", "CD", {
{"resource.map", 0, "55f909ba93a2515042a08d8a2da8414e", 11392},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13325145},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NONE },
// Gabriel Knight - English Windows CD (from jvprat)
@@ -599,7 +624,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"gk1", "CD", {
{"resource.map", 0, "372d059f75856afa6d73dd84cbb8913d", 10996},
{"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 12581736},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NONE },
// Gabriel Knight - German Windows CD (from Tobis87)
@@ -607,7 +632,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"gk1", "CD", {
{"resource.map", 0, "a7d3e55114c65647310373cb390815ba", 11392},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13400497},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::DE_DEU, Common::kPlatformWindows, 0, GUIO_NONE },
// Gabriel Knight - Spanish Windows CD (from jvprat)
@@ -615,7 +640,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"gk1", "CD", {
{"resource.map", 0, "7cb6e9bba15b544ec7a635c45bde9953", 11404},
{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13381599},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::ES_ESP, Common::kPlatformWindows, 0, GUIO_NONE },
// Gabriel Knight 2 - English Windows Non-Interactive Demo
@@ -623,7 +648,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"gk2", "Demo", {
{"resource.map", 0, "e0effce11c4908f4b91838741716c83d", 1351},
{"resource.000", 0, "d04cfc7f04b6f74d13025378be49ec2b", 4640330},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Gabriel Knight 2 - English DOS (from jvprat)
@@ -641,7 +666,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.005", 0, "14b62d4a3bddee57a03cb1495a798a0f", 38075705},
{"resmap.006", 0, "ce9359037277b7d7976da185c2fa0aad", 2977},
{"ressci.006", 0, "8e44e03890205a7be12f45aaba9644b4", 60659424},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Gabriel Knight 2 - French DOS (6-CDs Sierra Originals reedition)
@@ -659,7 +684,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.005", 0, "1eb5a72744799f5a5518543f5b4c3c79", 37882126},
{"resmap.006", 0, "11b2e722170b8c93fdaa5428e2c7676f", 3001},
{"ressci.006", 0, "4037d941aec39d2e654e20960429aefc", 60568486},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::FR_FRA, Common::kPlatformPC, 0,
GUIO_NOSPEECH },
@@ -672,7 +697,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 162783},
{"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 342309},
{"resource.003", 0, "e0dd44069a62a463fd124974b915f10d", 328912},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Hoyle 1 - English DOS (supplied by merkur in bug report #2719227)
@@ -680,7 +705,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"hoyle1", "", {
{"resource.map", 0, "1034a218943d12f1f36e753fa10c95b8", 4386},
{"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 518308},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
#if 0 // TODO: unknown if these files are corrupt
@@ -690,7 +715,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "2a72b1aba65fa6e339370eb86d8601d1", 5166},
{"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 218755},
{"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 439502},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
#endif
@@ -700,7 +725,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "4f894d203f64aa23d9ff64d30ae36926", 2100},
{"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 98138},
{"resource.002", 0, "8f2dd70abe01112eca464cda818b5eb6", 196631},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Hoyle 2 - English Amiga (from www.back2roots.org)
@@ -709,9 +734,16 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"hoyle2", "", {
{"resource.map", 0, "62ed48d20c580e5a98f102f7cd93706a", 1356},
{"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 222704},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
+
+ // Hoyle 2 - English Macintosh
+ // Executable scanning reports "x.yyy.zzz"
+ {"hoyle2", "", {
+ {"resource.map", 0, "1af1d3aa3cf564f93477c9f87e53f495", 1728},
+ {"resource.001", 0, "b73b8131669d69d41a326415e4519138", 482882},
{NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH
- },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_NOSPEECH },
#if 0 // TODO: unknown if these files are corrupt
// Hoyle 3 - English Amiga (from www.back2roots.org)
@@ -721,7 +753,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "f1f158e428398cb87fc41fb4aa8c2119", 2088},
{"resource.000", 0, "595b6039ea1356e7f96a52c58eedcf22", 355791},
{"resource.001", 0, "143df8aef214a2db34c2d48190742012", 632273},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
#endif
@@ -731,7 +763,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"hoyle3", "Demo", {
{"resource.map", 0, "0d06cacc87dc21a08cd017e73036f905", 735},
{"resource.001", 0, "24db2bccda0a3c43ac4a7b5edb116c7e", 797678},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Hoyle 3 - English DOS Floppy (from jvprat)
@@ -741,7 +773,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "7216a2972f9c595c45ab314941628e43", 2247},
{"resource.000", 0, "6ef28cac094dcd97fdb461662ead6f92", 541845},
{"resource.001", 0, "0a98a268ee99b92c233a0d7187c1f0fa", 845795},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Hoyle 3 - English DOS Floppy 1.0 (supplied by abevi in bug report #2612718)
@@ -749,31 +781,72 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "1728af1f6a85938c3522e64449e76ca1", 2205},
{"resource.000", 0, "6ef28cac094dcd97fdb461662ead6f92", 319905},
{"resource.001", 0, "0a98a268ee99b92c233a0d7187c1f0fa", 526438},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Hoyle 4 - English DOS Demo
+ {"hoyle4", "Demo", {
+ {"resource.map", 0, "60f764020a6b788bbbe415dbc2ccb9f3", 931},
+ {"resource.000", 0, "5fe3670e3ddcd4f85c10013b5453141a", 615522},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
+
+ // Hoyle 4 - English DOS Demo
// SCI interpreter version 1.001.200 (just a guess)
+ // Does anyone have this version? -clone2727
{"hoyle4", "Demo", {
{"resource.map", 0, "662087cb383e52e3cc4ae7ecb10e20aa", 938},
{"resource.000", 0, "24c10844792c54d476d272213cbac300", 675252},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
- // Jones in the Fast Lane - English DOS
+ // Hoyle 4 (Hoyle Classic Card Games) - English DOS/Win
+ // SCI1.1
+ // Supplied by abevi in bug report #3039291
+ {"hoyle4", "Demo", {
+ {"resource.map", 0, "2b577c975cc8d8d43f61b6a756129fe3", 4352},
+ {"resource.000", 0, "43e2c15ce436aab611a462ad0603e12d", 2000132},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
+ // Jones in the Fast Lane EGA - English DOS
+ // SCI interpreter version 1.000.172 (not 100% sure FIXME)
+ {"jones", "EGA", {
+ {"resource.map", 0, "be4cf9e8c1e253623ef35ae3b8a1d998", 1800},
+ {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 202105},
+ {"resource.002", 0, "b86daa3ba2784d1502da881eedb80d9b", 341771},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
+ // Jones in the Fast Lane EGA - English DOS (supplied by EddyDrama in bug report #3038761)
+ {"jones", "EGA", {
+ {"resource.map", 0, "8e92cf319180cc8b5b87b2ce93a4fe22", 1602},
+ {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 511528},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
+ // Jones in the Fast Lane VGA - English DOS
// SCI interpreter version 1.000.172
{"jones", "", {
{"resource.map", 0, "65cbe19b36fffc71c8e7b2686bd49ad7", 1800},
{"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 313476},
{"resource.002", 0, "b86daa3ba2784d1502da881eedb80d9b", 719747},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
+ // Jones in the Fast Lane VGA - English DOS (supplied by omer_mor in bug report #3037054)
+ // VERSION file reports "1.000.060"
+ {"jones", "", {
+ {"resource.map", 0, "db175ab494ab0666f19ab8f2597a8e49", 1602},
+ {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 994487},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Jones in the Fast Lane - English DOS CD
{"jones", "CD", {
{"resource.map", 0, "459f5b04467bc2107aec02f5c4b71b37", 4878},
{"resource.001", 0, "3876da2ce16fb7dea2f5d943d946fa84", 1652150},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO_NONE },
// King's Quest 1 SCI Remake - English Amiga (from www.back2roots.org)
@@ -785,7 +858,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "9ae2a13708d691cd42f9129173c4b39d", 795123},
{"resource.003", 0, "9ae2a13708d691cd42f9129173c4b39d", 763224},
{"resource.004", 0, "9ae2a13708d691cd42f9129173c4b39d", 820443},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// King's Quest 1 SCI Remake - English DOS Non-Interactive Demo
@@ -793,7 +866,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq1sci", "SCI Remake Demo", {
{"resource.map", 0, "59b13619078bd47011421468959ee5d4", 954},
{"resource.001", 0, "4cfb9040db152868f7cb6a1e8151c910", 296555},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// King's Quest 1 SCI Remake - English DOS (from the King's Quest Collection)
@@ -804,7 +877,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "fed9e0072ffd511d248674e60dee2099", 555439},
{"resource.002", 0, "fed9e0072ffd511d248674e60dee2099", 714062},
{"resource.003", 0, "fed9e0072ffd511d248674e60dee2099", 717478},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// King's Quest 4 - English Amiga (from www.back2roots.org)
@@ -817,7 +890,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "fb351106ec865fad9af5d78bd6b8e3cb", 663629},
{"resource.003", 0, "fd16c9c223f7dc5b65f06447615224ff", 683016},
{"resource.004", 0, "3fac034c7d130e055d05bc43a1f8d5f8", 549993},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// King's Quest 4 - English DOS Non-Interactive Demo
@@ -825,7 +898,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq4sci", "Demo", {
{"resource.map", 0, "992ac7cc31d3717fe53818a9bb6d1dae", 594},
{"resource.001", 0, "143e1c14f15ad0fbfc714f648a65f661", 205330},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// King's Quest 4 - English DOS (from the King's Quest Collection)
@@ -837,7 +910,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "77615c595388acf3d1df8e107bfb6b52", 536573},
{"resource.003", 0, "77615c595388acf3d1df8e107bfb6b52", 707591},
{"resource.004", 0, "77615c595388acf3d1df8e107bfb6b52", 479562},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// King's Quest 4 - English DOS
@@ -851,7 +924,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "851a62d00972dc4002f472cc0d84e71d", 321593},
{"resource.006", 0, "851a62d00972dc4002f472cc0d84e71d", 333777},
{"resource.007", 0, "851a62d00972dc4002f472cc0d84e71d", 341038},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// King's Quest 4 - English DOS
@@ -865,7 +938,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "0c8566848a76eea19a6d6220914030a7", 325102},
{"resource.006", 0, "0c8566848a76eea19a6d6220914030a7", 337288},
{"resource.007", 0, "0c8566848a76eea19a6d6220914030a7", 343882},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// King's Quest 5 - English Amiga (from www.back2roots.org)
@@ -881,10 +954,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "31a5487f4d942e6354d5be49d59707c9", 834146},
{"resource.006", 0, "26c0c25399b6715fec03fc3e12544fe3", 823048},
{"resource.007", 0, "b914b5901e786327213e779725d30dd1", 778772},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
- // King's Quest 5 - German Amiga
+ // King's Quest 5 - German Amiga (also includes english language)
// Executable scanning reports "1.004.024"
// SCI interpreter version 1.000.060
{"kq5", "", {
@@ -897,10 +970,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "5aa3d59968b569cd509dde00d4eb8751", 754201},
{"resource.006", 0, "56546b20db11a4836f900efa6d3a3e74", 672099},
{"resource.007", 0, "56546b20db11a4836f900efa6d3a3e74", 794194},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // King's Quest 5 - Italian Amiga
+ // King's Quest 5 - Italian Amiga (also includes english language)
// Executable scanning reports "1.004.024"
// SCI interpreter version 1.000.060
{"kq5", "", {
@@ -913,8 +986,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "de3c5c09e350fded36ca354998c2194d", 754784},
{"resource.006", 0, "11cb750f5f816445ad0f4b9f50a4f59a", 672527},
{"resource.007", 0, "11cb750f5f816445ad0f4b9f50a4f59a", 794259},
- {NULL, 0, NULL, 0}},
- Common::IT_ITA, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::IT_ITA, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// King's Quest 5 - English DOS CD (from the King's Quest Collection)
// Executable scanning reports "x.yyy.zzz", VERSION file reports "1.000.052"
@@ -923,7 +996,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "f68ba690e5920725dcf9328001b90e33", 13122},
{"resource.000", 0, "449471bfd77be52f18a3773c7f7d843d", 571368},
{"resource.001", 0, "b45a581ff8751e052c7e364f58d3617f", 16800210},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// King's Quest 5 - English DOS Floppy
@@ -938,11 +1011,27 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "b6c43441cb78a9b484efc8e614aac092", 1287999},
{"resource.006", 0, "672ede1136e9e401658538e51bd5dc22", 1172619},
{"resource.007", 0, "2f48faf27666b58c276dda20f91f4a93", 1240456},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
+ // King's Quest 5 - English DOS Floppy (supplied by omer_mor in bug report #3036996)
+ // VERSION file reports "0.000.051"
+ {"kq5", "", {
+ {"resource.map", 0, "8b2158083302568b73b16fa3655360fe", 8184},
+ {"resource.000", 0, "a591bd4b879fc832b8095c0b3befe9e2", 276398},
+ {"resource.001", 0, "c0f48d4a7ebeaa6aa074fc98d77423e9", 1099506},
+ {"resource.002", 0, "e0c40d0e85340357d2404f9b5ae1921c", 1061243},
+ {"resource.003", 0, "89c00d788d022c13a9b250fa96290ab0", 1110169},
+ {"resource.004", 0, "d68f0d8a52ac990aa5641b7087476253", 1153751},
+ {"resource.005", 0, "ef4f1166bc37b6cfab70234ea60ddc3d", 1032675},
+ {"resource.006", 0, "06cb3f689836086ebe08b1efc0126592", 921113},
+ {"resource.007", 0, "252249753c6e850eacceb8af634986d3", 1133608},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// King's Quest 5 EGA (supplied by markcoolio in bug report #2829470)
// SCI interpreter version 1.000.060
+ // VERSION file reports "0.000.055"
{"kq5", "EGA", {
{"resource.map", 0, "baf888a4e4797ce0de0b19d4e183583c", 7662},
{"resource.000", 0, "a591bd4b879fc832b8095c0b3befe9e2", 394242},
@@ -953,10 +1042,25 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "3cca5b2dae8afe94532edfdc98d7edbe", 669919},
{"resource.006", 0, "698c698570cde9015e4d51eb8d2e9db1", 666527},
{"resource.007", 0, "703d8df30e89541af337d7706540d5c4", 541743},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // King's Quest 5 - German DOS Floppy (supplied by markcoolio in bug report #2727101)
+ // King's Quest 5 EGA (supplied by omer_mor in bug report #3035421)
+ // VERSION file reports "0.000.062"
+ {"kq5", "EGA", {
+ {"resource.map", 0, "e17cfb38175382b9188da75c53bbab64", 7656},
+ {"resource.000", 0, "a591bd4b879fc832b8095c0b3befe9e2", 394072},
+ {"resource.001", 0, "c1eef048fa9fe76298c2d4705ef9549f", 561444},
+ {"resource.002", 0, "076aa0bf1d8d2c147d64aeffbe2928e5", 597580},
+ {"resource.003", 0, "ecb47cd04d06b2ab2f9f883667db6e81", 487633},
+ {"resource.004", 0, "4d74e8094ff57cea6ee92faf63dbd0af", 620749},
+ {"resource.005", 0, "3cca5b2dae8afe94532edfdc98d7edbe", 669961},
+ {"resource.006", 0, "698c698570cde9015e4d51eb8d2e9db1", 666541},
+ {"resource.007", 0, "703d8df30e89541af337d7706540d5c4", 541762},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
+ // King's Quest 5 - German DOS Floppy (supplied by markcoolio in bug report #2727101, also includes english language)
// SCI interpreter version 1.000.060
{"kq5", "", {
{"resource.map", 0, "bff44f0c326a71b1757c793a02b502d6", 8283},
@@ -968,10 +1072,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "9c429782d102739f6bbb81e8b953b0cb", 1267525},
{"resource.006", 0, "d1a75fdc01840664d00366cff6919366", 1208972},
{"resource.007", 0, "c07494f0cce7c05210893938786a955b", 1337361},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // King's Quest 5 - French DOS Floppy (from the King's Quest Collector's Edition 1994)
+ // King's Quest 5 - French DOS Floppy (from the King's Quest Collector's Edition 1994, also includes english language)
// Supplied by aroenai in bug report #2812611
// VERSION file reports "1.000", SCI interpreter version 1.000.784
{"kq5", "", {
@@ -984,10 +1088,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "f4b31cafc5defac75125c5f7b7f9a31a", 1268334},
{"resource.006", 0, "f7dc85307632ef657ceb1651204f6f51", 1210081},
{"resource.007", 0, "7db4d0a1d8d547c0019cb7d2a6acbdd4", 1338473},
- {NULL, 0, NULL, 0}},
- Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // King's Quest 5 - Italian DOS Floppy (from glorifindel)
+ // King's Quest 5 - Italian DOS Floppy (from glorifindel, includes english language)
// SCI interpreter version 1.000.060
{"kq5", "", {
{"resource.map", 0, "d55c9e83894a0885e37cd79bacf86384", 8283},
@@ -999,10 +1103,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "f4e441f284560eaa8022102315656a7d", 1267757},
{"resource.006", 0, "8eeabd92af71e766e323db2100879102", 1209325},
{"resource.007", 0, "dc10c107e0923b902326a040b9c166b9", 1337859},
- {NULL, 0, NULL, 0}},
- Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::IT_ITA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // King's Quest 5 - Polish DOS Floppy (supplied by jacek909 in bug report #2725722)
+ // King's Quest 5 - Polish DOS Floppy (supplied by jacek909 in bug report #2725722, includes english language?!)
// SCI interpreter version 1.000.060
{"kq5", "", {
{"resource.map", 0, "70010c20138541f89013bb5e1b30f16a", 7998},
@@ -1014,8 +1118,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "6556ff8e7c4d1acf6a78aea154daa76c", 1287869},
{"resource.006", 0, "da82e4beb744731d0a151f1d4922fafa", 1170456},
{"resource.007", 0, "431def14ca29cdb5e6a5e84d3f38f679", 1240176},
- {NULL, 0, NULL, 0}},
- Common::PL_POL, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::PL_POL, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// King's Quest 5 - English Macintosh
// VERSION file reports "1.000.055"
@@ -1029,9 +1133,17 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "432e2a58e4d496d730697db072437337", 1366732},
{"resource.006", 0, "3d22904a374c192f51e5665b74364133", 1264079},
{"resource.007", 0, "ffe17e23d5833a79f3695addfc149a56", 1361965},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_NOSPEECH },
+ // King's Quest 5 - FM-Towns (supplied by abevi in bug report #3038720)
+ {"kq5", "", {
+ {"resource.map", 0, "20c7cd248ff1a349ed354568eebd972b", 12733},
+ {"resource.000", 0, "71afd220d46bde1109c58e6acc0f3a01", 469094},
+ {"resource.001", 0, "72a569f46f1abf2d9d2b1526ad3799c3", 12808839},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformFMTowns, 0, GUIO_NONE },
+
// King's Quest 6 - English DOS Non-Interactive Demo
// Executable scanning reports "1.001.055", VERSION file reports "1.000.000"
// SCI interpreter version 1.001.055
@@ -1039,7 +1151,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "f75727c00a6d884234fa2a43c951943a", 706},
{"resource.000", 0, "535b1b920441ec73f42eaa4ccfd47b89", 264116},
{"resource.msg", 0, "54d1fdc936f98c81f9e4c19e04fb1510", 8260},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// King's Quest 6 - English DOS Floppy
@@ -1048,7 +1160,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a362063318eebe7d6423b1d9dc6213e1", 8703},
{"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324},
{"resource.msg", 0, "3cf5de44de36191f109d425b8450efc8", 258590},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// King's Quest 6 - German DOS Floppy (supplied by markcoolio in bug report #2727156)
@@ -1057,7 +1169,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a362063318eebe7d6423b1d9dc6213e1", 8703},
{"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324},
{"resource.msg", 0, "756297b2155db9e43f621c6f6fb763c3", 282822},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// King's Quest 6 - English DOS CD (from the King's Quest Collection)
@@ -1066,7 +1178,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq6", "CD", {
{"resource.map", 0, "7a550ebfeae2575ca00d47703a6a774c", 9215},
{"resource.000", 0, "233394a5f33b475ae5975e7e9a420865", 8376352},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// King's Quest 6 - English Windows CD (from the King's Quest Collection)
@@ -1075,7 +1187,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq6", "CD", {
{"resource.map", 0, "7a550ebfeae2575ca00d47703a6a774c", 9215},
{"resource.000", 0, "233394a5f33b475ae5975e7e9a420865", 8376352},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NONE },
// King's Quest 6 - Spanish DOS CD (from jvprat)
@@ -1085,7 +1197,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "a73a5ab04b8f60c4b75b946a4dccea5a", 8953},
{"resource.000", 0, "4da3ad5868a775549a7cc4f72770a58e", 8537260},
{"resource.msg", 0, "41eed2d3893e1ca6c3695deba4e9d2e8", 267102},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE },
// King's Quest 6 - English Macintosh Floppy
@@ -1093,7 +1205,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq6", "", {
{"Data1", 0, "f3c38a33c94293b8ff0337c1090a4973", 3916479},
{"Data2", 0, "b255edf327d7b366dce816b7debf3b94", 15046256},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO_NOSPEECH },
#ifdef ENABLE_SCI32
@@ -1104,7 +1216,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq7", "", {
{"resource.000", 0, "4948e4e1506f1e1c4e1d47abfa06b7f8", 204385195},
{"resource.map", 0, "40ccafb2195301504eba2e4f4f2c7f3d", 18925},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
// King's Quest 7 - English Windows (from the King's Quest Collection)
@@ -1112,7 +1224,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq7", "", {
{"resource.map", 0, "2be9ab94429c721af8e05c507e048a15", 18697},
{"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 203882535},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
// King's Quest 7 - English DOS (from FRG)
@@ -1120,7 +1232,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq7", "", {
{"resource.map", 0, "8676b0fbbd7362989a029fe72fea14c6", 18709},
{"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// King's Quest 7 - English Windows (from FRG)
@@ -1128,7 +1240,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq7", "", {
{"resource.map", 0, "8676b0fbbd7362989a029fe72fea14c6", 18709},
{"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
// King's Quest 7 - German Windows (supplied by markcoolio in bug report #2727402)
@@ -1136,7 +1248,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq7", "", {
{"resource.map", 0, "838b9ff132bd6962026fee832e8a7ddb", 18697},
{"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 206626576},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// King's Quest 7 - Spanish DOS (from jvprat)
@@ -1144,7 +1256,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq7", "", {
{"resource.map", 0, "0b62693cbe87e3aaca3e8655a437f27f", 18709},
{"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// King's Quest 7 - English DOS Non-Interactive Demo
@@ -1152,7 +1264,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"kq7", "Demo", {
{"resource.map", 0, "b44f774108d63faa1d021101221c5a54", 1690},
{"resource.000", 0, "d9659d2cf0c269c6a9dc776707f5bea0", 2433827},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
#endif // ENABLE_SCI32
@@ -1168,7 +1280,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "2ab23f64306b18c28302c8ec2964c5d6", 605134},
{"resource.004", 0, "aa553977f7e5804081de293800d3bcce", 695067},
{"resource.005", 0, "bfd870d51dc97729f0914095f58e6957", 676881},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Laura Bow - English Atari ST (from jvprat)
@@ -1180,7 +1292,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 721149},
{"resource.003", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 667365},
{"resource.004", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 683737},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO_NOSPEECH },
// Laura Bow - English DOS Non-Interactive Demo
@@ -1188,7 +1300,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"laurabow", "Demo", {
{"resource.map", 0, "e625726268ff4e123ada11f31f0249f3", 768},
{"resource.001", 0, "0c8912290af0890f8d95faeb4ddb2d68", 333031},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Laura Bow - English DOS 3.5" Floppy (from "The Roberta Williams Anthology"/1996)
@@ -1199,7 +1311,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 721381},
{"resource.003", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 667468},
{"resource.004", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 683807},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Laura Bow - English DOS (from FRG)
@@ -1213,10 +1325,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 327465},
{"resource.006", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 328390},
{"resource.007", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 317687},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Laura Bow - German DOS (from Tobis87)
+ // Laura Bow - German DOS (from Tobis87, also includes english language)
// SCI interpreter version 0.000.631 (or 0.000.685?)
{"laurabow", "", {
{"resource.map", 0, "b1905f6aa68ff65a057b080b1eae954c", 12030},
@@ -1227,8 +1339,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 327465},
{"resource.006", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 328390},
{"resource.007", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 317687},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Laura Bow 2 - English DOS Non-Interactive Demo (from FRG)
// Executable scanning reports "x.yyy.zzz"
@@ -1236,7 +1348,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"laurabow2", "Demo", {
{"resource.map", 0, "24dffc5db1d88c7999f13e8767ed7346", 855},
{"resource.000", 0, "2b2b1b4f7584f9b38fd13f6ab95634d1", 781912},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Laura Bow 2 - English DOS Floppy
@@ -1245,7 +1357,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"laurabow2", "", {
{"resource.map", 0, "610bfd9a852004222f0faaf5fc9e630a", 6489},
{"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5035964},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Laura Bow 2 - English DOS CD (from "The Roberta Williams Antology"/1996)
@@ -1254,7 +1366,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"laurabow2", "CD", {
{"resource.map", 0, "a70945e61ba7ac7bfea6b7bd72c6aec5", 7274},
{"resource.000", 0, "82578b8d5a7e09c4c58891ca49fae35b", 5598672},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// Laura Bow 2 v1.1 - French DOS Floppy (from Hkz)
@@ -1262,7 +1374,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "3b6dfbcda210bbc3f23fd1927113bf98", 6483},
{"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766},
{"resource.msg", 0, "0fceedfbdd85a4bc7851fdd9dd2d2f19", 278253},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Laura Bow 2 v1.1 - German DOS Floppy (from Tobis87, updated info from markcoolio in bug report #2723787, updated info from #2797962))
@@ -1271,7 +1383,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "3b6dfbcda210bbc3f23fd1927113bf98", 6483},
{"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766},
{"resource.msg", 0, "795c928cd00dfec9fbc62ebcd12e1f65", 303185},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Laura Bow 2 - Spanish DOS CD (from jvprat)
@@ -1280,7 +1392,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "3b6dfbcda210bbc3f23fd1927113bf98", 6483},
{"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766},
{"resource.msg", 0, "71f1f0cd9f082da2e750c793a8ed9d84", 286141},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE },
// Larry 1 EGA Remake - English DOS (from spookypeanut)
@@ -1291,7 +1403,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "38936d3c68b6f79d3ffb13955713fed7", 591352},
{"resource.002", 0, "24c958bc922b07f91e25e8c93aa01fcf", 491230},
{"resource.003", 0, "685cd6c1e05a695ab1e0db826337ee2a", 553279},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 1 VGA Remake - English Amiga (from www.back2roots.org)
@@ -1303,7 +1415,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "24ed6dc01b1e7fbc66c3d63a5994549a", 750465},
{"resource.002", 0, "5790ac0505f7ca98d4567132b875eb1e", 681041},
{"resource.003", 0, "4a34c3367c2fe7eb380d741374da1989", 572251},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Larry 1 VGA Remake - English DOS (from spookypeanut)
@@ -1313,7 +1425,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "d3bceaebef3f7be941c2038b3565161e", 922406},
{"resource.001", 0, "ec20246209d7b19f38989261e5c8f5b8", 1111226},
{"resource.002", 0, "85d6935ef77e6b0e16bc307640a0d913", 1088312},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 1 VGA Remake - English DOS (from FRG)
@@ -1323,7 +1435,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "d3bceaebef3f7be941c2038b3565161e", 918242},
{"resource.001", 0, "d34cadb11e1aefbb497cf91bc1d3baa7", 1114688},
{"resource.002", 0, "85b030bb66d5342b0a068f1208c431a8", 1078443},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 1 VGA Remake - English DOS Non-Interactive Demo
@@ -1331,10 +1443,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"lsl1sci", "VGA Remake, Demo", {
{"resource.map", 0, "434e1f6c39d71647b34f0ee57b2bbd68", 444},
{"resource.001", 0, "0c0768215c562d9dace4a5ca53696cf3", 359913},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
- // Larry 1 VGA Remake - Spanish DOS (from the Leisure Suit Larry Collection)
+ // Larry 1 VGA Remake - Spanish DOS (from the Leisure Suit Larry Collection, also includes english language)
// Executable scanning reports "1.SQ4.057", VERSION file reports "1.000"
// This version is known to be corrupted
// SCI interpreter version 1.000.510
@@ -1344,10 +1456,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "112648995dbc194037f1e4ed2e195910", 1063341},
{"resource.002", 0, "3fe2a3aec0ed53c7d6db1845a67e3aa2", 1095908},
{"resource.003", 0, "ac175df0ea9a2cba57f0248651856d27", 376556},
- {NULL, 0, NULL, 0}},
- Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Larry 1 VGA Remake - Russian DOS
+ // Larry 1 VGA Remake - Russian DOS (also includes english language?!)
// Executable scanning reports "1.000.510", VERSION file reports "2.0"
// SCI interpreter version 1.000.510
{"lsl1sci", "VGA Remake", {
@@ -1355,8 +1467,16 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "0d7b2afa666bd36d9535a15d3a837a66", 928566},
{"resource.001", 0, "bc8ca10c807515d959cbd91f9ba47735", 1123759},
{"resource.002", 0, "b7409ab32bc3bee2d6cce887cd33f2b6", 1092160},
- {NULL, 0, NULL, 0}},
- Common::RU_RUS, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::RU_RUS, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
+
+ // Larry 1 VGA Remake - Polish DOS (from Polish Leisure Suit Larry Collection, official release)
+ // SCI interpreter version 1.000.577, VERSION file reports "2.1" (this release does NOT include english text)
+ {"lsl1sci", "VGA Remake", {
+ {"resource.map", 0, "58330a85767e42a2487129913283ab5b", 3228},
+ {"resource.000", 0, "b6097ff35cdc8469f02150fe2f824198", 4781210},
+ AD_LISTEND},
+ Common::PL_POL, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 2 - English Amiga (from www.back2roots.org)
// Executable scanning reports "x.yyy.zzz"
@@ -1367,7 +1487,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "a0d4a625311d307257da7fc43d00459d", 630106},
{"resource.003", 0, "a0d4a625311d307257da7fc43d00459d", 570356},
{"resource.004", 0, "a0d4a625311d307257da7fc43d00459d", 717844},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Larry 2 - English DOS Non-Interactive Demo
@@ -1376,7 +1496,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"lsl2", "Demo", {
{"resource.map", 0, "03dba704bb77da55a91ad27b5a3cac09", 528},
{"resource.001", 0, "9f5520f0297206928df0b0b36493cd33", 127532},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Larry 2 - English DOS
@@ -1389,7 +1509,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "4a24443a25e2b1492462a52809605dc2", 204861},
{"resource.005", 0, "4a24443a25e2b1492462a52809605dc2", 277732},
{"resource.006", 0, "4a24443a25e2b1492462a52809605dc2", 345683},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 2 - English DOS
@@ -1404,7 +1524,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
// TODO/FIXME: is the version with size 208739 corrupted?
//{"resource.006", 0, "96033f57accfca903750413fd09193c8", 345818},
{"resource.006", 0, "96033f57accfca903750413fd09193c8", -1}, // 345818 or 208739
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 3 - English Amiga (from www.back2roots.org)
@@ -1418,7 +1538,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "5c10e462c8cf589610773e4fe8bfd996", 527238},
{"resource.004", 0, "f408e59cbee1457f042e5773b8c53951", 651634},
{"resource.005", 0, "433911eb764089d493aed1f958a5615a", 524259},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Larry 3 - English DOS
@@ -1429,7 +1549,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "f18441027154292836b973c655fa3175", 578024},
{"resource.003", 0, "f18441027154292836b973c655fa3175", 506807},
{"resource.004", 0, "f18441027154292836b973c655fa3175", 513651},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 3 - English DOS
@@ -1443,7 +1563,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "f18441027154292836b973c655fa3175", 302946},
{"resource.006", 0, "f18441027154292836b973c655fa3175", 282465},
{"resource.007", 0, "f18441027154292836b973c655fa3175", 257174},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 3 - English DOS Non-Interactive Demo
@@ -1452,10 +1572,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "33a2384f395470af3d2180e37ad0322a", 1140},
{"resource.001", 0, "f773d79b93dfd4052ec8c1cc64c1e6ab", 76525},
{"resource.002", 0, "f773d79b93dfd4052ec8c1cc64c1e6ab", 268299},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
- // Larry 3 - German DOS (from Tobis87, updated info from markcoolio in bug report #2723832)
+ // Larry 3 - German DOS (from Tobis87, updated info from markcoolio in bug report #2723832, also includes english language)
// Executable scanning reports "S.old.123"
// SCI interpreter version 0.000.572 (just a guess)
{"lsl3", "", {
@@ -1464,10 +1584,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "3827a9b17b926e12dcc336860f50612a", 672403},
{"resource.003", 0, "3827a9b17b926e12dcc336860f50612a", 587036},
{"resource.004", 0, "3827a9b17b926e12dcc336860f50612a", 691932},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Larry 3 - French DOS (provided by richiefs in bug report #2670691)
+ // Larry 3 - French DOS (provided by richiefs in bug report #2670691, also includes english language)
// Executable scanning reports "S.old.123"
// SCI interpreter version 0.000.572 (just a guess)
{"lsl3", "", {
@@ -1476,8 +1596,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "65f1bdaa20f6d0470e9d969f22473873", 671614},
{"resource.003", 0, "65f1bdaa20f6d0470e9d969f22473873", 586921},
{"resource.004", 0, "65f1bdaa20f6d0470e9d969f22473873", 690826},
- {NULL, 0, NULL, 0}},
- Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Larry 5 - English Amiga
// Executable scanning reports "1.004.023"
@@ -1491,10 +1611,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "3ce5901f1bc171ac0274d99a4eeb9e57", 623022},
{"resource.005", 0, "f8b2d1137bb767e5d232056b99dd69eb", 623621},
{"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 715598},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
- // Larry 5 - German Amiga
+ // Larry 5 - German Amiga (also includes english language)
// Executable scanning reports "1.004.024"
// SCI interpreter version 1.000.784
{"lsl5", "", {
@@ -1507,15 +1627,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "59eba83ad465b08d763b44f86afa86f6", 664717},
{"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 754966},
{"resource.007", 0, "59eba83ad465b08d763b44f86afa86f6", 683135},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Larry 5 - English DOS Non-Interactive Demo (from FRG)
// SCI interpreter version 1.000.181
{"lsl5", "Demo", {
{"resource.map", 0, "efe8d3f45ce4f6bd9a6643e0ac8d2a97", 504},
{"resource.001", 0, "8bd8d9c0b5f455ee1269d63ce86c50dd", 531380},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Larry 5 - English DOS (from spookypeanut)
@@ -1530,11 +1650,11 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "0cc8d35a744031c772ca7cd21ae95273", 1011944},
{"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1024810},
{"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 1030656},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 5 - German DOS (from Tobis87)
- // SCI interpreter version 1.000.510 (just a guess)
+ // SCI interpreter version T.A00.196
{"lsl5", "", {
{"resource.map", 0, "c97297aa76d4dd2ed144c7b7769e2caf", 6867},
{"resource.000", 0, "4c00c14b8181ad47076a51d86097d97e", 759095},
@@ -1545,8 +1665,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "0cc8d35a744031c772ca7cd21ae95273", 959342},
{"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1021774},
{"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 993408},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Larry 5 - French DOS (provided by richiefs in bug report #2670691)
// Executable scanning reports "1.lsl5.019"
@@ -1561,8 +1681,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "0cc8d35a744031c772ca7cd21ae95273", 920524},
{"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 946540},
{"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 958842},
- {NULL, 0, NULL, 0}},
- Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Larry 5 - Spanish DOS (from the Leisure Suit Larry Collection)
// Executable scanning reports "1.ls5.006", VERSION file reports "1.000, 4/21/92"
@@ -1577,15 +1697,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "0cc8d35a744031c772ca7cd21ae95273", 958079},
{"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1015136},
{"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 987222},
- {NULL, 0, NULL, 0}},
- Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Larry 5 - Italian DOS Floppy (from glorifindel)
// SCI interpreter version 1.000.510 (just a guess)
{"lsl5", "", {
{"resource.map", 0, "a99776df795127f387cb35dae872d4e4", 5919},
{"resource.000", 0, "a8989a5a89e7d4f702b26b378c7a357a", 7001981},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 6 - English DOS (from spookypeanut)
@@ -1593,7 +1713,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"lsl6", "", {
{"resource.map", 0, "bb8a39d9e2a77ba449a1e591109ad9a8", 6973},
{"resource.000", 0, "4462fe48c7452d98fddcec327a3e738d", 5789138},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 6 - English/German/French DOS CD - LORES
@@ -1601,7 +1721,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"lsl6", "", {
{"resource.map", 0, "0b91234b7112782962cb480b7791b6e2", 7263},
{"resource.000", 0, "57d5fe8bb9e044158514476ea7678eb0", 5754790},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// Larry 6 - German DOS CD - LORES (provided by richiefs in bug report #2670691)
@@ -1609,7 +1729,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"lsl6", "", {
{"resource.map", 0, "bafe85f32738854135991d4324ad147e", 7268},
{"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5773160},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NONE },
// Larry 6 - French DOS CD - LORES (provided by richiefs in bug report #2670691)
@@ -1617,7 +1737,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"lsl6", "", {
{"resource.map", 0, "97797ea775baaf18a1907d357d3c0ea6", 7268},
{"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5776092},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NONE },
// Larry 6 - Spanish DOS - LORES (from the Leisure Suit Larry Collection)
@@ -1625,7 +1745,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"lsl6", "", {
{"resource.map", 0, "633bf8f42170b6271019917c8009989b", 6943},
{"resource.000", 0, "7884a8db9253e29e6b37a2651fd90ba3", 5733116},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Crazy Nick's Software Picks: Leisure Suit Larry's Casino - English DOS (from the Leisure Suit Larry Collection)
@@ -1633,69 +1753,77 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"cnick-lsl", "", {
{"resource.map", 0, "194f1578f2624db813c9072359ad1639", 783},
{"resource.001", 0, "3733433b517ec3d14a3331d9ab3842ae", 344830},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Crazy Nick's Software Picks: King Graham's Board Game Challenge
{"cnick-kq", "", {
{"resource.map", 0, "44bc538a5cd24b39ffccc967c0ebf84d", 1137},
{"resource.001", 0, "470e7a4a3504635e70b623c44461e1ac", 451272},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Crazy Nick's Software Picks: Parlor Games with Laura Bow
{"cnick-laurabow", "", {
{"resource.map", 0, "3b826bfe64f8ff1ccf30eef93cd2f727", 999},
{"resource.001", 0, "985ac8db6f636f2b4334c04b0fbb44fb", 336698},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Crazy Nick's Software Picks: Robin Hood's Game of Skill and Chance
{"cnick-longbow", "", {
{"resource.map", 0, "4a5c81f485a2416bde12978506f2fb5f", 897},
{"resource.001", 0, "ef16dc9e867eb8eeb5b13e110b90bd4b", 571466},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Crazy Nick's Software Picks: Roger Wilco's Spaced Out Game Pack
{"cnick-sq", "", {
{"resource.map", 0, "b4d95b02d84e297441bd999d34eaa6b1", 879},
{"resource.001", 0, "82ff2b64a60117886fbcd6a3a8c977c6", 364921},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
#ifdef ENABLE_SCI32
// Larry 6 - English/German DOS CD - HIRES
// SCI interpreter version 2.100.002
- {"lsl6", "", {
+ {"lsl6hires", "", {
{"resource.map", 0, "0c0804434ea62278dd15032b1947426c", 8872},
{"resource.000", 0, "9a9f4870504444cda863dd14d077a680", 18520872},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// Larry 6 - German DOS CD - HIRES (provided by richiefs in bug report #2670691)
// SCI interpreter version 2.100.002
- {"lsl6", "", {
+ {"lsl6hires", "", {
{"resource.map", 0, "badfdf446ffed569a310d2c63a249421", 8896},
{"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18534274},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NONE },
// Larry 6 - French DOS CD - HIRES (provided by richiefs in bug report #2670691)
// SCI interpreter version 2.100.002
- {"lsl6", "", {
+ {"lsl6hires", "", {
{"resource.map", 0, "d184e9aa4f2d4b5670ddb3669db82cda", 8896},
{"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18538987},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NONE },
+ // Larry 7 - English DOS Demo (provided by richiefs in bug report #2670691)
+ // SCI interpreter version 2.100.002
+ {"lsl7", "Demo", {
+ {"ressci.000", 0, "5cc6159688b2dc03790a67c90ccc67f9", 10195878},
+ {"resmap.000", 0, "6a2b2811eef82e87cde91cf1de845af8", 2695},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
+
#ifdef ENABLE_SCI3_GAMES
// Larry 7 - English DOS CD (from spookypeanut)
// SCI interpreter version 3.000.000
{"lsl7", "", {
{"resmap.000", 0, "eae93e1b1d1ccc58b4691c371281c95d", 8188},
{"ressci.000", 0, "89353723488219e25589165d73ed663e", 66965678},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// Larry 7 - German DOS (from Tobis87)
@@ -1703,7 +1831,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"lsl7", "", {
{"resmap.000", 0, "c11e6bfcfc2f2d05da47e5a7df3e9b1a", 8188},
{"ressci.000", 0, "a8c6817bb94f332ff498a71c8b47f893", 66971724},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 7 - French DOS (provided by richiefs in bug report #2670691)
@@ -1711,7 +1839,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"lsl7", "", {
{"resmap.000", 0, "4407849fd52fe3efb0c30fba60cd5cd4", 8206},
{"ressci.000", 0, "dc37c3055fffbefb494ff22b145d377b", 66964472},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Larry 7 - Italian DOS CD (from glorifindel)
@@ -1719,7 +1847,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"lsl7", "", {
{"resmap.000", 0, "9852a97141f789413f29bf956052acdb", 8212},
{"ressci.000", 0, "440b9fed89590abb4e4386ed6f948ee2", 67140181},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NONE },
// Larry 7 - Spanish DOS (from the Leisure Suit Larry Collection)
@@ -1727,31 +1855,25 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"lsl7", "", {
{"resmap.000", 0, "8f3d603e1acc834a5d598b30cdfc93f3", 8188},
{"ressci.000", 0, "32792f9bc1bf3633a88b382bb3f6e40d", 67071418},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH },
-
- // Larry 7 - English DOS Demo (provided by richiefs in bug report #2670691)
- // SCI interpreter version 2.100.002
- {"lsl7", "Demo", {
- {"ressci.000", 0, "5cc6159688b2dc03790a67c90ccc67f9", 10195878},
- {"resmap.000", 0, "6a2b2811eef82e87cde91cf1de845af8", 2695},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
+#endif
// Lighthouse - English Windows Demo (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "1.00"
{"lighthouse", "Demo", {
{"resource.map", 0, "543124606352bfa5e07696ddf2a669be", 64},
{"resource.000", 0, "5d7714416b612463d750fb9c5690c859", 28952},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
+#ifdef ENABLE_SCI3_GAMES
// Lighthouse - English Windows Demo
// Executable scanning reports "3.000.000", VERSION file reports "1.00"
{"lighthouse", "Demo", {
{"resmap.000", 0, "3bdee7a16926975a4729f75cf6b80a92", 1525},
{"ressci.000", 0, "3c585827fa4a82f4c04a56a0bc52ccee", 11494351},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Lighthouse - English DOS (from jvprat)
@@ -1761,7 +1883,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.001", 0, "14e922c47b92156377cb49e241691792", 99591924},
{"resmap.002", 0, "c68db5333f152fea6ca2dfc75cad8b34", 7573},
{"ressci.002", 0, "175468431a979b9f317c294ce3bc1430", 94628315},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Lighthouse - Spanish DOS (from jvprat)
@@ -1771,7 +1893,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.001", 0, "18553177dbf83fb2cb6c8edcbb174183", 99543093},
{"resmap.002", 0, "e7dc85884a2417e2eff9de0c63dd65fa", 7630},
{"ressci.002", 0, "3c8d627c555b0e3e4f1d9955bc0f0df4", 94631127},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH },
#endif // ENABLE_SCI3_GAMES
@@ -1782,9 +1904,20 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "c2cf672c3f4251e7472d4542af3bf764", 933},
{"resource.000", 0, "8be56a3a88c065ee00c02c0e29199f3a", 14643},
{"resource.001", 0, "9e33566515b18bee7915db448063bba2", 871853},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
+ // Mixed-Up Fairy Tales - English DOS Floppy EGA (from omer_mor, bug report #3035350)
+ {"fairytales", "EGA", {
+ {"resource.map", 0, "daa94e9f327be6657eb97a51b490dbb1", 3219},
+ {"resource.000", 0, "6dc287611e510793b72e73110bbdd45d", 17819},
+ {"resource.001", 0, "5ad26e7af4d4c3a3185c66a44abd5220", 478401},
+ {"resource.002", 0, "4db83250f821607b634c99d663cae74a", 663713},
+ {"resource.003", 0, "509b2467ba779100d5933ed51a9ae32f", 560255},
+ {"resource.004", 0, "93afc85d5ffa60ea555d6cc336d22c03", 651109},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
// Mixed-Up Fairy Tales v1.000 - English DOS (supplied by markcoolio in bug report #2723791)
// Executable scanning reports "1.000.145"
{"fairytales", "", {
@@ -1794,7 +1927,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "6767f8c8585f617aaa91d442f41ae714", 1032989},
{"resource.003", 0, "b1288e0821ee358d1ffe877e5900c8ec", 1047565},
{"resource.004", 0, "f79daa70390d73746742ffcfc3dc4471", 937580},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Mixed-Up Fairy Tales - English DOS Floppy (from jvprat)
@@ -1805,7 +1938,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "49c8f7dcd9989e4491a93554bec325b0", 238019},
{"resource.002", 0, "564f516d991032e781492592a4eaa275", 1414142},
{"resource.003", 0, "dd6cef0c592eadb7e6be9a25307c57a2", 1344719},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Mixed-Up Mother Goose - English Amiga (from www.back2roots.org)
@@ -1815,15 +1948,23 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "4aa28ac93fae03cf854594da13d9229c", 2700},
{"resource.001", 0, "fb552ae550ca1dac19ed8f6a3767612d", 262885},
{"resource.002", 0, "fb552ae550ca1dac19ed8f6a3767612d", 817191},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
+ // Mixed-Up Mother Goose - English DOS Floppy EGA (from omer_mor, bug report #3035354)
+ {"mothergoose", "EGA", {
+ {"resource.map", 0, "3490f85dab47e504c41b7eb3312e285e", 2598},
+ {"resource.001", 0, "d893892d62b3f061357291d66775e360", 239906},
+ {"resource.002", 0, "d893892d62b3f061357291d66775e360", 719398},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
// Mixed-Up Mother Goose v2.000 - English DOS Floppy (supplied by markcoolio in bug report #2723795)
// Executable scanning reports "1.001.031"
{"mothergoose", "", {
{"resource.map", 0, "52aae15e493cafd1da7e1c9b657a5bb9", 7026},
{"resource.000", 0, "b7ecd8ae9e254e80310b5a668b276e6e", 2948975},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Mixed-Up Mother Goose - English DOS CD (from jvprat)
@@ -1832,7 +1973,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"mothergoose", "CD", {
{"resource.map", 0, "1c7f311b0a2c927b2fbe81ae341fb2f6", 5790},
{"resource.001", 0, "5a0ed1d745855148364de1b3be099bac", 4369438},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// Mixed-Up Mother Goose - English Windows Interactive Demo
@@ -1840,17 +1981,31 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"mothergoose", "Demo", {
{"resource.map", 0, "87f9dc1cafc4d4fa835fb2f00cf3a6ef", 4560},
{"resource.001", 0, "5a0ed1d745855148364de1b3be099bac", 2070072},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NOSPEECH },
+
+ // Mixed-Up Mother Goose - FM-Towns (supplied by abevi in bug report #3038720)
+ {"mothergoose", "", {
+ {"resource.map", 0, "b11e971ccd2040bebba59dfb409a08ef", 5772},
+ {"resource.001", 0, "d49625d9b8005ec01c852f8322a82867", 4330713},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformFMTowns, 0, GUIO_NONE },
#ifdef ENABLE_SCI32
// Mixed-Up Mother Goose Deluxe - English Windows/DOS CD (supplied by markcoolio in bug report #2723810)
// Executable scanning reports "2.100.002"
- {"mothergoose", "", {
+ {"mothergoosehires", "", {
{"resource.map", 0, "5159a1578c4306bfe070a3e4d8c2e1d3", 4741},
{"resource.000", 0, "1926925c95d82f0999590e93b02887c5", 15150768},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
+
+ // Mixed-Up Mother Goose Deluxe - Multilingual Windows CD (English/French/German/Spanish)
+ // Executable scanning reports "2.100.002"
+ {"mothergoosehires", "", {
+ {"resmap.000", 0, "ef611af561898dcfea87846919ebf3eb", 4969},
+ {"ressci.000", 0, "227685bc59d90821978d330713e44a7a", 17205800},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
#endif // ENABLE_SCI32
@@ -1859,7 +2014,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"msastrochicken", "", {
{"resource.map", 0, "5b457cbe5042f557e5b610148171f6c0", 1158},
{"resource.001", 0, "453ea81ef66a50cbe33ce06302afe47f", 229737},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
#ifdef ENABLE_SCI32
@@ -1880,7 +2035,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.006", 0, "3aae6559aa1df273bc542d5ac6330d75", 77901360},
{"resmap.007", 0, "afbd16ea77869a720afa1c5371de107d", 7972},
//{"ressci.007", 0, "3aae6559aa1df273bc542d5ac6330d75", 25859038},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Phantasmagoria - English DOS Demo
@@ -1888,7 +2043,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"phantasmagoria", "Demo", {
{"resmap.001", 0, "416138651ea828219ca454cae18341a3", 11518},
{"ressci.001", 0, "3aae6559aa1df273bc542d5ac6330d75", 65844612},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
#ifdef ENABLE_SCI3_GAMES
@@ -1905,7 +2060,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.004", 0, "53f457cddb0dffc056593905c4cbb989", 42447131},
{"resmap.005", 0, "8bd5ceeedcbe16dfe55d1b90dcd4be84", 1942},
{"ressci.005", 0, "05f9fe2bee749659acb3cd2c90252fc5", 67905112},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
#endif // ENABLE_SCI3_GAMES
@@ -1916,7 +2071,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"pepper", "", {
{"resource.map", 0, "72726dc81c1b4c1110c486be77369bc8", 5179},
{"resource.000", 0, "670d0c53622429f4b11275caf7f8d292", 5459574},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Pepper - English DOS Non-Interactive Demo
@@ -1924,7 +2079,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"pepper", "Demo", {
{"resource.map", 0, "379bb4fb896630b14f2d91ed21e36ba1", 984},
{"resource.000", 0, "118f6c31a93ec7fd9a231c61125229e3", 645494},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Pepper - English DOS/Windows Interactive Demo
@@ -1932,7 +2087,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"pepper", "Demo", {
{"resource.map", 0, "975e8df76106a5c13d12ab674f906a02", 2514},
{"resource.000", 0, "e6a918a2dd7a4bcecd8fb389f43287c2", 1698164},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Pepper - English DOS Interactive Demo
@@ -1940,7 +2095,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"pepper", "Demo", {
{"resource.map", 0, "9c9b7b900651a370dd3fb38d478b1798", 2524},
{"resource.000", 0, "e6a918a2dd7a4bcecd8fb389f43287c2", 1713544},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Police Quest 1 VGA Remake - English DOS (from the Police Quest Collection)
@@ -1948,7 +2103,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"pq1sci", "VGA Remake", {
{"resource.map", 0, "35efa814fb994b1cbdac9611e401da67", 5013},
{"resource.000", 0, "e0d5ddf34eda903a38f0837e2aa7145b", 6401433},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Police Quest 2 - English Amiga (from www.back2roots.org)
@@ -1959,7 +2114,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "523db0c07f1da2a822c2c39ee0482544", 179334},
{"resource.002", 0, "499737c21a28ac026e11ab817100d610", 511099},
{"resource.003", 0, "e008f5d6e2a7c4d4a0da0173e4fa8f8b", 553970},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Police Quest 2 - English DOS Non-Interactive Demo
@@ -1967,7 +2122,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"pq2", "Demo", {
{"resource.map", 0, "8b77d0d4650c2052b356cece28294b58", 576},
{"resource.001", 0, "376ef6d6eaaeed66e1424bd219c4b9ab", 215398},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Police Quest 2 - English DOS (provided by richiefs in bug report #2670691)
@@ -1980,7 +2135,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "77f02def3094af804fd2371db25b7100", 342149},
{"resource.005", 0, "77f02def3094af804fd2371db25b7100", 349899},
{"resource.006", 0, "77f02def3094af804fd2371db25b7100", 354991},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Police Quest 2 - English DOS (from the Police Quest Collection)
@@ -1990,7 +2145,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "77f02def3094af804fd2371db25b7100", 509525},
{"resource.002", 0, "77f02def3094af804fd2371db25b7100", 546000},
{"resource.003", 0, "77f02def3094af804fd2371db25b7100", 591851},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Police Quest 2 - English DOS (from FRG)
@@ -2000,9 +2155,28 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "77f02def3094af804fd2371db25b7100", 509760},
{"resource.002", 0, "77f02def3094af804fd2371db25b7100", 542897},
{"resource.003", 0, "77f02def3094af804fd2371db25b7100", 586857},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
+ // Police Quest 2 English DOS 1.001.006 (supplied by merkur-kun in bug report #3028479)
+ {"pq2", "", {
+ {"resource.map", 0, "8e1161c684b342742d30f938a4839a4b", 4518},
+ {"resource.001", 0, "77f02def3094af804fd2371db25b7100", 506563},
+ {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 541261},
+ {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 587511},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ // Police Quest 2 - Japanese PC-98 (also includes english language)
+ // SCI interpreter version unknown
+ {"pq2", "", {
+ {"resource.map", 0, "883804c616dca1d82373bf9fda3a71d2", 4656},
+ {"resource.001", 0, "05fdee43a228dd6ea4d1a92ccae3f788", 669319},
+ {"resource.002", 0, "05fdee43a228dd6ea4d1a92ccae3f788", 637662},
+ {"resource.003", 0, "05fdee43a228dd6ea4d1a92ccae3f788", 684395},
+ AD_LISTEND},
+ Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO_NOSPEECH },
+
// Police Quest 3 - English Amiga
// Executable scanning reports "1.004.024"
// SCI interpreter version 1.000.784
@@ -2013,10 +2187,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "f7044bb08a1fcbe5077791ed8d4996f0", 691207},
{"resource.003", 0, "630bfa65beb05f743552704ac2899dae", 759891},
{"resource.004", 0, "7b229fbdf30d670d0728cede3e984a7e", 838663},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
- // Police Quest 3 - German Amiga
+ // Police Quest 3 - German Amiga (also includes english language)
// Executable scanning reports "1.004.024"
// SCI interpreter version 1.000.784
{"pq3", "", {
@@ -2027,9 +2201,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "87361c17fd863b58f98828de68770279", 682288},
{"resource.004", 0, "6258d5dd85898d8e218eb8113ebc9059", 722738},
{"resource.005", 0, "6258d5dd85898d8e218eb8113ebc9059", 704485},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Police Quest 3 - English DOS (from the Police Quest Collection)
// Executable scanning reports "T.A00.178", VERSION file reports "1.00"
@@ -2041,9 +2214,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "c18e0d408e4f4f40365d42aa15931f67", 1153561},
{"resource.003", 0, "8791b9eef53edf77c2dac950142221d3", 1159791},
{"resource.004", 0, "1b91e891a3c60a941dac0eecdf83375b", 1143606},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Police Quest 3 - English DOS Non-Interactive Demo
// Executable scanning reports "T.A00.052"
@@ -2052,11 +2224,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "ec8e58e7663ae5173853abf6c76b52bb", 867},
{"resource.000", 0, "277f97771f7a6d89677141f02da313d6", 65150},
{"resource.001", 0, "5c5a551b6c86cce2ee75becb90e0b586", 624411},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
- // Police Quest 3 - German DOS (supplied by markcoolio in bug report #2723837)
+ // Police Quest 3 - German DOS (supplied by markcoolio in bug report #2723837, also includes english language)
// Executable scanning reports "T.A00.178"
// SCI interpreter version 1.000.510
{"pq3", "", {
@@ -2066,18 +2237,16 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "cce99b96a578b62ff6cebdae8d122feb", 1179358},
{"resource.003", 0, "4836f460f4cfc8de61e2df4c45775504", 1180956},
{"resource.004", 0, "0c3eb84b9755852d9e795e0d5c9373c7", 1171760},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Police Quest 4 - English DOS Non-Interactive Demo (from FRG)
// SCI interpreter version 1.001.096
{"pq4", "Demo", {
{"resource.map", 0, "be56f87a1c4a13062a30a362df860c2f", 1472},
{"resource.000", 0, "527d5684016e6816157cd15d9071b11b", 1121310},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
#ifdef ENABLE_SCI32
// Police Quest 4 - English DOS (from the Police Quest Collection)
@@ -2085,45 +2254,40 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"pq4", "", {
{"resource.map", 0, "379dfe80ed6bd16c47e4b950c4722eac", 11374},
{"resource.000", 0, "fd316a09b628b7032248139003369022", 18841068},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Police Quest 4 - English DOS
// SCI interpreter version 2.000.000 (a guess?)
{"pq4", "", {
{"resource.map", 0, "aed9643158ccf01b71f359db33137f82", 9895},
{"resource.000", 0, "da383857b3be1e4514daeba2524359e0", 15141432},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Police Quest 4 - French DOS (supplied by abevi in bug report #2612718)
// SCI interpreter version 2.000.000
{"pq4", "", {
{"resource.map", 0, "008030846edcc7c5c7a812c7f4ae4ceb", 9256},
{"resource.000", 0, "6ba98bd2e436739d87ecd2a9b99cabb4", 14730153},
- {NULL, 0, NULL, 0}},
- Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Police Quest 4 - German DOS (supplied by markcoolio in bug report #2723840)
// SCI interpreter version 2.000.000 (a guess?)
{"pq4", "", {
{"resource.map", 0, "2393ee728ab930b2762cb5889f9b5aff", 9256},
{"resource.000", 0, "6ba98bd2e436739d87ecd2a9b99cabb4", 14730155},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Police Quest: SWAT - English DOS/Windows Demo (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "0.001.200"
{"pqswat", "Demo", {
{"resource.map", 0, "8c96733ef94c21526792f7ca4e3f2120", 1648},
{"resource.000", 0, "d8892f1b8c56c8f7704325460f49b300", 3676175},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Police Quest: SWAT - English Windows (from the Police Quest Collection)
// Executable scanning reports "2.100.002", VERSION file reports "1.0c"
@@ -2137,9 +2301,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.003", 0, "00a755e917c442ca8cf1a1bea689e6fb", 45073980},
{"resmap.004", 0, "4228038906f041623e65789500b22285", 6835},
{"ressci.004", 0, "b7e619e6ecf62fe65d5116a3a422e5f0", 46223872},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
#endif // ENABLE_SCI32
// Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy (supplied by merkur in bug report #2718784)
@@ -2151,9 +2314,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "439ba9b6dde216e6eb97ef3a9830fbe4", 646869},
{"resource.003", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 642203},
{"resource.004", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 641688},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by markcoolio in bug report #2723843)
// Executable scanning reports "0.000.566"
@@ -2167,31 +2329,36 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "7288ed6d5da89b7a80b4af3897a7963a", 271185},
{"resource.006", 0, "69366c2a2f99917199fe1b60a4fee19d", 267852},
{"resource.007", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 272747},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
+ // Quest for Glory 1 / Hero's Quest - English DOS Demo
+ // Executable scanning reports "0.000.685"
+ {"qfg1", "Demo", {
+ {"resource.map", 0, "df34c758cbb9026da175793ff686b0e6", 882},
+ {"resource.001", 0, "73fbaafdd313b39aeedb80fbf85ecef1", 389884},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
- // Quest for Glory 1 - Japanese PC-98 5.25" Floppy
+ // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes english language)
// Executable scanning reports "S.old.201"
{"qfg1", "8 Colors", {
{"resource.map", 0, "5cbeb95dd2a4b7cb242b415cc6ec1c47", 6444},
{"resource.001", 0, "a21451ef6fa8179bd4b22c4950004c44", 859959},
{"resource.002", 0, "a21451ef6fa8179bd4b22c4950004c44", 1136968},
{"resource.003", 0, "a21451ef6fa8179bd4b22c4950004c44", 769897},
- {NULL, 0, NULL, 0}},
- Common::JA_JPN, Common::kPlatformPC98, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Quest for Glory 1 - Japanese PC-98 5.25" Floppy
+ // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes english language)
// Executable scanning reports "S.old.201"
{"qfg1", "16 Colors", {
{"resource.map", 0, "3ecaba33bf77cb434067a0b8aee15097", 6444},
{"resource.001", 0, "a21451ef6fa8179bd4b22c4950004c44", 864754},
{"resource.002", 0, "a21451ef6fa8179bd4b22c4950004c44", 1147121},
{"resource.003", 0, "a21451ef6fa8179bd4b22c4950004c44", 777575},
- {NULL, 0, NULL, 0}},
- Common::JA_JPN, Common::kPlatformPC98, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Quest for Glory 1 - English Amiga
// Executable scanning reports "1.002.020"
@@ -2204,9 +2371,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "16cd4414c37ae3bb6d6da33dce8e25e8", 654096},
{"resource.004", 0, "16cd4414c37ae3bb6d6da33dce8e25e8", 689124},
{"resource.005", 0, "5f3386ef2f2b1254e4a066f5d9027324", 609529},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Quest for Glory 1 (from abevi, bug report #2612718)
{"qfg1", "", {
@@ -2216,9 +2382,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "e64004e020fdf1813be52b639b08be89", 635561},
{"resource.003", 0, "f0af87c60ec869946da442833aa5afa8", 640502},
{"resource.004", 0, "f0af87c60ec869946da442833aa5afa8", 644575},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Quest for Glory 1 - English DOS
// SCI interpreter version 0.000.629
@@ -2229,36 +2394,32 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "05ddce5f437a516b89ede2438fac09d8", 635734},
{"resource.003", 0, "951299a82a8134ed12c5c18118d45c2f", 640483},
{"resource.004", 0, "951299a82a8134ed12c5c18118d45c2f", 644443},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Quest for Glory 1 VGA Remake - English DOS
// Executable scanning reports "2.000.411"
- {"qfg1", "VGA Remake", {
+ {"qfg1vga", "VGA Remake", {
{"resource.map", 0, "a731fb6c9c0b282443f7027bc8694d4c", 8469},
{"resource.000", 0, "ecace1a2771846b1a8aa1afdd44111a0", 6570147},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Quest for Glory 1 VGA Remake - English DOS Non-Interactive Demo (from FRG)
// SCI interpreter version 1.001.029
- {"qfg1", "VGA Remake, Demo", {
+ {"qfg1vga", "VGA Remake, Demo", {
{"resource.map", 0, "ac0257051c95a59c0cdc0be24d9b11fa", 729},
{"resource.000", 0, "ec6f5cf369054dd3e5392995e9975b9e", 768218},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Quest for Glory 1 VGA Remake - English Macintosh Floppy
// VERSION file reports "2.0"
- {"qfg1", "VGA Remake", {
+ {"qfg1vga", "VGA Remake", {
{"Data1", 0, "14f26bc75f24bb1ecc94532df17b5371", 1768155},
{"Data2", 0, "a7aee8bd46fc9cef7fd3bea93ef173e0", 6586422},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO_NOSPEECH },
// Quest for Glory 2 - English Amiga
// Executable scanning reports "1.003.004"
@@ -2273,9 +2434,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "a77d2576c842b2b06da57d4ac8fc51c0", 579975},
{"resource.006", 0, "ccf5dba33e5cab6d5872838c0f8db44c", 500039},
{"resource.007", 0, "4c9fc1587545879295cb9627f56a2cb8", 575056},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Quest for Glory 2 - English (from FRG)
// Executable scanning reports "1.000.072"
@@ -2286,9 +2446,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "df137dc7869cab07e1149ba2333c815c", 790750},
{"resource.003", 0, "b192607c42f6960ecdf2ad2e4f90e9bc", 972804},
{"resource.004", 0, "cd2de58e27665d5853530de93fae7cd6", 983617},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Quest for Glory 2 - English DOS
// Executable scanning reports "1.000.072"
@@ -2302,54 +2461,48 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "df137dc7869cab07e1149ba2333c815c", 478688},
{"resource.006", 0, "b1944bd664ddbd2859cdaa0c4a0d6281", 507489},
{"resource.007", 0, "cd2de58e27665d5853530de93fae7cd6", 490794},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Quest for Glory 2 - English DOS Non-Interactive Demo
// Executable scanning reports "1.000.046"
{"qfg2", "Demo", {
{"resource.map", 0, "e75eb86bdd517b3ef709058249986a87", 906},
{"resource.001", 0, "9b098f9e1008abe30e56c93b896494e6", 362123},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Quest for Glory 3 - English DOS Non-Interactive Demo (from FRG)
// Executable scanning reports "1.001.021", VERSION file reports "1.000, 0.001.059, 6.12.92"
{"qfg3", "Demo", {
{"resource.map", 0, "fd71de9b588a45f085317caacf050e91", 687},
{"resource.000", 0, "b6c69bf6c18bf177492249fe81fc6a6d", 648702},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Quest for Glory 3 - English DOS
// SCI interpreter version 1.001.050
{"qfg3", "", {
{"resource.map", 0, "19e2bf9b693932b5e2bb59b9f9ab86c9", 5958},
{"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868000},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Quest for Glory 3 - English DOS (supplied by abevi in bug report #2612718)
// SCI interpreter version 1.001.050
{"qfg3", "", {
{"resource.map", 0, "62c185d190363d7df06330fa0cc45b36", 5958},
{"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5867442},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Quest for Glory 3 - German DOS (supplied by markcoolio in bug report #2723846)
// Executable scanning reports "L.rry.083"
{"qfg3", "", {
{"resource.map", 0, "19e2bf9b693932b5e2bb59b9f9ab86c9", 5958},
{"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868042},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Quest for Glory 3 - Spanish DOS CD (from jvprat)
// Executable scanning reports "L.rry.083", VERSION file reports "1.000.000, June 30, 1994"
@@ -2357,18 +2510,16 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "10809197c33a5e62819311d8a2f73f85", 5978},
{"resource.000", 0, "ba7ac86155e4c531e46cd73c86daa80a", 5884098},
{"resource.msg", 0, "a63974730d294dec0bea10057c36e506", 256014},
- {NULL, 0, NULL, 0}},
- Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE },
// Quest for Glory 4 - English DOS Non-Interactive Demo (from FRG)
// SCI interpreter version 1.001.069 (just a guess)
{"qfg4", "Demo", {
{"resource.map", 0, "1ba7c7ae1efb315326d45cb931569b1b", 922},
{"resource.000", 0, "41ba03f0b188b029132daa3ece0d3e14", 623154},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
#ifdef ENABLE_SCI32
// Quest for Glory 4 1.1 Floppy - English DOS (supplied by markcool in bug report #2723852)
@@ -2376,58 +2527,33 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"qfg4", "", {
{"resource.map", 0, "685bdb1ed47bbbb0e5e25db392da83ce", 9301},
{"resource.000", 0, "f64fd6aa3977939a86ff30783dd677e1", 11004993},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Quest for Glory 4 1.1 Floppy - English DOS (supplied by abevi in bug report #2612718)
// SCI interpreter version 2.000.000
{"qfg4", "", {
{"resource.map", 0, "d10a4cc177d2091d744e2ad8c049b0ae", 9295},
{"resource.000", 0, "f64fd6aa3977939a86ff30783dd677e1", 11003589},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Quest for Glory 4 1.1 Floppy - German DOS (supplied by markcool in bug report #2723850)
- // SCI interpreter version 2.000.000 (a guess?)
+ // Executable scanning reports "2.000.000", VERSION file reports "1.1"
{"qfg4", "", {
{"resource.map", 0, "9e0abba8746f40565bc7eb5720522ecd", 9301},
{"resource.000", 0, "57f22cdc54eeb35fce1f26b31b5c3ee1", 11076197},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Quest for Glory 4 - English DOS/Windows (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "1.0"
{"qfg4", "", {
{"resource.map", 0, "aba367f2102e81782d961b14fbe3d630", 10246},
{"resource.000", 0, "263dce4aa34c49d3ad29bec889007b1c", 11571394},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
-
-#if 0
- // NOTE: This version looks to be exactly the same as the English one
- // Perhaps it's the English one?
-
- // Quest for Glory 4 - German DOS/Windows (from PCJoker 2/98)
- {"qfg4", "", {
- {"resource.map", 0, "aba367f2102e81782d961b14fbe3d630", 10246},
- {"resource.000", 0, "263dce4aa34c49d3ad29bec889007b1c", 11571394},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
-#endif
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Quest for Glory 4 - German DOS/Windows Disk V1.1 (from PCJoker 2/89)
- // SCI interpreter version 2.000.000 (a guess?)
- {"qfg4", "", {
- {"resource.map", 0, "9e0abba8746f40565bc7eb5720522ecd", 9301},
- {"resource.000", 0, "57f22cdc54eeb35fce1f26b31b5c3ee1", 11076197},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
#endif
// Slater & Charlie go camping
@@ -2435,9 +2561,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "1846b57fe84774be72f7c50ab3c90df0", 2256126},
{"resource.map", 0, "21f85414124dc23e54544a5536dc35cd", 4044},
{"resource.msg", 0, "c44f51fb955eae266fecf360ebcd5ad2", 1132},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NOSPEECH },
#ifdef ENABLE_SCI32
// RAMA - English DOS/Windows Demo
@@ -2445,9 +2570,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"rama", "Demo", {
{"resmap.001", 0, "775304e9b2a545156be4d94209550094", 1393},
{"ressci.001", 0, "259437fd75fdf51e8207fda8c01fa4fd", 2334384},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NONE },
#ifdef ENABLE_SCI3_GAMES
// RAMA - English Windows (from jvprat)
@@ -2459,9 +2583,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.002", 0, "2a68edd064e5e4937b5e9c74b38f2082", 128562138},
{"resmap.003", 0, "31ef4c0621711585d031f0ae81707251", 1636},
{"ressci.003", 0, "2a68edd064e5e4937b5e9c74b38f2082", 6860492},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NONE },
// RAMA - English Windows (from Quietust, in bug report #2850645)
{"rama", "", {
@@ -2471,18 +2594,16 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.002", 0, "2a68edd064e5e4937b5e9c74b38f2082", 128572432},
{"resmap.003", 0, "48841e4b84ef1b98b48d43566fda9e13", 1636},
{"ressci.003", 0, "2a68edd064e5e4937b5e9c74b38f2082", 6870356},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NONE },
// RAMA - Italian Windows CD (from glorifindel)
// SCI interpreter version 3.000.000 (a guess?)
{"rama", "", {
{"ressci.001", 0, "2a68edd064e5e4937b5e9c74b38f2082", 70611091},
{"resmap.001", 0, "70ba2ff04a2b7fb2c52420ba7fbd47c2", 8338},
- {NULL, 0, NULL, 0}},
- Common::IT_ITA, Common::kPlatformWindows, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::IT_ITA, Common::kPlatformWindows, 0, GUIO_NONE },
#endif // ENABLE_SCI3_GAMES
// Shivers - English Windows (from jvprat)
@@ -2490,26 +2611,23 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"shivers", "", {
{"resmap.000", 0, "f2ead37749ed8f6535a2445a7d05a0cc", 46525},
{"ressci.000", 0, "4294c6d7510935f2e0a52e302073c951", 262654836},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NONE },
// Shivers - German Windows (from Tobis87)
{"shivers", "", {
{"resmap.000", 0, "f483d0a1f78334c18052e92785c3086e", 46537},
{"ressci.000", 0, "6751b144671e2deed919eb9d284b07eb", 262390692},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformWindows, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformWindows, 0, GUIO_NONE },
// Shivers - English Windows Demo
// Executable scanning reports "2.100.002"
{"shivers", "Demo", {
{"resmap.000", 0, "d9e0bc5eddefcbe47f528760085d8927", 1186},
{"ressci.000", 0, "3a93c6340b54e07e65d0e5583354d186", 10505469},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NONE },
#ifdef ENABLE_SCI3_GAMES
@@ -2518,16 +2636,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"shivers2", "Demo", {
{"resmap.000", 0, "d8659188b84beaef076bd869837cd530", 634},
{"ressci.000", 0, "7fbac0807a044c9543e8ac376d200e59", 4925003},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NONE },
// Shivers 2 - English Windows (from abevi)
// VERSION.TXT Version 1.0 (3/25/97)
{"shivers2", "", {
{"ressci.001", 0, "a79d03d6eb75be0a79324f14e3d2ace4", 95346793},
{"resmap.001", 0, "a4804d436d90c4ec2e46b537f5e954db", 6268},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
#endif //ENABLE_SCI3_GAMES
@@ -2540,9 +2657,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "61b4f74039399e5aa1e737b16d0fc023", 1409},
{"resource.msg", 0, "1aeafe2b495de288d002109650b66614", 1364},
{"resource.000", 0, "8e10d4f05c1fd9f883384fa38a898489", 377394},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Space Quest 1 VGA Remake - English Amiga (from www.back2roots.org)
// SCI interpreter version 1.000.510 (just a guess)
@@ -2554,9 +2670,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "2588c1c2ca8b9bed0e3411948c0856a9", 839302},
{"resource.004", 0, "b25a1539c71701f7715f738c5037e9a6", 775515},
{"resource.005", 0, "640ffe1a9acde392cc33cc1b1a528328", 806324},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
// Space Quest 1 VGA Remake - English DOS (from the Space Quest Collection)
// Executable scanning reports "T.A00.081", VERSION file reports "2.000"
@@ -2568,18 +2683,27 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "a9e847c687529481f3a22b9bf01f45f7", 1169831},
{"resource.003", 0, "c47600e50c6fc591957ae0c5020ee7b8", 1213262},
{"resource.004", 0, "e19ea4ad131472f9238590f2e1d40289", 1203051},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
+ // Space Quest 1 VGA Remake - English Mac (from Fingolfin)
+ {"sq1sci", "VGA Remake", {
+ {"resource.map", 0, "5c6ad20407261b544238e8dce87afead", 5895},
+ {"resource.000", 0, "2c414644b23839069c8d1a93b721df16", 1017033},
+ {"resource.001", 0, "8744ae2ea6b316e91e2a35ab1aa301d2", 1024622},
+ {"resource.002", 0, "96860704f7a07ecc10bef223b4b2f153", 1273992},
+ {"resource.003", 0, "ae46e195e66df5a131917f0aa80b5669", 1242794},
+ {"resource.004", 0, "91d58a9eb2187c38424990afe4c12bc6", 1250949},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_NOSPEECH },
// Space Quest 1 VGA Remake - English Non-Interactive Demo (from FRG)
// SCI interpreter version 1.000.181
{"sq1sci", "VGA Remake, Demo", {
{"resource.map", 0, "5af709ac5e0e923e0b8174f49978c30e", 636},
{"resource.001", 0, "fd99ea43f57576ded7c86036996346cf", 507642},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Space Quest 1 VGA Remake - Spanish DOS Floppy (from jvprat)
// Executable scanning reports "T.A00.081", VERSION file reports "2.000"
@@ -2592,9 +2716,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "8c22700a02991b763f512f837636b3ca", 1211307},
{"resource.004", 0, "9b78228ad4f9f335fedf74f1812dcfca", 513325},
{"resource.005", 0, "7d4ebcb745c0bf8fc42e4013f52ecd49", 1101812},
- {NULL, 0, NULL, 0}},
- Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Space Quest 3 - English Amiga (from www.back2roots.org)
// SCI interpreter version 0.000.453 (just a guess)
@@ -2604,10 +2727,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 754432},
{"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 746496},
{"resource.004", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 761984},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
- // Space Quest 3 - German Amiga
+ // Space Quest 3 - German Amiga (also includes english language)
// Executable scanning reports "1.004.006"
// SCI interpreter version 0.000.453 (just a guess)
{"sq3", "", {
@@ -2617,15 +2740,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 712374},
{"resource.004", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 545053},
{"resource.005", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 687507},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Space Quest 3 - English DOS Non-Interactive Demo
// SCI interpreter version 0.000.453
{"sq3", "Demo", {
{"resource.map", 0, "ec66ac2b1ce58b2575ba00b65058de1a", 612},
{"resource.001", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 180245},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
// Space Quest 3 - English DOS (provided by richiefs in bug report #2670691)
@@ -2635,7 +2758,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 485158},
{"resource.002", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 720244},
{"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 688367},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Space Quest 3 - English DOS (from the Space Quest Collection)
@@ -2645,7 +2768,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 490247},
{"resource.002", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 715777},
{"resource.003", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 703370},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Space Quest 3 - English DOS (from abevi, bug report #2612718)
@@ -2657,10 +2780,19 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 321222},
{"resource.005", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 328278},
{"resource.006", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 356702},
- {NULL, 0, NULL, 0}},
+ AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Space Quest 3 - German DOS (from Tobis87)
+ // Space Quest 3 - English Mac (from Fingolfin)
+ {"sq3", "", {
+ {"resource.map", 0, "5c931675c6e01c4b418faca85d76c92c", 5844},
+ {"resource.001", 0, "0d8dfe42683b46f3131823233a91ce6a", 771917},
+ {"resource.002", 0, "0d8dfe42683b46f3131823233a91ce6a", 794072},
+ {"resource.003", 0, "0d8dfe42683b46f3131823233a91ce6a", 776536},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_NOSPEECH },
+
+ // Space Quest 3 - German DOS (from Tobis87, also includes english language)
// SCI interpreter version 0.000.453 (?)
{"sq3", "", {
{"resource.map", 0, "4965c78b5eff50d5e4148ce114594ba8", 7584},
@@ -2671,18 +2803,18 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "9107c2aa5398e28b5c5406df13491f85", 322107},
{"resource.006", 0, "9107c2aa5398e28b5c5406df13491f85", 320643},
{"resource.007", 0, "9107c2aa5398e28b5c5406df13491f85", 344287},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Space Quest 3 v1.052 - German DOS (supplied by markcoolio in bug report #2723860)
+ // Space Quest 3 v1.052 - German DOS (supplied by markcoolio in bug report #2723860, also includes english language)
// Executable scanning reports "S.old.114"
{"sq3", "", {
{"resource.map", 0, "f0dd735098c254f584878649c6f08dbc", 5154},
{"resource.001", 0, "9107c2aa5398e28b5c5406df13491f85", 567245},
{"resource.002", 0, "9107c2aa5398e28b5c5406df13491f85", 596768},
{"resource.003", 0, "9107c2aa5398e28b5c5406df13491f85", 693573},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Space Quest 4 - English Amiga
// Executable scanning reports "1.004.024"
@@ -2696,11 +2828,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "1887ed88bb34ae7238650e8f77f26315", 798226},
{"resource.005", 0, "3540d1cc84d674cf4b2c898b88a3b563", 790296},
{"resource.006", 0, "ade814bc4d56244c156d9e9bcfebbc11", 664085},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
- // Space Quest 4 - German Amiga (from www.back2roots.org)
+ // Space Quest 4 - German Amiga (from www.back2roots.org, also includes english language)
// SCI interpreter version 1.000.200 (just a guess)
{"sq4", "", {
{"resource.map", 0, "79641c0d43408e33c251a1d494d2575e", 6252},
@@ -2711,19 +2842,19 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "99c6a017da5e769a3b427ca52c8a564f", 824601},
{"resource.005", 0, "10ee1709e6559c724676d058199b75b5", 818745},
{"resource.006", 0, "67fb188b191d88efe8414af6ea297b93", 672675},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformAmiga, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Space Quest 4 - English DOS
+#if 0
+ // Space Quest 4 - English DOS - THIS VERSION IS PIRATED/CRACKED AND REPACKAGED =DO NOT RE-ADD=
// Executable scanning reports "1.000.753"
// SCI interpreter version 1.000.200 (just a guess)
{"sq4", "", {
{"resource.map", 0, "a18088c8aceb06025dbc945f29e02935", 5124},
{"resource.000", 0, "e1f46832cd2458796028e054a0466031", 5502009},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+#endif
// Space Quest 4 - English DOS
// Executable scanning reports "1.000.753"
@@ -2731,9 +2862,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"sq4", "", {
{"resource.map", 0, "71ccf4f82ac4efb588731acfb7bf2603", 5646},
{"resource.000", 0, "e1f46832cd2458796028e054a0466031", 933928},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Space Quest 4 1.052 - English DOS Floppy (supplied by markcoolio in bug report #2723865)
// Executable scanning reports "1.000.753"
@@ -2746,9 +2876,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "96fa33d89d838bc3f671c5b953e7a896", 1240130},
{"resource.004", 0, "ff9c87da3bc53473fdee8b9d3edbc93c", 1200631},
{"resource.005", 0, "e33019ac19f755ae33fbf49b4fc9066c", 1053294},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Space Quest 4 1.000 - English DOS Floppy (from abevi, bug report #2612718)
{"sq4", "", {
@@ -2759,11 +2888,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "47ee647b5b12232d27e63cc627c25899", 1321146},
{"resource.004", 0, "c06350184a490c10eb4585fff0aa3192", 1254368},
{"resource.005", 0, "b8d6efbd3235329bfe844c794097b2c9", 1098717},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Space Quest 4 - German DOS (from Tobis87)
+ // Space Quest 4 - German DOS (from Tobis87, also includes english language)
// SCI interpreter version 1.000.200 (just a guess)
{"sq4", "", {
{"resource.map", 0, "71715e775e3791178d606cfe6c7e1fb9", 6339},
@@ -2774,11 +2902,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "b8d6efbd3235329bfe844c794097b2c9", 1064761},
{"resource.005", 0, "47ee647b5b12232d27e63cc627c25899", 1156765},
{"resource.006", 0, "dfb023e4e2a1e7a00fa18f9ede72a91b", 924059},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Space Quest 4 - Italian DOS Floppy (from glorifindel)
+ // Space Quest 4 - Italian DOS Floppy (from glorifindel, also includes english language)
// SCI interpreter version 1.000.200 (just a guess)
{"sq4", "", {
{"resource.map", 0, "e753dfa96d68dd95f84f6cd80479a35e", 6135},
@@ -2788,42 +2915,38 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "5289000399d503b59da9e23129256f1a", 1325546},
{"resource.004", 0, "4277c61bed40a50dadc4b5a344520af2", 1251000},
{"resource.005", 0, "5f885abd335978e2fd4e5f886d7676c8", 1102880},
- {NULL, 0, NULL, 0}},
- Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::IT_ITA, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Space Quest 4 - Japanese PC-98 5.25" Floppy
+ // Space Quest 4 - Japanese PC-98 5.25" Floppy (also includes english language)
// SCI interpreter version 1.000.1068
{"sq4", "", {
{"resource.map", 0, "ca7bba01019222b6f3e54e9051067a99", 5283},
{"resource.000", 0, "161d719f38ed98d33f058a8cf3dc09c3", 952909},
{"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088},
{"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249},
- {NULL, 0, NULL, 0}},
- Common::JA_JPN, Common::kPlatformPC98, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Space Quest 4 - Japanese PC-98 5.25" Floppy
+ // Space Quest 4 - Japanese PC-98 5.25" Floppy (also includes english language)
// SCI interpreter version 1.000.1068
{"sq4", "", {
{"resource.map", 0, "ca7bba01019222b6f3e54e9051067a99", 5283},
{"resource.000", 0, "161d719f38ed98d33f058a8cf3dc09c3", 952909},
{"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088},
{"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC98, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Space Quest 4 - English DOS CD (from the Space Quest Collection)
// Executable scanning reports "1.001.064", VERSION file reports "1.0"
{"sq4", "CD", {
{"resource.map", 0, "ed90a8e3ccc53af6633ff6ab58392bae", 7054},
{"resource.000", 0, "63247e3901ab8963d4eece73747832e0", 5157378},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
- // Space Quest 4 - Spanish DOS CD (from jvprat)
+ // Space Quest 4 - Spanish DOS CD (from jvprat, is still text only, not talkie, also includes english language)
// Executable scanning reports "1.SQ4.057", VERSION file reports "1.000"
// SCI interpreter version 1.000.200 (just a guess)
{"sq4", "", {
@@ -2834,11 +2957,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "42a307941edeb1a3be31daeb2e4be90b", 1319306},
{"resource.004", 0, "776fba81c110d1908776232cbe190e20", 1253752},
{"resource.005", 0, "55fae26c2a92f16ef72c1e216e827c0f", 1098328},
- {NULL, 0, NULL, 0}},
- Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NONE },
- // Space Quest 4 - Spanish DOS Floppy (from jvprat)
+ // Space Quest 4 - Spanish DOS Floppy (from jvprat, also includes english language)
// Executable scanning reports "1.SQ4.056", VERSION file reports "1.000"
// SCI interpreter version 1.000.200 (just a guess)
{"sq4", "", {
@@ -2847,11 +2969,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "567608beb69d9dffdb42a8f39cb11a5e", 994323},
{"resource.002", 0, "74c62fa2146ff3b3b2ea2b3fb95b9af9", 1140801},
{"resource.003", 0, "42a307941edeb1a3be31daeb2e4be90b", 1088408},
- {NULL, 0, NULL, 0}},
- Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::ES_ESP, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Space Quest 4 1.000 - German DOS Floppy (supplied by markcoolio in bug report #2723862)
+ // Space Quest 4 1.000 - German DOS Floppy (supplied by markcoolio in bug report #2723862, also includes english language)
// Executable scanning reports "1.SQ4.030"
// SCI interpreter version 1.000.200 (just a guess)
{"sq4", "", {
@@ -2862,9 +2983,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "47ee647b5b12232d27e63cc627c25899", 1321146},
{"resource.004", 0, "c06350184a490c10eb4585fff0aa3192", 1254368},
{"resource.005", 0, "b8d6efbd3235329bfe844c794097b2c9", 1098717},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_ADDENGLISH, GUIO_NOSPEECH },
// Space Quest 4 - English Macintosh
// Executable scanning reports "x.yyy.zzz"
@@ -2878,9 +2998,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.004", 0, "20fc54556ebfc737506288a1a32f7705", 364217},
{"resource.005", 0, "869d16cab6641c80b06f4dcee18f86bc", 1426228},
{"resource.006", 0, "91d23407bc0447a3722fbeb952d7edee", 1402451},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_NOSPEECH },
// Space Quest 5 - English DOS (from the Space Quest Collection)
// Executable scanning reports "1.001.068", VERSION file reports "1.04"
@@ -2888,18 +3007,16 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "66317c12ac6e818d1f7c17e83c1d9819", 6143},
{"resource.000", 0, "4147edc5045e6d62998018b5614c58ec", 5496486},
{"resource.msg", 0, "bb8ad78793c26bdb3f77498b1d6515a9", 125988},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Space Quest 5 - English DOS
// SCI interpreter version 1.001.067
{"sq5", "", {
{"resource.map", 0, "8bde0a9adb9a3e9aaa861826874c9834", 6473},
{"resource.000", 0, "f4a48705764544d7cc64a7bb22a610df", 6025184},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Space Quest 5 v1.04 - German DOS (from Tobis87, updated information by markcool from bug reports #2723935 and #2724762)
// SCI interpreter version 1.001.068
@@ -2907,27 +3024,24 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "66317c12ac6e818d1f7c17e83c1d9819", 6143},
{"resource.000", 0, "4147edc5045e6d62998018b5614c58ec", 5496486},
{"resource.msg", 0, "7c71cfc36153cfe07b450423a51f7e68", 146282},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Space Quest 5 v1.04 - French DOS (from Hkz, Included in Space Quest Collector's Edition, with chapters I-V)
{"sq5", "", {
{"resource.map", 0, "66317c12ac6e818d1f7c17e83c1d9819", 6143},
{"resource.000", 0, "4147edc5045e6d62998018b5614c58ec", 5496486},
{"resource.msg", 0, "877c42380320eb1db7dad83ccd261214", 140374},
- {NULL, 0, NULL, 0}},
- Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// Space Quest 5 - Italian DOS Floppy (from glorifindel)
// SCI interpreter version 1.001.068 (just a guess)
{"sq5", "", {
{"resource.000", 0, "5040026519f37199f3616fb1d4704dff", 6047170},
{"resource.map", 0, "5b09168baa2f6e2e22787429b2d72f54", 6492},
- {NULL, 0, NULL, 0}},
- Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH },
#ifdef ENABLE_SCI32
// Space Quest 6 - English DOS/Win3.11 CD (from the Space Quest Collection)
@@ -2935,45 +3049,40 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"sq6", "", {
{"resource.map", 0, "6dddfa3a8f3a3a513ec9dfdfae955005", 10528},
{"resource.000", 0, "c4259ab7355aead07773397b1052827d", 41150806},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// Space Quest 6 - English DOS/Win3.11 CD ver 1.11 (from FRG)
// SCI interpreter version 2.100.002 (just a guess)
{"sq6", "", {
{"resource.map", 0, "e0615d6e4e10e37ae42e6a2a95aaf145", 10528},
{"resource.000", 0, "c4259ab7355aead07773397b1052827d", 41150806},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// Space Quest 6 - French DOS/Win3.11 CD (from French magazine Joystick - September 1997)
// Executable scanning reports "2.100.002", VERSION file reports "1.0"
{"sq6", "", {
{"resource.map", 0, "3c831625931d5079b73ae8c275f52c95", 10534},
{"resource.000", 0, "4195ca940f759424f62b90e262cc1737", 40932397},
- {NULL, 0, NULL, 0}},
- Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NONE },
// Space Quest 6 - German DOS (from Tobis87, updated info from markcoolio in bug report #2723884)
// SCI interpreter version 2.100.002 (just a guess)
{"sq6", "", {
{"resource.map", 0, "664d797415484f85c90b1b45aedc7686", 10534},
{"resource.000", 0, "ba87ba91e5bdabb4169dd0df75777722", 40933685},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NONE },
// Space Quest 6 - English DOS/Win3.11 Interactive Demo (from FRG)
// SCI interpreter version 2.100.002 (just a guess)
{"sq6", "Demo", {
{"resource.map", 0, "368f07b07433db3f819fa3fa0e5efee5", 2572},
{"resource.000", 0, "ab12724e078dea34b624e0d2a38dcd7c", 2272050},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
#endif // ENABLE_SCI32
// The Island of Dr. Brain - English DOS CD (from jvprat)
@@ -2981,27 +3090,24 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"islandbrain", "", {
{"resource.map", 0, "2388efef8430b041b0f3b00b9050e4a2", 3281},
{"resource.000", 0, "b3acd9b9dd7fe53c4ee133ac9a1acfab", 2103560},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
// The Island of Dr. Brain - English DOS (from Quietust)
// Executable scanning reports "1.001.053", VERSION file reports "1.1 2.3.93"
{"islandbrain", "", {
{"resource.map", 0, "3c07da06bdd1689f9d07af78fb94d0ec", 3101},
{"resource.000", 0, "ecc686e0034fb4d41de077ac7167b3cf", 1947866},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
// The Island of Dr. Brain - English DOS Non-Interactive Demo
// SCI interpreter version 1.001.053 (just a guess)
{"islandbrain", "Demo", {
{"resource.map", 0, "a8e5ca8ed1996974afa59f4c45e06195", 986},
{"resource.000", 0, "b3acd9b9dd7fe53c4ee133ac9a1acfab", 586560},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
#ifdef ENABLE_SCI32
// Torin's Passage - English Windows Interactive Demo
@@ -3009,18 +3115,16 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"torin", "Demo", {
{"resmap.000", 0, "9a3e172cde9963d0a969f26469318cec", 3403},
{"ressci.000", 0, "db3e290481c35c3224e9602e71e4a1f1", 5073868},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NOSPEECH },
// Torin's Passage - English Windows
// SCI interpreter version 2.100.002 (just a guess)
{"torin", "", {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
// Torin's Passage - Spanish Windows (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "1.0"
@@ -3028,59 +3132,66 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
// TODO: depend on one of the patches?
- {NULL, 0, NULL, 0}},
- Common::ES_ESP, Common::kPlatformWindows, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::ES_ESP, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
// Torin's Passage - French Windows
// SCI interpreter version 2.100.002 (just a guess)
{"torin", "", {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
- {NULL, 0, NULL, 0}},
- Common::FR_FRA, Common::kPlatformWindows, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
// Torin's Passage - German Windows
// SCI interpreter version 2.100.002 (just a guess)
{"torin", "", {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
- {NULL, 0, NULL, 0}},
- Common::DE_DEU, Common::kPlatformWindows, 0, GUIO_NOSPEECH
- },
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
// Torin's Passage - Italian Windows CD (from glorifindel)
// SCI interpreter version 2.100.002 (just a guess)
{"torin", "", {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
- {NULL, 0, NULL, 0}},
- Common::IT_ITA, Common::kPlatformWindows, 0, GUIO_NONE
- },
+ AD_LISTEND},
+ Common::IT_ITA, Common::kPlatformWindows, 0, GUIO_NONE },
#endif // ENABLE_SCI32
// SCI Fanmade Games
- FANMADE("Al Pond 2: Island Quest", "9625372e710d1a95d2027b48f9e325af", 1506, "a0f9aa65b9bf3d8703adff5a621f243c", 889843),
FANMADE("Al Pond: Island Quest 2", "4cba6a5a4c8f66f21935ed78b0511a92", 870, "876587dc9a5ec569287a3dc4b29139d8", 613769),
+ FANMADE("Al Pond 2: Island Quest", "9625372e710d1a95d2027b48f9e325af", 1506, "a0f9aa65b9bf3d8703adff5a621f243c", 889843),
+ FANMADE("Al Pond 2: Island Quest (Updated)", "64be277cdcc6aafce7d9f26e88ad31a8", 1500, "571547228a212d63315f0c114cf48d54", 885241),
FANMADE("Another DG Game: I Want My C64 Back", "4a8ca7ca2abd18899ef856f47665e2e9", 588, "12ff558d20c72e42cc6adb408f34d6d8", 150513),
FANMADE_L("Another DG Game: I Want My C64 Back", "13dc1d9ebc57daf8895412eee5e39fea", 576, "e2ad60b3a280171429db5c85f158f84a", 141697, Common::FR_FRA),
+ FANMADE("Aquarius: An Aquatic Experience", "2e23bc3b82f22a454be202ea593fb478", 480, "01555c8de683d25405bda270aa1ff014", 272372),
FANMADE("Bluntman and Chronic (Politically Correct Version)", "c3ef9fa6c7c5fb840078bf28d87c7f8b", 1362, "441636a9f6f86710844868fded868ee7", 596688),
FANMADE("Cascade Quest", "c94efc10d18c040b6e22a1dc6d3adfe1", 3468, "8ada33dfa945f81531e5508240b573de", 1432195),
- FANMADE("Curt Quest 1.0", "b0e555370380d218968a40a68eaaaffc", 1146, "c851182cdf6fc6a81b840f4d4875f1a0", 307165),
- FANMADE("Curt Quest 1.1", "54084c29346683296e45ef32d7ae74f3", 1128, "c851182cdf6fc6a81b840f4d4875f1a0", 302000),
+ FANMADE("Circus Quest", "35871f6b4e1df56af4113c0203a0b223", 630, "7d6f97d7935d8733f488d4cb74315e5b", 279627),
+ FANMADE("Curt's Quest 1.0", "b0e555370380d218968a40a68eaaaffc", 1146, "c851182cdf6fc6a81b840f4d4875f1a0", 307165),
+ FANMADE("Curt's Quest 1.1", "54084c29346683296e45ef32d7ae74f3", 1128, "c851182cdf6fc6a81b840f4d4875f1a0", 302000),
FANMADE("Demo Quest", "c89a0c9e0a4e4af0ecedb300a3b31dbf", 384, "a32f3495ba24764cba091119cc3f1e13", 160098),
FANMADE("Dr. Jummybummy's Space Adventure 2", "6ae6cb7de423f51736d9487b4ca0c6da", 810, "26e5b563f578e104d79689f36568b7cf", 394670),
FANMADE_L("Grostesteing: Plus Mechant que Jamais", "ec9a97ccb134f69249f6ea8b16c13d8e", 1500, "b869f5f11bfe2ab5f67f4f0c618f2ce1", 464657, Common::FR_FRA), // FIXME: Accent
- FANMADE("Jim Quest", "0af50be1d3f0cb77a09137709a76ef4f", 960, "9c042c136548b20d9183495668e03526", 496446),
+ FANMADE("Humanoid Demo", "97d8331293a6d57e8bad58c1efc89a63", 624, "fb354b9abe64011b12159e45d724633f", 452320),
+ FANMADE("Jim’s Quest 1: The Phantom Thesis", "0af50be1d3f0cb77a09137709a76ef4f", 960, "9c042c136548b20d9183495668e03526", 496446),
FANMADE("Knight's Quest Demo 1.0", "5e816edf993956752ed06fccfeeae6d9", 1260, "959321f88a22905fa1f8c6d897874744", 703836),
FANMADE("LockerGnome Quest", "3eeff9130206cad0c4e1551e2b9dd2c5", 420, "ae05ca90806fd90cc43f147c82d3547c", 158906),
- FANMADE("New Year's Mystery", "efd1beb5120293725065c95959144f81", 714, "b3bd3c2372ed6efa28adb12403c4c31a", 305027),
+ FANMADE("New Year's Mystery", "e4dcab1b1d3cb4a2c070a07a9c9589e0", 708, "e00ca5e44fd4e98d8174b467b31b0f21", 295425),
+ FANMADE("New Year's Mystery (Updated)", "efd1beb5120293725065c95959144f81", 714, "b3bd3c2372ed6efa28adb12403c4c31a", 305027),
+ FANMADE("Ocean Battle", "c2304a0568e0eb84f8e9a0915f01170a", 408, "46c520c1ac9b63528854d0f58c7e1b74", 142234),
FANMADE("Osama", "db8f1710453cfbecf4214b2946970043", 390, "7afd75d4620dedf97a84ae8f0a7523cf", 123827),
FANMADE("Quest for the Cheat", "a359d4cf27f98264b42b55c017671214", 882, "8a943029f73c4bc85d454b7f473455ba", 455209),
+ FANMADE("SCI Capture the Flag", "4cd679a51d93b8b27c6b38d81be24b8b", 432, "98ae1f6ed7b4c21f88addbf643dd1d2f", 147878),
FANMADE("SCI Companion Template", "ad54d4f504086cd597aa2348d0aa3b09", 354, "6798b7b601ce8154c1d1bc0f0edcdd18", 113061),
+ FANMADE("SCI Programming April 2010 Competition Template", "36e5c4011dd7c92e1ae4c6fede7d698d", 456, "20c87fbb7f73e2a3eb2c5dfab4d76b5a", 142221),
FANMADE("SCI Studio Template 3.0", "ca0dc8d586e0a8670b7621cde090b532", 354, "58a48ee692a86c0575e6bd0b00a92b9a", 113097),
FANMADE("SCI Quest", "9067e1f1e54436d2dbfce855524bc84a", 552, "ffa7d355cd9223f245289108a696bcd2", 149634),
+ FANMADE("SCI-Man", "3ab85bd39a86c11f85781764f9db09bb", 468, "bb8f9992f504a242bf0860e3588e150b", 131810),
+ FANMADE("The Farm Nightmare", "fb6cbfddaa7c055e2c3d8cf4c683a7db", 906, "50655e8b8925f717e698e08f006f40be", 338303),
+ FANMADE("The Gem Scenario", "ef5f61f4d2c6d31122d3e2baf89ad976", 642, "2f16be390dd90c3d7ca1c8a594ac0bfa", 244794),
FANMADE("The Legend of the Lost Jewel", "ba1bca315e3818c5626eda51bcfbcccf", 636, "9b0736d69924af0cff32a0f78db96855", 300398),
// FIXME: The vga demo does not have a resource.000/001 file.
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index e51867332a..f99d412c64 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -24,6 +24,7 @@
*/
#include "sci/engine/features.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/script.h"
#include "sci/engine/selector.h"
#include "sci/engine/vm.h"
@@ -37,6 +38,7 @@ GameFeatures::GameFeatures(SegManager *segMan, Kernel *kernel) : _segMan(segMan)
_doSoundType = SCI_VERSION_NONE;
_lofsType = SCI_VERSION_NONE;
_gfxFunctionsType = SCI_VERSION_NONE;
+ _messageFunctionType = SCI_VERSION_NONE;
_moveCountType = kMoveCountUninitialized;
#ifdef ENABLE_SCI32
@@ -51,13 +53,13 @@ reg_t GameFeatures::getDetectionAddr(const Common::String &objName, Selector slc
reg_t addr;
if (objAddr.isNull()) {
- warning("getDetectionAddr: %s object couldn't be found", objName.c_str());
+ error("getDetectionAddr: %s object couldn't be found", objName.c_str());
return NULL_REG;
}
if (methodNum == -1) {
- if (lookup_selector(_segMan, objAddr, slc, NULL, &addr) != kSelectorMethod) {
- warning("getDetectionAddr: target selector is not a method of object %s", objName.c_str());
+ if (lookupSelector(_segMan, objAddr, slc, NULL, &addr) != kSelectorMethod) {
+ error("getDetectionAddr: target selector is not a method of object %s", objName.c_str());
return NULL_REG;
}
} else {
@@ -69,7 +71,7 @@ reg_t GameFeatures::getDetectionAddr(const Common::String &objName, Selector slc
bool GameFeatures::autoDetectSoundType() {
// Look up the script address
- reg_t addr = getDetectionAddr("Sound", _kernel->_selectorCache.play);
+ reg_t addr = getDetectionAddr("Sound", SELECTOR(play));
if (!addr.segment)
return false;
@@ -83,17 +85,17 @@ bool GameFeatures::autoDetectSoundType() {
int16 opparams[4];
byte extOpcode;
byte opcode;
- offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams);
+ offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams);
opcode = extOpcode >> 1;
// Check for end of script
- if (opcode == op_ret || offset >= script->_bufSize)
+ if (opcode == op_ret || offset >= script->getBufSize())
break;
- // The play method of the Sound object pushes the DoSound command
- // that it'll use just before it calls DoSound. We intercept that here
- // in order to check what sound semantics are used, cause the position
- // of the sound commands has changed at some point during SCI1 middle
+ // The play method of the Sound object pushes the DoSound command that
+ // it will use just before it calls DoSound. We intercept that here in
+ // order to check what sound semantics are used, cause the position of
+ // the sound commands has changed at some point during SCI1 middle.
if (opcode == op_pushi) {
// Load the pushi parameter
intParam = opparams[0];
@@ -104,8 +106,8 @@ bool GameFeatures::autoDetectSoundType() {
if (kFuncNum == 6) { // kIsObject (SCI0-SCI11)
foundTarget = true;
} else if (kFuncNum == 45) { // kDoSound (SCI1)
- // First, check which DoSound function is called by the play method of
- // the Sound object
+ // First, check which DoSound function is called by the play
+ // method of the Sound object
switch (intParam) {
case 1:
_doSoundType = SCI_VERSION_0_EARLY;
@@ -118,8 +120,8 @@ bool GameFeatures::autoDetectSoundType() {
break;
default:
// Unknown case... should never happen. We fall back to
- // alternative detection here, which works in general, apart from
- // some transitive games like Jones CD
+ // alternative detection here, which works in general, apart
+ // from some transitive games like Jones CD
_doSoundType = foundTarget ? SCI_VERSION_1_LATE : SCI_VERSION_1_EARLY;
break;
}
@@ -136,9 +138,14 @@ bool GameFeatures::autoDetectSoundType() {
SciVersion GameFeatures::detectDoSoundType() {
if (_doSoundType == SCI_VERSION_NONE) {
if (getSciVersion() == SCI_VERSION_0_EARLY) {
- // This game is using early SCI0 sound code (different headers than SCI0 late)
+ // This game is using early SCI0 sound code (different headers than
+ // SCI0 late)
_doSoundType = SCI_VERSION_0_EARLY;
- } else if (_kernel->_selectorCache.nodePtr == -1) {
+#ifdef ENABLE_SCI32
+ } else if (getSciVersion() >= SCI_VERSION_2_1) {
+ _doSoundType = SCI_VERSION_2_1;
+#endif
+ } else if (SELECTOR(nodePtr) == -1) {
// No nodePtr selector, so this game is definitely using newer
// SCI0 sound code (i.e. SCI_VERSION_0_LATE)
_doSoundType = SCI_VERSION_0_LATE;
@@ -171,14 +178,16 @@ SciVersion GameFeatures::detectSetCursorType() {
// SCI1.1 games always use cursor views
_setCursorType = SCI_VERSION_1_1;
} else { // SCI1 late game, detect cursor semantics
- // If the Cursor object doesn't exist, we're using the SCI0 early kSetCursor semantics.
+ // If the Cursor object doesn't exist, we're using the SCI0 early
+ // kSetCursor semantics.
if (_segMan->findObjectByName("Cursor") == NULL_REG) {
_setCursorType = SCI_VERSION_0_EARLY;
debugC(1, kDebugLevelGraphics, "Detected SetCursor type: %s", getSciVersionDesc(_setCursorType));
return _setCursorType;
}
- // Check for the existence of the handCursor object (first found). This is based on KQ5.
+ // Check for the existence of the handCursor object (first found).
+ // This is based on KQ5.
reg_t objAddr = _segMan->findObjectByName("handCursor", 0);
// If that doesn't exist, we assume it uses SCI1.1 kSetCursor semantics
@@ -188,11 +197,13 @@ SciVersion GameFeatures::detectSetCursorType() {
return _setCursorType;
}
- // Now we check what the number variable holds in the handCursor object.
- uint16 number = GET_SEL32V(_segMan, objAddr, SELECTOR(number));
+ // Now we check what the number variable holds in the handCursor
+ // object.
+ uint16 number = readSelectorValue(_segMan, objAddr, SELECTOR(number));
- // If the number is 0, it uses views and therefore the SCI1.1 kSetCursor semantics,
- // otherwise it uses the SCI0 early kSetCursor semantics.
+ // If the number is 0, it uses views and therefore the SCI1.1
+ // kSetCursor semantics, otherwise it uses the SCI0 early kSetCursor
+ // semantics.
if (number == 0)
_setCursorType = SCI_VERSION_1_1;
else
@@ -205,9 +216,9 @@ SciVersion GameFeatures::detectSetCursorType() {
return _setCursorType;
}
-bool GameFeatures::autoDetectLofsType(int methodNum) {
+bool GameFeatures::autoDetectLofsType(Common::String gameSuperClassName, int methodNum) {
// Look up the script address
- reg_t addr = getDetectionAddr("Game", -1, methodNum);
+ reg_t addr = getDetectionAddr(gameSuperClassName.c_str(), -1, methodNum);
if (!addr.segment)
return false;
@@ -219,11 +230,11 @@ bool GameFeatures::autoDetectLofsType(int methodNum) {
int16 opparams[4];
byte extOpcode;
byte opcode;
- offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams);
+ offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams);
opcode = extOpcode >> 1;
// Check for end of script
- if (opcode == op_ret || offset >= script->_bufSize)
+ if (opcode == op_ret || offset >= script->getBufSize())
break;
if (opcode == op_lofsa || opcode == op_lofss) {
@@ -231,13 +242,13 @@ bool GameFeatures::autoDetectLofsType(int methodNum) {
uint16 lofs = opparams[0];
// Check for going out of bounds when interpreting as abs/rel
- if (lofs >= script->_bufSize)
+ if (lofs >= script->getBufSize())
_lofsType = SCI_VERSION_0_EARLY;
if ((signed)offset + (int16)lofs < 0)
_lofsType = SCI_VERSION_1_MIDDLE;
- if ((signed)offset + (int16)lofs >= (signed)script->_bufSize)
+ if ((signed)offset + (int16)lofs >= (signed)script->getBufSize())
_lofsType = SCI_VERSION_1_MIDDLE;
if (_lofsType != SCI_VERSION_NONE)
@@ -264,20 +275,35 @@ SciVersion GameFeatures::detectLofsType() {
return _lofsType;
}
+ // Find the "Game" object, super class of the actual game-object
+ const reg_t game = g_sci->getGameObject();
+ const Object *gameObject = _segMan->getObject(game);
+ reg_t gameSuperClass = NULL_REG;
+ if (gameObject) {
+ gameSuperClass = gameObject->getSuperClassSelector();
+ }
+
// Find a function of the game object which invokes lofsa/lofss
- reg_t gameClass = _segMan->findObjectByName("Game");
- Object *obj = _segMan->getObject(gameClass);
bool found = false;
+ if (!gameSuperClass.isNull()) {
+ Common::String gameSuperClassName = _segMan->getObjectName(gameSuperClass);
+ const Object *gameSuperObject = _segMan->getObject(gameSuperClass);
- for (uint m = 0; m < obj->getMethodCount(); m++) {
- found = autoDetectLofsType(m);
-
- if (found)
- break;
+ if (gameSuperObject) {
+ for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) {
+ found = autoDetectLofsType(gameSuperClassName, m);
+ if (found)
+ break;
+ }
+ } else {
+ warning("detectLofsType(): Could not get superclass object");
+ }
+ } else {
+ warning("detectLofsType(): Could not find superclass of game object");
}
if (!found) {
- warning("Lofs detection failed, taking an educated guess");
+ warning("detectLofsType(): failed, taking an educated guess");
if (getSciVersion() >= SCI_VERSION_1_MIDDLE)
_lofsType = SCI_VERSION_1_MIDDLE;
@@ -293,7 +319,7 @@ SciVersion GameFeatures::detectLofsType() {
bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) {
// Look up the script address
- reg_t addr = getDetectionAddr("Rm", _kernel->_selectorCache.overlay, methodNum);
+ reg_t addr = getDetectionAddr("Rm", SELECTOR(overlay), methodNum);
if (!addr.segment)
return false;
@@ -305,11 +331,11 @@ bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) {
int16 opparams[4];
byte extOpcode;
byte opcode;
- offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams);
+ offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams);
opcode = extOpcode >> 1;
// Check for end of script
- if (opcode == op_ret || offset >= script->_bufSize)
+ if (opcode == op_ret || offset >= script->getBufSize())
break;
if (opcode == op_callk) {
@@ -317,10 +343,10 @@ bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) {
uint16 argc = opparams[1];
if (kFuncNum == 8) { // kDrawPic (SCI0 - SCI11)
- // If kDrawPic is called with 6 parameters from the
- // overlay selector, the game is using old graphics functions.
+ // If kDrawPic is called with 6 parameters from the overlay
+ // selector, the game is using old graphics functions.
// Otherwise, if it's called with 8 parameters, it's using new
- // graphics functions
+ // graphics functions.
_gfxFunctionsType = (argc == 8) ? SCI_VERSION_0_LATE : SCI_VERSION_0_EARLY;
return true;
}
@@ -332,18 +358,50 @@ bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) {
SciVersion GameFeatures::detectGfxFunctionsType() {
if (_gfxFunctionsType == SCI_VERSION_NONE) {
- // This detection only works (and is only needed) for SCI0 games
- if (getSciVersion() >= SCI_VERSION_01) {
+ if (getSciVersion() == SCI_VERSION_0_EARLY) {
+ // Old SCI0 games always used old graphics functions
+ _gfxFunctionsType = SCI_VERSION_0_EARLY;
+ } else if (getSciVersion() >= SCI_VERSION_01) {
+ // SCI01 and newer games always used new graphics functions
_gfxFunctionsType = SCI_VERSION_0_LATE;
- } else if (getSciVersion() > SCI_VERSION_0_EARLY) {
+ } else { // SCI0 late
// Check if the game is using an overlay
- bool found = false;
+ bool searchRoomObj = false;
+ reg_t rmObjAddr = _segMan->findObjectByName("Rm");
+
+ if (SELECTOR(overlay) != -1) {
+ // The game has an overlay selector, check how it calls kDrawPic
+ // to determine the graphics functions type used
+ if (lookupSelector(_segMan, rmObjAddr, SELECTOR(overlay), NULL, NULL) == kSelectorMethod) {
+ if (!autoDetectGfxFunctionsType()) {
+ warning("Graphics functions detection failed, taking an educated guess");
+
+ // Try detecting the graphics function types from the
+ // existence of the motionCue selector (which is a bit
+ // of a hack)
+ if (_kernel->findSelector("motionCue") != -1)
+ _gfxFunctionsType = SCI_VERSION_0_LATE;
+ else
+ _gfxFunctionsType = SCI_VERSION_0_EARLY;
+ }
+ } else {
+ // The game has an overlay selector, but it's not a method
+ // of the Rm object (like in Hoyle 1 and 2), so search for
+ // other methods
+ searchRoomObj = true;
+ }
+ } else {
+ // The game doesn't have an overlay selector, so search for it
+ // manually
+ searchRoomObj = true;
+ }
- if (_kernel->_selectorCache.overlay == -1) {
- // No overlay selector found, check if any method of the Rm object
- // is calling kDrawPic, as the overlay selector might be missing in demos
+ if (searchRoomObj) {
+ // If requested, check if any method of the Rm object is calling
+ // kDrawPic, as the overlay selector might be missing in demos
+ bool found = false;
- Object *obj = _segMan->getObject(_segMan->findObjectByName("Rm"));
+ const Object *obj = _segMan->getObject(rmObjAddr);
for (uint m = 0; m < obj->getMethodCount(); m++) {
found = autoDetectGfxFunctionsType(m);
if (found)
@@ -351,30 +409,12 @@ SciVersion GameFeatures::detectGfxFunctionsType() {
}
if (!found) {
- // No overlay selector found, therefore the game is definitely
- // using old graphics functions
+ // No method of the Rm object is calling kDrawPic, thus the
+ // game doesn't have overlays and is using older graphics
+ // functions
_gfxFunctionsType = SCI_VERSION_0_EARLY;
}
- } else { // _kernel->_selectorCache.overlay != -1
- // An in-between case: The game does not have a shiftParser
- // selector, but it does have an overlay selector, so it uses an
- // overlay. Therefore, check it to see how it calls kDrawPic to
- // determine the graphics functions type used
-
- if (!autoDetectGfxFunctionsType()) {
- warning("Graphics functions detection failed, taking an educated guess");
-
- // Try detecting the graphics function types from the existence of the motionCue
- // selector (which is a bit of a hack)
- if (_kernel->findSelector("motionCue") != -1)
- _gfxFunctionsType = SCI_VERSION_0_LATE;
- else
- _gfxFunctionsType = SCI_VERSION_0_EARLY;
- }
}
- } else { // (getSciVersion() == SCI_VERSION_0_EARLY)
- // Old SCI0 games always used old graphics functions
- _gfxFunctionsType = SCI_VERSION_0_EARLY;
}
debugC(1, kDebugLevelVM, "Detected graphics functions type: %s", getSciVersionDesc(_gfxFunctionsType));
@@ -383,10 +423,60 @@ SciVersion GameFeatures::detectGfxFunctionsType() {
return _gfxFunctionsType;
}
+SciVersion GameFeatures::detectMessageFunctionType() {
+ if (_messageFunctionType != SCI_VERSION_NONE)
+ return _messageFunctionType;
+
+ if (getSciVersion() > SCI_VERSION_1_1) {
+ _messageFunctionType = SCI_VERSION_1_1;
+ return _messageFunctionType;
+ } else if (getSciVersion() < SCI_VERSION_1_1) {
+ _messageFunctionType = SCI_VERSION_1_LATE;
+ return _messageFunctionType;
+ }
+
+ Common::List<ResourceId> *resources = g_sci->getResMan()->listResources(kResourceTypeMessage, -1);
+
+ if (resources->empty()) {
+ delete resources;
+
+ // No messages found, so this doesn't really matter anyway...
+ _messageFunctionType = SCI_VERSION_1_1;
+ return _messageFunctionType;
+ }
+
+ Resource *res = g_sci->getResMan()->findResource(*resources->begin(), false);
+ assert(res);
+ delete resources;
+
+ // Only v2 Message resources use the kGetMessage kernel function.
+ // v3-v5 use the kMessage kernel function.
+
+ if (READ_SCI11ENDIAN_UINT32(res->data) / 1000 == 2)
+ _messageFunctionType = SCI_VERSION_1_LATE;
+ else
+ _messageFunctionType = SCI_VERSION_1_1;
+
+ debugC(1, kDebugLevelVM, "Detected message function type: %s", getSciVersionDesc(_messageFunctionType));
+ return _messageFunctionType;
+}
+
#ifdef ENABLE_SCI32
bool GameFeatures::autoDetectSci21KernelType() {
+ // First, check if the Sound object is loaded
+ reg_t soundObjAddr = _segMan->findObjectByName("Sound");
+ if (soundObjAddr.isNull()) {
+ // Usually, this means that the Sound object isn't loaded yet.
+ // This case doesn't occur in early SCI2.1 games, and we've only
+ // seen it happen in the RAMA demo, thus we can assume that the
+ // game is using a SCI2.1 table
+ warning("autoDetectSci21KernelType(): Sound object not loaded, assuming a SCI2.1 table");
+ _sci21KernelType = SCI_VERSION_2_1;
+ return true;
+ }
+
// Look up the script address
- reg_t addr = getDetectionAddr("Sound", _kernel->_selectorCache.play);
+ reg_t addr = getDetectionAddr("Sound", SELECTOR(play));
if (!addr.segment)
return false;
@@ -398,20 +488,22 @@ bool GameFeatures::autoDetectSci21KernelType() {
int16 opparams[4];
byte extOpcode;
byte opcode;
- offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams);
+ offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams);
opcode = extOpcode >> 1;
// Check for end of script
- if (opcode == op_ret || offset >= script->_bufSize)
+ if (opcode == op_ret || offset >= script->getBufSize())
break;
if (opcode == op_callk) {
uint16 kFuncNum = opparams[0];
// Here we check for the kDoSound opcode that's used in SCI2.1.
- // Finding 0x40 as kDoSound in the Sound::play() function means the game is using
- // the modified SCI2 kernel table found in some older SCI2.1 games (GK2 demo, KQ7 v1.4).
- // Finding 0x75 as kDoSound means the game is using the regular SCI2.1 kernel table.
+ // Finding 0x40 as kDoSound in the Sound::play() function means the
+ // game is using the modified SCI2 kernel table found in some older
+ // SCI2.1 games (GK2 demo, KQ7 v1.4).
+ // Finding 0x75 as kDoSound means the game is using the regular
+ // SCI2.1 kernel table.
if (kFuncNum == 0x40) {
_sci21KernelType = SCI_VERSION_2;
return true;
@@ -438,7 +530,7 @@ SciVersion GameFeatures::detectSci21KernelType() {
bool GameFeatures::autoDetectMoveCountType() {
// Look up the script address
- reg_t addr = getDetectionAddr("Motion", _kernel->_selectorCache.doit);
+ reg_t addr = getDetectionAddr("Motion", SELECTOR(doit));
if (!addr.segment)
return false;
@@ -451,11 +543,11 @@ bool GameFeatures::autoDetectMoveCountType() {
int16 opparams[4];
byte extOpcode;
byte opcode;
- offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams);
+ offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams);
opcode = extOpcode >> 1;
// Check for end of script
- if (opcode == op_ret || offset >= script->_bufSize)
+ if (opcode == op_ret || offset >= script->getBufSize())
break;
if (opcode == op_callk) {
@@ -481,7 +573,7 @@ MoveCountType GameFeatures::detectMoveCountType() {
_moveCountType = kIncrementMoveCount;
} else {
if (!autoDetectMoveCountType()) {
- warning("Move count autodetection failed");
+ error("Move count autodetection failed");
_moveCountType = kIncrementMoveCount; // Most games do this, so best guess
}
}
diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h
index 77c2f0cff7..755054fb25 100644
--- a/engines/sci/engine/features.h
+++ b/engines/sci/engine/features.h
@@ -31,6 +31,12 @@
namespace Sci {
+enum MoveCountType {
+ kMoveCountUninitialized,
+ kIgnoreMoveCount,
+ kIncrementMoveCount
+};
+
class GameFeatures {
public:
GameFeatures(SegManager *segMan, Kernel *kernel);
@@ -60,6 +66,12 @@ public:
* @return Graphics functions type, SCI_VERSION_0_EARLY / SCI_VERSION_0_LATE
*/
SciVersion detectGfxFunctionsType();
+
+ /**
+ * Autodetects the message function used
+ * @return Message function type, SCI_VERSION_1_LATE / SCI_VERSION_1_1
+ */
+ SciVersion detectMessageFunctionType();
#ifdef ENABLE_SCI32
/**
@@ -91,7 +103,7 @@ public:
private:
reg_t getDetectionAddr(const Common::String &objName, Selector slc, int methodNum = -1);
- bool autoDetectLofsType(int methodNum);
+ bool autoDetectLofsType(Common::String gameSuperClassName, int methodNum);
bool autoDetectGfxFunctionsType(int methodNum = -1);
bool autoDetectSoundType();
bool autoDetectMoveCountType();
@@ -99,7 +111,7 @@ private:
bool autoDetectSci21KernelType();
#endif
- SciVersion _doSoundType, _setCursorType, _lofsType, _gfxFunctionsType;
+ SciVersion _doSoundType, _setCursorType, _lofsType, _gfxFunctionsType, _messageFunctionType;
#ifdef ENABLE_SCI32
SciVersion _sci21KernelType;
#endif
diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp
deleted file mode 100644
index 4ac2a22531..0000000000
--- a/engines/sci/engine/game.cpp
+++ /dev/null
@@ -1,320 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/system.h"
-#include "common/file.h"
-
-#include "engines/advancedDetector.h" // for ADGF_DEMO
-
-#include "sci/sci.h"
-#include "sci/resource.h"
-#include "sci/engine/features.h"
-#include "sci/engine/state.h"
-#include "sci/engine/kernel.h"
-#include "sci/engine/message.h"
-#include "sci/graphics/gui.h"
-#include "sci/graphics/menu.h"
-#include "sci/sound/audio.h"
-#include "sci/sound/music.h"
-
-namespace Sci {
-
-struct OldNewIdTableEntry {
- const char *oldId;
- const char *newId;
- SciVersion version;
-};
-
-static const OldNewIdTableEntry s_oldNewTable[] = {
- { "arthur", "camelot", SCI_VERSION_NONE },
- { "brain", "castlebrain", SCI_VERSION_1_MIDDLE }, // Amiga
- { "brain", "castlebrain", SCI_VERSION_1_LATE },
- { "demo", "christmas1988", SCI_VERSION_NONE },
- { "card", "christmas1990", SCI_VERSION_1_EARLY, },
- { "card", "christmas1992", SCI_VERSION_1_1 },
- { "RH Budget", "cnick-longbow", SCI_VERSION_NONE },
- // iceman is the same
- { "icedemo", "iceman", SCI_VERSION_NONE },
- // longbow is the same
- { "eco", "ecoquest", SCI_VERSION_NONE },
- { "eco2", "ecoquest2", SCI_VERSION_NONE }, // EcoQuest 2 demo
- { "rain", "ecoquest2", SCI_VERSION_NONE }, // EcoQuest 2 full
- { "fp", "freddypharkas", SCI_VERSION_NONE },
- { "emc", "funseeker", SCI_VERSION_NONE },
- { "gk", "gk1", SCI_VERSION_NONE },
- { "hoyledemo", "hoyle1", SCI_VERSION_NONE },
- { "cardgames", "hoyle1", SCI_VERSION_NONE },
- { "solitare", "hoyle2", SCI_VERSION_NONE },
- // hoyle3 is the same
- // hoyle4 is the same
- { "brain", "islandbrain", SCI_VERSION_1_1 },
- { "demo000", "kq1sci", SCI_VERSION_NONE },
- { "kq1", "kq1sci", SCI_VERSION_NONE },
- { "kq4", "kq4sci", SCI_VERSION_NONE },
- { "mm1", "laurabow", SCI_VERSION_NONE },
- { "cb1", "laurabow", SCI_VERSION_NONE },
- { "lb2", "laurabow2", SCI_VERSION_NONE },
- { "rh", "longbow", SCI_VERSION_NONE },
- { "ll1", "lsl1sci", SCI_VERSION_NONE },
- { "lsl1", "lsl1sci", SCI_VERSION_NONE },
- // lsl2 is the same
- { "lsl3", "lsl3", SCI_VERSION_NONE },
- { "ll5", "lsl5", SCI_VERSION_NONE },
- // lsl5 is the same
- // lsl6 is the same
- { "mg", "mothergoose", SCI_VERSION_NONE },
- { "twisty", "pepper", SCI_VERSION_NONE },
- { "pq1", "pq1sci", SCI_VERSION_NONE },
- { "pq", "pq2", SCI_VERSION_NONE },
- // pq3 is the same
- // pq4 is the same
- { "tales", "fairytales", SCI_VERSION_NONE },
- { "hq", "qfg1", SCI_VERSION_NONE }, // QFG1 SCI0/EGA
- { "glory", "qfg1", SCI_VERSION_0_LATE }, // QFG1 SCI0/EGA
- { "trial", "qfg2", SCI_VERSION_NONE },
- { "hq2demo", "qfg2", SCI_VERSION_NONE },
- { "thegame", "slater", SCI_VERSION_NONE },
- { "sq1demo", "sq1sci", SCI_VERSION_NONE },
- { "sq1", "sq1sci", SCI_VERSION_NONE },
- // sq3 is the same
- // sq4 is the same
- // sq5 is the same
- // torin is the same
-
- // TODO: SCI2.1, SCI3 IDs
-
- { "", "", SCI_VERSION_NONE }
-};
-
-Common::String convertSierraGameId(const char *gameId, uint32 *gameFlags, ResourceManager *resMan) {
- // Convert the id to lower case, so that we match all upper/lower case variants.
- Common::String sierraId = gameId;
- sierraId.toLowercase();
-
- // If the game has less than the expected scripts, it's a demo
- uint32 demoThreshold = 100;
- // ...but there are some exceptions
- if (sierraId == "brain" || sierraId == "lsl1" ||
- sierraId == "mg" || sierraId == "pq" ||
- sierraId == "jones" ||
- sierraId == "cardgames" || sierraId == "solitare" ||
- sierraId == "hoyle3" || sierraId == "hoyle4")
- demoThreshold = 40;
- if (sierraId == "fp" || sierraId == "gk" || sierraId == "pq4")
- demoThreshold = 150;
-
- Common::List<ResourceId> *resources = resMan->listResources(kResourceTypeScript, -1);
- if (resources->size() < demoThreshold) {
- *gameFlags |= ADGF_DEMO;
-
- // Crazy Nick's Picks
- if (sierraId == "lsl1" && resources->size() == 34)
- return "cnick-lsl";
- if (sierraId == "sq4" && resources->size() == 34)
- return "cnick-sq";
-
- // TODO: cnick-kq, cnick-laurabow and cnick-longbow (their resources can't be read)
-
- // Handle Astrochicken 1 (SQ3) and 2 (SQ4)
- if (sierraId == "sq3" && resources->size() == 20)
- return "astrochicken";
- if (sierraId == "sq4")
- return "msastrochicken";
- }
-
- for (const OldNewIdTableEntry *cur = s_oldNewTable; cur->oldId[0]; ++cur) {
- if (sierraId == cur->oldId) {
- // Distinguish same IDs from the SCI version
- if (cur->version != SCI_VERSION_NONE && cur->version != getSciVersion())
- continue;
-
- return cur->newId;
- }
- }
-
- if (sierraId == "glory") {
- // This could either be qfg1 VGA, qfg3 or qfg4 demo (all SCI1.1),
- // or qfg4 full (SCI2)
- // qfg1 VGA doesn't have view 1
- if (!resMan->testResource(ResourceId(kResourceTypeView, 1)))
- return "qfg1";
-
- // qfg4 full is SCI2
- if (getSciVersion() == SCI_VERSION_2)
- return "qfg4";
-
- // qfg4 demo has less than 50 scripts
- if (resources->size() < 50)
- return "qfg4";
-
- // Otherwise it's qfg3
- return "qfg3";
- }
-
- return sierraId;
-}
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion) {
- if (getSciVersion() > SCI_VERSION_0_LATE)
- sound_flags |= SFX_STATE_FLAG_MULTIPLAY;
-
- s->sfx_init_flags = sound_flags;
- s->_sound.sfx_init(g_sci->getResMan(), sound_flags, soundVersion);
-
- return 0;
-}
-#endif
-
-// Architectural stuff: Init/Unintialize engine
-int script_init_engine(EngineState *s) {
- s->_msgState = new MessageState(s->_segMan);
- s->gc_countdown = GC_INTERVAL - 1;
-
- SegmentId script_000_segment = s->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK);
-
- if (script_000_segment <= 0) {
- debug(2, "Failed to instantiate script.000");
- return 1;
- }
-
- s->script_000 = s->_segMan->getScript(script_000_segment);
-
- s->sys_strings = s->_segMan->allocateSysStrings(&s->sys_strings_segment);
-
- // Allocate static buffer for savegame and CWD directories
- SystemString *str = &s->sys_strings->_strings[SYS_STRING_SAVEDIR];
- str->_name = "savedir";
- str->_maxSize = MAX_SAVE_DIR_SIZE;
- str->_value = (char *)calloc(MAX_SAVE_DIR_SIZE, sizeof(char));
-
- s->r_acc = s->r_prev = NULL_REG;
- s->restAdjust = 0;
-
- s->_executionStack.clear(); // Start without any execution stack
- s->execution_stack_base = -1; // No vm is running yet
-
- s->restarting_flags = SCI_GAME_IS_NOT_RESTARTING;
-
- debug(2, "Engine initialized");
-
- return 0;
-}
-
-/*************************************************************/
-/* Game instance stuff: Init/Unitialize state-dependant data */
-/*************************************************************/
-
-int game_init(EngineState *s) {
- // FIXME Use new VM instantiation code all over the place
- DataStack *stack;
-
- stack = s->_segMan->allocateStack(VM_STACK_SIZE, NULL);
- s->stack_base = stack->_entries;
- s->stack_top = stack->_entries + stack->_capacity;
-
- if (!script_instantiate(g_sci->getResMan(), s->_segMan, 0)) {
- warning("game_init(): Could not instantiate script 0");
- return 1;
- }
-
- if (s->_voc) {
- s->_voc->parserIsValid = false; // Invalidate parser
- s->_voc->parser_event = NULL_REG; // Invalidate parser event
- s->_voc->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE);
- }
-
- // Initialize menu TODO: Actually this should be another init()
- if (g_sci->_gfxMenu)
- g_sci->_gfxMenu->reset();
-
- s->successor = NULL; // No successor
-
- SystemString *str = &s->sys_strings->_strings[SYS_STRING_PARSER_BASE];
- str->_name = "parser-base";
- str->_maxSize = MAX_PARSER_BASE;
- str->_value = (char *)calloc(MAX_PARSER_BASE, sizeof(char));
-
- s->game_start_time = g_system->getMillis();
- s->last_wait_time = s->game_start_time;
-
- srand(g_system->getMillis()); // Initialize random number generator
-
-// script_dissect(0, s->_selectorNames);
- // The first entry in the export table of script 0 points to the game object
- s->_gameObj = s->_segMan->lookupScriptExport(0, 0);
- uint32 gameFlags = 0; // unused
- s->_gameId = convertSierraGameId(s->_segMan->getObjectName(s->_gameObj), &gameFlags, g_sci->getResMan());
-
- debug(2, " \"%s\" at %04x:%04x", s->_gameId.c_str(), PRINT_REG(s->_gameObj));
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- if (s->sfx_init_flags & SFX_STATE_FLAG_NOSOUND)
- game_init_sound(s, 0, g_sci->_features->detectDoSoundType());
-#endif
-
- // Load game language into printLang property of game object
- // FIXME: It's evil to achieve this as a side effect of a getter.
- // Much better to have an explicit init method for this.
- g_sci->getSciLanguage();
-
- return 0;
-}
-
-int game_exit(EngineState *s) {
- s->_executionStack.clear();
-
- if (!s->successor) {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- s->_sound.sfx_exit();
- // Reinit because some other code depends on having a valid state
- game_init_sound(s, SFX_STATE_FLAG_NOSOUND, g_sci->_features->detectDoSoundType());
-#else
- g_sci->_audio->stopAllAudio();
- s->_soundCmd->clearPlayList();
-#endif
- }
-
- // Note: It's a bad idea to delete the segment manager here
- // when loading a game.
- // This function is called right after a game is loaded, and
- // the segment manager has already been initialized from the
- // save game. Deleting or resetting it here will result in
- // invalidating the loaded save state
- if (s->restarting_flags & SCI_GAME_IS_RESTARTING_NOW)
- s->_segMan->resetSegMan();
-
- // TODO Free parser segment here
-
- // TODO Free scripts here
-
- // Close all opened file handles
- s->_fileHandles.clear();
- s->_fileHandles.resize(5);
-
- return 0;
-}
-
-} // End of namespace Sci
diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp
index c2f1c15776..936b83d760 100644
--- a/engines/sci/engine/gc.cpp
+++ b/engines/sci/engine/gc.cpp
@@ -28,11 +28,9 @@
namespace Sci {
-//#define DEBUG_GC
-
struct WorklistManager {
Common::Array<reg_t> _worklist;
- reg_t_hash_map _map;
+ AddrSet _map;
void push(reg_t reg) {
if (!reg.segment) // No numbers
@@ -46,14 +44,19 @@ struct WorklistManager {
_map.setVal(reg, true);
_worklist.push_back(reg);
}
+
+ void pushArray(const Common::Array<reg_t> &tmp) {
+ for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
+ push(*it);
+ }
};
-static reg_t_hash_map *normalise_hashmap_ptrs(SegManager *segMan, reg_t_hash_map &nonnormal_map) {
- reg_t_hash_map *normal_map = new reg_t_hash_map();
+static AddrSet *normalizeAddresses(SegManager *segMan, const AddrSet &nonnormal_map) {
+ AddrSet *normal_map = new AddrSet();
- for (reg_t_hash_map::iterator i = nonnormal_map.begin(); i != nonnormal_map.end(); ++i) {
+ for (AddrSet::const_iterator i = nonnormal_map.begin(); i != nonnormal_map.end(); ++i) {
reg_t reg = i->_key;
- SegmentObj *mobj = (reg.segment < segMan->_heap.size()) ? segMan->_heap[reg.segment] : NULL;
+ SegmentObj *mobj = segMan->getSegmentObj(reg.segment);
if (mobj) {
reg = mobj->findCanonicAddress(segMan, reg);
@@ -65,14 +68,9 @@ static reg_t_hash_map *normalise_hashmap_ptrs(SegManager *segMan, reg_t_hash_map
}
-void add_outgoing_refs(void *refcon, reg_t addr) {
- WorklistManager *wm = (WorklistManager *)refcon;
- wm->push(addr);
-}
-
-reg_t_hash_map *find_all_used_references(EngineState *s) {
+AddrSet *findAllActiveReferences(EngineState *s) {
SegManager *segMan = s->_segMan;
- reg_t_hash_map *normal_map = NULL;
+ AddrSet *normal_map = NULL;
WorklistManager wm;
uint i;
@@ -84,22 +82,19 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
wm.push(s->r_prev);
// Init: Value Stack
// We do this one by hand since the stack doesn't know the current execution stack
- Common::List<ExecStack>::iterator iter;
- {
- iter = s->_executionStack.reverse_begin();
+ Common::List<ExecStack>::iterator iter = s->_executionStack.reverse_begin();
- // Skip fake kernel stack frame if it's on top
- if (((*iter).type == EXEC_STACK_TYPE_KERNEL))
- --iter;
+ // Skip fake kernel stack frame if it's on top
+ if (((*iter).type == EXEC_STACK_TYPE_KERNEL))
+ --iter;
- assert((iter != s->_executionStack.end()) && ((*iter).type != EXEC_STACK_TYPE_KERNEL));
+ assert((iter != s->_executionStack.end()) && ((*iter).type != EXEC_STACK_TYPE_KERNEL));
- ExecStack &xs = *iter;
- reg_t *pos;
+ ExecStack &xs = *iter;
+ reg_t *pos;
- for (pos = s->stack_base; pos < xs.sp; pos++)
- wm.push(*pos);
- }
+ for (pos = s->stack_base; pos < xs.sp; pos++)
+ wm.push(*pos);
debugC(2, kDebugLevelGC, "[GC] -- Finished adding value stack");
@@ -118,24 +113,18 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
debugC(2, kDebugLevelGC, "[GC] -- Finished adding execution stack");
+ const Common::Array<SegmentObj *> &heap = segMan->getSegments();
+
// Init: Explicitly loaded scripts
- for (i = 1; i < segMan->_heap.size(); i++)
- if (segMan->_heap[i]
- && segMan->_heap[i]->getType() == SEG_TYPE_SCRIPT) {
- Script *script = (Script *)segMan->_heap[i];
+ for (i = 1; i < heap.size(); i++) {
+ if (heap[i] && heap[i]->getType() == SEG_TYPE_SCRIPT) {
+ Script *script = (Script *)heap[i];
if (script->getLockers()) { // Explicitly loaded?
- // Locals, if present
- wm.push(make_reg(script->_localsSegment, 0));
-
- // All objects (may be classes, may be indirectly reachable)
- ObjMap::iterator it;
- const ObjMap::iterator end = script->_objects.end();
- for (it = script->_objects.begin(); it != end; ++it) {
- wm.push(it->_value.getPos());
- }
+ wm.pushArray(script->listObjectReferences());
}
}
+ }
debugC(2, kDebugLevelGC, "[GC] -- Finished explicitly loaded scripts, done with root set");
@@ -146,76 +135,64 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
wm._worklist.pop_back();
if (reg.segment != stack_seg) { // No need to repeat this one
debugC(2, kDebugLevelGC, "[GC] Checking %04x:%04x", PRINT_REG(reg));
- if (reg.segment < segMan->_heap.size() && segMan->_heap[reg.segment])
- segMan->_heap[reg.segment]->listAllOutgoingReferences(reg, &wm, add_outgoing_refs);
+ if (reg.segment < heap.size() && heap[reg.segment]) {
+ // Valid heap object? Find its outgoing references!
+ wm.pushArray(heap[reg.segment]->listAllOutgoingReferences(reg));
+ }
}
}
// Normalise
- normal_map = normalise_hashmap_ptrs(segMan, wm._map);
+ normal_map = normalizeAddresses(segMan, wm._map);
return normal_map;
}
-struct deallocator_t {
- SegManager *segMan;
- SegmentObj *mobj;
-#ifdef DEBUG_GC
- char *segnames[SEG_TYPE_MAX + 1];
- int segcount[SEG_TYPE_MAX + 1];
-#endif
- reg_t_hash_map *use_map;
-};
-
-void free_unless_used(void *refcon, reg_t addr) {
- deallocator_t *deallocator = (deallocator_t *)refcon;
- reg_t_hash_map *use_map = deallocator->use_map;
-
- if (!use_map->contains(addr)) {
- // Not found -> we can free it
- deallocator->mobj->freeAtAddress(deallocator->segMan, addr);
-#ifdef DEBUG_GC
- debugC(2, kDebugLevelGC, "[GC] Deallocating %04x:%04x", PRINT_REG(addr));
- deallocator->segcount[deallocator->mobj->getType()]++;
-#endif
- }
-
-}
-
void run_gc(EngineState *s) {
- uint seg_nr;
- deallocator_t deallocator;
SegManager *segMan = s->_segMan;
-#ifdef DEBUG_GC
+ // Some debug stuff
debugC(2, kDebugLevelGC, "[GC] Running...");
- memset(&(deallocator.segcount), 0, sizeof(int) * (SEG_TYPE_MAX + 1));
-#endif
-
- deallocator.segMan = segMan;
- deallocator.use_map = find_all_used_references(s);
-
- for (seg_nr = 1; seg_nr < segMan->_heap.size(); seg_nr++) {
- if (segMan->_heap[seg_nr] != NULL) {
- deallocator.mobj = segMan->_heap[seg_nr];
-#ifdef DEBUG_GC
- deallocator.segnames[deallocator.mobj->getType()] = deallocator.mobj->type; // FIXME: add a segment "name"
-#endif
- deallocator.mobj->listAllDeallocatable(seg_nr, &deallocator, free_unless_used);
+ const char *segnames[SEG_TYPE_MAX + 1];
+ int segcount[SEG_TYPE_MAX + 1];
+ memset(segnames, 0, sizeof(segnames));
+ memset(segcount, 0, sizeof(segcount));
+
+ // Compute the set of all segments references currently in use.
+ AddrSet *activeRefs = findAllActiveReferences(s);
+
+ // Iterate over all segments, and check for each whether it
+ // contains stuff that can be collected.
+ const Common::Array<SegmentObj *> &heap = segMan->getSegments();
+ for (uint seg = 1; seg < heap.size(); seg++) {
+ SegmentObj *mobj = heap[seg];
+ if (mobj != NULL) {
+ const SegmentType type = mobj->getType();
+ segnames[type] = SegmentObj::getSegmentTypeName(type);
+
+ // Get a list of all deallocatable objects in this segment,
+ // then free any which are not referenced from somewhere.
+ const Common::Array<reg_t> tmp = mobj->listAllDeallocatable(seg);
+ for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) {
+ const reg_t addr = *it;
+ if (!activeRefs->contains(addr)) {
+ // Not found -> we can free it
+ mobj->freeAtAddress(segMan, addr);
+ debugC(2, kDebugLevelGC, "[GC] Deallocating %04x:%04x", PRINT_REG(addr));
+ segcount[type]++;
+ }
+ }
+
}
}
- delete deallocator.use_map;
+ delete activeRefs;
-#ifdef DEBUG_GC
- {
- int i;
- debugC(2, kDebugLevelGC, "[GC] Summary:");
- for (i = 0; i <= SEG_TYPE_MAX; i++)
- if (deallocator.segcount[i])
- debugC(2, kDebugLevelGC, "\t%d\t* %s", deallocator.segcount[i], deallocator.segnames[i]);
- }
-#endif
+ // Output debug summary of garbage collection
+ debugC(2, kDebugLevelGC, "[GC] Summary:");
+ for (int i = 0; i <= SEG_TYPE_MAX; i++)
+ if (segcount[i])
+ debugC(2, kDebugLevelGC, "\t%d\t* %s", segcount[i], segnames[i]);
}
} // End of namespace Sci
diff --git a/engines/sci/engine/gc.h b/engines/sci/engine/gc.h
index 9f9347ca18..f4318a1453 100644
--- a/engines/sci/engine/gc.h
+++ b/engines/sci/engine/gc.h
@@ -33,29 +33,24 @@
namespace Sci {
-struct reg_t_EqualTo {
- bool operator()(const reg_t& x, const reg_t& y) const {
- return (x.segment == y.segment) && (x.offset == y.offset);
- }
-};
-
struct reg_t_Hash {
uint operator()(const reg_t& x) const {
- return (x.segment << 3) | x.offset;
+ return (x.segment << 3) ^ x.offset ^ (x.offset << 16);
}
};
/*
- * The reg_t_hash_map is actually really a hashset
+ * The AddrSet is a "set" of reg_t values.
+ * We don't have a HashSet type, so we abuse a HashMap for this.
*/
-typedef Common::HashMap<reg_t, bool, reg_t_Hash, reg_t_EqualTo> reg_t_hash_map;
+typedef Common::HashMap<reg_t, bool, reg_t_Hash> AddrSet;
/**
* Finds all used references and normalises them to their memory addresses
* @param s The state to gather all information from
* @return A hash map containing entries for all used references
*/
-reg_t_hash_map *find_all_used_references(EngineState *s);
+AddrSet *findAllActiveReferences(EngineState *s);
/**
* Runs garbage collection on the current system state
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 49266f3a18..157884fac3 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -27,388 +27,52 @@
#include "sci/engine/kernel.h"
#include "sci/event.h"
#include "sci/resource.h"
+#include "sci/engine/features.h"
+#include "sci/engine/kernel_tables.h"
#include "sci/engine/state.h"
+#include "sci/engine/workarounds.h"
#include "common/system.h"
namespace Sci {
-// Default kernel name table
-#define SCI_KNAMES_DEFAULT_ENTRIES_NR 0x89
-
-static const char *sci_default_knames[SCI_KNAMES_DEFAULT_ENTRIES_NR] = {
- /*0x00*/ "Load",
- /*0x01*/ "UnLoad",
- /*0x02*/ "ScriptID",
- /*0x03*/ "DisposeScript",
- /*0x04*/ "Clone",
- /*0x05*/ "DisposeClone",
- /*0x06*/ "IsObject",
- /*0x07*/ "RespondsTo",
- /*0x08*/ "DrawPic",
- /*0x09*/ "Dummy", // Show
- /*0x0a*/ "PicNotValid",
- /*0x0b*/ "Animate",
- /*0x0c*/ "SetNowSeen",
- /*0x0d*/ "NumLoops",
- /*0x0e*/ "NumCels",
- /*0x0f*/ "CelWide",
- /*0x10*/ "CelHigh",
- /*0x11*/ "DrawCel",
- /*0x12*/ "AddToPic",
- /*0x13*/ "NewWindow",
- /*0x14*/ "GetPort",
- /*0x15*/ "SetPort",
- /*0x16*/ "DisposeWindow",
- /*0x17*/ "DrawControl",
- /*0x18*/ "HiliteControl",
- /*0x19*/ "EditControl",
- /*0x1a*/ "TextSize",
- /*0x1b*/ "Display",
- /*0x1c*/ "GetEvent",
- /*0x1d*/ "GlobalToLocal",
- /*0x1e*/ "LocalToGlobal",
- /*0x1f*/ "MapKeyToDir",
- /*0x20*/ "DrawMenuBar",
- /*0x21*/ "MenuSelect",
- /*0x22*/ "AddMenu",
- /*0x23*/ "DrawStatus",
- /*0x24*/ "Parse",
- /*0x25*/ "Said",
- /*0x26*/ "SetSynonyms", // Portrait (KQ6 hires)
- /*0x27*/ "HaveMouse",
- /*0x28*/ "SetCursor",
- // FOpen (SCI0)
- // FPuts (SCI0)
- // FGets (SCI0)
- // FClose (SCI0)
- /*0x29*/ "SaveGame",
- /*0x2a*/ "RestoreGame",
- /*0x2b*/ "RestartGame",
- /*0x2c*/ "GameIsRestarting",
- /*0x2d*/ "DoSound",
- /*0x2e*/ "NewList",
- /*0x2f*/ "DisposeList",
- /*0x30*/ "NewNode",
- /*0x31*/ "FirstNode",
- /*0x32*/ "LastNode",
- /*0x33*/ "EmptyList",
- /*0x34*/ "NextNode",
- /*0x35*/ "PrevNode",
- /*0x36*/ "NodeValue",
- /*0x37*/ "AddAfter",
- /*0x38*/ "AddToFront",
- /*0x39*/ "AddToEnd",
- /*0x3a*/ "FindKey",
- /*0x3b*/ "DeleteKey",
- /*0x3c*/ "Random",
- /*0x3d*/ "Abs",
- /*0x3e*/ "Sqrt",
- /*0x3f*/ "GetAngle",
- /*0x40*/ "GetDistance",
- /*0x41*/ "Wait",
- /*0x42*/ "GetTime",
- /*0x43*/ "StrEnd",
- /*0x44*/ "StrCat",
- /*0x45*/ "StrCmp",
- /*0x46*/ "StrLen",
- /*0x47*/ "StrCpy",
- /*0x48*/ "Format",
- /*0x49*/ "GetFarText",
- /*0x4a*/ "ReadNumber",
- /*0x4b*/ "BaseSetter",
- /*0x4c*/ "DirLoop",
- /*0x4d*/ "CanBeHere", // CantBeHere in newer SCI versions
- /*0x4e*/ "OnControl",
- /*0x4f*/ "InitBresen",
- /*0x50*/ "DoBresen",
- /*0x51*/ "Platform", // DoAvoider (SCI0)
- /*0x52*/ "SetJump",
- /*0x53*/ "SetDebug",
- /*0x54*/ "Dummy", // InspectObj
- /*0x55*/ "Dummy", // ShowSends
- /*0x56*/ "Dummy", // ShowObjs
- /*0x57*/ "Dummy", // ShowFree
- /*0x58*/ "MemoryInfo",
- /*0x59*/ "Dummy", // StackUsage
- /*0x5a*/ "Dummy", // Profiler
- /*0x5b*/ "GetMenu",
- /*0x5c*/ "SetMenu",
- /*0x5d*/ "GetSaveFiles",
- /*0x5e*/ "GetCWD",
- /*0x5f*/ "CheckFreeSpace",
- /*0x60*/ "ValidPath",
- /*0x61*/ "CoordPri",
- /*0x62*/ "StrAt",
- /*0x63*/ "DeviceInfo",
- /*0x64*/ "GetSaveDir",
- /*0x65*/ "CheckSaveGame",
- /*0x66*/ "ShakeScreen",
- /*0x67*/ "FlushResources",
- /*0x68*/ "SinMult",
- /*0x69*/ "CosMult",
- /*0x6a*/ "SinDiv",
- /*0x6b*/ "CosDiv",
- /*0x6c*/ "Graph",
- /*0x6d*/ "Joystick",
- // End of kernel function table for SCI0
- /*0x6e*/ "ShiftScreen",
- /*0x6f*/ "Palette",
- /*0x70*/ "MemorySegment",
- /*0x71*/ "Intersections", // MoveCursor (SCI1 late), PalVary (SCI1.1)
- /*0x72*/ "Memory",
- /*0x73*/ "ListOps",
- /*0x74*/ "FileIO",
- /*0x75*/ "DoAudio",
- /*0x76*/ "DoSync",
- /*0x77*/ "AvoidPath",
- /*0x78*/ "Sort", // StrSplit (SCI01)
- /*0x79*/ "ATan",
- /*0x7a*/ "Lock",
- /*0x7b*/ "StrSplit",
- /*0x7c*/ "GetMessage", // Message (SCI1.1)
- /*0x7d*/ "IsItSkip",
- /*0x7e*/ "MergePoly",
- /*0x7f*/ "ResCheck",
- /*0x80*/ "AssertPalette",
- /*0x81*/ "TextColors",
- /*0x82*/ "TextFonts",
- /*0x83*/ "Dummy", // Record
- /*0x84*/ "Dummy", // PlayBack
- /*0x85*/ "ShowMovie",
- /*0x86*/ "SetVideoMode",
- /*0x87*/ "SetQuitStr",
- /*0x88*/ "Dummy" // DbugStr
-};
-
-struct SciKernelFunction {
- const char *name;
- KernelFunc *fun; /* The actual function */
- const char *signature; /* kfunct signature */
-};
-
-#define DEFUN(name, fun, sig) {name, fun, sig}
-
-SciKernelFunction kfunct_mappers[] = {
- /*00*/ DEFUN("Load", kLoad, "iii*"),
- /*01*/ DEFUN("UnLoad", kUnLoad, "i.*"), // Work around SQ1 bug, when exiting the Ulence flats bar
- /*02*/ DEFUN("ScriptID", kScriptID, "Ioi*"),
- /*03*/ DEFUN("DisposeScript", kDisposeScript, "Oii*"), // Work around QfG1 bug
- /*04*/ DEFUN("Clone", kClone, "o"),
- /*05*/ DEFUN("DisposeClone", kDisposeClone, "o"),
- /*06*/ DEFUN("IsObject", kIsObject, "."),
- /*07*/ DEFUN("RespondsTo", kRespondsTo, ".i"),
- /*08*/ DEFUN("DrawPic", kDrawPic, "i*"),
-
- /*0a*/ DEFUN("PicNotValid", kPicNotValid, "i*"),
- /*0b*/ DEFUN("Animate", kAnimate, "LI*"), // More like (li?)?
- /*0c*/ DEFUN("SetNowSeen", kSetNowSeen, "oi*"), // The second parameter is ignored
- /*0d*/ DEFUN("NumLoops", kNumLoops, "o"),
- /*0e*/ DEFUN("NumCels", kNumCels, "o"),
- /*0f*/ DEFUN("CelWide", kCelWide, "iOi*"),
- /*10*/ DEFUN("CelHigh", kCelHigh, "iOi*"),
- /*11*/ DEFUN("DrawCel", kDrawCel, "iiiiii*i*r*"),
- /*12*/ DEFUN("AddToPic", kAddToPic, "Il*"),
- // FIXME: signature check removed (set to .*) as kNewWindow is different in Mac versions
- /*13*/ DEFUN("NewWindow", kNewWindow, "*."),
- ///*13*/ DEFUN("NewWindow", kNewWindow, "iiiiZRi*"),
- /*14*/ DEFUN("GetPort", kGetPort, ""),
- /*15*/ DEFUN("SetPort", kSetPort, "ii*"),
- /*16*/ DEFUN("DisposeWindow", kDisposeWindow, "ii*"),
- /*17*/ DEFUN("DrawControl", kDrawControl, "o"),
- /*18*/ DEFUN("HiliteControl", kHiliteControl, "o"),
- /*19*/ DEFUN("EditControl", kEditControl, "ZoZo"),
- /*1a*/ DEFUN("TextSize", kTextSize, "rZrii*r*"),
- /*1b*/ DEFUN("Display", kDisplay, ".*"),
- /*1c*/ DEFUN("GetEvent", kGetEvent, "ioi*"), // Mac versions pass an extra 3rd parameter (ignored - always 0?)
- /*1d*/ DEFUN("GlobalToLocal", kGlobalToLocal, "oo*"),
- /*1e*/ DEFUN("LocalToGlobal", kLocalToGlobal, "oo*"),
- /*1f*/ DEFUN("MapKeyToDir", kMapKeyToDir, "o"),
- /*20*/ DEFUN("DrawMenuBar", kDrawMenuBar, "i"),
- /*21*/ DEFUN("MenuSelect", kMenuSelect, "oi*"),
- /*22*/ DEFUN("AddMenu", kAddMenu, "rr"),
- /*23*/ DEFUN("DrawStatus", kDrawStatus, "Zri*"),
- /*24*/ DEFUN("Parse", kParse, "ro"),
- /*25*/ DEFUN("Said", kSaid, "Zr"),
- /*26*/ DEFUN("SetSynonyms", kSetSynonyms, "o"),
- /*27*/ DEFUN("HaveMouse", kHaveMouse, ""),
- /*28*/ DEFUN("SetCursor", kSetCursor, "i*"),
- // FIXME: The number 0x28 occurs twice :-)
- /*28*/ DEFUN("MoveCursor", kMoveCursor, "ii"),
- /*29*/ DEFUN("FOpen", kFOpen, "ri"),
- /*2a*/ DEFUN("FPuts", kFPuts, "ir"),
- /*2b*/ DEFUN("FGets", kFGets, "rii"),
- /*2c*/ DEFUN("FClose", kFClose, "i"),
- /*2d*/ DEFUN("SaveGame", kSaveGame, "rirr*"),
- /*2e*/ DEFUN("RestoreGame", kRestoreGame, "rir*"),
- /*2f*/ DEFUN("RestartGame", kRestartGame, ""),
- /*30*/ DEFUN("GameIsRestarting", kGameIsRestarting, "i*"),
- /*31*/ DEFUN("DoSound", kDoSound, "iIo*"),
- /*32*/ DEFUN("NewList", kNewList, ""),
- /*33*/ DEFUN("DisposeList", kDisposeList, "l"),
- /*34*/ DEFUN("NewNode", kNewNode, ".."),
- /*35*/ DEFUN("FirstNode", kFirstNode, "Zl"),
- /*36*/ DEFUN("LastNode", kLastNode, "l"),
- /*37*/ DEFUN("EmptyList", kEmptyList, "l"),
- /*38*/ DEFUN("NextNode", kNextNode, "n"),
- /*39*/ DEFUN("PrevNode", kPrevNode, "n"),
- /*3a*/ DEFUN("NodeValue", kNodeValue, "Zn"),
- /*3b*/ DEFUN("AddAfter", kAddAfter, "lnn"),
- /*3c*/ DEFUN("AddToFront", kAddToFront, "ln"),
- /*3d*/ DEFUN("AddToEnd", kAddToEnd, "ln"),
- /*3e*/ DEFUN("FindKey", kFindKey, "l."),
- /*3f*/ DEFUN("DeleteKey", kDeleteKey, "l."),
- /*40*/ DEFUN("Random", kRandom, "i*"),
- /*41*/ DEFUN("Abs", kAbs, "Oi"),
- /*42*/ DEFUN("Sqrt", kSqrt, "i"),
- /*43*/ DEFUN("GetAngle", kGetAngle, "iiiii*"), // occasionally KQ6 passes a 5th argument by mistake
- /*44*/ DEFUN("GetDistance", kGetDistance, "iiiii*"),
- /*45*/ DEFUN("Wait", kWait, "i"),
- /*46*/ DEFUN("GetTime", kGetTime, "i*"),
- /*47*/ DEFUN("StrEnd", kStrEnd, "r"),
- /*48*/ DEFUN("StrCat", kStrCat, "rr"),
- /*49*/ DEFUN("StrCmp", kStrCmp, "rri*"),
- /*4a*/ DEFUN("StrLen", kStrLen, "Zr"),
- /*4b*/ DEFUN("StrCpy", kStrCpy, "rZri*"),
- /*4c*/ DEFUN("Format", kFormat, "r.*"),
- /*4d*/ DEFUN("GetFarText", kGetFarText, "iiZr"),
- /*4e*/ DEFUN("ReadNumber", kReadNumber, "r"),
- /*4f*/ DEFUN("BaseSetter", kBaseSetter, "o"),
- /*50*/ DEFUN("DirLoop", kDirLoop, "oi"),
- // Opcode 51 is defined twice for a reason: In older SCI versions
- // it is CanBeHere, whereas in newer version it is CantBeHere
- /*51*/ DEFUN("CanBeHere", kCanBeHere, "ol*"),
- /*51*/ DEFUN("CantBeHere", kCantBeHere, "ol*"),
- /*52*/ DEFUN("OnControl", kOnControl, "i*"),
- /*53*/ DEFUN("InitBresen", kInitBresen, "oi*"),
- /*54*/ DEFUN("DoBresen", kDoBresen, "o"),
- /*55*/ DEFUN("DoAvoider", kDoAvoider, "o"),
- /*56*/ DEFUN("SetJump", kSetJump, "oiii"),
- /*57*/ DEFUN("SetDebug", kSetDebug, "i*"),
- /*5c*/ DEFUN("MemoryInfo", kMemoryInfo, "i"),
- /*5f*/ DEFUN("GetMenu", kGetMenu, "i."),
- /*60*/ DEFUN("SetMenu", kSetMenu, "i.*"),
- /*61*/ DEFUN("GetSaveFiles", kGetSaveFiles, "rrr"),
- /*62*/ DEFUN("GetCWD", kGetCWD, "r"),
- /*63*/ DEFUN("CheckFreeSpace", kCheckFreeSpace, "r.*"),
- /*64*/ DEFUN("ValidPath", kValidPath, "r"),
- /*65*/ DEFUN("CoordPri", kCoordPri, "ii*"),
- /*66*/ DEFUN("StrAt", kStrAt, "rii*"),
- /*67*/ DEFUN("DeviceInfo", kDeviceInfo, "i.*"),
- /*68*/ DEFUN("GetSaveDir", kGetSaveDir, ".*"), // accepts a parameter in SCI2+ games
- /*69*/ DEFUN("CheckSaveGame", kCheckSaveGame, ".*"),
- /*6a*/ DEFUN("ShakeScreen", kShakeScreen, "ii*"),
- /*6b*/ DEFUN("FlushResources", kFlushResources, "i"),
- /*6c*/ DEFUN("TimesSin", kTimesSin, "ii"),
- /*6d*/ DEFUN("TimesCos", kTimesCos, "ii"),
- /*6e*/ DEFUN("6e", kTimesSin, "ii"),
- /*6f*/ DEFUN("6f", kTimesCos, "ii"),
- /*70*/ DEFUN("Graph", kGraph, ".*"),
- /*71*/ DEFUN("Joystick", kJoystick, ".*"),
-
- // Experimental functions
- /*74*/ DEFUN("FileIO", kFileIO, "i.*"),
- /*(?)*/ DEFUN("Memory", kMemory, "i.*"),
- /*(?)*/ DEFUN("Sort", kSort, "ooo"),
- /*(?)*/ DEFUN("AvoidPath", kAvoidPath, "ii.*"),
- /*(?)*/ DEFUN("Lock", kLock, "iii*"),
- /*(?)*/ DEFUN("Palette", kPalette, "i.*"),
- /*(?)*/ DEFUN("IsItSkip", kIsItSkip, "iiiii"),
- /*7b*/ DEFUN("StrSplit", kStrSplit, "rrZr"),
-
- // Non-experimental functions without a fixed ID
- DEFUN("CosMult", kTimesCos, "ii"),
- DEFUN("SinMult", kTimesSin, "ii"),
-
- // Misc functions
- /*(?)*/ DEFUN("CosDiv", kCosDiv, "ii"),
- /*(?)*/ DEFUN("PriCoord", kPriCoord, "i"),
- /*(?)*/ DEFUN("SinDiv", kSinDiv, "ii"),
- /*(?)*/ DEFUN("TimesCot", kTimesCot, "ii"),
- /*(?)*/ DEFUN("TimesTan", kTimesTan, "ii"),
- DEFUN("Message", kMessage, ".*"),
- DEFUN("GetMessage", kGetMessage, "iiir"),
- DEFUN("DoAudio", kDoAudio, ".*"),
- DEFUN("DoSync", kDoSync, ".*"),
- DEFUN("MemorySegment", kMemorySegment, "iri*"),
- DEFUN("Intersections", kIntersections, "iiiiriiiri"),
- DEFUN("ResCheck", kResCheck, "iii*"),
- DEFUN("SetQuitStr", kSetQuitStr, "r"),
- DEFUN("ShowMovie", kShowMovie, ".*"),
- DEFUN("SetVideoMode", kSetVideoMode, "i"),
- DEFUN("Platform", kPlatform, "i.*"),
- DEFUN("TextColors", kTextColors, ".*"),
- DEFUN("TextFonts", kTextFonts, ".*"),
- DEFUN("Portrait", kPortrait, ".*"),
-
-#ifdef ENABLE_SCI32
- // SCI2 Kernel Functions
- DEFUN("IsHiRes", kIsHiRes, ""),
- DEFUN("Array", kArray, ".*"),
- DEFUN("ListAt", kListAt, "li"),
- DEFUN("String", kString, ".*"),
- DEFUN("AddScreenItem", kAddScreenItem, "o"),
- DEFUN("UpdateScreenItem", kUpdateScreenItem, "o"),
- DEFUN("DeleteScreenItem", kDeleteScreenItem, "o"),
- DEFUN("AddPlane", kAddPlane, "o"),
- DEFUN("DeletePlane", kDeletePlane, "o"),
- DEFUN("UpdatePlane", kUpdatePlane, "o"),
- DEFUN("RepaintPlane", kRepaintPlane, "o"),
- DEFUN("GetHighPlanePri", kGetHighPlanePri, ""),
- DEFUN("FrameOut", kFrameOut, ""),
- DEFUN("ListEachElementDo", kListEachElementDo, "li.*"),
- DEFUN("ListFirstTrue", kListFirstTrue, "li.*"),
- DEFUN("ListAllTrue", kListAllTrue, "li.*"),
- DEFUN("ListIndexOf", kListIndexOf, "lZo"),
- DEFUN("OnMe", kOnMe, "iio.*"),
- DEFUN("InPolygon", kInPolygon, "iio"),
- DEFUN("CreateTextBitmap", kCreateTextBitmap, "iiio"),
-
- // SCI2.1 Kernel Functions
- DEFUN("Save", kSave, ".*"),
- DEFUN("List", kList, ".*"),
- DEFUN("Robot", kRobot, ".*"),
- DEFUN("IsOnMe", kOnMe, "iio.*"), // TODO: this seems right, but verify...
-
-#endif
-
- // its a stub, but its needed for Pharkas to work
- DEFUN("PalVary", kPalVary, "ii*"),
- DEFUN("AssertPalette", kAssertPalette, "i"),
-
-#if 0
- // Stub functions
- /*09*/ DEFUN("Show", kShow, "i"),
- DEFUN("ShiftScreen", kShiftScreen, ".*"),
- DEFUN("ListOps", kListOps, ".*"),
- DEFUN("ATan", kATan, ".*"),
- DEFUN("MergePoly", kMergePoly, ".*"),
- DEFUN("Record", kRecord, ".*"),
- DEFUN("PlayBack", kPlayBack, ".*"),
- DEFUN("DbugStr", kDbugStr, ".*"),
-#endif
-
- {NULL, NULL, NULL} // Terminator
-};
-
-Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) : _resMan(resMan), _segMan(segMan) {
+Kernel::Kernel(ResourceManager *resMan, SegManager *segMan)
+ : _resMan(resMan), _segMan(segMan), _invalid("<invalid>") {
loadSelectorNames();
mapSelectors(); // Map a few special selectors for later use
}
Kernel::~Kernel() {
- for (KernelFuncsContainer::iterator i = _kernelFuncs.begin(); i != _kernelFuncs.end(); ++i)
- // TODO: Doing a const_cast is not that nice actually... But since KernelFuncWithSignature
- // keeps the signature member as "const char *" there is no way around it.
- // Think of a clever way to avoid this.
- free(const_cast<char *>(i->signature));
+ for (KernelFunctionArray::iterator it = _kernelFuncs.begin(); it != _kernelFuncs.end(); ++it) {
+ if (it->subFunctionCount) {
+ uint16 subFunctionNr = 0;
+ while (subFunctionNr < it->subFunctionCount) {
+ delete[] it->subFunctions[subFunctionNr].signature;
+ subFunctionNr++;
+ }
+ delete[] it->subFunctions;
+ }
+ delete[] it->signature;
+ }
}
uint Kernel::getSelectorNamesSize() const {
return _selectorNames.size();
}
-const Common::String &Kernel::getSelectorName(uint selector) const {
+const Common::String &Kernel::getSelectorName(uint selector) {
+ if (selector >= _selectorNames.size()) {
+ // This should only occur in games w/o a selector-table
+ // We need this for proper workaround tables
+ // TODO: maybe check, if there is a fixed selector-table and error() out in that case
+ for (uint loopSelector = _selectorNames.size(); loopSelector <= selector; ++loopSelector)
+ _selectorNames.push_back(Common::String::printf("<noname%d>", loopSelector));
+ }
+
+ // Ensure that the selector has a name
+ if (_selectorNames[selector].empty())
+ _selectorNames[selector] = Common::String::printf("<noname%d>", selector);
+
return _selectorNames[selector];
}
@@ -417,12 +81,10 @@ uint Kernel::getKernelNamesSize() const {
}
const Common::String &Kernel::getKernelName(uint number) const {
- // FIXME: The following check is a temporary workaround for
- // an issue leading to crashes when using the debugger's backtrace
- // command.
- static const Common::String invalid = "(invalid)";
+ // FIXME: The following check is a temporary workaround for an issue
+ // leading to crashes when using the debugger's backtrace command.
if (number >= _kernelNames.size())
- return invalid;
+ return _invalid;
return _kernelNames[number];
}
@@ -477,165 +139,241 @@ void Kernel::loadSelectorNames() {
}
}
-static void kernel_compile_signature(const char **s) {
- const char *src = *s;
- char *result;
- int ellipsis = 0;
- char v;
- int index = 0;
-
- if (!src)
- return; // NULL signature: Nothing to do
-
- result = (char *)malloc(strlen(*s) + 1);
-
- while (*src) {
- char c;
- v = 0;
-
- if (ellipsis) {
- error("Failed compiling kernel function signature '%s': non-terminal ellipsis '%c'", *s, *src);
- }
-
- do {
- char cc;
- cc = c = *src++;
- if (c >= 'A' || c <= 'Z')
- cc = c | KSIG_SPEC_SUM_DONE;
-
- switch (cc) {
- case KSIG_SPEC_LIST:
- v |= KSIG_LIST;
- break;
-
- case KSIG_SPEC_NODE:
- v |= KSIG_NODE;
- break;
-
- case KSIG_SPEC_REF:
- v |= KSIG_REF;
- break;
-
- case KSIG_SPEC_OBJECT:
- v |= KSIG_OBJECT;
- break;
-
- case KSIG_SPEC_ARITHMETIC:
- v |= KSIG_ARITHMETIC;
- break;
-
- case KSIG_SPEC_NULL:
- v |= KSIG_NULL;
- break;
-
- case KSIG_SPEC_ANY:
- v |= KSIG_ANY;
- break;
-
- case KSIG_SPEC_ELLIPSIS:
- v |= KSIG_ELLIPSIS;
- ellipsis = 1;
- break;
-
- default:
- error("INTERNAL ERROR when compiling kernel function signature '%s': (%02x) not understood (aka"
- " '%c')\n", *s, c, c);
+// this parses a written kernel signature into an internal memory format
+// [io] -> either integer or object
+// (io) -> optionally integer AND an object
+// (i) -> optional integer
+// . -> any type
+// i* -> optional multiple integers
+// .* -> any parameters afterwards (or none)
+static uint16 *parseKernelSignature(const char *kernelName, const char *writtenSig) {
+ const char *curPos;
+ char curChar;
+ uint16 *result = NULL;
+ uint16 *writePos = NULL;
+ int size = 0;
+ bool validType = false;
+ bool optionalType = false;
+ bool eitherOr = false;
+ bool optional = false;
+ bool hadOptional = false;
+
+ // No signature given? no signature out
+ if (!writtenSig)
+ return NULL;
+
+ // First, we check how many bytes the result will be
+ // we also check, if the written signature makes any sense
+ curPos = writtenSig;
+ while (*curPos) {
+ curChar = *curPos;
+ switch (curChar) {
+ case '[': // either or
+ if (eitherOr)
+ error("signature for k%s: '[' used within '[]'", kernelName);
+ eitherOr = true;
+ validType = false;
+ break;
+ case ']': // either or end
+ if (!eitherOr)
+ error("signature for k%s: ']' used without leading '['", kernelName);
+ if (!validType)
+ error("signature for k%s: '[]' does not surround valid type(s)", kernelName);
+ eitherOr = false;
+ validType = false;
+ size++;
+ break;
+ case '(': // optional
+ if (optional)
+ error("signature for k%s: '(' used within '()' brackets", kernelName);
+ if (eitherOr)
+ error("signature for k%s: '(' used within '[]' brackets", kernelName);
+ optional = true;
+ validType = false;
+ optionalType = false;
+ break;
+ case ')': // optional end
+ if (!optional)
+ error("signature for k%s: ')' used without leading '('", kernelName);
+ if (!optionalType)
+ error("signature for k%s: '()' does not to surround valid type(s)", kernelName);
+ optional = false;
+ validType = false;
+ hadOptional = true;
+ break;
+ case '0': // allowed types
+ case 'i':
+ case 'o':
+ case 'r':
+ case 'l':
+ case 'n':
+ case '.':
+ case '!':
+ if ((hadOptional) & (!optional))
+ error("signature for k%s: non-optional type may not follow optional type", kernelName);
+ validType = true;
+ if (optional)
+ optionalType = true;
+ if (!eitherOr)
+ size++;
+ break;
+ case '*': // accepts more of the same parameter (must be last char)
+ if (!validType) {
+ if ((writtenSig == curPos) || (*(curPos - 1) != ']'))
+ error("signature for k%s: a valid type must be in front of '*'", kernelName);
}
- } while (*src && (*src == KSIG_SPEC_ELLIPSIS || (c < 'a' && c != KSIG_SPEC_ANY)));
-
- // To handle sum types
- result[index++] = v;
- }
-
- result[index] = 0;
- *s = result; // Write back
-}
-
-void Kernel::mapFunctions() {
- int mapped = 0;
- int ignored = 0;
- uint functions_nr = _kernelNames.size();
-
- _kernelFuncs.resize(functions_nr);
-
- for (uint functnr = 0; functnr < functions_nr; functnr++) {
- int found = -1;
-
- // First, get the name, if known, of the kernel function with number functnr
- Common::String sought_name = _kernelNames[functnr];
-
- // Reset the table entry
- _kernelFuncs[functnr].fun = NULL;
- _kernelFuncs[functnr].signature = NULL;
- _kernelFuncs[functnr].orig_name = sought_name;
-
- if (sought_name.empty()) {
- // No name was given -> must be an unknown opcode
- warning("Kernel function %x unknown", functnr);
- _kernelFuncs[functnr].isDummy = true;
- continue;
- }
-
- // Don't map dummy functions - they will never be called
- if (sought_name == "Dummy") {
- _kernelFuncs[functnr].isDummy = true;
- continue;
+ if (eitherOr)
+ error("signature for k%s: '*' may not be inside '[]'", kernelName);
+ if (optional) {
+ if ((*(curPos + 1) != ')') || (*(curPos + 2) != 0))
+ error("signature for k%s: '*' may only be used for last type", kernelName);
+ } else {
+ if (*(curPos + 1) != 0)
+ error("signature for k%s: '*' may only be used for last type", kernelName);
+ }
+ break;
+ default:
+ error("signature for k%s: '%c' unknown", kernelName, *curPos);
}
+ curPos++;
+ }
- // If the name is known, look it up in kfunct_mappers. This table
- // maps kernel func names to actual function (pointers).
- for (uint seeker = 0; (found == -1) && kfunct_mappers[seeker].name; seeker++)
- if (sought_name == kfunct_mappers[seeker].name)
- found = seeker; // Found a kernel function with the correct name!
-
- if (found == -1) {
- // No match but a name was given -> stub
- warning("Kernel function %s[%x] unmapped", sought_name.c_str(), functnr);
- _kernelFuncs[functnr].isDummy = true;
- } else {
- // A match in kfunct_mappers was found
- if (kfunct_mappers[found].fun) {
- _kernelFuncs[functnr].fun = kfunct_mappers[found].fun;
- _kernelFuncs[functnr].signature = kfunct_mappers[found].signature;
- _kernelFuncs[functnr].isDummy = false;
- kernel_compile_signature(&(_kernelFuncs[functnr].signature));
- ++mapped;
- } else {
- //warning("Ignoring function %s\n", kfunct_mappers[found].name);
- ++ignored;
+ uint16 signature = 0;
+
+ // Now we allocate buffer with required size and fill it
+ result = new uint16[size + 1];
+ writePos = result;
+ curPos = writtenSig;
+ do {
+ curChar = *curPos;
+ if (!eitherOr) {
+ // not within either-or, check if next character forces output
+ switch (curChar) {
+ case 0:
+ case '[':
+ case '(':
+ case ')':
+ case 'i':
+ case 'o':
+ case 'r':
+ case 'l':
+ case 'n':
+ case '.':
+ case '!':
+ // and we also got some signature pending?
+ if (signature) {
+ if (!(signature & SIG_MAYBE_ANY))
+ error("signature for k%s: invalid ('!') may only get used in combination with a real type", kernelName);
+ if ((signature & SIG_IS_INVALID) && ((signature & SIG_MAYBE_ANY) == (SIG_TYPE_NULL | SIG_TYPE_INTEGER)))
+ error("signature for k%s: invalid ('!') should not be used on exclusive null/integer type", kernelName);
+ if (optional) {
+ signature |= SIG_IS_OPTIONAL;
+ if (curChar != ')')
+ signature |= SIG_NEEDS_MORE;
+ }
+ *writePos = signature;
+ writePos++;
+ signature = 0;
+ }
}
}
- } // for all functions requesting to be mapped
+ switch (curChar) {
+ case '[': // either or
+ eitherOr = true;
+ break;
+ case ']': // either or end
+ eitherOr = false;
+ break;
+ case '(': // optional
+ optional = true;
+ break;
+ case ')': // optional end
+ optional = false;
+ break;
+ case '0':
+ if (signature & SIG_TYPE_NULL)
+ error("signature for k%s: NULL ('0') specified more than once", kernelName);
+ signature |= SIG_TYPE_NULL;
+ break;
+ case 'i':
+ if (signature & SIG_TYPE_INTEGER)
+ error("signature for k%s: integer ('i') specified more than once", kernelName);
+ signature |= SIG_TYPE_INTEGER | SIG_TYPE_NULL;
+ break;
+ case 'o':
+ if (signature & SIG_TYPE_OBJECT)
+ error("signature for k%s: object ('o') specified more than once", kernelName);
+ signature |= SIG_TYPE_OBJECT;
+ break;
+ case 'r':
+ if (signature & SIG_TYPE_REFERENCE)
+ error("signature for k%s: reference ('r') specified more than once", kernelName);
+ signature |= SIG_TYPE_REFERENCE;
+ break;
+ case 'l':
+ if (signature & SIG_TYPE_LIST)
+ error("signature for k%s: list ('l') specified more than once", kernelName);
+ signature |= SIG_TYPE_LIST;
+ break;
+ case 'n':
+ if (signature & SIG_TYPE_NODE)
+ error("signature for k%s: node ('n') specified more than once", kernelName);
+ signature |= SIG_TYPE_NODE;
+ break;
+ case '.':
+ if (signature & SIG_MAYBE_ANY)
+ error("signature for k%s: maybe-any ('.') shouldn't get specified with other types in front of it", kernelName);
+ signature |= SIG_MAYBE_ANY;
+ break;
+ case '!':
+ if (signature & SIG_IS_INVALID)
+ error("signature for k%s: invalid ('!') specified more than once", kernelName);
+ signature |= SIG_IS_INVALID;
+ break;
+ case '*': // accepts more of the same parameter
+ signature |= SIG_MORE_MAY_FOLLOW;
+ break;
+ default:
+ break;
+ }
+ curPos++;
+ } while (curChar);
- debugC(2, kDebugLevelVM, "Handled %d/%d kernel functions, mapping %d and ignoring %d.",
- mapped + ignored, _kernelNames.size(), mapped, ignored);
+ // Write terminator
+ *writePos = 0;
- return;
+ return result;
}
-int Kernel::findRegType(reg_t reg) {
- // No segment? Must be arithmetic
+uint16 Kernel::findRegType(reg_t reg) {
+ // No segment? Must be integer
if (!reg.segment)
- return reg.offset ? KSIG_ARITHMETIC : KSIG_ARITHMETIC | KSIG_NULL;
+ return SIG_TYPE_INTEGER | (reg.offset ? 0 : SIG_TYPE_NULL);
+
+ if (reg.segment == 0xFFFF)
+ return SIG_TYPE_UNINITIALIZED;
// Otherwise it's an object
SegmentObj *mobj = _segMan->getSegmentObj(reg.segment);
if (!mobj)
- return 0; // Invalid
+ return SIG_TYPE_ERROR;
+ uint16 result = 0;
if (!mobj->isValidOffset(reg.offset))
- warning("[KERN] ref %04x:%04x is invalid", PRINT_REG(reg));
+ result |= SIG_IS_INVALID;
switch (mobj->getType()) {
case SEG_TYPE_SCRIPT:
- if (reg.offset <= (*(Script *)mobj)._bufSize &&
+ if (reg.offset <= (*(Script *)mobj).getBufSize() &&
reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET &&
- RAW_IS_OBJECT((*(Script *)mobj)._buf + reg.offset)) {
- return ((Script *)mobj)->getObject(reg.offset) ? KSIG_OBJECT : KSIG_REF;
+ RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) {
+ result |= ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE;
} else
- return KSIG_REF;
+ result |= SIG_TYPE_REFERENCE;
+ break;
case SEG_TYPE_CLONES:
- return KSIG_OBJECT;
+ result |= SIG_TYPE_OBJECT;
+ break;
case SEG_TYPE_LOCALS:
case SEG_TYPE_STACK:
case SEG_TYPE_SYS_STRINGS:
@@ -645,58 +383,372 @@ int Kernel::findRegType(reg_t reg) {
case SEG_TYPE_ARRAY:
case SEG_TYPE_STRING:
#endif
- return KSIG_REF;
+ result |= SIG_TYPE_REFERENCE;
+ break;
case SEG_TYPE_LISTS:
- return KSIG_LIST;
+ result |= SIG_TYPE_LIST;
+ break;
case SEG_TYPE_NODES:
- return KSIG_NODE;
+ result |= SIG_TYPE_NODE;
+ break;
default:
- return 0;
+ return SIG_TYPE_ERROR;
}
+ return result;
}
-bool Kernel::signatureMatch(const char *sig, int argc, const reg_t *argv) {
- // Always "match" if no signature is given
- if (!sig)
- return true;
+struct SignatureDebugType {
+ uint16 typeCheck;
+ const char *text;
+};
- while (*sig && argc) {
- if ((*sig & KSIG_ANY) != KSIG_ANY) {
- int type = findRegType(*argv);
+static const SignatureDebugType signatureDebugTypeList[] = {
+ { SIG_TYPE_NULL, "null" },
+ { SIG_TYPE_INTEGER, "integer" },
+ { SIG_TYPE_UNINITIALIZED, "uninitialized" },
+ { SIG_TYPE_OBJECT, "object" },
+ { SIG_TYPE_REFERENCE, "reference" },
+ { SIG_TYPE_LIST, "list" },
+ { SIG_TYPE_NODE, "node" },
+ { SIG_TYPE_ERROR, "error" },
+ { SIG_IS_INVALID, "invalid" },
+ { 0, NULL }
+};
- if (!type) {
- warning("[KERN] Could not determine type of ref %04x:%04x; failing signature check", PRINT_REG(*argv));
- return false;
- }
+static void kernelSignatureDebugType(const uint16 type) {
+ bool firstPrint = true;
- if (!(type & *sig)) {
- warning("kernel_matches_signature: %d args left, is %d, should be %d", argc, type, *sig);
- return false;
- }
+ const SignatureDebugType *list = signatureDebugTypeList;
+ while (list->typeCheck) {
+ if (type & list->typeCheck) {
+ if (!firstPrint)
+ printf(", ");
+ printf("%s", list->text);
+ firstPrint = false;
+ }
+ list++;
+ }
+}
+// Shows kernel call signature and current arguments for debugging purposes
+void Kernel::signatureDebug(const uint16 *sig, int argc, const reg_t *argv) {
+ int argnr = 0;
+ while (*sig || argc) {
+ printf("parameter %d: ", argnr++);
+ if (argc) {
+ reg_t parameter = *argv;
+ printf("%04x:%04x (", PRINT_REG(parameter));
+ int regType = findRegType(parameter);
+ if (regType)
+ kernelSignatureDebugType(regType);
+ else
+ printf("unknown type of %04x:%04x", PRINT_REG(parameter));
+ printf(")");
+ argv++;
+ argc--;
+ } else {
+ printf("not passed");
+ }
+ if (*sig) {
+ const uint16 signature = *sig;
+ if ((signature & SIG_MAYBE_ANY) == SIG_MAYBE_ANY) {
+ printf(", may be any");
+ } else {
+ printf(", should be ");
+ kernelSignatureDebugType(signature);
+ }
+ if (signature & SIG_IS_OPTIONAL)
+ printf(" (optional)");
+ if (signature & SIG_NEEDS_MORE)
+ printf(" (needs more)");
+ if (signature & SIG_MORE_MAY_FOLLOW)
+ printf(" (more may follow)");
+ sig++;
}
- if (!(*sig & KSIG_ELLIPSIS))
- ++sig;
- ++argv;
- --argc;
+ printf("\n");
}
+}
+
+bool Kernel::signatureMatch(const uint16 *sig, int argc, const reg_t *argv) {
+ uint16 nextSig = *sig;
+ uint16 curSig = nextSig;
+ while (nextSig && argc) {
+ curSig = nextSig;
+ int type = findRegType(*argv);
+
+ if ((type & SIG_IS_INVALID) && (!(curSig & SIG_IS_INVALID)))
+ return false; // pointer is invalid and signature doesn't allow that?
- if (argc) {
- warning("kernel_matches_signature: too many arguments");
- return false; // Too many arguments
+ if (!((type & ~SIG_IS_INVALID) & curSig))
+ return false; // type mismatch
+
+ if (!(curSig & SIG_MORE_MAY_FOLLOW)) {
+ sig++;
+ nextSig = *sig;
+ } else {
+ nextSig |= SIG_IS_OPTIONAL; // more may follow -> assumes followers are optional
+ }
+ argv++;
+ argc--;
}
- if (*sig == 0 || (*sig & KSIG_ELLIPSIS))
+
+ // Too many arguments?
+ if (argc)
+ return false;
+ // Signature end reached?
+ if (nextSig == 0)
return true;
- warning("kernel_matches_signature: too few arguments");
+ // current parameter is optional?
+ if (curSig & SIG_IS_OPTIONAL) {
+ // yes, check if nothing more is required
+ if (!(curSig & SIG_NEEDS_MORE))
+ return true;
+ } else {
+ // no, check if next parameter is optional
+ if (nextSig & SIG_IS_OPTIONAL)
+ return true;
+ }
+ // Too few arguments or more optional arguments required
return false;
}
-void Kernel::setDefaultKernelNames(Common::String gameId) {
- _kernelNames = Common::StringArray(sci_default_knames, SCI_KNAMES_DEFAULT_ENTRIES_NR);
+void Kernel::mapFunctions() {
+ int mapped = 0;
+ int ignored = 0;
+ uint functionCount = _kernelNames.size();
+ byte platformMask = 0;
+ SciVersion myVersion = getSciVersion();
+
+ switch (g_sci->getPlatform()) {
+ case Common::kPlatformPC:
+ platformMask = SIGFOR_DOS;
+ break;
+ case Common::kPlatformPC98:
+ platformMask = SIGFOR_PC98;
+ break;
+ case Common::kPlatformWindows:
+ platformMask = SIGFOR_WIN;
+ break;
+ case Common::kPlatformMacintosh:
+ platformMask = SIGFOR_MAC;
+ break;
+ case Common::kPlatformAmiga:
+ platformMask = SIGFOR_AMIGA;
+ break;
+ case Common::kPlatformAtariST:
+ platformMask = SIGFOR_ATARI;
+ break;
+ default:
+ break;
+ }
+
+ _kernelFuncs.resize(functionCount);
+
+ for (uint id = 0; id < functionCount; id++) {
+ // First, get the name, if known, of the kernel function with number functnr
+ Common::String kernelName = _kernelNames[id];
+
+ // Reset the table entry
+ _kernelFuncs[id].function = NULL;
+ _kernelFuncs[id].signature = NULL;
+ _kernelFuncs[id].name = NULL;
+ _kernelFuncs[id].workarounds = NULL;
+ _kernelFuncs[id].subFunctions = NULL;
+ _kernelFuncs[id].subFunctionCount = 0;
+ _kernelFuncs[id].debugLogging = false;
+ if (kernelName.empty()) {
+ // No name was given -> must be an unknown opcode
+ warning("Kernel function %x unknown", id);
+ continue;
+ }
+
+ // Don't map dummy functions - they will never be called
+ if (kernelName == "Dummy") {
+ _kernelFuncs[id].function = kDummy;
+ continue;
+ }
+
+ // If the name is known, look it up in s_kernelMap. This table
+ // maps kernel func names to actual function (pointers).
+ SciKernelMapEntry *kernelMap = s_kernelMap;
+ bool nameMatch = false;
+ while (kernelMap->name) {
+ if (kernelName == kernelMap->name) {
+ if ((kernelMap->fromVersion == SCI_VERSION_NONE) || (kernelMap->fromVersion <= myVersion))
+ if ((kernelMap->toVersion == SCI_VERSION_NONE) || (kernelMap->toVersion >= myVersion))
+ if (platformMask & kernelMap->forPlatform)
+ break;
+ nameMatch = true;
+ }
+ kernelMap++;
+ }
+
+ if (kernelMap->name) {
+ // A match was found
+ _kernelFuncs[id].function = kernelMap->function;
+ _kernelFuncs[id].name = kernelMap->name;
+ _kernelFuncs[id].signature = parseKernelSignature(kernelMap->name, kernelMap->signature);
+ _kernelFuncs[id].workarounds = kernelMap->workarounds;
+ if (kernelMap->subFunctions) {
+ // Get version for subfunction identification
+ SciVersion mySubVersion = (SciVersion)kernelMap->function(NULL, 0, NULL).offset;
+ // Now check whats the highest subfunction-id for this version
+ const SciKernelMapSubEntry *kernelSubMap = kernelMap->subFunctions;
+ uint16 subFunctionCount = 0;
+ while (kernelSubMap->function) {
+ if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion))
+ if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion))
+ if (subFunctionCount <= kernelSubMap->id)
+ subFunctionCount = kernelSubMap->id + 1;
+ kernelSubMap++;
+ }
+ if (!subFunctionCount)
+ error("k%s[%x]: no subfunctions found for requested version", kernelName.c_str(), id);
+ // Now allocate required memory and go through it again
+ _kernelFuncs[id].subFunctionCount = subFunctionCount;
+ KernelSubFunction *subFunctions = new KernelSubFunction[subFunctionCount];
+ _kernelFuncs[id].subFunctions = subFunctions;
+ memset(subFunctions, 0, sizeof(KernelSubFunction) * subFunctionCount);
+ // And fill this info out
+ kernelSubMap = kernelMap->subFunctions;
+ uint kernelSubNr = 0;
+ while (kernelSubMap->function) {
+ if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion))
+ if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) {
+ uint subId = kernelSubMap->id;
+ if (!subFunctions[subId].function) {
+ subFunctions[subId].function = kernelSubMap->function;
+ subFunctions[subId].name = kernelSubMap->name;
+ subFunctions[subId].workarounds = kernelSubMap->workarounds;
+ if (kernelSubMap->signature) {
+ subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMap->signature);
+ } else {
+ // we go back the submap to find the previous signature for that kernel call
+ const SciKernelMapSubEntry *kernelSubMapBack = kernelSubMap;
+ uint kernelSubLeft = kernelSubNr;
+ while (kernelSubLeft) {
+ kernelSubLeft--;
+ kernelSubMapBack--;
+ if (kernelSubMapBack->name == kernelSubMap->name) {
+ if (kernelSubMapBack->signature) {
+ subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMapBack->signature);
+ break;
+ }
+ }
+ }
+ if (!subFunctions[subId].signature)
+ error("k%s: no previous signatures", kernelSubMap->name);
+ }
+ }
+ }
+ kernelSubMap++;
+ kernelSubNr++;
+ }
+ }
+ ++mapped;
+ } else {
+ if (nameMatch)
+ error("k%s[%x]: not found for this version/platform", kernelName.c_str(), id);
+ // No match but a name was given -> stub
+ warning("k%s[%x]: unmapped", kernelName.c_str(), id);
+ _kernelFuncs[id].function = kStub;
+ }
+ } // for all functions requesting to be mapped
+
+ debugC(2, kDebugLevelVM, "Handled %d/%d kernel functions, mapping %d and ignoring %d.",
+ mapped + ignored, _kernelNames.size(), mapped, ignored);
+
+ return;
+}
+
+bool Kernel::debugSetFunction(const char *kernelName, int logging, int breakpoint) {
+ if (strcmp(kernelName, "*")) {
+ for (uint id = 0; id < _kernelFuncs.size(); id++) {
+ if (_kernelFuncs[id].name) {
+ if (strcmp(kernelName, _kernelFuncs[id].name) == 0) {
+ if (_kernelFuncs[id].subFunctions) {
+ // sub-functions available and main name matched, in that case set logging of all sub-functions
+ KernelSubFunction *kernelSubCall = _kernelFuncs[id].subFunctions;
+ uint kernelSubCallCount = _kernelFuncs[id].subFunctionCount;
+ for (uint subId = 0; subId < kernelSubCallCount; subId++) {
+ if (kernelSubCall->function) {
+ if (logging != -1)
+ kernelSubCall->debugLogging = logging == 1 ? true : false;
+ if (breakpoint != -1)
+ kernelSubCall->debugBreakpoint = breakpoint == 1 ? true : false;
+ }
+ kernelSubCall++;
+ }
+ return true;
+ }
+ // function name matched, set for this one and exit
+ if (logging != -1)
+ _kernelFuncs[id].debugLogging = logging == 1 ? true : false;
+ if (breakpoint != -1)
+ _kernelFuncs[id].debugBreakpoint = breakpoint == 1 ? true : false;
+ return true;
+ } else {
+ // main name was not matched
+ if (_kernelFuncs[id].subFunctions) {
+ // Sub-Functions available
+ KernelSubFunction *kernelSubCall = _kernelFuncs[id].subFunctions;
+ uint kernelSubCallCount = _kernelFuncs[id].subFunctionCount;
+ for (uint subId = 0; subId < kernelSubCallCount; subId++) {
+ if (kernelSubCall->function) {
+ if (strcmp(kernelName, kernelSubCall->name) == 0) {
+ // sub-function name matched, set for this one and exit
+ if (logging != -1)
+ kernelSubCall->debugLogging = logging == 1 ? true : false;
+ if (breakpoint != -1)
+ kernelSubCall->debugBreakpoint = breakpoint == 1 ? true : false;
+ return true;
+ }
+ }
+ kernelSubCall++;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+ // Set debugLogging for all calls
+ for (uint id = 0; id < _kernelFuncs.size(); id++) {
+ if (_kernelFuncs[id].name) {
+ if (!_kernelFuncs[id].subFunctions) {
+ // No sub-functions, enable actual kernel function
+ if (logging != -1)
+ _kernelFuncs[id].debugLogging = logging == 1 ? true : false;
+ if (breakpoint != -1)
+ _kernelFuncs[id].debugBreakpoint = breakpoint == 1 ? true : false;
+ } else {
+ // Sub-Functions available, enable those too
+ KernelSubFunction *kernelSubCall = _kernelFuncs[id].subFunctions;
+ uint kernelSubCallCount = _kernelFuncs[id].subFunctionCount;
+ for (uint subId = 0; subId < kernelSubCallCount; subId++) {
+ if (kernelSubCall->function) {
+ if (logging != -1)
+ kernelSubCall->debugLogging = logging == 1 ? true : false;
+ if (breakpoint != -1)
+ kernelSubCall->debugBreakpoint = breakpoint == 1 ? true : false;
+ }
+ kernelSubCall++;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+void Kernel::setDefaultKernelNames(GameFeatures *features) {
+ _kernelNames = Common::StringArray(s_defaultKernelNames, ARRAYSIZE(s_defaultKernelNames));
// Some (later) SCI versions replaced CanBeHere by CantBeHere
- if (_selectorCache.cantBeHere != -1)
- _kernelNames[0x4d] = "CantBeHere";
+ if (_selectorCache.cantBeHere != -1) {
+ // hoyle 3 has cantBeHere selector but is assuming to call kCanBeHere
+ if (g_sci->getGameId() != GID_HOYLE3)
+ _kernelNames[0x4d] = "CantBeHere";
+ }
switch (getSciVersion()) {
case SCI_VERSION_0_EARLY:
@@ -727,18 +779,27 @@ void Kernel::setDefaultKernelNames(Common::String gameId) {
break;
case SCI_VERSION_1_1:
- // In KQ6 CD, the empty kSetSynonyms function has been replaced
- // with kPortrait. In KQ6 Mac, kPlayBack has been replaced by
- // kShowMovie.
- if (gameId == "kq6") {
- if (g_sci->getPlatform() == Common::kPlatformMacintosh)
- _kernelNames[0x84] = "ShowMovie";
- else
+ // In SCI1.1, kSetSynonyms is an empty function
+ _kernelNames[0x26] = "Empty";
+
+ if (g_sci->getGameId() == GID_KQ6) {
+ // In the Windows version of KQ6 CD, the empty kSetSynonyms
+ // function has been replaced with kPortrait. In KQ6 Mac,
+ // kPlayBack has been replaced by kShowMovie.
+ if (g_sci->getPlatform() == Common::kPlatformWindows)
_kernelNames[0x26] = "Portrait";
+ else if (g_sci->getPlatform() == Common::kPlatformMacintosh)
+ _kernelNames[0x84] = "ShowMovie";
+ } else if (g_sci->getGameId() == GID_QFG4 && g_sci->isDemo()) {
+ _kernelNames[0x7b] = "RemapColors"; // QFG4 Demo has this SCI2 function instead of StrSplit
}
_kernelNames[0x71] = "PalVary";
- _kernelNames[0x7c] = "Message";
+
+ // At least EcoQuest 1 demo uses kGetMessage instead of kMessage.
+ // Detect which function to use.
+ if (features->detectMessageFunctionType() == SCI_VERSION_1_1)
+ _kernelNames[0x7c] = "Message";
break;
default:
@@ -747,20 +808,52 @@ void Kernel::setDefaultKernelNames(Common::String gameId) {
}
}
-bool Kernel::loadKernelNames(Common::String gameId) {
+#ifdef ENABLE_SCI32
+
+enum {
+ kKernelEntriesSci2 = 0x8b,
+ kKernelEntriesGk2Demo = 0xa0,
+ kKernelEntriesSci21 = 0x9d
+};
+
+void Kernel::setKernelNamesSci2() {
+ _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesSci2);
+}
+
+void Kernel::setKernelNamesSci21(GameFeatures *features) {
+ // Some SCI games use a modified SCI2 kernel table instead of the
+ // SCI2.1 kernel table. The GK2 demo does this as well as at least
+ // one version of KQ7 (1.4). We detect which version to use based on
+ // how kDoSound is called from Sound::play().
+
+ // This is interesting because they all have the same interpreter
+ // version (2.100.002), yet they would not be compatible with other
+ // games of the same interpreter.
+
+ if (features->detectSci21KernelType() == SCI_VERSION_2) {
+ _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesGk2Demo);
+ // OnMe is IsOnMe here, but they should be compatible
+ _kernelNames[0x23] = "Robot"; // Graph in SCI2
+ _kernelNames[0x2e] = "Priority"; // DisposeTextBitmap in SCI2
+ } else
+ _kernelNames = Common::StringArray(sci21_default_knames, kKernelEntriesSci21);
+}
+
+#endif
+
+void Kernel::loadKernelNames(GameFeatures *features) {
_kernelNames.clear();
#ifdef ENABLE_SCI32
if (getSciVersion() >= SCI_VERSION_2_1)
- setKernelNamesSci21();
+ setKernelNamesSci21(features);
else if (getSciVersion() == SCI_VERSION_2)
setKernelNamesSci2();
else
#endif
- setDefaultKernelNames(gameId);
+ setDefaultKernelNames(features);
mapFunctions();
- return true;
}
Common::String Kernel::lookupText(reg_t address, int index) {
@@ -769,31 +862,50 @@ Common::String Kernel::lookupText(reg_t address, int index) {
if (address.segment)
return _segMan->getString(address);
- else {
- int textlen;
- int _index = index;
- textres = _resMan->findResource(ResourceId(kResourceTypeText, address.offset), 0);
-
- if (!textres) {
- error("text.%03d not found", address.offset);
- return NULL; /* Will probably segfault */
- }
- textlen = textres->size;
- seeker = (char *) textres->data;
+ int textlen;
+ int _index = index;
+ textres = _resMan->findResource(ResourceId(kResourceTypeText, address.offset), 0);
- while (index--)
- while ((textlen--) && (*seeker++))
- ;
+ if (!textres) {
+ error("text.%03d not found", address.offset);
+ return NULL; /* Will probably segfault */
+ }
- if (textlen)
- return seeker;
- else {
- error("Index %d out of bounds in text.%03d", _index, address.offset);
- return NULL;
- }
+ textlen = textres->size;
+ seeker = (char *) textres->data;
+
+ while (index--)
+ while ((textlen--) && (*seeker++))
+ ;
+
+ if (textlen)
+ return seeker;
+
+ error("Index %d out of bounds in text.%03d", _index, address.offset);
+ return NULL;
+}
+// TODO: script_adjust_opcode_formats should probably be part of the
+// constructor (?) of a VirtualMachine or a ScriptManager class.
+void script_adjust_opcode_formats() {
+ if (g_sci->_features->detectLofsType() != SCI_VERSION_0_EARLY) {
+ g_opcode_formats[op_lofsa][0] = Script_Offset;
+ g_opcode_formats[op_lofss][0] = Script_Offset;
}
+
+#ifdef ENABLE_SCI32
+ // In SCI32, some arguments are now words instead of bytes
+ if (getSciVersion() >= SCI_VERSION_2) {
+ g_opcode_formats[op_calle][2] = Script_Word;
+ g_opcode_formats[op_callk][1] = Script_Word;
+ g_opcode_formats[op_super][1] = Script_Word;
+ g_opcode_formats[op_send][0] = Script_Word;
+ g_opcode_formats[op_self][0] = Script_Word;
+ g_opcode_formats[op_call][1] = Script_Word;
+ g_opcode_formats[op_callb][1] = Script_Word;
+ }
+#endif
}
} // End of namespace Sci
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 7717743e19..b6247b46f1 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -31,7 +31,7 @@
#include "common/rect.h"
#include "common/str-array.h"
-#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
+#include "sci/engine/selector.h"
#include "sci/engine/vm_types.h" // for reg_t
#include "sci/engine/vm.h"
@@ -39,6 +39,8 @@ namespace Sci {
struct Node; // from segment.h
struct List; // from segment.h
+struct SelectorCache; // from selector.h
+struct SciWorkaroundEntry; // from workarounds.h
/**
* @defgroup VocabularyResources Vocabulary resources in SCI
@@ -92,82 +94,69 @@ struct List; // from segment.h
//@{
//#define DEBUG_PARSER // enable for parser debugging
-//#define DISABLE_VALIDATIONS // enable to stop validation checks
// ---- Kernel signatures -----------------------------------------------------
-#define KSIG_TERMINATOR 0
-
-// Uncompiled signatures
-#define KSIG_SPEC_ARITMETIC 'i'
-#define KSIG_SPEC_LIST 'l'
-#define KSIG_SPEC_NODE 'n'
-#define KSIG_SPEC_OBJECT 'o'
-#define KSIG_SPEC_REF 'r' // Said Specs and strings
-#define KSIG_SPEC_ARITHMETIC 'i'
-#define KSIG_SPEC_NULL 'z'
-#define KSIG_SPEC_ANY '.'
-#define KSIG_SPEC_ELLIPSIS '*' // Arbitrarily more TYPED arguments
-
-#define KSIG_SPEC_SUM_DONE ('a' - 'A') // Use small letters to indicate end of sum type
-/* Use capital letters for sum types, e.g.
-** "LNoLr" for a function which takes two arguments:
-** (1) list, node or object
-** (2) list or ref
-*/
-
-// Compiled signatures
-#define KSIG_LIST 0x01
-#define KSIG_NODE 0x02
-#define KSIG_OBJECT 0x04
-#define KSIG_REF 0x08
-#define KSIG_ARITHMETIC 0x10
-
-#define KSIG_NULL 0x40
-#define KSIG_ANY 0x5f
-#define KSIG_ELLIPSIS 0x80
+
+// internal kernel signature data
+enum {
+ SIG_TYPE_NULL = 0x01, // may be 0:0 [0]
+ SIG_TYPE_INTEGER = 0x02, // may be 0:* [i], automatically also allows null
+ SIG_TYPE_UNINITIALIZED = 0x04, // may be FFFF:* -> not allowable, only used for comparison
+ SIG_TYPE_OBJECT = 0x08, // may be object [o]
+ SIG_TYPE_REFERENCE = 0x10, // may be reference [r]
+ SIG_TYPE_LIST = 0x20, // may be list [l]
+ SIG_TYPE_NODE = 0x40, // may be node [n]
+ SIG_TYPE_ERROR = 0x80, // happens, when there is a identification error - only used for comparison
+ SIG_IS_INVALID = 0x100, // ptr is invalid [!] -> invalid offset
+ SIG_IS_OPTIONAL = 0x200, // is optional
+ SIG_NEEDS_MORE = 0x400, // needs at least one additional parameter following
+ SIG_MORE_MAY_FOLLOW = 0x800 // may have more parameters of the same type following
+};
+
+// this does not include SIG_TYPE_UNINITIALIZED, because we can not allow uninitialized values anywhere
+#define SIG_MAYBE_ANY (SIG_TYPE_NULL | SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_LIST | SIG_TYPE_NODE)
+
// ----------------------------------------------------------------------------
/* Generic description: */
-typedef reg_t KernelFunc(EngineState *s, int argc, reg_t *argv);
-
-struct KernelFuncWithSignature {
- KernelFunc *fun; /**< The actual function */
- const char *signature; /**< KernelFunc signature */
- Common::String orig_name; /**< Original name, in case we couldn't map it */
- bool isDummy;
+typedef reg_t KernelFunctionCall(EngineState *s, int argc, reg_t *argv);
+
+struct KernelSubFunction {
+ KernelFunctionCall *function;
+ const char *name;
+ uint16 *signature;
+ const SciWorkaroundEntry *workarounds;
+ bool debugLogging;
+ bool debugBreakpoint;
};
-enum AutoDetectedFeatures {
- kFeatureOldScriptHeader = 1 << 0
+struct KernelFunction {
+ KernelFunctionCall *function;
+ const char *name;
+ uint16 *signature;
+ const SciWorkaroundEntry *workarounds;
+ KernelSubFunction *subFunctions;
+ uint16 subFunctionCount;
+ bool debugLogging;
+ bool debugBreakpoint;
};
class Kernel {
public:
/**
- * Initializes the SCI kernel
+ * Initializes the SCI kernel.
*/
Kernel(ResourceManager *resMan, SegManager *segMan);
~Kernel();
uint getSelectorNamesSize() const;
- const Common::String &getSelectorName(uint selector) const;
+ const Common::String &getSelectorName(uint selector);
uint getKernelNamesSize() const;
const Common::String &getKernelName(uint number) const;
/**
- * Loads the kernel function names.
- *
- * This function reads the kernel function name table from resource_map,
- * and fills the _kernelNames array with them.
- * The resulting list has the same format regardless of the format of the
- * name table of the resource (the format changed between version 0 and 1).
- * @return true on success, false on failure
- */
- bool loadKernelNames(Common::String gameId);
-
- /**
- * Determines the selector ID of a selector by its name
+ * Determines the selector ID of a selector by its name.
* @param selectorName Name of the selector to look up
* @return The appropriate selector ID, or -1 on error
*/
@@ -178,22 +167,24 @@ public:
void dumpScriptObject(char *data, int seeker, int objsize);
void dumpScriptClass(char *data, int seeker, int objsize);
- SelectorCache _selectorCache; /**< Shortcut list for important selectors */
- typedef Common::Array<KernelFuncWithSignature> KernelFuncsContainer;
- KernelFuncsContainer _kernelFuncs; /**< Table of kernel functions */
+ SelectorCache _selectorCache; /**< Shortcut list for important selectors. */
+ typedef Common::Array<KernelFunction> KernelFunctionArray;
+ KernelFunctionArray _kernelFuncs; /**< Table of kernel functions. */
/**
* Determines whether a list of registers matches a given signature.
* If no signature is given (i.e., if sig is NULL), this is always
* treated as a match.
*
- * @param segMan pointer to the segment manager
* @param sig signature to test against
* @param argc number of arguments to test
* @param argv argument list
* @return true if the signature was matched, false otherwise
*/
- bool signatureMatch(const char *sig, int argc, const reg_t *argv);
+ bool signatureMatch(const uint16 *sig, int argc, const reg_t *argv);
+
+ // Prints out debug information in case a signature check fails
+ void signatureDebug(const uint16 *sig, int argc, const reg_t *argv);
/**
* Determines the type of the object indicated by reg.
@@ -202,15 +193,15 @@ public:
* KSIG_INVALID set if the type of reg can be determined, but is invalid.
* 0 on error.
*/
- int findRegType(reg_t reg);
+ uint16 findRegType(reg_t reg);
/******************** Text functionality ********************/
/**
- * Looks up text referenced by scripts
- * SCI uses two values to reference to text: An address, and an index. The address
- * determines whether the text should be read from a resource file, or from the heap,
- * while the index either refers to the number of the string in the specified source,
- * or to a relative position inside the text.
+ * Looks up text referenced by scripts.
+ * SCI uses two values to reference to text: An address, and an index. The
+ * address determines whether the text should be read from a resource file,
+ * or from the heap, while the index either refers to the number of the
+ * string in the specified source, or to a relative position inside the text.
*
* @param address The address to look up
* @param index The relative index
@@ -218,22 +209,37 @@ public:
*/
Common::String lookupText(reg_t address, int index);
+ /**
+ * Loads the kernel function names.
+ *
+ * This function reads the kernel function name table from resource_map,
+ * and fills the _kernelNames array with them.
+ * The resulting list has the same format regardless of the format of the
+ * name table of the resource (the format changed between version 0 and 1).
+ */
+ void loadKernelNames(GameFeatures *features);
+
+ /**
+ * Sets debug flags for a kernel function
+ */
+ bool debugSetFunction(const char *kernelName, int logging, int breakpoint);
+
private:
/**
- * Sets the default kernel function names, based on the SCI version used
+ * Sets the default kernel function names, based on the SCI version used.
*/
- void setDefaultKernelNames(Common::String gameId);
+ void setDefaultKernelNames(GameFeatures *features);
#ifdef ENABLE_SCI32
/**
- * Sets the default kernel function names to the SCI2 kernel functions
+ * Sets the default kernel function names to the SCI2 kernel functions.
*/
void setKernelNamesSci2();
/**
- * Sets the default kernel function names to the SCI2.1 kernel functions
+ * Sets the default kernel function names to the SCI2.1 kernel functions.
*/
- void setKernelNamesSci21();
+ void setKernelNamesSci21(GameFeatures *features);
#endif
/**
@@ -248,36 +254,26 @@ private:
Common::StringArray checkStaticSelectorNames();
/**
- * Maps special selectors
+ * Maps special selectors.
*/
void mapSelectors();
/**
- * Maps kernel functions
+ * Maps kernel functions.
*/
void mapFunctions();
ResourceManager *_resMan;
SegManager *_segMan;
- uint32 features;
// Kernel-related lists
Common::StringArray _selectorNames;
Common::StringArray _kernelNames;
+
+ const Common::String _invalid;
};
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-/******************** Misc functions ********************/
-
-/**
- * Get all sound events, apply their changes to the heap
- */
-void process_sound_events(EngineState *s);
-
-/******************** Constants ********************/
-#endif
-
-/* Maximum length of a savegame name (including terminator character) */
+/* Maximum length of a savegame name (including terminator character). */
#define SCI_MAX_SAVENAME_LENGTH 0x24
/******************** Kernel functions ********************/
@@ -414,6 +410,7 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv);
reg_t kDoSync(EngineState *s, int argc, reg_t *argv);
reg_t kMemorySegment(EngineState *s, int argc, reg_t *argv);
reg_t kIntersections(EngineState *s, int argc, reg_t *argv);
+reg_t kMergePoly(EngineState *s, int argc, reg_t *argv);
reg_t kResCheck(EngineState *s, int argc, reg_t *argv);
reg_t kSetQuitStr(EngineState *s, int argc, reg_t *argv);
reg_t kShowMovie(EngineState *s, int argc, reg_t *argv);
@@ -422,6 +419,10 @@ reg_t kStrSplit(EngineState *s, int argc, reg_t *argv);
reg_t kPlatform(EngineState *s, int argc, reg_t *argv);
reg_t kTextColors(EngineState *s, int argc, reg_t *argv);
reg_t kTextFonts(EngineState *s, int argc, reg_t *argv);
+reg_t kDummy(EngineState *s, int argc, reg_t *argv);
+reg_t kEmpty(EngineState *s, int argc, reg_t *argv);
+reg_t kStub(EngineState *s, int argc, reg_t *argv);
+reg_t kStubNull(EngineState *s, int argc, reg_t *argv);
#ifdef ENABLE_SCI32
// SCI2 Kernel Functions
@@ -429,6 +430,8 @@ reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv);
reg_t kArray(EngineState *s, int argc, reg_t *argv);
reg_t kListAt(EngineState *s, int argc, reg_t *argv);
reg_t kString(EngineState *s, int argc, reg_t *argv);
+reg_t kMulDiv(EngineState *s, int argc, reg_t *argv);
+reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv);
// "Screen items" in SCI32 are views
reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv);
reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv);
@@ -450,10 +453,91 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv);
reg_t kInPolygon(EngineState *s, int argc, reg_t *argv);
// SCI2.1 Kernel Functions
+reg_t kText(EngineState *s, int argc, reg_t *argv);
reg_t kSave(EngineState *s, int argc, reg_t *argv);
reg_t kList(EngineState *s, int argc, reg_t *argv);
reg_t kRobot(EngineState *s, int argc, reg_t *argv);
+reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv);
+reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv);
+reg_t kCD(EngineState *s, int argc, reg_t *argv);
+reg_t kAddPicAt(EngineState *s, int argc, reg_t *argv);
+
+reg_t kAddBefore(EngineState *s, int argc, reg_t *argv);
+reg_t kMoveToFront(EngineState *s, int argc, reg_t *argv);
+reg_t kMoveToEnd(EngineState *s, int argc, reg_t *argv);
+#endif
+reg_t kDoSoundInit(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundPlay(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundRestore(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundDispose(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundMute(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundStop(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundStopAll(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundPause(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundResumeAfterRestore(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundMasterVolume(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundUpdate(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundFade(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundGetPolyphony(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundUpdateCues(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundSendMidi(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundReverb(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundSetHold(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundDummy(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundGetAudioCapability(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundSuspend(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundSetVolume(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundSetPriority(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundSetLoop(EngineState *s, int argc, reg_t *argv);
+
+reg_t kGraphGetColorCount(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphSaveBox(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphRestoreBox(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphFillBoxBackground(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphFillBoxForeground(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphFillBoxAny(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphUpdateBox(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphRedrawBox(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphAdjustPriority(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphSaveUpscaledHiresBox(EngineState *s, int argc, reg_t *argv);
+
+reg_t kPalVaryInit(EngineState *s, int argc, reg_t *argv);
+reg_t kPalVaryReverse(EngineState *s, int argc, reg_t *argv);
+reg_t kPalVaryGetCurrentStep(EngineState *s, int argc, reg_t *argv);
+reg_t kPalVaryDeinit(EngineState *s, int argc, reg_t *argv);
+reg_t kPalVaryChangeTarget(EngineState *s, int argc, reg_t *argv);
+reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv);
+reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv);
+reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv);
+
+reg_t kPaletteSetFromResource(EngineState *s, int argc, reg_t *argv);
+reg_t kPaletteSetFlag(EngineState *s, int argc, reg_t *argv);
+reg_t kPaletteUnsetFlag(EngineState *s, int argc, reg_t *argv);
+reg_t kPaletteSetIntensity(EngineState *s, int argc, reg_t *argv);
+reg_t kPaletteFindColor(EngineState *s, int argc, reg_t *argv);
+reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv);
+reg_t kPaletteSave(EngineState *s, int argc, reg_t *argv);
+reg_t kPaletteRestore(EngineState *s, int argc, reg_t *argv);
+
+reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOReadRaw(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOWriteRaw(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOUnlink(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOReadString(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOSeek(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOFindFirst(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOFindNext(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIORename(EngineState *s, int argc, reg_t *argv);
+#ifdef ENABLE_SCI32
+reg_t kFileIOReadByte(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOWriteByte(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOReadWord(EngineState *s, int argc, reg_t *argv);
+reg_t kFileIOWriteWord(EngineState *s, int argc, reg_t *argv);
#endif
//@}
diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp
deleted file mode 100644
index 465e0e92df..0000000000
--- a/engines/sci/engine/kernel32.cpp
+++ /dev/null
@@ -1,790 +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$
- *
- */
-
-#ifdef ENABLE_SCI32
-
-#include "sci/engine/features.h"
-#include "sci/engine/kernel.h"
-#include "sci/engine/segment.h"
-#include "sci/engine/state.h"
-#include "sci/engine/selector.h"
-#include "sci/graphics/gui.h"
-#include "sci/graphics/gui32.h"
-#include "sci/graphics/frameout.h"
-
-#include "common/system.h"
-
-namespace Sci {
-
-// NOTE: 0x72-0x79, 0x85-0x86, 0x88 are from the GK2 demo (which has debug support) and are
-// just Dummy in other SCI2 games.
-static const char *sci2_default_knames[] = {
- /*0x00*/ "Load",
- /*0x01*/ "UnLoad",
- /*0x02*/ "ScriptID",
- /*0x03*/ "DisposeScript",
- /*0x04*/ "Lock",
- /*0x05*/ "ResCheck",
- /*0x06*/ "Purge",
- /*0x07*/ "Clone",
- /*0x08*/ "DisposeClone",
- /*0x09*/ "RespondsTo",
- /*0x0a*/ "SetNowSeen",
- /*0x0b*/ "NumLoops",
- /*0x0c*/ "NumCels",
- /*0x0d*/ "CelWide",
- /*0x0e*/ "CelHigh",
- /*0x0f*/ "GetHighPlanePri",
- /*0x10*/ "GetHighItemPri",
- /*0x11*/ "ShakeScreen",
- /*0x12*/ "OnMe",
- /*0x13*/ "ShowMovie",
- /*0x14*/ "SetVideoMode",
- /*0x15*/ "AddScreenItem",
- /*0x16*/ "DeleteScreenItem",
- /*0x17*/ "UpdateScreenItem",
- /*0x18*/ "FrameOut",
- /*0x19*/ "AddPlane",
- /*0x1a*/ "DeletePlane",
- /*0x1b*/ "UpdatePlane",
- /*0x1c*/ "RepaintPlane",
- /*0x1d*/ "SetShowStyle",
- /*0x1e*/ "ShowStylePercent",
- /*0x1f*/ "SetScroll",
- /*0x20*/ "AddMagnify",
- /*0x21*/ "DeleteMagnify",
- /*0x22*/ "IsHiRes",
- /*0x23*/ "Graph",
- /*0x24*/ "InvertRect",
- /*0x25*/ "TextSize",
- /*0x26*/ "Message",
- /*0x27*/ "TextColors",
- /*0x28*/ "TextFonts",
- /*0x29*/ "Dummy",
- /*0x2a*/ "SetQuitStr",
- /*0x2b*/ "EditText",
- /*0x2c*/ "InputText",
- /*0x2d*/ "CreateTextBitmap",
- /*0x2e*/ "DisposeTextBitmap",
- /*0x2f*/ "GetEvent",
- /*0x30*/ "GlobalToLocal",
- /*0x31*/ "LocalToGlobal",
- /*0x32*/ "MapKeyToDir",
- /*0x33*/ "HaveMouse",
- /*0x34*/ "SetCursor",
- /*0x35*/ "VibrateMouse",
- /*0x36*/ "SaveGame",
- /*0x37*/ "RestoreGame",
- /*0x38*/ "RestartGame",
- /*0x39*/ "GameIsRestarting",
- /*0x3a*/ "MakeSaveCatName",
- /*0x3b*/ "MakeSaveFileName",
- /*0x3c*/ "GetSaveFiles",
- /*0x3d*/ "GetSaveDir",
- /*0x3e*/ "CheckSaveGame",
- /*0x3f*/ "CheckFreeSpace",
- /*0x40*/ "DoSound",
- /*0x41*/ "DoAudio",
- /*0x42*/ "DoSync",
- /*0x43*/ "NewList",
- /*0x44*/ "DisposeList",
- /*0x45*/ "NewNode",
- /*0x46*/ "FirstNode",
- /*0x47*/ "LastNode",
- /*0x48*/ "EmptyList",
- /*0x49*/ "NextNode",
- /*0x4a*/ "PrevNode",
- /*0x4b*/ "NodeValue",
- /*0x4c*/ "AddAfter",
- /*0x4d*/ "AddToFront",
- /*0x4e*/ "AddToEnd",
- /*0x4f*/ "Dummy",
- /*0x50*/ "Dummy",
- /*0x51*/ "FindKey",
- /*0x52*/ "Dummy",
- /*0x53*/ "Dummy",
- /*0x54*/ "Dummy",
- /*0x55*/ "DeleteKey",
- /*0x56*/ "Dummy",
- /*0x57*/ "Dummy",
- /*0x58*/ "ListAt",
- /*0x59*/ "ListIndexOf",
- /*0x5a*/ "ListEachElementDo",
- /*0x5b*/ "ListFirstTrue",
- /*0x5c*/ "ListAllTrue",
- /*0x5d*/ "Random",
- /*0x5e*/ "Abs",
- /*0x5f*/ "Sqrt",
- /*0x60*/ "GetAngle",
- /*0x61*/ "GetDistance",
- /*0x62*/ "ATan",
- /*0x63*/ "SinMult",
- /*0x64*/ "CosMult",
- /*0x65*/ "SinDiv",
- /*0x66*/ "CosDiv",
- /*0x67*/ "GetTime",
- /*0x68*/ "Platform",
- /*0x69*/ "BaseSetter",
- /*0x6a*/ "DirLoop",
- /*0x6b*/ "CantBeHere",
- /*0x6c*/ "InitBresen",
- /*0x6d*/ "DoBresen",
- /*0x6e*/ "SetJump",
- /*0x6f*/ "AvoidPath",
- /*0x70*/ "InPolygon",
- /*0x71*/ "MergePoly",
- /*0x72*/ "SetDebug",
- /*0x73*/ "InspectObject",
- /*0x74*/ "MemoryInfo",
- /*0x75*/ "Profiler",
- /*0x76*/ "Record",
- /*0x77*/ "PlayBack",
- /*0x78*/ "MonoOut",
- /*0x79*/ "SetFatalStr",
- /*0x7a*/ "GetCWD",
- /*0x7b*/ "ValidPath",
- /*0x7c*/ "FileIO",
- /*0x7d*/ "Dummy",
- /*0x7e*/ "DeviceInfo",
- /*0x7f*/ "Palette",
- /*0x80*/ "PalVary",
- /*0x81*/ "PalCycle",
- /*0x82*/ "Array",
- /*0x83*/ "String",
- /*0x84*/ "RemapColors",
- /*0x85*/ "IntegrityChecking",
- /*0x86*/ "CheckIntegrity",
- /*0x87*/ "ObjectIntersect",
- /*0x88*/ "MarkMemory",
- /*0x89*/ "TextWidth",
- /*0x8a*/ "PointSize",
-
- // GK2 Demo only kernel functions
- /*0x8b*/ "AddLine",
- /*0x8c*/ "DeleteLine",
- /*0x8d*/ "UpdateLine",
- /*0x8e*/ "AddPolygon",
- /*0x8f*/ "DeletePolygon",
- /*0x90*/ "UpdatePolygon",
- /*0x91*/ "Bitmap",
- /*0x92*/ "ScrollWindow",
- /*0x93*/ "SetFontRes",
- /*0x94*/ "MovePlaneItems",
- /*0x95*/ "PreloadResource",
- /*0x96*/ "Dummy",
- /*0x97*/ "ResourceTrack",
- /*0x98*/ "CheckCDisc",
- /*0x99*/ "GetSaveCDisc",
- /*0x9a*/ "TestPoly",
- /*0x9b*/ "WinHelp",
- /*0x9c*/ "LoadChunk",
- /*0x9d*/ "SetPalStyleRange",
- /*0x9e*/ "AddPicAt",
- /*0x9f*/ "MessageBox"
-};
-
-static const char *sci21_default_knames[] = {
- /*0x00*/ "Load",
- /*0x01*/ "UnLoad",
- /*0x02*/ "ScriptID",
- /*0x03*/ "DisposeScript",
- /*0x04*/ "Lock",
- /*0x05*/ "ResCheck",
- /*0x06*/ "Purge",
- /*0x07*/ "SetLanguage",
- /*0x08*/ "Dummy",
- /*0x09*/ "Dummy",
- /*0x0a*/ "Clone",
- /*0x0b*/ "DisposeClone",
- /*0x0c*/ "RespondsTo",
- /*0x0d*/ "FindSelector",
- /*0x0e*/ "FindClass",
- /*0x0f*/ "Dummy",
- /*0x10*/ "Dummy",
- /*0x11*/ "Dummy",
- /*0x12*/ "Dummy",
- /*0x13*/ "Dummy",
- /*0x14*/ "SetNowSeen",
- /*0x15*/ "NumLoops",
- /*0x16*/ "NumCels",
- /*0x17*/ "IsOnMe",
- /*0x18*/ "AddMagnify",
- /*0x19*/ "DeleteMagnify",
- /*0x1a*/ "CelRect",
- /*0x1b*/ "BaseLineSpan",
- /*0x1c*/ "CelWide",
- /*0x1d*/ "CelHigh",
- /*0x1e*/ "AddScreenItem",
- /*0x1f*/ "DeleteScreenItem",
- /*0x20*/ "UpdateScreenItem",
- /*0x21*/ "FrameOut",
- /*0x22*/ "CelInfo",
- /*0x23*/ "Bitmap",
- /*0x24*/ "CelLink",
- /*0x25*/ "Dummy",
- /*0x26*/ "Dummy",
- /*0x27*/ "Dummy",
- /*0x28*/ "AddPlane",
- /*0x29*/ "DeletePlane",
- /*0x2a*/ "UpdatePlane",
- /*0x2b*/ "RepaintPlane",
- /*0x2c*/ "GetHighPlanePri",
- /*0x2d*/ "GetHighItemPri",
- /*0x2e*/ "SetShowStyle",
- /*0x2f*/ "ShowStylePercent",
- /*0x30*/ "SetScroll",
- /*0x31*/ "MovePlaneItems",
- /*0x32*/ "ShakeScreen",
- /*0x33*/ "Dummy",
- /*0x34*/ "Dummy",
- /*0x35*/ "Dummy",
- /*0x36*/ "Dummy",
- /*0x37*/ "IsHiRes",
- /*0x38*/ "SetVideoMode",
- /*0x39*/ "ShowMovie",
- /*0x3a*/ "Robot",
- /*0x3b*/ "CreateTextBitmap",
- /*0x3c*/ "Random",
- /*0x3d*/ "Abs",
- /*0x3e*/ "Sqrt",
- /*0x3f*/ "GetAngle",
- /*0x40*/ "GetDistance",
- /*0x41*/ "ATan",
- /*0x42*/ "SinMult",
- /*0x43*/ "CosMult",
- /*0x44*/ "SinDiv",
- /*0x45*/ "CosDiv",
- /*0x46*/ "Text",
- /*0x47*/ "Dummy",
- /*0x48*/ "Message",
- /*0x49*/ "Font",
- /*0x4a*/ "EditText",
- /*0x4b*/ "InputText",
- /*0x4c*/ "ScrollWindow",
- /*0x4d*/ "Dummy",
- /*0x4e*/ "Dummy",
- /*0x4f*/ "Dummy",
- /*0x50*/ "GetEvent",
- /*0x51*/ "GlobalToLocal",
- /*0x52*/ "LocalToGlobal",
- /*0x53*/ "MapKeyToDir",
- /*0x54*/ "HaveMouse",
- /*0x55*/ "SetCursor",
- /*0x56*/ "VibrateMouse", // NOTE: Not in SCI3, instead replaced by Dummy.
- /*0x57*/ "Dummy",
- /*0x58*/ "Dummy",
- /*0x59*/ "Dummy",
- /*0x5a*/ "List",
- /*0x5b*/ "Array",
- /*0x5c*/ "String",
- /*0x5d*/ "FileIO",
- /*0x5e*/ "BaseSetter",
- /*0x5f*/ "DirLoop",
- /*0x60*/ "CantBeHere",
- /*0x61*/ "InitBresen",
- /*0x62*/ "DoBresen",
- /*0x63*/ "SetJump",
- /*0x64*/ "AvoidPath",
- /*0x65*/ "InPolygon",
- /*0x66*/ "MergePoly",
- /*0x67*/ "ObjectIntersect",
- /*0x68*/ "Dummy",
- /*0x69*/ "MemoryInfo",
- /*0x6a*/ "DeviceInfo",
- /*0x6b*/ "Palette",
- /*0x6c*/ "PalVary",
- /*0x6d*/ "PalCycle",
- /*0x6e*/ "RemapColors",
- /*0x6f*/ "AddLine",
- /*0x70*/ "DeleteLine",
- /*0x71*/ "UpdateLine",
- /*0x72*/ "AddPolygon",
- /*0x73*/ "DeletePolygon",
- /*0x74*/ "UpdatePolygon",
- /*0x75*/ "DoSound",
- /*0x76*/ "DoAudio",
- /*0x77*/ "DoSync",
- /*0x78*/ "Save",
- /*0x79*/ "GetTime",
- /*0x7a*/ "Platform",
- /*0x7b*/ "CD",
- /*0x7c*/ "SetQuitStr",
- /*0x7d*/ "GetConfig",
- /*0x7e*/ "Table",
- /*0x7f*/ "WinHelp", // Windows only
- /*0x80*/ "Dummy",
- /*0x81*/ "Dummy",
- /*0x82*/ "Dummy",
- /*0x83*/ "Dummy",
- /*0x84*/ "Dummy",
- /*0x85*/ "Dummy",
- /*0x86*/ "Dummy",
- /*0x87*/ "Dummy",
- /*0x88*/ "Dummy",
- /*0x89*/ "Dummy",
- /*0x8a*/ "LoadChunk",
- /*0x8b*/ "SetPalStyleRange",
- /*0x8c*/ "AddPicAt",
- /*0x8d*/ "Dummy",
- /*0x8e*/ "NewRoom",
- /*0x8f*/ "Dummy",
- /*0x90*/ "Priority",
- /*0x91*/ "MorphOn",
- /*0x92*/ "PlayVMD",
- /*0x93*/ "SetHotRectangles",
- /*0x94*/ "MulDiv",
- /*0x95*/ "GetSierraProfileInt", // Windows only
- /*0x96*/ "GetSierraProfileString", // Windows only
- /*0x97*/ "SetWindowsOption", // Windows only
- /*0x98*/ "GetWindowsOption", // Windows only
- /*0x99*/ "WinDLL", // Windows only
-
- // SCI3
- /*0x9a*/ "Dummy",
- /*0x9b*/ "Dummy",
- /*0x9c*/ "DeletePic"
-};
-
-enum {
- kKernelEntriesSci2 = 0x8b,
- kKernelEntriesGk2Demo = 0xa0,
- kKernelEntriesSci21 = 0x9a,
- kKernelEntriesSci3 = 0x9d
-};
-
-void Kernel::setKernelNamesSci2() {
- _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesSci2);
-}
-
-void Kernel::setKernelNamesSci21() {
- // Some SCI games use a modified SCI2 kernel table instead of the SCI2.1/SCI3 kernel table.
- // The GK2 demo does this as well as at least one version of KQ7. We detect which version
- // to use based on where kDoSound is called from Sound::play().
-
- // This is interesting because they all have the same interpreter version (2.100.002), yet
- // they would not be compatible with other games of the same interpreter.
-
- if (g_sci->_features->detectSci21KernelType() == SCI_VERSION_2) {
- _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesGk2Demo);
- // OnMe is IsOnMe here, but they should be compatible
- _kernelNames[0x23] = "Robot"; // Graph in SCI2
- _kernelNames[0x2e] = "Priority"; // DisposeTextBitmap in SCI2
- } else {
- // TODO: Differentiate between SCI2.1/3
- _kernelNames = Common::StringArray(sci21_default_knames, kKernelEntriesSci3);
- }
-}
-
-// SCI2 Kernel Functions
-
-reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) {
- // Returns 0 if the screen width or height is less than 640 or 400, respectively.
- if (g_system->getWidth() < 640 || g_system->getHeight() < 400)
- return make_reg(0, 0);
-
- return make_reg(0, 1);
-}
-
-reg_t kArray(EngineState *s, int argc, reg_t *argv) {
- switch (argv[0].toUint16()) {
- case 0: { // New
- reg_t arrayHandle;
- SciArray<reg_t> *array = s->_segMan->allocateArray(&arrayHandle);
- array->setType(argv[2].toUint16());
- array->setSize(argv[1].toUint16());
- return arrayHandle;
- }
- case 1: { // Size
- SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
- return make_reg(0, array->getSize());
- }
- case 2: { // At (return value at an index)
- SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
- return array->getValue(argv[2].toUint16());
- }
- case 3: { // Atput (put value at an index)
- SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
-
- uint32 index = argv[2].toUint16();
- uint32 count = argc - 3;
-
- if (index + count > 65535)
- break;
-
- if (array->getSize() < index + count)
- array->setSize(index + count);
-
- for (uint16 i = 0; i < count; i++)
- array->setValue(i + index, argv[i + 3]);
-
- return argv[1]; // We also have to return the handle
- }
- case 4: // Free
- // Freeing of arrays is handled by the garbage collector
- return s->r_acc;
- case 5: { // Fill
- SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
- uint16 index = argv[2].toUint16();
-
- // A count of -1 means fill the rest of the array
- uint16 count = argv[3].toSint16() == -1 ? array->getSize() - index : argv[3].toUint16();
- uint16 arraySize = array->getSize();
-
- if (arraySize < index + count)
- array->setSize(index + count);
-
- for (uint16 i = 0; i < count; i++)
- array->setValue(i + index, argv[4]);
-
- return argv[1];
- }
- case 6: { // Cpy
- SciArray<reg_t> *array1 = s->_segMan->lookupArray(argv[1]);
- SciArray<reg_t> *array2 = s->_segMan->lookupArray(argv[3]);
- uint32 index1 = argv[2].toUint16();
- uint32 index2 = argv[4].toUint16();
-
- // The original engine ignores bad copies too
- if (index2 > array2->getSize())
- break;
-
- // A count of -1 means fill the rest of the array
- uint32 count = argv[5].toSint16() == -1 ? array2->getSize() - index2 : argv[5].toUint16();
-
- if (array1->getSize() < index1 + count)
- array1->setSize(index1 + count);
-
- for (uint16 i = 0; i < count; i++)
- array1->setValue(i + index1, array2->getValue(i + index2));
-
- return argv[1];
- }
- case 7: // Cmp
- // Not implemented in SSCI
- return s->r_acc;
- case 8: { // Dup
- SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
- reg_t arrayHandle;
- SciArray<reg_t> *dupArray = s->_segMan->allocateArray(&arrayHandle);
-
- dupArray->setType(array->getType());
- dupArray->setSize(array->getSize());
-
- for (uint32 i = 0; i < array->getSize(); i++)
- dupArray->setValue(i, array->getValue(i));
-
- return arrayHandle;
- }
- case 9: // Getdata
- if (!s->_segMan->isHeapObject(argv[1]))
- return argv[1];
-
- return GET_SEL32(s->_segMan, argv[1], SELECTOR(data));
- default:
- error("Unknown kArray subop %d", argv[0].toUint16());
- }
-
- return NULL_REG;
-}
-
-reg_t kString(EngineState *s, int argc, reg_t *argv) {
- switch (argv[0].toUint16()) {
- case 0: { // New
- reg_t stringHandle;
- SciString *string = s->_segMan->allocateString(&stringHandle);
- string->setSize(argv[1].toUint16());
-
- // Make sure the first character is a null character
- if (string->getSize() > 0)
- string->setValue(0, 0);
-
- return stringHandle;
- }
- case 1: // Size
- return make_reg(0, s->_segMan->getString(argv[1]).size());
- case 2: // At (return value at an index)
- return make_reg(0, s->_segMan->getString(argv[1])[argv[2].toUint16()]);
- case 3: { // Atput (put value at an index)
- SciString *string = s->_segMan->lookupString(argv[1]);
-
- uint32 index = argv[2].toUint16();
- uint32 count = argc - 3;
-
- if (index + count > 65535)
- break;
-
- if (string->getSize() < index + count)
- string->setSize(index + count);
-
- for (uint16 i = 0; i < count; i++)
- string->setValue(i + index, argv[i + 3].toUint16());
-
- return argv[1]; // We also have to return the handle
- }
- case 4: // Free
- // Freeing of strings is handled by the garbage collector
- return s->r_acc;
- case 5: { // Fill
- SciString *string = s->_segMan->lookupString(argv[1]);
- uint16 index = argv[2].toUint16();
-
- // A count of -1 means fill the rest of the array
- uint16 count = argv[3].toSint16() == -1 ? string->getSize() - index : argv[3].toUint16();
- uint16 stringSize = string->getSize();
-
- if (stringSize < index + count)
- string->setSize(index + count);
-
- for (uint16 i = 0; i < count; i++)
- string->setValue(i + index, argv[4].toUint16());
-
- return argv[1];
- }
- case 6: { // Cpy
- Common::String string2 = s->_segMan->getString(argv[3]);
- uint32 index1 = argv[2].toUint16();
- uint32 index2 = argv[4].toUint16();
-
- // The original engine ignores bad copies too
- if (index2 > string2.size())
- break;
-
- // A count of -1 means fill the rest of the array
- uint32 count = argv[5].toSint16() == -1 ? string2.size() - index2 + 1 : argv[5].toUint16();
-
- // We have a special case here for argv[1] being a system string
- if (argv[1].segment == s->sys_strings_segment) {
- // Resize if necessary
- if ((uint32)s->sys_strings->_strings[argv[1].toUint16()]._maxSize < index1 + count) {
- delete[] s->sys_strings->_strings[argv[1].toUint16()]._value;
- s->sys_strings->_strings[argv[1].toUint16()]._maxSize = index1 + count;
- s->sys_strings->_strings[argv[1].toUint16()]._value = new char[index1 + count];
- memset(s->sys_strings->_strings[argv[1].toUint16()]._value, 0, index1 + count);
- }
-
- strncpy(s->sys_strings->_strings[argv[1].toUint16()]._value + index1, string2.c_str() + index2, count);
- } else {
- SciString *string1 = s->_segMan->lookupString(argv[1]);
-
- if (string1->getSize() < index1 + count)
- string1->setSize(index1 + count);
-
- // Note: We're accessing from c_str() here because the string's size ignores
- // the trailing 0 and therefore triggers an assert when doing string2[i + index2].
- for (uint16 i = 0; i < count; i++)
- string1->setValue(i + index1, string2.c_str()[i + index2]);
- }
-
- } return argv[1];
- case 7: { // Cmp
- Common::String string1 = argv[1].isNull() ? "" : s->_segMan->getString(argv[1]);
- Common::String string2 = argv[2].isNull() ? "" : s->_segMan->getString(argv[2]);
-
- if (argc == 4) // Strncmp
- return make_reg(0, strncmp(string1.c_str(), string2.c_str(), argv[3].toUint16()));
- else // Strcmp
- return make_reg(0, strcmp(string1.c_str(), string2.c_str()));
- }
- case 8: { // Dup
- Common::String string = s->_segMan->getString(argv[1]);
- reg_t stringHandle;
- SciString *dupString = s->_segMan->allocateString(&stringHandle);
- dupString->setSize(string.size() + 1);
-
- for (uint32 i = 0; i < string.size(); i++)
- dupString->setValue(i, string.c_str()[i]);
-
- dupString->setValue(dupString->getSize() - 1, 0);
-
- return stringHandle;
- }
- case 9: // Getdata
- if (!s->_segMan->isHeapObject(argv[1]))
- return argv[1];
-
- return GET_SEL32(s->_segMan, argv[1], SELECTOR(data));
- case 10: // Stringlen
- return make_reg(0, s->_segMan->strlen(argv[1]));
- case 11: { // Printf
- reg_t stringHandle;
- s->_segMan->allocateString(&stringHandle);
-
- reg_t *adjustedArgs = new reg_t[argc];
- adjustedArgs[0] = stringHandle;
- memcpy(&adjustedArgs[1], argv + 1, (argc - 1) * sizeof(reg_t));
-
- kFormat(s, argc, adjustedArgs);
- delete[] adjustedArgs;
- return stringHandle;
- }
- case 12: // Printf Buf
- return kFormat(s, argc - 1, argv + 1);
- case 13: { // atoi
- Common::String string = s->_segMan->getString(argv[1]);
- return make_reg(0, (uint16)atoi(string.c_str()));
- }
- default:
- error("Unknown kString subop %d", argv[0].toUint16());
- }
-
- return NULL_REG;
-}
-
-reg_t kSave(EngineState *s, int argc, reg_t *argv) {
- switch (argv[0].toUint16()) {
- case 2: // GetSaveDir
- // Yay! Reusing the old kernel function!
- return kGetSaveDir(s, argc - 1, argv + 1);
- case 8:
- // TODO
- // This function has to return something other than 0 to proceed
- return s->r_acc;
- default:
- warning("Unknown/unhandled kSave subop %d", argv[0].toUint16());
- }
-
- return NULL_REG;
-}
-
-reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) {
- reg_t viewObj = argv[0];
-
- g_sci->_gfxFrameout->kernelAddScreenItem(viewObj);
- return NULL_REG;
-}
-
-reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv) {
- //reg_t viewObj = argv[0];
-
- //warning("kUpdateScreenItem, object %04x:%04x, view %d, loop %d, cel %d, pri %d", PRINT_REG(viewObj), viewId, loopNo, celNo, priority);
- return NULL_REG;
-}
-
-reg_t kDeleteScreenItem(EngineState *s, int argc, reg_t *argv) {
- reg_t viewObj = argv[0];
-
- g_sci->_gfxFrameout->kernelDeleteScreenItem(viewObj);
-
- /*
- reg_t viewObj = argv[0];
- uint16 viewId = GET_SEL32V(s->_segMan, viewObj, SELECTOR(view));
- int16 loopNo = GET_SEL32V(s->_segMan, viewObj, SELECTOR(loop));
- int16 celNo = GET_SEL32V(s->_segMan, viewObj, SELECTOR(cel));
- //int16 leftPos = 0;
- //int16 topPos = 0;
- int16 priority = GET_SEL32V(s->_segMan, viewObj, SELECTOR(priority));
- //int16 control = 0;
- */
-
- // TODO
-
- //warning("kDeleteScreenItem, view %d, loop %d, cel %d, pri %d", viewId, loopNo, celNo, priority);
- return NULL_REG;
-}
-
-reg_t kAddPlane(EngineState *s, int argc, reg_t *argv) {
- reg_t planeObj = argv[0];
-
- g_sci->_gfxFrameout->kernelAddPlane(planeObj);
- warning("kAddPlane object %04x:%04x", PRINT_REG(planeObj));
- return NULL_REG;
-}
-
-reg_t kDeletePlane(EngineState *s, int argc, reg_t *argv) {
- reg_t planeObj = argv[0];
-
- g_sci->_gfxFrameout->kernelDeletePlane(planeObj);
- warning("kDeletePlane object %04x:%04x", PRINT_REG(planeObj));
- return NULL_REG;
-}
-
-reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv) {
- reg_t planeObj = argv[0];
-
- g_sci->_gfxFrameout->kernelUpdatePlane(planeObj);
- return s->r_acc;
-}
-
-reg_t kRepaintPlane(EngineState *s, int argc, reg_t *argv) {
- reg_t picObj = argv[0];
-
- // TODO
-
- warning("kRepaintPlane object %04x:%04x", PRINT_REG(picObj));
- return NULL_REG;
-}
-
-reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv) {
- warning("kGetHighPlanePri: %d", g_sci->_gfxFrameout->kernelGetHighPlanePri());
- return make_reg(0, g_sci->_gfxFrameout->kernelGetHighPlanePri());
-}
-
-reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) {
- // This kernel call likely seems to be doing the screen updates,
- // as its called right after a view is updated
-
- // TODO
- g_sci->_gfxFrameout->kernelFrameout();
-
- return NULL_REG;
-}
-
-reg_t kOnMe(EngineState *s, int argc, reg_t *argv) {
- // Tests if the cursor is on the passed object
-
- uint16 x = argv[0].toUint16();
- uint16 y = argv[1].toUint16();
- reg_t targetObject = argv[2];
- // TODO: argv[3] - it's usually 0
- Common::Rect nsRect;
-
- // Get the bounding rectangle of the object
- nsRect.left = GET_SEL32V(s->_segMan, targetObject, SELECTOR(nsLeft));
- nsRect.top = GET_SEL32V(s->_segMan, targetObject, SELECTOR(nsTop));
- nsRect.right = GET_SEL32V(s->_segMan, targetObject, SELECTOR(nsRight));
- nsRect.bottom = GET_SEL32V(s->_segMan, targetObject, SELECTOR(nsBottom));
-
- //warning("kOnMe: (%d, %d) on object %04x:%04x, parameter %d", argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), argv[3].toUint16());
-
- return make_reg(0, nsRect.contains(x, y));
-}
-
-reg_t kInPolygon(EngineState *s, int argc, reg_t *argv) {
- // kAvoidPath already implements this
- return kAvoidPath(s, argc, argv);
-}
-
-reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) {
- // TODO: argument 0 is usually 0, and arguments 1 and 2 are usually 1
- reg_t object = argv[3];
- Common::String text = s->_segMan->getString(GET_SEL32(s->_segMan, object, SELECTOR(text)));
- debug("kCreateTextBitmap: %s", text.c_str());
-
- return NULL_REG;
-}
-
-} // End of namespace Sci
-
-#endif // ENABLE_SCI32
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
new file mode 100644
index 0000000000..b2b8eb593e
--- /dev/null
+++ b/engines/sci/engine/kernel_tables.h
@@ -0,0 +1,1031 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 SCI_ENGINE_KERNEL_TABLES_H
+#define SCI_ENGINE_KERNEL_TABLES_H
+
+#include "sci/engine/workarounds.h"
+
+namespace Sci {
+
+// [io] -> either integer or object
+// (io) -> optionally integer AND an object
+// (i) -> optional integer
+// . -> any type
+// i* -> optional multiple integers
+// .* -> any parameters afterwards (or none)
+
+struct SciKernelMapSubEntry {
+ SciVersion fromVersion;
+ SciVersion toVersion;
+
+ uint16 id;
+
+ const char *name;
+ KernelFunctionCall *function;
+
+ const char *signature;
+ const SciWorkaroundEntry *workarounds;
+};
+
+#define SCI_SUBOPENTRY_TERMINATOR { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, NULL, NULL, NULL, NULL }
+
+
+#define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE
+#define SIG_SCI0 SCI_VERSION_NONE, SCI_VERSION_01
+#define SIG_SCI1 SCI_VERSION_1_EGA, SCI_VERSION_1_LATE
+#define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1
+#define SIG_SINCE_SCI11 SCI_VERSION_1_1, SCI_VERSION_NONE
+#define SIG_SCI21 SCI_VERSION_2_1, SCI_VERSION_2_1
+
+#define SIG_SCI16 SCI_VERSION_NONE, SCI_VERSION_1_1
+#define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE
+
+// SCI-Sound-Version
+#define SIG_SOUNDSCI0 SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE
+#define SIG_SOUNDSCI1EARLY SCI_VERSION_1_EARLY, SCI_VERSION_1_EARLY
+#define SIG_SOUNDSCI1LATE SCI_VERSION_1_LATE, SCI_VERSION_1_LATE
+#define SIG_SOUNDSCI21 SCI_VERSION_2_1, SCI_VERSION_2_1
+
+#define SIGFOR_ALL 0x3f
+#define SIGFOR_DOS 1 << 0
+#define SIGFOR_PC98 1 << 1
+#define SIGFOR_WIN 1 << 2
+#define SIGFOR_MAC 1 << 3
+#define SIGFOR_AMIGA 1 << 4
+#define SIGFOR_ATARI 1 << 5
+#define SIGFOR_PC SIGFOR_DOS|SIGFOR_WIN
+
+#define SIG_EVERYWHERE SIG_SCIALL, SIGFOR_ALL
+
+#define MAP_CALL(_name_) #_name_, k##_name_
+
+// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kDoSound_subops[] = {
+ { SIG_SOUNDSCI0, 0, MAP_CALL(DoSoundInit), "o", NULL },
+ { SIG_SOUNDSCI0, 1, MAP_CALL(DoSoundPlay), "o", NULL },
+ { SIG_SOUNDSCI0, 2, MAP_CALL(DoSoundRestore), "(o)", NULL },
+ { SIG_SOUNDSCI0, 3, MAP_CALL(DoSoundDispose), "o", NULL },
+ { SIG_SOUNDSCI0, 4, MAP_CALL(DoSoundMute), "(i)", NULL },
+ { SIG_SOUNDSCI0, 5, MAP_CALL(DoSoundStop), "o", NULL },
+ { SIG_SOUNDSCI0, 6, MAP_CALL(DoSoundPause), "i", NULL },
+ { SIG_SOUNDSCI0, 7, MAP_CALL(DoSoundResumeAfterRestore), "", NULL },
+ { SIG_SOUNDSCI0, 8, MAP_CALL(DoSoundMasterVolume), "(i)", NULL },
+ { SIG_SOUNDSCI0, 9, MAP_CALL(DoSoundUpdate), "o", NULL },
+ { SIG_SOUNDSCI0, 10, MAP_CALL(DoSoundFade), "o", kDoSoundFade_workarounds },
+ { SIG_SOUNDSCI0, 11, MAP_CALL(DoSoundGetPolyphony), "", NULL },
+ { SIG_SOUNDSCI0, 12, MAP_CALL(DoSoundStopAll), "", NULL },
+ { SIG_SOUNDSCI1EARLY, 0, MAP_CALL(DoSoundMasterVolume), NULL, NULL },
+ { SIG_SOUNDSCI1EARLY, 1, MAP_CALL(DoSoundMute), NULL, NULL },
+ { SIG_SOUNDSCI1EARLY, 2, MAP_CALL(DoSoundRestore), NULL, NULL },
+ { SIG_SOUNDSCI1EARLY, 3, MAP_CALL(DoSoundGetPolyphony), NULL, NULL },
+ { SIG_SOUNDSCI1EARLY, 4, MAP_CALL(DoSoundUpdate), NULL, NULL },
+ { SIG_SOUNDSCI1EARLY, 5, MAP_CALL(DoSoundInit), NULL, NULL },
+ { SIG_SOUNDSCI1EARLY, 6, MAP_CALL(DoSoundDispose), NULL, NULL },
+ { SIG_SOUNDSCI1EARLY, 7, MAP_CALL(DoSoundPlay), "oi", NULL },
+ // ^^ TODO: In SCI1-SCI1.1 DoSound (play) is called by 2 methods of the Sound object: play and
+ // playBed. The methods are the same, apart from the second integer parameter: it's 0 in
+ // play and 1 in playBed, to distinguish the caller. It's passed on, we should find out what
+ // it actually does internally
+ { SIG_SOUNDSCI1EARLY, 8, MAP_CALL(DoSoundStop), NULL, NULL },
+ { SIG_SOUNDSCI1EARLY, 9, MAP_CALL(DoSoundPause), "[o0]i", NULL },
+ { SIG_SOUNDSCI1EARLY, 10, MAP_CALL(DoSoundFade), "oiiii", kDoSoundFade_workarounds },
+ { SIG_SOUNDSCI1EARLY, 11, MAP_CALL(DoSoundUpdateCues), "o", NULL },
+ { SIG_SOUNDSCI1EARLY, 12, MAP_CALL(DoSoundSendMidi), "oiii", NULL },
+ { SIG_SOUNDSCI1EARLY, 13, MAP_CALL(DoSoundReverb), "i", NULL },
+ { SIG_SOUNDSCI1EARLY, 14, MAP_CALL(DoSoundSetHold), "oi", NULL },
+ { SIG_SOUNDSCI1EARLY, 15, MAP_CALL(DoSoundDummy), "", NULL },
+ // ^^ Longbow demo
+ { SIG_SOUNDSCI1LATE, 0, MAP_CALL(DoSoundMasterVolume), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 1, MAP_CALL(DoSoundMute), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 2, MAP_CALL(DoSoundRestore), "", NULL },
+ { SIG_SOUNDSCI1LATE, 3, MAP_CALL(DoSoundGetPolyphony), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 4, MAP_CALL(DoSoundGetAudioCapability), "", NULL },
+ { SIG_SOUNDSCI1LATE, 5, MAP_CALL(DoSoundSuspend), "i", NULL },
+ { SIG_SOUNDSCI1LATE, 6, MAP_CALL(DoSoundInit), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 7, MAP_CALL(DoSoundDispose), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 8, MAP_CALL(DoSoundPlay), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 9, MAP_CALL(DoSoundStop), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 10, MAP_CALL(DoSoundPause), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 11, MAP_CALL(DoSoundFade), "oiiii(i)", kDoSoundFade_workarounds },
+ { SIG_SOUNDSCI1LATE, 12, MAP_CALL(DoSoundSetHold), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 13, MAP_CALL(DoSoundDummy), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 14, MAP_CALL(DoSoundSetVolume), "oi", NULL },
+ { SIG_SOUNDSCI1LATE, 15, MAP_CALL(DoSoundSetPriority), "oi", NULL },
+ { SIG_SOUNDSCI1LATE, 16, MAP_CALL(DoSoundSetLoop), "oi", NULL },
+ { SIG_SOUNDSCI1LATE, 17, MAP_CALL(DoSoundUpdateCues), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 18, MAP_CALL(DoSoundSendMidi), "oiii(i)", NULL },
+ { SIG_SOUNDSCI1LATE, 19, MAP_CALL(DoSoundReverb), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 20, MAP_CALL(DoSoundUpdate), NULL, NULL },
+#ifdef ENABLE_SCI32
+ { SIG_SOUNDSCI21, 0, MAP_CALL(DoSoundMasterVolume), NULL, NULL },
+ { SIG_SOUNDSCI21, 1, MAP_CALL(DoSoundMute), NULL, NULL },
+ { SIG_SOUNDSCI21, 2, MAP_CALL(DoSoundRestore), NULL, NULL },
+ { SIG_SOUNDSCI21, 3, MAP_CALL(DoSoundGetPolyphony), NULL, NULL },
+ { SIG_SOUNDSCI21, 4, MAP_CALL(DoSoundGetAudioCapability), NULL, NULL },
+ { SIG_SOUNDSCI21, 5, MAP_CALL(DoSoundSuspend), NULL, NULL },
+ { SIG_SOUNDSCI21, 6, MAP_CALL(DoSoundInit), NULL, NULL },
+ { SIG_SOUNDSCI21, 7, MAP_CALL(DoSoundDispose), NULL, NULL },
+ { SIG_SOUNDSCI21, 8, MAP_CALL(DoSoundPlay), "o(i)", NULL },
+ // ^^ TODO: if this is really the only change between SCI1LATE AND SCI21, we could rename the
+ // SIG_SOUNDSCI1LATE #define to SIG_SINCE_SOUNDSCI1LATE and make it being SCI1LATE+. Although
+ // I guess there are many more changes somewhere
+ // TODO: Quest for Glory 4 (SCI2.1) uses the old scheme, we need to detect it accordingly
+ // signature for SCI21 should be "o"
+ { SIG_SOUNDSCI21, 9, MAP_CALL(DoSoundStop), NULL, NULL },
+ { SIG_SOUNDSCI21, 10, MAP_CALL(DoSoundPause), NULL, NULL },
+ { SIG_SOUNDSCI21, 11, MAP_CALL(DoSoundFade), NULL, NULL },
+ { SIG_SOUNDSCI21, 12, MAP_CALL(DoSoundSetHold), NULL, NULL },
+ { SIG_SOUNDSCI21, 13, MAP_CALL(DoSoundDummy), NULL, NULL },
+ { SIG_SOUNDSCI21, 14, MAP_CALL(DoSoundSetVolume), NULL, NULL },
+ { SIG_SOUNDSCI21, 15, MAP_CALL(DoSoundSetPriority), NULL, NULL },
+ { SIG_SOUNDSCI21, 16, MAP_CALL(DoSoundSetLoop), NULL, NULL },
+ { SIG_SOUNDSCI21, 17, MAP_CALL(DoSoundUpdateCues), NULL, NULL },
+ { SIG_SOUNDSCI21, 18, MAP_CALL(DoSoundSendMidi), NULL, NULL },
+ { SIG_SOUNDSCI21, 19, MAP_CALL(DoSoundReverb), NULL, NULL },
+ { SIG_SOUNDSCI21, 20, MAP_CALL(DoSoundUpdate), NULL, NULL },
+#endif
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
+// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kGraph_subops[] = {
+ { SIG_SCI32, 1, MAP_CALL(StubNull), "", NULL }, // called by gk1 sci32 right at the start
+ { SIG_SCIALL, 2, MAP_CALL(GraphGetColorCount), "", NULL },
+ // 3 - set palette via resource
+ { SIG_SCIALL, 4, MAP_CALL(GraphDrawLine), "iiiii(i)(i)", kGraphDrawLine_workarounds },
+ // 5 - nop
+ // 6 - draw pattern
+ { SIG_SCIALL, 7, MAP_CALL(GraphSaveBox), "iiiii", kGraphSaveBox_workarounds },
+ { SIG_SCIALL, 8, MAP_CALL(GraphRestoreBox), "[r0!]", kGraphRestoreBox_workarounds },
+ // ^ this may get called with invalid references, we check them within restoreBits() and sierra sci behaves the same
+ { SIG_SCIALL, 9, MAP_CALL(GraphFillBoxBackground), "iiii", NULL },
+ { SIG_SCIALL, 10, MAP_CALL(GraphFillBoxForeground), "iiii", kGraphFillBoxForeground_workarounds },
+ { SIG_SCIALL, 11, MAP_CALL(GraphFillBoxAny), "iiiiii(i)(i)", kGraphFillBoxAny_workarounds },
+ { SIG_SCI11, 12, MAP_CALL(GraphUpdateBox), "iiii(i)(r0)", kGraphUpdateBox_workarounds }, // kq6 hires
+ { SIG_SCIALL, 12, MAP_CALL(GraphUpdateBox), "iiii(i)", kGraphUpdateBox_workarounds },
+ { SIG_SCIALL, 13, MAP_CALL(GraphRedrawBox), "iiii", kGraphRedrawBox_workarounds },
+ { SIG_SCIALL, 14, MAP_CALL(GraphAdjustPriority), "ii", NULL },
+ { SIG_SCI11, 15, MAP_CALL(GraphSaveUpscaledHiresBox), "iiii", NULL }, // kq6 hires
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
+// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kPalVary_subops[] = {
+ { SIG_SCI21, 0, MAP_CALL(PalVaryInit), "ii(i)(i)(i)", NULL },
+ { SIG_SCIALL, 0, MAP_CALL(PalVaryInit), "ii(i)(i)", NULL },
+ { SIG_SCIALL, 1, MAP_CALL(PalVaryReverse), "(i)(i)(i)", NULL },
+ { SIG_SCIALL, 2, MAP_CALL(PalVaryGetCurrentStep), "", NULL },
+ { SIG_SCIALL, 3, MAP_CALL(PalVaryDeinit), "", NULL },
+ { SIG_SCIALL, 4, MAP_CALL(PalVaryChangeTarget), "i", NULL },
+ { SIG_SCIALL, 5, MAP_CALL(PalVaryChangeTicks), "i", NULL },
+ { SIG_SCIALL, 6, MAP_CALL(PalVaryPauseResume), "i", NULL },
+ { SIG_SCI32, 8, MAP_CALL(PalVaryUnknown), "i", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
+// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kPalette_subops[] = {
+ { SIG_SCIALL, 1, MAP_CALL(PaletteSetFromResource), "i(i)", NULL },
+ { SIG_SCIALL, 2, MAP_CALL(PaletteSetFlag), "iii", NULL },
+ { SIG_SCIALL, 3, MAP_CALL(PaletteUnsetFlag), "iii", kPaletteUnsetFlag_workarounds },
+ { SIG_SCIALL, 4, MAP_CALL(PaletteSetIntensity), "iii(i)", NULL },
+ { SIG_SCIALL, 5, MAP_CALL(PaletteFindColor), "iii", NULL },
+ { SIG_SCIALL, 6, MAP_CALL(PaletteAnimate), "i*", NULL },
+ { SIG_SCIALL, 7, MAP_CALL(PaletteSave), "", NULL },
+ { SIG_SCIALL, 8, MAP_CALL(PaletteRestore), "[r0]", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
+static const SciKernelMapSubEntry kFileIO_subops[] = {
+ { SIG_SCI32, 0, MAP_CALL(FileIOOpen), "r(i)", NULL },
+ { SIG_SCIALL, 0, MAP_CALL(FileIOOpen), "ri", NULL },
+ { SIG_SCIALL, 1, MAP_CALL(FileIOClose), "i", NULL },
+ { SIG_SCIALL, 2, MAP_CALL(FileIOReadRaw), "iri", NULL },
+ { SIG_SCIALL, 3, MAP_CALL(FileIOWriteRaw), "iri", NULL },
+ { SIG_SCIALL, 4, MAP_CALL(FileIOUnlink), "r", NULL },
+ { SIG_SCIALL, 5, MAP_CALL(FileIOReadString), "rii", NULL },
+ { SIG_SCIALL, 6, MAP_CALL(FileIOWriteString), "ir", NULL },
+ { SIG_SCIALL, 7, MAP_CALL(FileIOSeek), "iii", NULL },
+ { SIG_SCIALL, 8, MAP_CALL(FileIOFindFirst), "rri", NULL },
+ { SIG_SCIALL, 9, MAP_CALL(FileIOFindNext), "r", NULL },
+ { SIG_SCIALL, 10, MAP_CALL(FileIOExists), "r", NULL },
+ { SIG_SINCE_SCI11, 11, MAP_CALL(FileIORename), "rr", NULL },
+#ifdef ENABLE_SCI32
+ { SIG_SCI32, 13, MAP_CALL(FileIOReadByte), "i", NULL },
+ { SIG_SCI32, 14, MAP_CALL(FileIOWriteByte), "ii", NULL },
+ { SIG_SCI32, 15, MAP_CALL(FileIOReadWord), "i", NULL },
+ { SIG_SCI32, 16, MAP_CALL(FileIOWriteWord), "ii", NULL },
+ { SIG_SCI32, 19, MAP_CALL(Stub), "r", NULL }, // for Torin / Torin demo
+#endif
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
+#ifdef ENABLE_SCI32
+// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kList_subops[] = {
+ { SIG_SCI21, 0, MAP_CALL(NewList), "", NULL },
+ { SIG_SCI21, 1, MAP_CALL(DisposeList), "l", NULL },
+ { SIG_SCI21, 2, MAP_CALL(NewNode), ".", NULL },
+ { SIG_SCI21, 3, MAP_CALL(FirstNode), "[l0]", NULL },
+ { SIG_SCI21, 4, MAP_CALL(LastNode), "l", NULL },
+ { SIG_SCI21, 5, MAP_CALL(EmptyList), "l", NULL },
+ { SIG_SCI21, 6, MAP_CALL(NextNode), "n", NULL },
+ { SIG_SCI21, 7, MAP_CALL(PrevNode), "n", NULL },
+ { SIG_SCI21, 8, MAP_CALL(NodeValue), "[n0]", NULL },
+ { SIG_SCI21, 9, MAP_CALL(AddAfter), "lnn.", NULL },
+ { SIG_SCI21, 10, MAP_CALL(AddToFront), "ln.", NULL },
+ { SIG_SCI21, 11, MAP_CALL(AddToEnd), "ln.", NULL },
+ { SIG_SCI21, 12, MAP_CALL(AddBefore), "ln.", NULL },
+ { SIG_SCI21, 13, MAP_CALL(MoveToFront), "ln", NULL },
+ { SIG_SCI21, 14, MAP_CALL(MoveToEnd), "ln", NULL },
+ { SIG_SCI21, 15, MAP_CALL(FindKey), "l.", NULL },
+ { SIG_SCI21, 16, MAP_CALL(DeleteKey), "l.", NULL },
+ { SIG_SCI21, 17, MAP_CALL(ListAt), "li", NULL },
+ // FIXME: This doesn't seem to be ListIndexOf. In Torin demo, an index is
+ // passed as a second parameter instead of an object. Thus, it seems to
+ // be something like ListAt instead... If we swap the two subops though,
+ // Torin demo crashes complaining that it tried to send to a non-object,
+ // therefore the semantics might be different here (signature was l[o0])
+ // In SQ6 object is passed right when skipping the intro
+ { SIG_SCI21, 18, MAP_CALL(StubNull), "l[io]", NULL },
+ { SIG_SCI21, 19, MAP_CALL(ListEachElementDo), "li(.*)", NULL },
+ { SIG_SCI21, 20, MAP_CALL(ListFirstTrue), "li(.*)", NULL },
+ { SIG_SCI21, 21, MAP_CALL(ListAllTrue), "li(.*)", NULL },
+ { SIG_SCI21, 22, MAP_CALL(Sort), "ooo", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
+#endif
+
+struct SciKernelMapEntry {
+ const char *name;
+ KernelFunctionCall *function;
+
+ SciVersion fromVersion;
+ SciVersion toVersion;
+ byte forPlatform;
+
+ const char *signature;
+ const SciKernelMapSubEntry *subFunctions;
+ const SciWorkaroundEntry *workarounds;
+};
+
+// name, version/platform, signature, sub-signatures, workarounds
+static SciKernelMapEntry s_kernelMap[] = {
+ { MAP_CALL(Abs), SIG_EVERYWHERE, "i", NULL, kAbs_workarounds },
+ { MAP_CALL(AddAfter), SIG_EVERYWHERE, "lnn", NULL, NULL },
+ { MAP_CALL(AddMenu), SIG_EVERYWHERE, "rr", NULL, NULL },
+ { MAP_CALL(AddToEnd), SIG_EVERYWHERE, "ln", NULL, NULL },
+ { MAP_CALL(AddToFront), SIG_EVERYWHERE, "ln", NULL, NULL },
+ { MAP_CALL(AddToPic), SIG_EVERYWHERE, "[il](iiiiii)", NULL, NULL },
+ { MAP_CALL(Animate), SIG_EVERYWHERE, "(l0)(i)", NULL, NULL },
+ { MAP_CALL(AssertPalette), SIG_EVERYWHERE, "i", NULL, NULL },
+ { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii(.*)", NULL, NULL },
+ { MAP_CALL(BaseSetter), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL },
+#ifdef ENABLE_SCI32
+ { "CantBeHere", kCantBeHere32, SIG_SCI32, SIGFOR_ALL, "ol", NULL, NULL },
+#endif
+ { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL },
+ { MAP_CALL(CelHigh), SIG_EVERYWHERE, "ii(i)", NULL, kCelHigh_workarounds },
+ { MAP_CALL(CelWide), SIG_EVERYWHERE, "ii(i)", NULL, kCelWide_workarounds },
+ { MAP_CALL(CheckFreeSpace), SIG_SCI32, SIGFOR_ALL, "r.*", NULL, NULL },
+ { MAP_CALL(CheckFreeSpace), SIG_SCI11, SIGFOR_ALL, "r(i)", NULL, NULL },
+ { MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r", NULL, NULL },
+ { MAP_CALL(CheckSaveGame), SIG_EVERYWHERE, ".*", NULL, NULL },
+ { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(CoordPri), SIG_EVERYWHERE, "i(i)", NULL, NULL },
+ { MAP_CALL(CosDiv), SIG_EVERYWHERE, "ii", NULL, NULL },
+ { MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL, NULL },
+ { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i(r)(r)(i)", NULL, kDeviceInfo_workarounds }, // subop
+ { MAP_CALL(Display), SIG_EVERYWHERE, "[ir]([ir!]*)", NULL, NULL },
+ // ^ we allow invalid references here, because kDisplay gets called with those in e.g. pq3 during intro
+ // restoreBits() checks and skips invalid handles, so that's fine. Sierra SCI behaved the same
+ { MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL, NULL },
+ { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL, NULL },
+ { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "i(i*)", NULL, kDisposeScript_workarounds },
+ { MAP_CALL(DisposeWindow), SIG_EVERYWHERE, "i(i)", NULL, NULL },
+ { MAP_CALL(DoAudio), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(DoAvoider), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(DoBresen), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(DoSound), SIG_EVERYWHERE, "i(.*)", kDoSound_subops, NULL },
+ { MAP_CALL(DoSync), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiii(i)(i)([ri])", NULL, NULL }, // reference for kq6 hires
+ { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiii(i)(i)", NULL, NULL },
+ { MAP_CALL(DrawControl), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(DrawMenuBar), SIG_EVERYWHERE, "i", NULL, NULL },
+ { MAP_CALL(DrawPic), SIG_EVERYWHERE, "i(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(DrawStatus), SIG_EVERYWHERE, "[r0](i)(i)", NULL, NULL },
+ { MAP_CALL(EditControl), SIG_EVERYWHERE, "[o0][o0]", NULL, NULL },
+ { MAP_CALL(Empty), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(EmptyList), SIG_EVERYWHERE, "l", NULL, NULL },
+ { MAP_CALL(FClose), SIG_EVERYWHERE, "i", NULL, NULL },
+ { MAP_CALL(FGets), SIG_EVERYWHERE, "rii", NULL, NULL },
+ { MAP_CALL(FOpen), SIG_EVERYWHERE, "ri", NULL, NULL },
+ { MAP_CALL(FPuts), SIG_EVERYWHERE, "ir", NULL, NULL },
+ { MAP_CALL(FileIO), SIG_EVERYWHERE, "i(.*)", kFileIO_subops, NULL },
+ { MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL, kFindKey_workarounds },
+ { MAP_CALL(FirstNode), SIG_EVERYWHERE, "[l0]", NULL, NULL },
+ { MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL, NULL },
+ { MAP_CALL(Format), SIG_EVERYWHERE, "r(.*)", NULL, NULL },
+ { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "(i)", NULL, NULL },
+ { MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiii", NULL, kGetAngle_workarounds },
+ { MAP_CALL(GetCWD), SIG_EVERYWHERE, "r", NULL, NULL },
+ { MAP_CALL(GetDistance), SIG_EVERYWHERE, "ii(i)(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(GetEvent), SIG_SCIALL, SIGFOR_MAC, "io(i*)", NULL, NULL },
+ { MAP_CALL(GetEvent), SIG_EVERYWHERE, "io", NULL, NULL },
+ { MAP_CALL(GetFarText), SIG_EVERYWHERE, "ii[r0]", NULL, NULL },
+ { MAP_CALL(GetMenu), SIG_EVERYWHERE, "i.", NULL, NULL },
+ { MAP_CALL(GetMessage), SIG_EVERYWHERE, "iiir", NULL, NULL },
+ { MAP_CALL(GetPort), SIG_EVERYWHERE, "", NULL, NULL },
+ { MAP_CALL(GetSaveDir), SIG_SCI32, SIGFOR_ALL, "(r*)", NULL, NULL },
+ { MAP_CALL(GetSaveDir), SIG_EVERYWHERE, "", NULL, NULL },
+ { MAP_CALL(GetSaveFiles), SIG_EVERYWHERE, "rrr", NULL, NULL },
+ { MAP_CALL(GetTime), SIG_EVERYWHERE, "(i)", NULL, NULL },
+ { MAP_CALL(GlobalToLocal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL },
+ { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(Graph), SIG_EVERYWHERE, NULL, kGraph_subops, NULL },
+ { MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL, NULL },
+ { MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(InitBresen), SIG_EVERYWHERE, "o(i)", NULL, NULL },
+ { MAP_CALL(Intersections), SIG_EVERYWHERE, "iiiiriiiri", NULL, NULL },
+ { MAP_CALL(IsItSkip), SIG_EVERYWHERE, "iiiii", NULL, NULL },
+ { MAP_CALL(IsObject), SIG_EVERYWHERE, ".", NULL, kIsObject_workarounds },
+ { MAP_CALL(Joystick), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(LastNode), SIG_EVERYWHERE, "l", NULL, NULL },
+ { MAP_CALL(Load), SIG_EVERYWHERE, "ii(i*)", NULL, NULL },
+ { MAP_CALL(LocalToGlobal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL },
+ { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(Lock), SIG_EVERYWHERE, "ii(i)", NULL, NULL },
+ { MAP_CALL(MapKeyToDir), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(Memory), SIG_EVERYWHERE, "i(.*)", NULL, kMemory_workarounds }, // subop
+ { MAP_CALL(MemoryInfo), SIG_EVERYWHERE, "i", NULL, NULL },
+ { MAP_CALL(MemorySegment), SIG_EVERYWHERE, "ir(i)", NULL, NULL }, // subop
+ { MAP_CALL(MenuSelect), SIG_EVERYWHERE, "o(i)", NULL, NULL },
+ { MAP_CALL(MergePoly), SIG_EVERYWHERE, "rli", NULL, NULL },
+ { MAP_CALL(Message), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(MoveCursor), SIG_EVERYWHERE, "ii", NULL, NULL },
+ { MAP_CALL(NewList), SIG_EVERYWHERE, "", NULL, NULL },
+ { MAP_CALL(NewNode), SIG_EVERYWHERE, "..", NULL, NULL },
+ { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, ".*", NULL, NULL },
+ { MAP_CALL(NewWindow), SIG_SCI0, SIGFOR_ALL, "iiii[r0]i(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(NewWindow), SIG_SCI1, SIGFOR_ALL, "iiii[ir]i(i)(i)([ir])(i)(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(NewWindow), SIG_SCI11, SIGFOR_ALL, "iiiiiiii[r0]i(i)(i)(i)", NULL, kNewWindow_workarounds },
+ { MAP_CALL(NextNode), SIG_EVERYWHERE, "n", NULL, NULL },
+ { MAP_CALL(NodeValue), SIG_EVERYWHERE, "[n0]", NULL, NULL },
+ { MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(NumLoops), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(OnControl), SIG_EVERYWHERE, "ii(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(PalVary), SIG_EVERYWHERE, "i(i*)", kPalVary_subops, NULL },
+ { MAP_CALL(Palette), SIG_EVERYWHERE, "i(.*)", kPalette_subops, NULL },
+ { MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL, NULL },
+ { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "(i)", NULL, NULL },
+ { MAP_CALL(Platform), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(Portrait), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(PrevNode), SIG_EVERYWHERE, "n", NULL, NULL },
+ { MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL, NULL },
+ { MAP_CALL(Random), SIG_EVERYWHERE, "i(i)(i)", NULL, NULL },
+ { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, NULL },
+ { MAP_CALL(ResCheck), SIG_EVERYWHERE, "ii(iiii)", NULL, NULL },
+ { MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL },
+ { MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL, NULL },
+ { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir", NULL, NULL },
+ { MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL },
+ { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rir(r)", NULL, NULL },
+ { MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL },
+ { MAP_CALL(SetCursor), SIG_SCI21, SIGFOR_ALL, "i(i)([io])(i*)", NULL, NULL },
+ // TODO: SCI2.1 may supply an object optionally (mother goose sci21 right on startup) - find out why
+ { MAP_CALL(SetCursor), SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(iiiiii)", NULL, NULL },
+ { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i(i)(i)(i)(i)", NULL, kSetCursor_workarounds },
+ { MAP_CALL(SetDebug), SIG_EVERYWHERE, "(i*)", NULL, NULL },
+ { MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL, NULL },
+ { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i(.*)", NULL, NULL },
+ { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "o(i)", NULL, NULL },
+ { MAP_CALL(SetPort), SIG_EVERYWHERE, "i(iiiii)(i)", NULL, kSetPort_workarounds },
+ { MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL, NULL },
+ { MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(SetVideoMode), SIG_EVERYWHERE, "i", NULL, NULL },
+ { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "(i)(i)", NULL, NULL },
+ { MAP_CALL(ShowMovie), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(SinDiv), SIG_EVERYWHERE, "ii", NULL, NULL },
+ { MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL, NULL },
+ { MAP_CALL(Sqrt), SIG_EVERYWHERE, "i", NULL, NULL },
+ { MAP_CALL(StrAt), SIG_EVERYWHERE, "ri(i)", NULL, kStrAt_workarounds },
+ { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, NULL },
+ { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rr(i)", NULL, NULL },
+ { MAP_CALL(StrCpy), SIG_EVERYWHERE, "r[r0](i)", NULL, NULL },
+ { MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL, NULL },
+ { MAP_CALL(StrLen), SIG_EVERYWHERE, "[r0]", NULL, NULL },
+ { MAP_CALL(StrSplit), SIG_EVERYWHERE, "rr[r0]", NULL, NULL },
+ { MAP_CALL(TextColors), SIG_EVERYWHERE, "(i*)", NULL, NULL },
+ { MAP_CALL(TextFonts), SIG_EVERYWHERE, "(i*)", NULL, NULL },
+ { MAP_CALL(TextSize), SIG_SCIALL, SIGFOR_MAC, "r[r0]i(i)(r0)(i)", NULL, NULL },
+ { MAP_CALL(TextSize), SIG_EVERYWHERE, "r[r0]i(i)(r0)", NULL, NULL },
+ { MAP_CALL(TimesCos), SIG_EVERYWHERE, "ii", NULL, NULL },
+ { "CosMult", kTimesCos, SIG_EVERYWHERE, "ii", NULL, NULL },
+ { MAP_CALL(TimesCot), SIG_EVERYWHERE, "ii", NULL, NULL },
+ { MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL, NULL },
+ { "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL, NULL },
+ { MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL, NULL },
+ { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ri]", NULL, kUnLoad_workarounds },
+ { MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL, NULL },
+ { MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL, NULL },
+
+#ifdef ENABLE_SCI32
+ // SCI2 Kernel Functions
+ { MAP_CALL(AddPlane), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(AddScreenItem), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(Array), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i(.*)", NULL, NULL },
+ { MAP_CALL(DeletePlane), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(FrameOut), SIG_EVERYWHERE, "", NULL, NULL },
+ { MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL, NULL },
+ { MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL, NULL },
+ { MAP_CALL(IsHiRes), SIG_EVERYWHERE, "", NULL, NULL },
+ { MAP_CALL(ListAllTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL },
+ { MAP_CALL(ListAt), SIG_EVERYWHERE, "li", NULL, NULL },
+ { MAP_CALL(ListEachElementDo), SIG_EVERYWHERE, "li(.*)", NULL, NULL },
+ { MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL },
+ { MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "l[o0]", NULL, NULL },
+ { MAP_CALL(OnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL },
+ { MAP_CALL(RepaintPlane), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(String), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(UpdatePlane), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL, NULL },
+
+ // SCI2.1 Kernel Functions
+ { MAP_CALL(CD), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL },
+ { MAP_CALL(List), SIG_SCI21, SIGFOR_ALL, "(.*)", kList_subops, NULL },
+ { MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL, NULL },
+ { MAP_CALL(PlayVMD), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(Robot), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(Save), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(Text), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(AddPicAt), SIG_EVERYWHERE, "oiii", NULL, NULL },
+ { NULL, NULL, SIG_EVERYWHERE, NULL, NULL, NULL }
+#endif
+};
+
+/** Default kernel name table. */
+static const char *s_defaultKernelNames[] = {
+ /*0x00*/ "Load",
+ /*0x01*/ "UnLoad",
+ /*0x02*/ "ScriptID",
+ /*0x03*/ "DisposeScript",
+ /*0x04*/ "Clone",
+ /*0x05*/ "DisposeClone",
+ /*0x06*/ "IsObject",
+ /*0x07*/ "RespondsTo",
+ /*0x08*/ "DrawPic",
+ /*0x09*/ "Dummy", // Show
+ /*0x0a*/ "PicNotValid",
+ /*0x0b*/ "Animate",
+ /*0x0c*/ "SetNowSeen",
+ /*0x0d*/ "NumLoops",
+ /*0x0e*/ "NumCels",
+ /*0x0f*/ "CelWide",
+ /*0x10*/ "CelHigh",
+ /*0x11*/ "DrawCel",
+ /*0x12*/ "AddToPic",
+ /*0x13*/ "NewWindow",
+ /*0x14*/ "GetPort",
+ /*0x15*/ "SetPort",
+ /*0x16*/ "DisposeWindow",
+ /*0x17*/ "DrawControl",
+ /*0x18*/ "HiliteControl",
+ /*0x19*/ "EditControl",
+ /*0x1a*/ "TextSize",
+ /*0x1b*/ "Display",
+ /*0x1c*/ "GetEvent",
+ /*0x1d*/ "GlobalToLocal",
+ /*0x1e*/ "LocalToGlobal",
+ /*0x1f*/ "MapKeyToDir",
+ /*0x20*/ "DrawMenuBar",
+ /*0x21*/ "MenuSelect",
+ /*0x22*/ "AddMenu",
+ /*0x23*/ "DrawStatus",
+ /*0x24*/ "Parse",
+ /*0x25*/ "Said",
+ /*0x26*/ "SetSynonyms", // Portrait (KQ6 hires)
+ /*0x27*/ "HaveMouse",
+ /*0x28*/ "SetCursor",
+ // FOpen (SCI0)
+ // FPuts (SCI0)
+ // FGets (SCI0)
+ // FClose (SCI0)
+ /*0x29*/ "SaveGame",
+ /*0x2a*/ "RestoreGame",
+ /*0x2b*/ "RestartGame",
+ /*0x2c*/ "GameIsRestarting",
+ /*0x2d*/ "DoSound",
+ /*0x2e*/ "NewList",
+ /*0x2f*/ "DisposeList",
+ /*0x30*/ "NewNode",
+ /*0x31*/ "FirstNode",
+ /*0x32*/ "LastNode",
+ /*0x33*/ "EmptyList",
+ /*0x34*/ "NextNode",
+ /*0x35*/ "PrevNode",
+ /*0x36*/ "NodeValue",
+ /*0x37*/ "AddAfter",
+ /*0x38*/ "AddToFront",
+ /*0x39*/ "AddToEnd",
+ /*0x3a*/ "FindKey",
+ /*0x3b*/ "DeleteKey",
+ /*0x3c*/ "Random",
+ /*0x3d*/ "Abs",
+ /*0x3e*/ "Sqrt",
+ /*0x3f*/ "GetAngle",
+ /*0x40*/ "GetDistance",
+ /*0x41*/ "Wait",
+ /*0x42*/ "GetTime",
+ /*0x43*/ "StrEnd",
+ /*0x44*/ "StrCat",
+ /*0x45*/ "StrCmp",
+ /*0x46*/ "StrLen",
+ /*0x47*/ "StrCpy",
+ /*0x48*/ "Format",
+ /*0x49*/ "GetFarText",
+ /*0x4a*/ "ReadNumber",
+ /*0x4b*/ "BaseSetter",
+ /*0x4c*/ "DirLoop",
+ /*0x4d*/ "CanBeHere", // CantBeHere in newer SCI versions
+ /*0x4e*/ "OnControl",
+ /*0x4f*/ "InitBresen",
+ /*0x50*/ "DoBresen",
+ /*0x51*/ "Platform", // DoAvoider (SCI0)
+ /*0x52*/ "SetJump",
+ /*0x53*/ "SetDebug",
+ /*0x54*/ "Dummy", // InspectObj
+ /*0x55*/ "Dummy", // ShowSends
+ /*0x56*/ "Dummy", // ShowObjs
+ /*0x57*/ "Dummy", // ShowFree
+ /*0x58*/ "MemoryInfo",
+ /*0x59*/ "Dummy", // StackUsage
+ /*0x5a*/ "Dummy", // Profiler
+ /*0x5b*/ "GetMenu",
+ /*0x5c*/ "SetMenu",
+ /*0x5d*/ "GetSaveFiles",
+ /*0x5e*/ "GetCWD",
+ /*0x5f*/ "CheckFreeSpace",
+ /*0x60*/ "ValidPath",
+ /*0x61*/ "CoordPri",
+ /*0x62*/ "StrAt",
+ /*0x63*/ "DeviceInfo",
+ /*0x64*/ "GetSaveDir",
+ /*0x65*/ "CheckSaveGame",
+ /*0x66*/ "ShakeScreen",
+ /*0x67*/ "FlushResources",
+ /*0x68*/ "SinMult",
+ /*0x69*/ "CosMult",
+ /*0x6a*/ "SinDiv",
+ /*0x6b*/ "CosDiv",
+ /*0x6c*/ "Graph",
+ /*0x6d*/ "Joystick",
+ // End of kernel function table for SCI0
+ /*0x6e*/ "Dummy", // ShiftScreen
+ /*0x6f*/ "Palette",
+ /*0x70*/ "MemorySegment",
+ /*0x71*/ "Intersections", // MoveCursor (SCI1 late), PalVary (SCI1.1)
+ /*0x72*/ "Memory",
+ /*0x73*/ "Dummy", // ListOps
+ /*0x74*/ "FileIO",
+ /*0x75*/ "DoAudio",
+ /*0x76*/ "DoSync",
+ /*0x77*/ "AvoidPath",
+ /*0x78*/ "Sort", // StrSplit (SCI01)
+ /*0x79*/ "Dummy", // ATan
+ /*0x7a*/ "Lock",
+ /*0x7b*/ "StrSplit",
+ /*0x7c*/ "GetMessage", // Message (SCI1.1)
+ /*0x7d*/ "IsItSkip",
+ /*0x7e*/ "MergePoly",
+ /*0x7f*/ "ResCheck",
+ /*0x80*/ "AssertPalette",
+ /*0x81*/ "TextColors",
+ /*0x82*/ "TextFonts",
+ /*0x83*/ "Dummy", // Record
+ /*0x84*/ "Dummy", // PlayBack
+ /*0x85*/ "ShowMovie",
+ /*0x86*/ "SetVideoMode",
+ /*0x87*/ "SetQuitStr",
+ /*0x88*/ "Dummy" // DbugStr
+};
+
+#ifdef ENABLE_SCI32
+
+// NOTE: 0x72-0x79, 0x85-0x86, 0x88 are from the GK2 demo (which has debug support) and are
+// just Dummy in other SCI2 games.
+static const char *sci2_default_knames[] = {
+ /*0x00*/ "Load",
+ /*0x01*/ "UnLoad",
+ /*0x02*/ "ScriptID",
+ /*0x03*/ "DisposeScript",
+ /*0x04*/ "Lock",
+ /*0x05*/ "ResCheck",
+ /*0x06*/ "Purge",
+ /*0x07*/ "Clone",
+ /*0x08*/ "DisposeClone",
+ /*0x09*/ "RespondsTo",
+ /*0x0a*/ "SetNowSeen",
+ /*0x0b*/ "NumLoops",
+ /*0x0c*/ "NumCels",
+ /*0x0d*/ "CelWide",
+ /*0x0e*/ "CelHigh",
+ /*0x0f*/ "GetHighPlanePri",
+ /*0x10*/ "GetHighItemPri",
+ /*0x11*/ "ShakeScreen",
+ /*0x12*/ "OnMe",
+ /*0x13*/ "ShowMovie",
+ /*0x14*/ "SetVideoMode",
+ /*0x15*/ "AddScreenItem",
+ /*0x16*/ "DeleteScreenItem",
+ /*0x17*/ "UpdateScreenItem",
+ /*0x18*/ "FrameOut",
+ /*0x19*/ "AddPlane",
+ /*0x1a*/ "DeletePlane",
+ /*0x1b*/ "UpdatePlane",
+ /*0x1c*/ "RepaintPlane",
+ /*0x1d*/ "SetShowStyle",
+ /*0x1e*/ "ShowStylePercent",
+ /*0x1f*/ "SetScroll",
+ /*0x20*/ "AddMagnify",
+ /*0x21*/ "DeleteMagnify",
+ /*0x22*/ "IsHiRes",
+ /*0x23*/ "Graph",
+ /*0x24*/ "InvertRect",
+ /*0x25*/ "TextSize",
+ /*0x26*/ "Message",
+ /*0x27*/ "TextColors",
+ /*0x28*/ "TextFonts",
+ /*0x29*/ "Dummy",
+ /*0x2a*/ "SetQuitStr",
+ /*0x2b*/ "EditText",
+ /*0x2c*/ "InputText",
+ /*0x2d*/ "CreateTextBitmap",
+ /*0x2e*/ "DisposeTextBitmap",
+ /*0x2f*/ "GetEvent",
+ /*0x30*/ "GlobalToLocal",
+ /*0x31*/ "LocalToGlobal",
+ /*0x32*/ "MapKeyToDir",
+ /*0x33*/ "HaveMouse",
+ /*0x34*/ "SetCursor",
+ /*0x35*/ "VibrateMouse",
+ /*0x36*/ "SaveGame",
+ /*0x37*/ "RestoreGame",
+ /*0x38*/ "RestartGame",
+ /*0x39*/ "GameIsRestarting",
+ /*0x3a*/ "MakeSaveCatName",
+ /*0x3b*/ "MakeSaveFileName",
+ /*0x3c*/ "GetSaveFiles",
+ /*0x3d*/ "GetSaveDir",
+ /*0x3e*/ "CheckSaveGame",
+ /*0x3f*/ "CheckFreeSpace",
+ /*0x40*/ "DoSound",
+ /*0x41*/ "DoAudio",
+ /*0x42*/ "DoSync",
+ /*0x43*/ "NewList",
+ /*0x44*/ "DisposeList",
+ /*0x45*/ "NewNode",
+ /*0x46*/ "FirstNode",
+ /*0x47*/ "LastNode",
+ /*0x48*/ "EmptyList",
+ /*0x49*/ "NextNode",
+ /*0x4a*/ "PrevNode",
+ /*0x4b*/ "NodeValue",
+ /*0x4c*/ "AddAfter",
+ /*0x4d*/ "AddToFront",
+ /*0x4e*/ "AddToEnd",
+ /*0x4f*/ "Dummy",
+ /*0x50*/ "Dummy",
+ /*0x51*/ "FindKey",
+ /*0x52*/ "Dummy",
+ /*0x53*/ "Dummy",
+ /*0x54*/ "Dummy",
+ /*0x55*/ "DeleteKey",
+ /*0x56*/ "Dummy",
+ /*0x57*/ "Dummy",
+ /*0x58*/ "ListAt",
+ /*0x59*/ "ListIndexOf",
+ /*0x5a*/ "ListEachElementDo",
+ /*0x5b*/ "ListFirstTrue",
+ /*0x5c*/ "ListAllTrue",
+ /*0x5d*/ "Random",
+ /*0x5e*/ "Abs",
+ /*0x5f*/ "Sqrt",
+ /*0x60*/ "GetAngle",
+ /*0x61*/ "GetDistance",
+ /*0x62*/ "ATan",
+ /*0x63*/ "SinMult",
+ /*0x64*/ "CosMult",
+ /*0x65*/ "SinDiv",
+ /*0x66*/ "CosDiv",
+ /*0x67*/ "GetTime",
+ /*0x68*/ "Platform",
+ /*0x69*/ "BaseSetter",
+ /*0x6a*/ "DirLoop",
+ /*0x6b*/ "CantBeHere",
+ /*0x6c*/ "InitBresen",
+ /*0x6d*/ "DoBresen",
+ /*0x6e*/ "SetJump",
+ /*0x6f*/ "AvoidPath",
+ /*0x70*/ "InPolygon",
+ /*0x71*/ "MergePoly",
+ /*0x72*/ "SetDebug",
+ /*0x73*/ "InspectObject",
+ /*0x74*/ "MemoryInfo",
+ /*0x75*/ "Profiler",
+ /*0x76*/ "Record",
+ /*0x77*/ "PlayBack",
+ /*0x78*/ "MonoOut",
+ /*0x79*/ "SetFatalStr",
+ /*0x7a*/ "GetCWD",
+ /*0x7b*/ "ValidPath",
+ /*0x7c*/ "FileIO",
+ /*0x7d*/ "Dummy",
+ /*0x7e*/ "DeviceInfo",
+ /*0x7f*/ "Palette",
+ /*0x80*/ "PalVary",
+ /*0x81*/ "PalCycle",
+ /*0x82*/ "Array",
+ /*0x83*/ "String",
+ /*0x84*/ "RemapColors",
+ /*0x85*/ "IntegrityChecking",
+ /*0x86*/ "CheckIntegrity",
+ /*0x87*/ "ObjectIntersect",
+ /*0x88*/ "MarkMemory",
+ /*0x89*/ "TextWidth",
+ /*0x8a*/ "PointSize",
+
+ // GK2 Demo (and similar) only kernel functions
+ /*0x8b*/ "AddLine",
+ /*0x8c*/ "DeleteLine",
+ /*0x8d*/ "UpdateLine",
+ /*0x8e*/ "AddPolygon",
+ /*0x8f*/ "DeletePolygon",
+ /*0x90*/ "UpdatePolygon",
+ /*0x91*/ "Bitmap",
+ /*0x92*/ "ScrollWindow",
+ /*0x93*/ "SetFontRes",
+ /*0x94*/ "MovePlaneItems",
+ /*0x95*/ "PreloadResource",
+ /*0x96*/ "Dummy",
+ /*0x97*/ "ResourceTrack",
+ /*0x98*/ "CheckCDisc",
+ /*0x99*/ "GetSaveCDisc",
+ /*0x9a*/ "TestPoly",
+ /*0x9b*/ "WinHelp",
+ /*0x9c*/ "LoadChunk",
+ /*0x9d*/ "SetPalStyleRange",
+ /*0x9e*/ "AddPicAt",
+ /*0x9f*/ "MessageBox"
+};
+
+static const char *sci21_default_knames[] = {
+ /*0x00*/ "Load",
+ /*0x01*/ "UnLoad",
+ /*0x02*/ "ScriptID",
+ /*0x03*/ "DisposeScript",
+ /*0x04*/ "Lock",
+ /*0x05*/ "ResCheck",
+ /*0x06*/ "Purge",
+ /*0x07*/ "SetLanguage",
+ /*0x08*/ "Dummy",
+ /*0x09*/ "Dummy",
+ /*0x0a*/ "Clone",
+ /*0x0b*/ "DisposeClone",
+ /*0x0c*/ "RespondsTo",
+ /*0x0d*/ "FindSelector",
+ /*0x0e*/ "FindClass",
+ /*0x0f*/ "Dummy",
+ /*0x10*/ "Dummy",
+ /*0x11*/ "Dummy",
+ /*0x12*/ "Dummy",
+ /*0x13*/ "Dummy",
+ /*0x14*/ "SetNowSeen",
+ /*0x15*/ "NumLoops",
+ /*0x16*/ "NumCels",
+ /*0x17*/ "IsOnMe",
+ /*0x18*/ "AddMagnify",
+ /*0x19*/ "DeleteMagnify",
+ /*0x1a*/ "CelRect",
+ /*0x1b*/ "BaseLineSpan",
+ /*0x1c*/ "CelWide",
+ /*0x1d*/ "CelHigh",
+ /*0x1e*/ "AddScreenItem",
+ /*0x1f*/ "DeleteScreenItem",
+ /*0x20*/ "UpdateScreenItem",
+ /*0x21*/ "FrameOut",
+ /*0x22*/ "CelInfo",
+ /*0x23*/ "Bitmap",
+ /*0x24*/ "CelLink",
+ /*0x25*/ "Dummy",
+ /*0x26*/ "Dummy",
+ /*0x27*/ "Dummy",
+ /*0x28*/ "AddPlane",
+ /*0x29*/ "DeletePlane",
+ /*0x2a*/ "UpdatePlane",
+ /*0x2b*/ "RepaintPlane",
+ /*0x2c*/ "GetHighPlanePri",
+ /*0x2d*/ "GetHighItemPri",
+ /*0x2e*/ "SetShowStyle",
+ /*0x2f*/ "ShowStylePercent",
+ /*0x30*/ "SetScroll",
+ /*0x31*/ "MovePlaneItems",
+ /*0x32*/ "ShakeScreen",
+ /*0x33*/ "Dummy",
+ /*0x34*/ "Dummy",
+ /*0x35*/ "Dummy",
+ /*0x36*/ "Dummy",
+ /*0x37*/ "IsHiRes",
+ /*0x38*/ "SetVideoMode",
+ /*0x39*/ "ShowMovie",
+ /*0x3a*/ "Robot",
+ /*0x3b*/ "CreateTextBitmap",
+ /*0x3c*/ "Random",
+ /*0x3d*/ "Abs",
+ /*0x3e*/ "Sqrt",
+ /*0x3f*/ "GetAngle",
+ /*0x40*/ "GetDistance",
+ /*0x41*/ "ATan",
+ /*0x42*/ "SinMult",
+ /*0x43*/ "CosMult",
+ /*0x44*/ "SinDiv",
+ /*0x45*/ "CosDiv",
+ /*0x46*/ "Text",
+ /*0x47*/ "Dummy",
+ /*0x48*/ "Message",
+ /*0x49*/ "Font",
+ /*0x4a*/ "EditText",
+ /*0x4b*/ "InputText",
+ /*0x4c*/ "ScrollWindow",
+ /*0x4d*/ "Dummy",
+ /*0x4e*/ "Dummy",
+ /*0x4f*/ "Dummy",
+ /*0x50*/ "GetEvent",
+ /*0x51*/ "GlobalToLocal",
+ /*0x52*/ "LocalToGlobal",
+ /*0x53*/ "MapKeyToDir",
+ /*0x54*/ "HaveMouse",
+ /*0x55*/ "SetCursor",
+ /*0x56*/ "VibrateMouse",
+ /*0x57*/ "Dummy",
+ /*0x58*/ "Dummy",
+ /*0x59*/ "Dummy",
+ /*0x5a*/ "List",
+ /*0x5b*/ "Array",
+ /*0x5c*/ "String",
+ /*0x5d*/ "FileIO",
+ /*0x5e*/ "BaseSetter",
+ /*0x5f*/ "DirLoop",
+ /*0x60*/ "CantBeHere",
+ /*0x61*/ "InitBresen",
+ /*0x62*/ "DoBresen",
+ /*0x63*/ "SetJump",
+ /*0x64*/ "AvoidPath",
+ /*0x65*/ "InPolygon",
+ /*0x66*/ "MergePoly",
+ /*0x67*/ "ObjectIntersect",
+ /*0x68*/ "Dummy",
+ /*0x69*/ "MemoryInfo",
+ /*0x6a*/ "DeviceInfo",
+ /*0x6b*/ "Palette",
+ /*0x6c*/ "PalVary",
+ /*0x6d*/ "PalCycle",
+ /*0x6e*/ "RemapColors",
+ /*0x6f*/ "AddLine",
+ /*0x70*/ "DeleteLine",
+ /*0x71*/ "UpdateLine",
+ /*0x72*/ "AddPolygon",
+ /*0x73*/ "DeletePolygon",
+ /*0x74*/ "UpdatePolygon",
+ /*0x75*/ "DoSound",
+ /*0x76*/ "DoAudio",
+ /*0x77*/ "DoSync",
+ /*0x78*/ "Save",
+ /*0x79*/ "GetTime",
+ /*0x7a*/ "Platform",
+ /*0x7b*/ "CD",
+ /*0x7c*/ "SetQuitStr",
+ /*0x7d*/ "GetConfig",
+ /*0x7e*/ "Table",
+ /*0x7f*/ "WinHelp", // Windows only
+ /*0x80*/ "Dummy",
+ /*0x81*/ "Dummy",
+ /*0x82*/ "Dummy",
+ /*0x83*/ "PrintDebug", // used by Shivers 2 (demo and full)
+ /*0x84*/ "Dummy",
+ /*0x85*/ "Dummy",
+ /*0x86*/ "Dummy",
+ /*0x87*/ "Dummy",
+ /*0x88*/ "Dummy",
+ /*0x89*/ "Dummy",
+ /*0x8a*/ "LoadChunk",
+ /*0x8b*/ "SetPalStyleRange",
+ /*0x8c*/ "AddPicAt",
+ /*0x8d*/ "Dummy",
+ /*0x8e*/ "NewRoom",
+ /*0x8f*/ "Dummy",
+ /*0x90*/ "Priority",
+ /*0x91*/ "MorphOn",
+ /*0x92*/ "PlayVMD",
+ /*0x93*/ "SetHotRectangles",
+ /*0x94*/ "MulDiv",
+ /*0x95*/ "GetSierraProfileInt", // Windows only
+ /*0x96*/ "GetSierraProfileString", // Windows only
+ /*0x97*/ "SetWindowsOption", // Windows only
+ /*0x98*/ "GetWindowsOption", // Windows only
+ /*0x99*/ "WinDLL", // Windows only
+ /*0x9a*/ "Dummy",
+ /*0x9b*/ "Dummy",
+ /*0x9c*/ "DeletePic"
+};
+
+#endif
+
+#define END Script_None
+
+opcode_format g_opcode_formats[128][4] = {
+ /*00*/
+ {Script_None}, {Script_None}, {Script_None}, {Script_None},
+ /*04*/
+ {Script_None}, {Script_None}, {Script_None}, {Script_None},
+ /*08*/
+ {Script_None}, {Script_None}, {Script_None}, {Script_None},
+ /*0C*/
+ {Script_None}, {Script_None}, {Script_None}, {Script_None},
+ /*10*/
+ {Script_None}, {Script_None}, {Script_None}, {Script_None},
+ /*14*/
+ {Script_None}, {Script_None}, {Script_None}, {Script_SRelative, END},
+ /*18*/
+ {Script_SRelative, END}, {Script_SRelative, END}, {Script_SVariable, END}, {Script_None},
+ /*1C*/
+ {Script_SVariable, END}, {Script_None}, {Script_None}, {Script_Variable, END},
+ /*20*/
+ {Script_SRelative, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_SVariable, Script_Byte, END},
+ /*24 (24=ret)*/
+ {Script_End}, {Script_Byte, END}, {Script_Invalid}, {Script_Invalid},
+ /*28*/
+ {Script_Variable, END}, {Script_Invalid}, {Script_Byte, END}, {Script_Variable, Script_Byte, END},
+ /*2C*/
+ {Script_SVariable, END}, {Script_SVariable, Script_Variable, END}, {Script_None}, {Script_Invalid},
+ /*30*/
+ {Script_None}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END},
+ /*34*/
+ {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END},
+ /*38*/
+ {Script_Property, END}, {Script_SRelative, END}, {Script_SRelative, END}, {Script_None},
+ /*3C*/
+ {Script_None}, {Script_None}, {Script_None}, {Script_Word},
+ /*40-4F*/
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ /*50-5F*/
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ /*60-6F*/
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ /*70-7F*/
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
+ {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}
+};
+#undef END
+
+} // End of namespace Sci
+
+#endif // SCI_ENGINE_KERNEL_TABLES_H
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index 156035b30d..3395811700 100644
--- a/engines/sci/engine/kevent.cpp
+++ b/engines/sci/engine/kevent.cpp
@@ -31,8 +31,6 @@
#include "sci/console.h"
#include "sci/debug.h" // for g_debug_simulated_key
#include "sci/event.h"
-#include "sci/graphics/gui.h"
-#include "sci/graphics/gui32.h"
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/cursor.h"
@@ -43,50 +41,58 @@ namespace Sci {
reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
int mask = argv[0].toUint16();
reg_t obj = argv[1];
- sciEvent curEvent;
+ SciEvent curEvent;
int oldx, oldy;
int modifier_mask = getSciVersion() <= SCI_VERSION_01 ? SCI_KEYMOD_ALL : SCI_KEYMOD_NO_FOOLOCK;
SegManager *segMan = s->_segMan;
Common::Point mousePos;
+ // Limit the mouse cursor position, if necessary
+ g_sci->_gfxCursor->refreshPosition();
mousePos = g_sci->_gfxCursor->getPosition();
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2_1)
+ g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
+#endif
// If there's a simkey pending, and the game wants a keyboard event, use the
// simkey instead of a normal event
if (g_debug_simulated_key && (mask & SCI_EVENT_KEYBOARD)) {
- PUT_SEL32V(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD); // Keyboard event
- PUT_SEL32V(segMan, obj, SELECTOR(message), g_debug_simulated_key);
- PUT_SEL32V(segMan, obj, SELECTOR(modifiers), SCI_KEYMOD_NUMLOCK); // Numlock on
- PUT_SEL32V(segMan, obj, SELECTOR(x), mousePos.x);
- PUT_SEL32V(segMan, obj, SELECTOR(y), mousePos.y);
+ writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD); // Keyboard event
+ writeSelectorValue(segMan, obj, SELECTOR(message), g_debug_simulated_key);
+ writeSelectorValue(segMan, obj, SELECTOR(modifiers), SCI_KEYMOD_NUMLOCK); // Numlock on
+ writeSelectorValue(segMan, obj, SELECTOR(x), mousePos.x);
+ writeSelectorValue(segMan, obj, SELECTOR(y), mousePos.y);
g_debug_simulated_key = 0;
return make_reg(0, 1);
}
oldx = mousePos.x;
oldy = mousePos.y;
- curEvent = s->_event->get(mask);
+ curEvent = g_sci->getEventManager()->getSciEvent(mask);
- if (s->_voc)
- s->_voc->parser_event = NULL_REG; // Invalidate parser event
+ if (g_sci->getVocabulary())
+ g_sci->getVocabulary()->parser_event = NULL_REG; // Invalidate parser event
- PUT_SEL32V(segMan, obj, SELECTOR(x), mousePos.x);
- PUT_SEL32V(segMan, obj, SELECTOR(y), mousePos.y);
+ writeSelectorValue(segMan, obj, SELECTOR(x), mousePos.x);
+ writeSelectorValue(segMan, obj, SELECTOR(y), mousePos.y);
//s->_gui->moveCursor(s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y);
switch (curEvent.type) {
case SCI_EVENT_QUIT:
- quit_vm();
+ s->abortScriptProcessing = kAbortQuitGame; // Terminate VM
+ g_sci->_debugState.seeking = kDebugSeekNothing;
+ g_sci->_debugState.runningStep = 0;
break;
case SCI_EVENT_KEYBOARD:
- PUT_SEL32V(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD); // Keyboard event
+ writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD); // Keyboard event
s->r_acc = make_reg(0, 1);
- PUT_SEL32V(segMan, obj, SELECTOR(message), curEvent.character);
+ writeSelectorValue(segMan, obj, SELECTOR(message), curEvent.character);
// We only care about the translated character
- PUT_SEL32V(segMan, obj, SELECTOR(modifiers), curEvent.modifiers & modifier_mask);
+ writeSelectorValue(segMan, obj, SELECTOR(modifiers), curEvent.modifiers & modifier_mask);
break;
case SCI_EVENT_MOUSE_RELEASE:
@@ -111,9 +117,9 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
break;
}
- PUT_SEL32V(segMan, obj, SELECTOR(type), curEvent.type);
- PUT_SEL32V(segMan, obj, SELECTOR(message), 0);
- PUT_SEL32V(segMan, obj, SELECTOR(modifiers), (curEvent.modifiers | extra_bits) & modifier_mask);
+ writeSelectorValue(segMan, obj, SELECTOR(type), curEvent.type);
+ writeSelectorValue(segMan, obj, SELECTOR(message), 0);
+ writeSelectorValue(segMan, obj, SELECTOR(modifiers), (curEvent.modifiers | extra_bits) & modifier_mask);
s->r_acc = make_reg(0, 1);
}
break;
@@ -122,12 +128,12 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
s->r_acc = NULL_REG; // Unknown or no event
}
- if ((s->r_acc.offset) && (g_debugState.stopOnEvent)) {
- g_debugState.stopOnEvent = false;
+ if ((s->r_acc.offset) && (g_sci->_debugState.stopOnEvent)) {
+ g_sci->_debugState.stopOnEvent = false;
- // A SCI event occured, and we have been asked to stop, so open the debug console
+ // A SCI event occurred, and we have been asked to stop, so open the debug console
Console *con = g_sci->getSciDebugger();
- con->DebugPrintf("SCI event occured: ");
+ con->DebugPrintf("SCI event occurred: ");
switch (curEvent.type) {
case SCI_EVENT_QUIT:
con->DebugPrintf("quit event\n");
@@ -147,16 +153,14 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
con->onFrame();
}
-#ifndef USE_OLD_MUSIC_FUNCTIONS
if (g_sci->_features->detectDoSoundType() <= SCI_VERSION_0_LATE) {
- // If we're running a SCI0 game, update the sound cues, to compensate
- // for the fact that SCI0 does not poll to update the sound cues itself,
- // like SCI01 and later do with cmdUpdateSoundCues. kGetEvent is called
- // quite often, so emulate the SCI01 behavior of cmdUpdateSoundCues with
- // this call
- s->_soundCmd->updateSci0Cues();
+ // If we're running a sound-SCI0 game, update the sound cues, to
+ // compensate for the fact that sound-SCI0 does not poll to update
+ // the sound cues itself, like sound-SCI1 and later do with
+ // cmdUpdateSoundCues. kGetEvent is called quite often, so emulate
+ // the sound-SCI1 behavior of cmdUpdateSoundCues with this call
+ g_sci->_soundCmd->updateSci0Cues();
}
-#endif
return s->r_acc;
}
@@ -165,9 +169,9 @@ reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) {
reg_t obj = argv[0];
SegManager *segMan = s->_segMan;
- if (GET_SEL32V(segMan, obj, SELECTOR(type)) == SCI_EVENT_KEYBOARD) { // Keyboard
+ if (readSelectorValue(segMan, obj, SELECTOR(type)) == SCI_EVENT_KEYBOARD) { // Keyboard
int mover = -1;
- switch (GET_SEL32V(segMan, obj, SELECTOR(message))) {
+ switch (readSelectorValue(segMan, obj, SELECTOR(message))) {
case SCI_KEY_HOME:
mover = 8;
break;
@@ -201,8 +205,11 @@ reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) {
}
if (mover >= 0) {
- PUT_SEL32V(segMan, obj, SELECTOR(type), SCI_EVENT_JOYSTICK);
- PUT_SEL32V(segMan, obj, SELECTOR(message), mover);
+ if (g_sci->getEventManager()->getUsesNewKeyboardDirectionType())
+ writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD | SCI_EVENT_DIRECTION);
+ else
+ writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_DIRECTION);
+ writeSelectorValue(segMan, obj, SELECTOR(message), mover);
return make_reg(0, 1);
} else
return NULL_REG;
@@ -212,18 +219,18 @@ reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) {
}
reg_t kGlobalToLocal(EngineState *s, int argc, reg_t *argv) {
- reg_t obj = argc ? argv[0] : NULL_REG; // Can this really happen? Lars
+ reg_t obj = argv[0];
reg_t planeObject = argc > 1 ? argv[1] : NULL_REG; // SCI32
SegManager *segMan = s->_segMan;
if (obj.segment) {
- int16 x = GET_SEL32V(segMan, obj, SELECTOR(x));
- int16 y = GET_SEL32V(segMan, obj, SELECTOR(y));
+ int16 x = readSelectorValue(segMan, obj, SELECTOR(x));
+ int16 y = readSelectorValue(segMan, obj, SELECTOR(y));
g_sci->_gfxCoordAdjuster->kernelGlobalToLocal(x, y, planeObject);
- PUT_SEL32V(segMan, obj, SELECTOR(x), x);
- PUT_SEL32V(segMan, obj, SELECTOR(y), y);
+ writeSelectorValue(segMan, obj, SELECTOR(x), x);
+ writeSelectorValue(segMan, obj, SELECTOR(y), y);
}
return s->r_acc;
@@ -231,18 +238,18 @@ reg_t kGlobalToLocal(EngineState *s, int argc, reg_t *argv) {
}
reg_t kLocalToGlobal(EngineState *s, int argc, reg_t *argv) {
- reg_t obj = argc ? argv[0] : NULL_REG; // Can this really happen? Lars
+ reg_t obj = argv[0];
reg_t planeObject = argc > 1 ? argv[1] : NULL_REG; // SCI32
SegManager *segMan = s->_segMan;
if (obj.segment) {
- int16 x = GET_SEL32V(segMan, obj, SELECTOR(x));
- int16 y = GET_SEL32V(segMan, obj, SELECTOR(y));
+ int16 x = readSelectorValue(segMan, obj, SELECTOR(x));
+ int16 y = readSelectorValue(segMan, obj, SELECTOR(y));
g_sci->_gfxCoordAdjuster->kernelLocalToGlobal(x, y, planeObject);
- PUT_SEL32V(segMan, obj, SELECTOR(x), x);
- PUT_SEL32V(segMan, obj, SELECTOR(y), y);
+ writeSelectorValue(segMan, obj, SELECTOR(x), x);
+ writeSelectorValue(segMan, obj, SELECTOR(y), y);
}
return s->r_acc;
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index e6b9a5388c..39c32ccc68 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -36,14 +36,13 @@
namespace Sci {
-enum {
- MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */
-};
-
struct SavegameDesc {
- int id;
+ uint id;
+ int virtualId; // straight numbered, according to id but w/o gaps
int date;
int time;
+ int version;
+ char name[SCI_MAX_SAVENAME_LENGTH];
};
/*
@@ -99,7 +98,7 @@ enum {
-void file_open(EngineState *s, const char *filename, int mode) {
+reg_t file_open(EngineState *s, const char *filename, int mode) {
// QfG3 character import prepends /\ to the filenames.
if (filename[0] == '/' && filename[1] == '\\')
filename += 2;
@@ -113,15 +112,17 @@ void file_open(EngineState *s, const char *filename, int mode) {
if (mode == _K_FILE_MODE_OPEN_OR_FAIL) {
// Try to open file, abort if not possible
inFile = saveFileMan->openForLoading(wrappedName);
- // If no matching savestate exists: fall back to reading from a regular file
+ // If no matching savestate exists: fall back to reading from a regular
+ // file
if (!inFile)
inFile = SearchMan.createReadStreamForMember(englishName);
- // Special case for LSL3: It tries to create a new dummy file, LARRY3.DRV
- // Apparently, if the file doesn't exist here, it should be created. The game
- // scripts then go ahead and fill its contents with data. It seems to be a similar
- // case as the dummy MEMORY.DRV file in LSL5, but LSL5 creates the file if it can't
- // find it with a separate call to file_open()
+ // Special case for LSL3: It tries to create a new dummy file,
+ // LARRY3.DRV. Apparently, if the file doesn't exist here, it should be
+ // created. The game scripts then go ahead and fill its contents with
+ // data. It seems to be a similar case as the dummy MEMORY.DRV file in
+ // LSL5, but LSL5 creates the file if it can't find it with a separate
+ // call to file_open().
if (!inFile && englishName == "LARRY3.DRV") {
outFile = saveFileMan->openForSaving(wrappedName);
outFile->finalize();
@@ -131,29 +132,29 @@ void file_open(EngineState *s, const char *filename, int mode) {
}
if (!inFile)
- warning("file_open(_K_FILE_MODE_OPEN_OR_FAIL) failed to open file '%s'", englishName.c_str());
+ debugC(2, kDebugLevelFile, " -> file_open(_K_FILE_MODE_OPEN_OR_FAIL): failed to open file '%s'", englishName.c_str());
} else if (mode == _K_FILE_MODE_CREATE) {
// Create the file, destroying any content it might have had
outFile = saveFileMan->openForSaving(wrappedName);
if (!outFile)
- warning("file_open(_K_FILE_MODE_CREATE) failed to create file '%s'", englishName.c_str());
+ debugC(2, kDebugLevelFile, " -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str());
} else if (mode == _K_FILE_MODE_OPEN_OR_CREATE) {
// Try to open file, create it if it doesn't exist
outFile = saveFileMan->openForSaving(wrappedName);
if (!outFile)
- warning("file_open(_K_FILE_MODE_CREATE) failed to create file '%s'", englishName.c_str());
- // QfG1 opens the character export file with _K_FILE_MODE_CREATE first, closes it immediately and opens it again
- // with this here
- // Perhaps other games use this for read access as well
- // I guess changing this whole code into using virtual files and writing them after close would be more appropriate
+ debugC(2, kDebugLevelFile, " -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str());
+ // QfG1 opens the character export file with _K_FILE_MODE_CREATE first,
+ // closes it immediately and opens it again with this here. Perhaps
+ // other games use this for read access as well. I guess changing this
+ // whole code into using virtual files and writing them after close
+ // would be more appropriate.
} else {
error("file_open: unsupported mode %d (filename '%s')", mode, englishName.c_str());
}
if (!inFile && !outFile) { // Failed
- debug(3, "file_open() failed");
- s->r_acc = SIGNAL_REG;
- return;
+ debugC(2, kDebugLevelFile, " -> file_open() failed");
+ return SIGNAL_REG;
}
// Find a free file handle
@@ -161,7 +162,8 @@ void file_open(EngineState *s, const char *filename, int mode) {
while ((handle < s->_fileHandles.size()) && s->_fileHandles[handle].isOpen())
handle++;
- if (handle == s->_fileHandles.size()) { // Hit size limit => Allocate more space
+ if (handle == s->_fileHandles.size()) {
+ // Hit size limit => Allocate more space
s->_fileHandles.resize(s->_fileHandles.size() + 1);
}
@@ -169,18 +171,16 @@ void file_open(EngineState *s, const char *filename, int mode) {
s->_fileHandles[handle]._out = outFile;
s->_fileHandles[handle]._name = englishName;
- s->r_acc = make_reg(0, handle);
-
- debug(3, " -> opened file '%s' with handle %d", englishName.c_str(), handle);
+ debugC(2, kDebugLevelFile, " -> opened file '%s' with handle %d", englishName.c_str(), handle);
+ return make_reg(0, handle);
}
reg_t kFOpen(EngineState *s, int argc, reg_t *argv) {
Common::String name = s->_segMan->getString(argv[0]);
int mode = argv[1].toUint16();
- debug(3, "kFOpen(%s,0x%x)", name.c_str(), mode);
- file_open(s, name.c_str(), mode);
- return s->r_acc;
+ debugC(2, kDebugLevelFile, "kFOpen(%s,0x%x)", name.c_str(), mode);
+ return file_open(s, name.c_str(), mode);
}
static FileHandle *getFileFromHandle(EngineState *s, uint handle) {
@@ -198,7 +198,7 @@ static FileHandle *getFileFromHandle(EngineState *s, uint handle) {
}
reg_t kFClose(EngineState *s, int argc, reg_t *argv) {
- debug(3, "kFClose(%d)", argv[0].toUint16());
+ debugC(2, kDebugLevelFile, "kFClose(%d)", argv[0].toUint16());
if (argv[0] != SIGNAL_REG) {
FileHandle *f = getFileFromHandle(s, argv[0].toUint16());
if (f)
@@ -219,8 +219,6 @@ reg_t kFPuts(EngineState *s, int argc, reg_t *argv) {
}
static void fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) {
- debugC(2, kDebugLevelFile, "FGets'ing %d bytes from handle %d", maxsize, handle);
-
FileHandle *f = getFileFromHandle(s, handle);
if (!f)
return;
@@ -242,79 +240,7 @@ static void fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) {
*dest = f->_in->readByte();
}
- debugC(2, kDebugLevelFile, "FGets'ed \"%s\"", dest);
-}
-
-static int _savegame_index_struct_compare(const void *a, const void *b) {
- const SavegameDesc *A = (const SavegameDesc *)a;
- const SavegameDesc *B = (const SavegameDesc *)b;
-
- if (B->date != A->date)
- return B->date - A->date;
- return B->time - A->time;
-}
-
-void listSavegames(Common::Array<SavegameDesc> &saves) {
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
-
- // Load all saves
- Common::StringArray saveNames = saveFileMan->listSavefiles(g_sci->getSavegamePattern());
-
- for (Common::StringArray::const_iterator iter = saveNames.begin(); iter != saveNames.end(); ++iter) {
- Common::String filename = *iter;
- Common::SeekableReadStream *in;
- if ((in = saveFileMan->openForLoading(filename))) {
- SavegameMetadata meta;
- if (!get_savegame_metadata(in, &meta)) {
- // invalid
- delete in;
- continue;
- }
- delete in;
-
- SavegameDesc desc;
- desc.id = strtol(filename.end() - 3, NULL, 10);
- desc.date = meta.savegame_date;
- // We need to fix date in here, because we save DDMMYYYY instead of YYYYMMDD, so sorting wouldnt work
- desc.date = ((desc.date & 0xFFFF) << 16) | ((desc.date & 0xFF0000) >> 8) | ((desc.date & 0xFF000000) >> 24);
- desc.time = meta.savegame_time;
- debug(3, "Savegame in file %s ok, id %d", filename.c_str(), desc.id);
-
- saves.push_back(desc);
- }
- }
-
- // Sort the list by creation date of the saves
- qsort(saves.begin(), saves.size(), sizeof(SavegameDesc), _savegame_index_struct_compare);
-}
-
-bool Console::cmdListSaves(int argc, const char **argv) {
- Common::Array<SavegameDesc> saves;
- listSavegames(saves);
-
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
-
- for (uint i = 0; i < saves.size(); i++) {
- Common::String filename = g_sci->getSavegameName(saves[i].id);
- Common::SeekableReadStream *in;
- if ((in = saveFileMan->openForLoading(filename))) {
- SavegameMetadata meta;
- if (!get_savegame_metadata(in, &meta)) {
- // invalid
- delete in;
- continue;
- }
-
- if (!meta.savegame_name.empty()) {
- if (meta.savegame_name.lastChar() == '\n')
- meta.savegame_name.deleteLastChar();
-
- DebugPrintf("%s: '%s'\n", filename.c_str(), meta.savegame_name.c_str());
- }
- delete in;
- }
- }
- return true;
+ debugC(2, kDebugLevelFile, " -> FGets'ed \"%s\"", dest);
}
reg_t kFGets(EngineState *s, int argc, reg_t *argv) {
@@ -322,7 +248,7 @@ reg_t kFGets(EngineState *s, int argc, reg_t *argv) {
char *buf = new char[maxsize];
int handle = argv[2].toUint16();
- debug(3, "kFGets(%d,%d)", handle, maxsize);
+ debugC(2, kDebugLevelFile, "kFGets(%d, %d)", handle, maxsize);
fgets_wrapper(s, buf, maxsize, handle);
s->_segMan->memcpy(argv[0], (const byte*)buf, maxsize);
return argv[0];
@@ -337,11 +263,14 @@ reg_t kGetCWD(EngineState *s, int argc, reg_t *argv) {
// TODO/FIXME: Is "/" a good value? Maybe "" or "." or "C:\" are better?
s->_segMan->strcpy(argv[0], "/");
- debug(3, "kGetCWD() -> %s", "/");
+ debugC(2, kDebugLevelFile, "kGetCWD() -> %s", "/");
return argv[0];
}
+static void listSavegames(Common::Array<SavegameDesc> &saves);
+static int findSavegame(Common::Array<SavegameDesc> &saves, uint saveId);
+
enum {
K_DEVICE_INFO_GET_DEVICE = 0,
K_DEVICE_INFO_GET_CURRENT_DEVICE = 1,
@@ -353,6 +282,14 @@ enum {
};
reg_t kDeviceInfo(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getGameId() == GID_FANMADE && argc == 1) {
+ // WORKAROUND: The fan game script library calls kDeviceInfo with one parameter.
+ // According to the scripts, it wants to call CurDevice. However, it fails to
+ // provide the subop to the function.
+ s->_segMan->strcpy(argv[0], "/");
+ return s->r_acc;
+ }
+
int mode = argv[0].toUint16();
switch (mode) {
@@ -400,21 +337,25 @@ reg_t kDeviceInfo(EngineState *s, int argc, reg_t *argv) {
break;
case K_DEVICE_INFO_GET_SAVEFILE_NAME: {
Common::String game_prefix = s->_segMan->getString(argv[2]);
- int savegame_id = argv[3].toUint16();
+ uint virtualId = argv[3].toUint16();
s->_segMan->strcpy(argv[1], "__throwaway");
- debug(3, "K_DEVICE_INFO_GET_SAVEFILE_NAME(%s,%d) -> %s", game_prefix.c_str(), savegame_id, "__throwaway");
+ debug(3, "K_DEVICE_INFO_GET_SAVEFILE_NAME(%s,%d) -> %s", game_prefix.c_str(), virtualId, "__throwaway");
+ if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END))
+ error("kDeviceInfo(deleteSave): invalid savegame-id specified");
+ uint savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START;
Common::Array<SavegameDesc> saves;
listSavegames(saves);
- int savedir_nr = saves[savegame_id].id;
- Common::String filename = g_sci->getSavegameName(savedir_nr);
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
- saveFileMan->removeSavefile(filename);
+ if (findSavegame(saves, savegameId) != -1) {
+ // Confirmed that this id still lives...
+ Common::String filename = g_sci->getSavegameName(savegameId);
+ Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+ saveFileMan->removeSavefile(filename);
}
break;
+ }
default:
- // TODO: Not all sub-commands are handled. E.g. KQ5CD calls sub-command 5
- warning("Unknown DeviceInfo() sub-command: %d", mode);
+ error("Unknown DeviceInfo() sub-command: %d", mode);
break;
}
@@ -428,155 +369,237 @@ reg_t kGetSaveDir(EngineState *s, int argc, reg_t *argv) {
warning("kGetSaveDir called with %d parameter(s): %04x:%04x", argc, PRINT_REG(argv[0]));
#endif
- return make_reg(s->sys_strings_segment, SYS_STRING_SAVEDIR);
+ return make_reg(s->_segMan->getSysStringsSegment(), SYS_STRING_SAVEDIR);
}
reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) {
-#ifdef ENABLE_SCI32
- // TODO: SCI32 uses a parameter here.
- if (argc > 1)
- warning("kCheckFreeSpace called with %d parameter(s): %04x:%04x", argc, PRINT_REG(argv[1]));
-#endif
+ if (argc > 1) {
+ // SCI1.1/SCI32
+ // TODO: don't know if those are right for SCI32 as well
+ // Please note that sierra sci supported both calls either w/ or w/o opcode in SCI1.1
+ switch (argv[1].toUint16()) {
+ case 0: // return saved game size
+ return make_reg(0, 0); // we return 0
+
+ case 1: // return free harddisc space (shifted right somehow)
+ return make_reg(0, 0x7fff); // we return maximum
+
+ case 2: // same as call w/o opcode
+ break;
+ return make_reg(0, 1);
+
+ default:
+ error("kCheckFreeSpace: called with unknown sub-op %d", argv[1].toUint16());
+ }
+ }
Common::String path = s->_segMan->getString(argv[0]);
debug(3, "kCheckFreeSpace(%s)", path.c_str());
- // We simply always pretend that there is enough space.
- // The alternative would be to write a big test file, which is not nice
- // on systems where doing so is very slow.
+ // We simply always pretend that there is enough space. The alternative
+ // would be to write a big test file, which is not nice on systems where
+ // doing so is very slow.
return make_reg(0, 1);
}
+static bool _savegame_sort_byDate(const SavegameDesc &l, const SavegameDesc &r) {
+ if (l.date != r.date)
+ return (l.date > r.date);
+ return (l.time > r.time);
+}
+
+// Create a sorted array containing all found savedgames
+static void listSavegames(Common::Array<SavegameDesc> &saves) {
+ Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+
+ // Load all saves
+ Common::StringArray saveNames = saveFileMan->listSavefiles(g_sci->getSavegamePattern());
+
+ for (Common::StringArray::const_iterator iter = saveNames.begin(); iter != saveNames.end(); ++iter) {
+ Common::String filename = *iter;
+ Common::SeekableReadStream *in;
+ if ((in = saveFileMan->openForLoading(filename))) {
+ SavegameMetadata meta;
+ if (!get_savegame_metadata(in, &meta) || meta.savegame_name.empty()) {
+ // invalid
+ delete in;
+ continue;
+ }
+ delete in;
+
+ SavegameDesc desc;
+ desc.id = strtol(filename.end() - 3, NULL, 10);
+ desc.date = meta.savegame_date;
+ // We need to fix date in here, because we save DDMMYYYY instead of
+ // YYYYMMDD, so sorting wouldn't work
+ desc.date = ((desc.date & 0xFFFF) << 16) | ((desc.date & 0xFF0000) >> 8) | ((desc.date & 0xFF000000) >> 24);
+ desc.time = meta.savegame_time;
+ desc.version = meta.savegame_version;
+
+ if (meta.savegame_name.lastChar() == '\n')
+ meta.savegame_name.deleteLastChar();
+
+ Common::strlcpy(desc.name, meta.savegame_name.c_str(), SCI_MAX_SAVENAME_LENGTH);
+
+ debug(3, "Savegame in file %s ok, id %d", filename.c_str(), desc.id);
+
+ saves.push_back(desc);
+ }
+ }
+
+ // Sort the list by creation date of the saves
+ Common::sort(saves.begin(), saves.end(), _savegame_sort_byDate);
+}
+
+// Find a savedgame according to virtualId and return the position within our array
+static int findSavegame(Common::Array<SavegameDesc> &saves, uint savegameId) {
+ for (uint saveNr = 0; saveNr < saves.size(); saveNr++) {
+ if (saves[saveNr].id == savegameId)
+ return saveNr;
+ }
+ return -1;
+}
+
+// The scripts get IDs ranging from 1000->1999, because the scripts require us to assign unique ids THAT EVEN STAY BETWEEN
+// SAVES and the scripts also use "saves-count + 1" to create a new savedgame slot.
+// SCI1.1 actually recycles ids, in that case we will currently get "0".
+// This behaviour is required especially for LSL6. In this game, it's possible to quick save. The scripts will use
+// the last-used id for that feature. If we don't assign sticky ids, the feature will overwrite different saves all the
+// time. And sadly we can't just use the actual filename ids directly, because of the creation method for new slots.
+
+bool Console::cmdListSaves(int argc, const char **argv) {
+ Common::Array<SavegameDesc> saves;
+ listSavegames(saves);
+
+ for (uint i = 0; i < saves.size(); i++) {
+ Common::String filename = g_sci->getSavegameName(saves[i].id);
+ DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name);
+ }
+
+ return true;
+}
+
reg_t kCheckSaveGame(EngineState *s, int argc, reg_t *argv) {
Common::String game_id = s->_segMan->getString(argv[0]);
- int savedir_nr = argv[1].toUint16();
+ uint16 virtualId = argv[1].toUint16();
- debug(3, "kCheckSaveGame(%s, %d)", game_id.c_str(), savedir_nr);
+ debug(3, "kCheckSaveGame(%s, %d)", game_id.c_str(), virtualId);
Common::Array<SavegameDesc> saves;
listSavegames(saves);
- savedir_nr = saves[savedir_nr].id;
-
- if (savedir_nr > MAX_SAVEGAME_NR - 1) {
+ // we allow 0 (happens in QfG2 when trying to restore from an empty saved game list) and return false in that case
+ if (virtualId == 0)
return NULL_REG;
- }
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
- Common::String filename = g_sci->getSavegameName(savedir_nr);
- Common::SeekableReadStream *in;
- if ((in = saveFileMan->openForLoading(filename))) {
- // found a savegame file
+ // Find saved-game
+ if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END))
+ error("kCheckSaveGame: called with invalid savegameId!");
+ uint savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START;
+ int savegameNr = findSavegame(saves, savegameId);
+ if (savegameNr == -1)
+ return NULL_REG;
- SavegameMetadata meta;
- if (!get_savegame_metadata(in, &meta)) {
- // invalid
- s->r_acc = make_reg(0, 0);
- } else {
- s->r_acc = make_reg(0, 1);
- }
- delete in;
- } else {
- s->r_acc = make_reg(0, 1);
- }
+ // Check for compatible savegame version
+ int ver = saves[savegameNr].version;
+ if (ver < MINIMUM_SAVEGAME_VERSION || ver > CURRENT_SAVEGAME_VERSION)
+ return NULL_REG;
- return s->r_acc;
+ // Otherwise we assume the savegame is OK
+ return TRUE_REG;
}
reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) {
Common::String game_id = s->_segMan->getString(argv[0]);
- reg_t nametarget = argv[1];
- reg_t *nameoffsets = s->_segMan->derefRegPtr(argv[2], 0);
debug(3, "kGetSaveFiles(%s)", game_id.c_str());
+ // Scripts ask for current save files, we can assume that if afterwards they ask us to create a new slot they really
+ // mean new slot instead of overwriting the old one
+ s->_lastSaveVirtualId = SAVEGAMEID_OFFICIALRANGE_START;
+
Common::Array<SavegameDesc> saves;
listSavegames(saves);
+ uint totalSaves = MIN<uint>(saves.size(), MAX_SAVEGAME_NR);
- s->r_acc = NULL_REG;
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+ reg_t *slot = s->_segMan->derefRegPtr(argv[2], totalSaves);
- for (uint i = 0; i < saves.size(); i++) {
- Common::String filename = g_sci->getSavegameName(saves[i].id);
- Common::SeekableReadStream *in;
- if ((in = saveFileMan->openForLoading(filename))) {
- // found a savegame file
-
- SavegameMetadata meta;
- if (!get_savegame_metadata(in, &meta)) {
- // invalid
- delete in;
- continue;
- }
-
- if (!meta.savegame_name.empty()) {
- if (meta.savegame_name.lastChar() == '\n')
- meta.savegame_name.deleteLastChar();
-
- *nameoffsets = s->r_acc; // Store savegame ID
- ++s->r_acc.offset; // Increase number of files found
+ if (!slot) {
+ warning("kGetSaveFiles: %04X:%04X invalid or too small to hold slot data", PRINT_REG(argv[2]));
+ totalSaves = 0;
+ }
- nameoffsets++; // Make sure the next ID string address is written to the next pointer
- Common::String name = meta.savegame_name;
- if (name.size() > SCI_MAX_SAVENAME_LENGTH-1)
- name = Common::String(meta.savegame_name.c_str(), SCI_MAX_SAVENAME_LENGTH-1);
- s->_segMan->strcpy(nametarget, name.c_str());
+ const uint bufSize = (totalSaves * SCI_MAX_SAVENAME_LENGTH) + 1;
+ char *saveNames = new char[bufSize];
+ char *saveNamePtr = saveNames;
- // Increase name offset pointer accordingly
- nametarget.offset += SCI_MAX_SAVENAME_LENGTH;
- }
- delete in;
- }
+ for (uint i = 0; i < totalSaves; i++) {
+ *slot++ = make_reg(0, saves[i].id + SAVEGAMEID_OFFICIALRANGE_START); // Store the virtual savegame-id ffs. see above
+ strcpy(saveNamePtr, saves[i].name);
+ saveNamePtr += SCI_MAX_SAVENAME_LENGTH;
}
- //free(gfname);
- s->_segMan->strcpy(nametarget, ""); // Terminate list
+ *saveNamePtr = 0; // Terminate list
- return s->r_acc;
+ s->_segMan->memcpy(argv[1], (byte *)saveNames, bufSize);
+ delete[] saveNames;
+
+ return make_reg(0, totalSaves);
}
reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) {
Common::String game_id = s->_segMan->getString(argv[0]);
- int savedir_nr = argv[1].toUint16();
- int savedir_id; // Savegame ID, derived from savedir_nr and the savegame ID list
+ uint virtualId = argv[1].toUint16();
Common::String game_description = s->_segMan->getString(argv[2]);
Common::String version;
if (argc > 3)
version = s->_segMan->getString(argv[3]);
- debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), savedir_nr, game_description.c_str(), version.c_str());
+ debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), virtualId, game_description.c_str(), version.c_str());
+
+ // We check here, we don't want to delete a users save in case we are within a kernel function
+ if (s->executionStackBase) {
+ warning("kSaveGame - won't save from within kernel function");
+ return NULL_REG;
+ }
Common::Array<SavegameDesc> saves;
listSavegames(saves);
- if (savedir_nr >= 0 && (uint)savedir_nr < saves.size()) {
- // Overwrite
- savedir_id = saves[savedir_nr].id;
- } else if (savedir_nr >= 0 && savedir_nr < MAX_SAVEGAME_NR) {
- uint i = 0;
-
- savedir_id = 0;
-
- // First, look for holes
- while (i < saves.size()) {
- if (saves[i].id == savedir_id) {
- ++savedir_id;
- i = 0;
- } else
- ++i;
- }
- if (savedir_id >= MAX_SAVEGAME_NR) {
- warning("Internal error: Free savegame ID is %d, shouldn't happen", savedir_id);
+ uint savegameId;
+ if ((virtualId >= SAVEGAMEID_OFFICIALRANGE_START) && (virtualId <= SAVEGAMEID_OFFICIALRANGE_END)) {
+ // savegameId is an actual Id, so search for it just to make sure
+ savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START;
+ if (findSavegame(saves, savegameId) == -1)
return NULL_REG;
+ } else if (virtualId < SAVEGAMEID_OFFICIALRANGE_START) {
+ // virtualId is low, we assume that scripts expect us to create new slot
+ if (virtualId == s->_lastSaveVirtualId) {
+ // if last virtual id is the same as this one, we assume that caller wants to overwrite last save
+ savegameId = s->_lastSaveNewId;
+ } else {
+ uint savegameNr;
+ // savegameId is in lower range, scripts expect us to create a new slot
+ for (savegameId = 0; savegameId < SAVEGAMEID_OFFICIALRANGE_START; savegameId++) {
+ for (savegameNr = 0; savegameNr < saves.size(); savegameNr++) {
+ if (savegameId == saves[savegameNr].id)
+ break;
+ }
+ if (savegameNr == saves.size())
+ break;
+ }
+ if (savegameId == SAVEGAMEID_OFFICIALRANGE_START)
+ error("kSavegame: no more savegame slots available");
}
-
- // This loop terminates when savedir_id is not in [x | ex. n. saves [n].id = x]
} else {
- warning("Savegame ID %d is not allowed", savedir_nr);
- return NULL_REG;
+ error("kSaveGame: invalid savegameId used");
}
- Common::String filename = g_sci->getSavegameName(savedir_id);
+ // Save in case caller wants to overwrite last newly created save
+ s->_lastSaveVirtualId = virtualId;
+ s->_lastSaveNewId = savegameId;
+
+ Common::String filename = g_sci->getSavegameName(savegameId);
Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
Common::OutSaveFile *out;
if (!(out = saveFileMan->openForSaving(filename))) {
@@ -585,7 +608,7 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) {
return NULL_REG;
}
- if (gamestate_save(s, out, game_description.c_str(), version.c_str())) {
+ if (!gamestate_save(s, out, game_description.c_str(), version.c_str())) {
warning("Saving the game failed.");
s->r_acc = NULL_REG;
} else {
@@ -605,35 +628,41 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) {
reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
Common::String game_id = !argv[0].isNull() ? s->_segMan->getString(argv[0]) : "";
- int savedir_nr = argv[1].toUint16();
+ uint savegameId = argv[1].toUint16();
- debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savedir_nr);
+ debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savegameId);
- if (!argv[0].isNull()) {
- Common::Array<SavegameDesc> saves;
- listSavegames(saves);
-
- savedir_nr = saves[savedir_nr].id;
+ if (argv[0].isNull()) {
+ // Loading from the launcher, don't adjust the ID of the saved game
} else {
- // Loading from launcher, no change necessary
+ if ((savegameId < 1000) || (savegameId > 1999)) {
+ warning("Savegame ID %d is not allowed", savegameId);
+ return TRUE_REG;
+ }
+ savegameId -= 1000;
}
- if (savedir_nr > -1) {
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
- Common::String filename = g_sci->getSavegameName(savedir_nr);
- Common::SeekableReadStream *in;
- if ((in = saveFileMan->openForLoading(filename))) {
- // found a savegame file
+ Common::Array<SavegameDesc> saves;
+ listSavegames(saves);
+ if (findSavegame(saves, savegameId) == -1) {
+ warning("Savegame ID %d not found", savegameId);
+ return TRUE_REG;
+ }
- gamestate_restore(s, in);
- delete in;
+ Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+ Common::String filename = g_sci->getSavegameName(savegameId);
+ Common::SeekableReadStream *in;
+ if ((in = saveFileMan->openForLoading(filename))) {
+ // found a savegame file
- return s->r_acc;
- }
+ gamestate_restore(s, in);
+ delete in;
+
+ return s->r_acc;
}
- s->r_acc = make_reg(0, 1);
- warning("Savegame #%d not found", savedir_nr);
+ s->r_acc = TRUE_REG;
+ warning("Savegame #%d not found", savegameId);
return s->r_acc;
}
@@ -647,28 +676,6 @@ reg_t kValidPath(EngineState *s, int argc, reg_t *argv) {
return make_reg(0, 1);
}
-enum {
- K_FILEIO_OPEN = 0,
- K_FILEIO_CLOSE = 1,
- K_FILEIO_READ_RAW = 2,
- K_FILEIO_WRITE_RAW = 3,
- K_FILEIO_UNLINK = 4,
- K_FILEIO_READ_STRING = 5,
- K_FILEIO_WRITE_STRING = 6,
- K_FILEIO_SEEK = 7,
- K_FILEIO_FIND_FIRST = 8,
- K_FILEIO_FIND_NEXT = 9,
- K_FILEIO_FILE_EXISTS = 10,
- // SCI1.1
- K_FILEIO_RENAME = 11,
- // SCI32
- // 12?
- K_FILEIO_READ_BYTE = 13,
- K_FILEIO_WRITE_BYTE = 14,
- K_FILEIO_READ_WORD = 15,
- K_FILEIO_WRITE_WORD = 16
-};
-
reg_t DirSeeker::firstFile(const Common::String &mask, reg_t buffer, SegManager *segMan) {
// Verify that we are given a valid buffer
if (!buffer.segment) {
@@ -684,7 +691,8 @@ reg_t DirSeeker::firstFile(const Common::String &mask, reg_t buffer, SegManager
Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
_savefiles = saveFileMan->listSavefiles(wrappedMask);
- // Reset the list iterator and write the first match to the output buffer, if any.
+ // Reset the list iterator and write the first match to the output buffer,
+ // if any.
_iter = _savefiles.begin();
return nextFile(segMan);
}
@@ -708,258 +716,298 @@ reg_t DirSeeker::nextFile(SegManager *segMan) {
}
reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
- int func_nr = argv[0].toUint16();
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
- switch (func_nr) {
- case K_FILEIO_OPEN : {
- Common::String name = s->_segMan->getString(argv[1]);
+reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) {
+ Common::String name = s->_segMan->getString(argv[0]);
- // SCI32 can call K_FILEIO_OPEN with only two arguments. It seems to just be checking if it exists.
- int mode = (argc < 3) ? (int)_K_FILE_MODE_OPEN_OR_FAIL : argv[2].toUint16();
+ // SCI32 can call K_FILEIO_OPEN with only one argument. It seems to
+ // just be checking if it exists.
+ int mode = (argc < 2) ? (int)_K_FILE_MODE_OPEN_OR_FAIL : argv[1].toUint16();
- // SQ4 floppy prepends /\ to the filenames
- if (name.hasPrefix("/\\")) {
- name.deleteChar(0);
- name.deleteChar(0);
- }
+ // SQ4 floppy prepends /\ to the filenames
+ if (name.hasPrefix("/\\")) {
+ name.deleteChar(0);
+ name.deleteChar(0);
+ }
- // SQ4 floppy attempts to update the savegame index file sq4sg.dir
- // when deleting saved games. We don't use an index file for saving
- // or loading, so just stop the game from modifying the file here
- // in order to avoid having it saved in the ScummVM save directory
- if (name == "sq4sg.dir") {
- debugC(2, kDebugLevelFile, "Not opening unused file sq4sg.dir");
- return SIGNAL_REG;
- }
+ // SQ4 floppy attempts to update the savegame index file sq4sg.dir when
+ // deleting saved games. We don't use an index file for saving or
+ // loading, so just stop the game from modifying the file here in order
+ // to avoid having it saved in the ScummVM save directory.
+ if (name == "sq4sg.dir") {
+ debugC(2, kDebugLevelFile, "Not opening unused file sq4sg.dir");
+ return SIGNAL_REG;
+ }
- if (name.empty()) {
- warning("Attempted to open a file with an empty filename");
- return SIGNAL_REG;
- }
- file_open(s, name.c_str(), mode);
- debug(3, "K_FILEIO_OPEN(%s,0x%x)", name.c_str(), mode);
- break;
+ if (name.empty()) {
+ warning("Attempted to open a file with an empty filename");
+ return SIGNAL_REG;
}
- case K_FILEIO_CLOSE : {
- debug(3, "K_FILEIO_CLOSE(%d)", argv[1].toUint16());
+ debugC(2, kDebugLevelFile, "kFileIO(open): %s, 0x%x", name.c_str(), mode);
+ return file_open(s, name.c_str(), mode);
+}
- FileHandle *f = getFileFromHandle(s, argv[1].toUint16());
- if (f)
- f->close();
- break;
+reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) {
+ debugC(2, kDebugLevelFile, "kFileIO(close): %d", argv[0].toUint16());
+
+ FileHandle *f = getFileFromHandle(s, argv[0].toUint16());
+ if (f) {
+ f->close();
+ return SIGNAL_REG;
}
- case K_FILEIO_READ_RAW : {
- int handle = argv[1].toUint16();
- int size = argv[3].toUint16();
- char *buf = new char[size];
- debug(3, "K_FILEIO_READ_RAW(%d,%d)", handle, size);
+ return NULL_REG;
+}
+reg_t kFileIOReadRaw(EngineState *s, int argc, reg_t *argv) {
+ int handle = argv[0].toUint16();
+ int size = argv[2].toUint16();
+ int bytesRead = 0;
+ char *buf = new char[size];
+ debugC(2, kDebugLevelFile, "kFileIO(readRaw): %d, %d", handle, size);
- FileHandle *f = getFileFromHandle(s, handle);
- if (f) {
- s->r_acc = make_reg(0, f->_in->read(buf, size));
- s->_segMan->memcpy(argv[2], (const byte*)buf, size);
- }
+ FileHandle *f = getFileFromHandle(s, handle);
+ if (f) {
+ bytesRead = f->_in->read(buf, size);
+ s->_segMan->memcpy(argv[1], (const byte*)buf, size);
+ }
- delete[] buf;
- break;
+ delete[] buf;
+ return make_reg(0, bytesRead);
+}
+
+reg_t kFileIOWriteRaw(EngineState *s, int argc, reg_t *argv) {
+ int handle = argv[0].toUint16();
+ int size = argv[2].toUint16();
+ char *buf = new char[size];
+ bool success = false;
+ s->_segMan->memcpy((byte*)buf, argv[1], size);
+ debugC(2, kDebugLevelFile, "kFileIO(writeRaw): %d, %d", handle, size);
+
+ FileHandle *f = getFileFromHandle(s, handle);
+ if (f) {
+ f->_out->write(buf, size);
+ success = true;
}
- case K_FILEIO_WRITE_RAW : {
- int handle = argv[1].toUint16();
- int size = argv[3].toUint16();
- char *buf = new char[size];
- s->_segMan->memcpy((byte*)buf, argv[2], size);
- debug(3, "K_FILEIO_WRITE_RAW(%d,%d)", handle, size);
- FileHandle *f = getFileFromHandle(s, handle);
- if (f)
- f->_out->write(buf, size);
+ delete[] buf;
+ if (success)
+ return NULL_REG;
+ return make_reg(0, 6); // DOS - invalid handle
+}
- delete[] buf;
- break;
+reg_t kFileIOUnlink(EngineState *s, int argc, reg_t *argv) {
+ Common::String name = s->_segMan->getString(argv[0]);
+ Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+ bool result;
+
+ // SQ4 floppy prepends /\ to the filenames
+ if (name.hasPrefix("/\\")) {
+ name.deleteChar(0);
+ name.deleteChar(0);
+ }
+
+ // Special case for SQ4 floppy: This game has hardcoded names for all of
+ // its savegames, and they are all named "sq4sg.xxx", where xxx is the
+ // slot. We just take the slot number here, and delete the appropriate
+ // save game.
+ if (name.hasPrefix("sq4sg.")) {
+ // Special handling for SQ4... get the slot number and construct the
+ // save game name.
+ int slotNum = atoi(name.c_str() + name.size() - 3);
+ Common::Array<SavegameDesc> saves;
+ listSavegames(saves);
+ int savedir_nr = saves[slotNum].id;
+ name = g_sci->getSavegameName(savedir_nr);
+ result = saveFileMan->removeSavefile(name);
+ } else {
+ const Common::String wrappedName = g_sci->wrapFilename(name);
+ result = saveFileMan->removeSavefile(wrappedName);
}
- case K_FILEIO_UNLINK : {
- Common::String name = s->_segMan->getString(argv[1]);
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
- // SQ4 floppy prepends /\ to the filenames
- if (name.hasPrefix("/\\")) {
- name.deleteChar(0);
- name.deleteChar(0);
- }
- // Special case for SQ4 floppy: This game has hardcoded names for all of its
- // savegames, and they are all named "sq4sg.xxx", where xxx is the slot. We just
- // take the slot number here, and delete the appropriate save game
- if (name.hasPrefix("sq4sg.")) {
- // Special handling for SQ4... get the slot number and construct the save game name
- int slotNum = atoi(name.c_str() + name.size() - 3);
- Common::Array<SavegameDesc> saves;
- listSavegames(saves);
- int savedir_nr = saves[slotNum].id;
- name = g_sci->getSavegameName(savedir_nr);
- saveFileMan->removeSavefile(name);
- } else {
- const Common::String wrappedName = g_sci->wrapFilename(name);
- saveFileMan->removeSavefile(wrappedName);
- }
+ debugC(2, kDebugLevelFile, "kFileIO(unlink): %s", name.c_str());
+ if (result)
+ return NULL_REG;
+ return make_reg(0, 2); // DOS - file not found error code
+}
- debug(3, "K_FILEIO_UNLINK(%s)", name.c_str());
+reg_t kFileIOReadString(EngineState *s, int argc, reg_t *argv) {
+ int size = argv[1].toUint16();
+ char *buf = new char[size];
+ int handle = argv[2].toUint16();
+ debugC(2, kDebugLevelFile, "kFileIO(readString): %d, %d", handle, size);
- // TODO/FIXME: Should we return something (like, a bool indicating
- // whether deleting the save succeeded or failed)?
- break;
- }
- case K_FILEIO_READ_STRING : {
- int size = argv[2].toUint16();
- char *buf = new char[size];
- int handle = argv[3].toUint16();
- debug(3, "K_FILEIO_READ_STRING(%d,%d)", handle, size);
+ fgets_wrapper(s, buf, size, handle);
+ s->_segMan->memcpy(argv[0], (const byte*)buf, size);
+ delete[] buf;
+ return argv[0];
+}
- fgets_wrapper(s, buf, size, handle);
- s->_segMan->memcpy(argv[1], (const byte*)buf, size);
- delete[] buf;
- return argv[1];
- }
- case K_FILEIO_WRITE_STRING : {
- int handle = argv[1].toUint16();
- int size = argv[3].toUint16();
- Common::String str = s->_segMan->getString(argv[2]);
- debug(3, "K_FILEIO_WRITE_STRING(%d,%d)", handle, size);
-
- // CHECKME: Is the size parameter used at all?
- // In the LSL5 password protection it is zero, and we should
- // then write a full string. (Not sure if it should write the
- // terminating zero.)
-
- FileHandle *f = getFileFromHandle(s, handle);
- if (f)
- f->_out->write(str.c_str(), str.size());
- break;
- }
- case K_FILEIO_SEEK : {
- int handle = argv[1].toUint16();
- int offset = argv[2].toUint16();
- int whence = argv[3].toUint16();
- debug(3, "K_FILEIO_SEEK(%d,%d,%d)", handle, offset, whence);
+reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) {
+ int handle = argv[0].toUint16();
+ Common::String str = s->_segMan->getString(argv[1]);
+ debugC(2, kDebugLevelFile, "kFileIO(writeString): %d", handle);
+
+ FileHandle *f = getFileFromHandle(s, handle);
+ if (f)
+ f->_out->write(str.c_str(), str.size());
+ return NULL_REG;
+ return make_reg(0, 6); // DOS - invalid handle
+}
+
+reg_t kFileIOSeek(EngineState *s, int argc, reg_t *argv) {
+ int handle = argv[0].toUint16();
+ int offset = argv[1].toUint16();
+ int whence = argv[2].toUint16();
+ debugC(2, kDebugLevelFile, "kFileIO(seek): %d, %d, %d", handle, offset, whence);
- FileHandle *f = getFileFromHandle(s, handle);
- if (f)
- s->r_acc = make_reg(0, f->_in->seek(offset, whence));
- break;
- }
- case K_FILEIO_FIND_FIRST : {
- Common::String mask = s->_segMan->getString(argv[1]);
- reg_t buf = argv[2];
- int attr = argv[3].toUint16(); // We won't use this, Win32 might, though...
- debug(3, "K_FILEIO_FIND_FIRST(%s,0x%x)", mask.c_str(), attr);
-
- // We remove ".*". mask will get prefixed, so we will return all additional files for that gameid
- if (mask == "*.*")
- mask = "*";
-
- // QfG3 uses this mask for the character import
- if (mask == "/\\*.*")
- mask = "*";
-//#ifndef WIN32
-// if (mask == "*.*")
-// mask = "*"; // For UNIX
-//#endif
- s->r_acc = s->_dirseeker.firstFile(mask, buf, s->_segMan);
+ FileHandle *f = getFileFromHandle(s, handle);
+ if (f)
+ s->r_acc = make_reg(0, f->_in->seek(offset, whence));
+ return SIGNAL_REG;
+}
- break;
- }
- case K_FILEIO_FIND_NEXT : {
- debug(3, "K_FILEIO_FIND_NEXT()");
- s->r_acc = s->_dirseeker.nextFile(s->_segMan);
- break;
+reg_t kFileIOFindFirst(EngineState *s, int argc, reg_t *argv) {
+ Common::String mask = s->_segMan->getString(argv[0]);
+ reg_t buf = argv[1];
+ int attr = argv[2].toUint16(); // We won't use this, Win32 might, though...
+ debugC(2, kDebugLevelFile, "kFileIO(findFirst): %s, 0x%x", mask.c_str(), attr);
+
+ // QfG3 uses "/\*.*" for the character import, QfG4 uses "/\*"
+ if (mask.hasPrefix("/\\")) {
+ mask.deleteChar(0);
+ mask.deleteChar(0);
}
- case K_FILEIO_FILE_EXISTS : {
- Common::String name = s->_segMan->getString(argv[1]);
- // Check for regular file
- bool exists = Common::File::exists(name);
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
- const Common::String wrappedName = g_sci->wrapFilename(name);
+ // We remove ".*". mask will get prefixed, so we will return all additional files for that gameid
+ if (mask == "*.*")
+ mask = "*";
+ return s->_dirseeker.firstFile(mask, buf, s->_segMan);
+}
- if (!exists)
- exists = !saveFileMan->listSavefiles(name).empty();
+reg_t kFileIOFindNext(EngineState *s, int argc, reg_t *argv) {
+ debugC(2, kDebugLevelFile, "kFileIO(findNext)");
+ return s->_dirseeker.nextFile(s->_segMan);
+}
- if (!exists) {
- // Try searching for the file prepending target-
- Common::SeekableReadStream *inFile = saveFileMan->openForLoading(wrappedName);
- exists = (inFile != 0);
- delete inFile;
- }
+reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) {
+ Common::String name = s->_segMan->getString(argv[0]);
- // Special case for non-English versions of LSL5: The English version of LSL5 calls
- // kFileIO(), case K_FILEIO_OPEN for reading to check if memory.drv exists (which is
- // where the game's password is stored). If it's not found, it calls kFileIO() again,
- // case K_FILEIO_OPEN for writing and creates a new file. Non-English versions call
- // kFileIO(), case K_FILEIO_FILE_EXISTS instead, and fail if memory.drv can't be found.
- // We create a default memory.drv file with no password, so that the game can continue
- if (!exists && name == "memory.drv") {
- // Create a new file, and write the bytes for the empty password string inside
- byte defaultContent[] = { 0xE9, 0xE9, 0xEB, 0xE1, 0x0D, 0x0A, 0x31, 0x30, 0x30, 0x30 };
- Common::WriteStream *outFile = saveFileMan->openForSaving(wrappedName);
- for (int i = 0; i < 10; i++)
- outFile->writeByte(defaultContent[i]);
- outFile->finalize();
- delete outFile;
- exists = true;
- }
+ // Check for regular file
+ bool exists = Common::File::exists(name);
+ Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+ const Common::String wrappedName = g_sci->wrapFilename(name);
+
+ if (!exists)
+ exists = !saveFileMan->listSavefiles(name).empty();
+
+ if (!exists) {
+ // Try searching for the file prepending target-
+ Common::SeekableReadStream *inFile = saveFileMan->openForLoading(wrappedName);
+ exists = (inFile != 0);
+ delete inFile;
+ }
+
+ // Special case for non-English versions of LSL5: The English version of
+ // LSL5 calls kFileIO(), case K_FILEIO_OPEN for reading to check if
+ // memory.drv exists (which is where the game's password is stored). If
+ // it's not found, it calls kFileIO() again, case K_FILEIO_OPEN for
+ // writing and creates a new file. Non-English versions call kFileIO(),
+ // case K_FILEIO_FILE_EXISTS instead, and fail if memory.drv can't be
+ // found. We create a default memory.drv file with no password, so that
+ // the game can continue.
+ if (!exists && name == "memory.drv") {
+ // Create a new file, and write the bytes for the empty password
+ // string inside
+ byte defaultContent[] = { 0xE9, 0xE9, 0xEB, 0xE1, 0x0D, 0x0A, 0x31, 0x30, 0x30, 0x30 };
+ Common::WriteStream *outFile = saveFileMan->openForSaving(wrappedName);
+ for (int i = 0; i < 10; i++)
+ outFile->writeByte(defaultContent[i]);
+ outFile->finalize();
+ delete outFile;
+ exists = true;
+ }
+
+ debugC(2, kDebugLevelFile, "kFileIO(fileExists) %s -> %d", name.c_str(), exists);
+ return make_reg(0, exists);
+}
- debug(3, "K_FILEIO_FILE_EXISTS(%s) -> %d", name.c_str(), exists);
- return make_reg(0, exists);
- }
- case K_FILEIO_RENAME: {
- Common::String oldName = s->_segMan->getString(argv[1]);
- Common::String newName = s->_segMan->getString(argv[2]);
+reg_t kFileIORename(EngineState *s, int argc, reg_t *argv) {
+ Common::String oldName = s->_segMan->getString(argv[0]);
+ Common::String newName = s->_segMan->getString(argv[1]);
+
+ // SCI1.1 returns 0 on success and a DOS error code on fail. SCI32
+ // returns -1 on fail. We just return -1 for all versions.
+ if (g_engine->getSaveFileManager()->renameSavefile(oldName, newName))
+ return NULL_REG;
+ else
+ return SIGNAL_REG;
+}
- // SCI1.1 returns 0 on success and a DOS error code on fail. SCI32 returns -1 on fail.
- // We just return -1 for all versions.
- if (g_engine->getSaveFileManager()->renameSavefile(oldName, newName))
- return NULL_REG;
- else
- return SIGNAL_REG;
- }
#ifdef ENABLE_SCI32
- case K_FILEIO_READ_BYTE: {
- // Read the byte into the low byte of the accumulator
- FileHandle *f = getFileFromHandle(s, argv[1].toUint16());
- if (!f)
- return NULL_REG;
-
- return make_reg(0, (s->r_acc.toUint16() & 0xff00) | f->_in->readByte());
- }
- case K_FILEIO_WRITE_BYTE: {
- FileHandle *f = getFileFromHandle(s, argv[1].toUint16());
- if (f)
- f->_out->writeByte(argv[2].toUint16() & 0xff);
- break;
- }
- case K_FILEIO_READ_WORD: {
- FileHandle *f = getFileFromHandle(s, argv[1].toUint16());
- if (!f)
- return NULL_REG;
-
- return make_reg(0, f->_in->readUint16LE());
- }
- case K_FILEIO_WRITE_WORD: {
- FileHandle *f = getFileFromHandle(s, argv[1].toUint16());
- if (f)
- f->_out->writeUint16LE(argv[2].toUint16());
- break;
+reg_t kFileIOReadByte(EngineState *s, int argc, reg_t *argv) {
+ // Read the byte into the low byte of the accumulator
+ FileHandle *f = getFileFromHandle(s, argv[0].toUint16());
+ if (!f)
+ return NULL_REG;
+ return make_reg(0, (s->r_acc.toUint16() & 0xff00) | f->_in->readByte());
+}
+
+reg_t kFileIOWriteByte(EngineState *s, int argc, reg_t *argv) {
+ FileHandle *f = getFileFromHandle(s, argv[0].toUint16());
+ if (f)
+ f->_out->writeByte(argv[1].toUint16() & 0xff);
+ return s->r_acc; // FIXME: does this really doesn't return anything?
+}
+
+reg_t kFileIOReadWord(EngineState *s, int argc, reg_t *argv) {
+ FileHandle *f = getFileFromHandle(s, argv[0].toUint16());
+ if (!f)
+ return NULL_REG;
+ return make_reg(0, f->_in->readUint16LE());
+}
+
+reg_t kFileIOWriteWord(EngineState *s, int argc, reg_t *argv) {
+ FileHandle *f = getFileFromHandle(s, argv[0].toUint16());
+ if (f)
+ f->_out->writeUint16LE(argv[1].toUint16());
+ return s->r_acc; // FIXME: does this really doesn't return anything?
+}
+
+reg_t kCD(EngineState *s, int argc, reg_t *argv) {
+ // TODO: Stub
+ switch (argv[0].toUint16()) {
+ case 0:
+ // Return whether the contents of disc argv[1] is available.
+ return TRUE_REG;
+ default:
+ warning("CD(%d)", argv[0].toUint16());
}
- case 19:
- // TODO: Torin's Passage uses this early on in the Sierra logo
- warning("kFileIO(19)");
- break;
-#endif
+
+ return NULL_REG;
+}
+
+reg_t kSave(EngineState *s, int argc, reg_t *argv) {
+ switch (argv[0].toUint16()) {
+ case 0: // Called by kq7 when starting chapters
+ return SIGNAL_REG;
+ case 2: // GetSaveDir
+ // Yay! Reusing the old kernel function!
+ return kGetSaveDir(s, argc - 1, argv + 1);
+ case 8:
+ // TODO
+ // This function has to return something other than 0 to proceed
+ return s->r_acc;
default:
- error("Unknown FileIO() sub-command: %d", func_nr);
+ warning("Unknown/unhandled kSave subop %d", argv[0].toUint16());
}
- return s->r_acc;
+ return NULL_REG;
}
+#endif
+
} // End of namespace Sci
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index d587790b6c..e1e92b1cf9 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -23,20 +23,21 @@
*
*/
+#include "common/system.h"
+
+#include "engines/util.h"
#include "graphics/cursorman.h"
-#include "graphics/video/avi_decoder.h"
#include "graphics/surface.h"
+#include "gui/message.h"
+
#include "sci/sci.h"
#include "sci/debug.h" // for g_debug_sleeptime_factor
#include "sci/resource.h"
-#include "sci/video/seq_decoder.h"
#include "sci/engine/features.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
#include "sci/engine/kernel.h"
-#include "sci/graphics/gui.h"
-#include "sci/graphics/gui32.h"
#include "sci/graphics/animate.h"
#include "sci/graphics/cache.h"
#include "sci/graphics/compare.h"
@@ -44,15 +45,21 @@
#include "sci/graphics/cursor.h"
#include "sci/graphics/palette.h"
#include "sci/graphics/paint16.h"
+#include "sci/graphics/picture.h"
#include "sci/graphics/ports.h"
+#include "sci/graphics/robot.h"
#include "sci/graphics/screen.h"
+#include "sci/graphics/text16.h"
#include "sci/graphics/view.h"
+#ifdef ENABLE_SCI32
+#include "sci/graphics/frameout.h"
+#endif
namespace Sci {
void _k_dirloop(reg_t object, uint16 angle, EngineState *s, int argc, reg_t *argv) {
- GuiResourceId viewId = GET_SEL32V(s->_segMan, object, SELECTOR(view));
- uint16 signal = GET_SEL32V(s->_segMan, object, SELECTOR(signal));
+ GuiResourceId viewId = readSelectorValue(s->_segMan, object, SELECTOR(view));
+ uint16 signal = readSelectorValue(s->_segMan, object, SELECTOR(signal));
int16 loopNo;
int16 maxLoops;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
@@ -91,7 +98,7 @@ void _k_dirloop(reg_t object, uint16 angle, EngineState *s, int argc, reg_t *arg
if ((loopNo > 1) && (maxLoops < 4))
return;
- PUT_SEL32V(s->_segMan, object, SELECTOR(loop), loopNo);
+ writeSelectorValue(s->_segMan, object, SELECTOR(loop), loopNo);
}
static reg_t kSetCursorSci0(EngineState *s, int argc, reg_t *argv) {
@@ -125,9 +132,10 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) {
break;
case -1:
// TODO: Special case at least in kq6, check disassembly
+ // Does something with magCursor, which is set on argc = 10, which we don't support
break;
case -2:
- // TODO: Special case at least in kq6, check disassembly
+ g_sci->_gfxCursor->kernelResetMoveZone();
break;
default:
g_sci->_gfxCursor->kernelShow();
@@ -141,10 +149,22 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) {
g_sci->_gfxCursor->kernelSetPos(pos);
break;
case 4: {
- int16 top = argv[0].toSint16();
- int16 left = argv[1].toSint16();
- int16 bottom = argv[2].toSint16();
- int16 right = argv[3].toSint16();
+ int16 top, left, bottom, right;
+
+ if (getSciVersion() >= SCI_VERSION_2) {
+ top = argv[1].toSint16();
+ left = argv[0].toSint16();
+ bottom = argv[3].toSint16();
+ right = argv[2].toSint16();
+ } else {
+ top = argv[0].toSint16();
+ left = argv[1].toSint16();
+ bottom = argv[2].toSint16();
+ right = argv[3].toSint16();
+ }
+ // bottom/right needs to be included into our movezone, because we compare it like any regular Common::Rect
+ bottom++;
+ right++;
if ((right >= left) && (bottom >= top)) {
Common::Rect rect = Common::Rect(left, top, right, bottom);
@@ -154,8 +174,8 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) {
}
break;
}
+ case 9: // case for kq5cd, we are getting calling with 4 additional 900d parameters
case 5:
- case 9:
hotspot = new Common::Point(argv[3].toSint16(), argv[4].toSint16());
// Fallthrough
case 3:
@@ -164,8 +184,20 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) {
else
g_sci->_gfxCursor->kernelSetView(argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), hotspot);
break;
+ case 10:
+ // Freddy pharkas, when using the whiskey glass to read the prescription (bug #3034973)
+ // magnifier support, disabled using argc == 1, argv == -1
+ warning("kSetCursor: unsupported magnifier");
+ // we just set the view cursor currently
+ g_sci->_gfxCursor->kernelSetView(argv[5].toUint16(), argv[6].toUint16(), argv[7].toUint16(), hotspot);
+ // argv[0] -> 1, 2, 4 -> maybe magnification multiplier
+ // argv[1-4] -> rect for magnification
+ // argv[5, 6, 7] -> view resource for cursor
+ // argv[8] -> picture resource for mag
+ // argv[9] -> color for magnifier replacement
+ break;
default :
- warning("kSetCursor: Unhandled case: %d arguments given", argc);
+ error("kSetCursor: Unhandled case: %d arguments given", argc);
break;
}
return s->r_acc;
@@ -178,7 +210,7 @@ reg_t kSetCursor(EngineState *s, int argc, reg_t *argv) {
case SCI_VERSION_1_1:
return kSetCursorSci11(s, argc, argv);
default:
- warning("Unknown SetCursor type");
+ error("Unknown SetCursor type");
return NULL_REG;
}
}
@@ -199,121 +231,108 @@ reg_t kPicNotValid(EngineState *s, int argc, reg_t *argv) {
return make_reg(0, g_sci->_gfxScreen->kernelPicNotValid(newPicNotValid));
}
-Common::Rect kGraphCreateRect(int16 x, int16 y, int16 x1, int16 y1) {
+static Common::Rect getGraphRect(reg_t *argv) {
+ int16 x = argv[1].toSint16();
+ int16 y = argv[0].toSint16();
+ int16 x1 = argv[3].toSint16();
+ int16 y1 = argv[2].toSint16();
if (x > x1) SWAP(x, x1);
if (y > y1) SWAP(y, y1);
return Common::Rect(x, y, x1, y1);
}
-// Graph subfunctions
-enum {
- K_GRAPH_GET_COLORS_NR = 2,
- // 3 - SET PALETTE VIA RESOURCE
- K_GRAPH_DRAW_LINE = 4,
- // 5 - NOP
- // 6 - DRAW PATTERN
- K_GRAPH_SAVE_BOX = 7,
- K_GRAPH_RESTORE_BOX = 8,
- K_GRAPH_FILL_BOX_BACKGROUND = 9,
- K_GRAPH_FILL_BOX_FOREGROUND = 10,
- K_GRAPH_FILL_BOX_ANY = 11,
- K_GRAPH_UPDATE_BOX = 12,
- K_GRAPH_REDRAW_BOX = 13,
- K_GRAPH_ADJUST_PRIORITY = 14,
- K_GRAPH_SAVE_UPSCALEDHIRES_BOX = 15 // KQ6CD Windows version
-};
+static Common::Point getGraphPoint(reg_t *argv) {
+ int16 x = argv[1].toSint16();
+ int16 y = argv[0].toSint16();
+ return Common::Point(x, y);
+}
reg_t kGraph(EngineState *s, int argc, reg_t *argv) {
- int16 x = 0, y = 0, x1 = 0, y1 = 0;
- uint16 screenMask;
- int16 priority, control, color, colorMask;
- Common::Rect rect;
-
- if (argc >= 5) {
- x = argv[2].toSint16();
- y = argv[1].toSint16();
- x1 = argv[4].toSint16();
- y1 = argv[3].toSint16();
- }
-
- switch (argv[0].toSint16()) {
- case K_GRAPH_GET_COLORS_NR:
- if (g_sci->getResMan()->isAmiga32color())
- return make_reg(0, 32);
- return make_reg(0, !g_sci->getResMan()->isVGA() ? 16 : 256);
-
- case K_GRAPH_DRAW_LINE:
- priority = (argc > 6) ? argv[6].toSint16() : -1;
- control = (argc > 7) ? argv[7].toSint16() : -1;
- color = argv[5].toSint16();
-
- // TODO: Find out why we get >15 for color in EGA
- if (!g_sci->getResMan()->isVGA() && !g_sci->getResMan()->isAmiga32color())
- color &= 0x0F;
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
- g_sci->_gfxPaint16->kernelGraphDrawLine(Common::Point(x, y), Common::Point(x1, y1), color, priority, control);
- break;
+reg_t kGraphGetColorCount(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isAmiga32color())
+ return make_reg(0, 32);
+ return make_reg(0, !g_sci->getResMan()->isVGA() ? 16 : 256);
+}
- case K_GRAPH_SAVE_BOX:
- rect = kGraphCreateRect(x, y, x1, y1);
- screenMask = (argc > 5) ? argv[5].toUint16() : 0;
- return g_sci->_gfxPaint16->kernelGraphSaveBox(rect, screenMask);
+reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv) {
+ int16 color = argv[4].toSint16();
+ int16 priority = (argc > 5) ? argv[5].toSint16() : -1;
+ int16 control = (argc > 6) ? argv[6].toSint16() : -1;
- case K_GRAPH_RESTORE_BOX:
- // This may be called with a memoryhandle from SAVE_BOX or SAVE_UPSCALEDHIRES_BOX
- g_sci->_gfxPaint16->kernelGraphRestoreBox(argv[1]);
- break;
+ // TODO: Find out why we get >15 for color in EGA
+ if (!g_sci->getResMan()->isVGA() && !g_sci->getResMan()->isAmiga32color())
+ color &= 0x0F;
- case K_GRAPH_FILL_BOX_BACKGROUND:
- rect = kGraphCreateRect(x, y, x1, y1);
- g_sci->_gfxPaint16->kernelGraphFillBoxBackground(rect);
- break;
+ g_sci->_gfxPaint16->kernelGraphDrawLine(getGraphPoint(argv), getGraphPoint(argv + 2), color, priority, control);
+ return s->r_acc;
+}
- case K_GRAPH_FILL_BOX_FOREGROUND:
- rect = kGraphCreateRect(x, y, x1, y1);
- g_sci->_gfxPaint16->kernelGraphFillBoxForeground(rect);
- break;
+reg_t kGraphSaveBox(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ uint16 screenMask = argv[4].toUint16() & GFX_SCREEN_MASK_ALL;
+ return g_sci->_gfxPaint16->kernelGraphSaveBox(rect, screenMask);
+}
- case K_GRAPH_FILL_BOX_ANY:
- priority = (argc > 7) ? argv[7].toSint16() : -1;
- control = (argc > 8) ? argv[8].toSint16() : -1;
- color = argv[6].toSint16();
- colorMask = argv[5].toUint16();
+reg_t kGraphRestoreBox(EngineState *s, int argc, reg_t *argv) {
+ // This may be called with a memoryhandle from SAVE_BOX or SAVE_UPSCALEDHIRES_BOX
+ g_sci->_gfxPaint16->kernelGraphRestoreBox(argv[0]);
+ return s->r_acc;
+}
- rect = kGraphCreateRect(x, y, x1, y1);
- g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control);
- break;
+reg_t kGraphFillBoxBackground(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ g_sci->_gfxPaint16->kernelGraphFillBoxBackground(rect);
+ return s->r_acc;
+}
- case K_GRAPH_UPDATE_BOX: {
- rect = kGraphCreateRect(x, y, x1, y1);
- bool hiresMode = (argc > 6) ? true : false;
- // argc == 7 on upscaled hires
- g_sci->_gfxPaint16->kernelGraphUpdateBox(rect, hiresMode);
- break;
- }
+reg_t kGraphFillBoxForeground(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ g_sci->_gfxPaint16->kernelGraphFillBoxForeground(rect);
+ return s->r_acc;
+}
- case K_GRAPH_REDRAW_BOX:
- rect = kGraphCreateRect(x, y, x1, y1);
- g_sci->_gfxPaint16->kernelGraphRedrawBox(rect);
- break;
+reg_t kGraphFillBoxAny(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ int16 colorMask = argv[4].toUint16();
+ int16 color = argv[5].toSint16();
+ int16 priority = (argc > 6) ? argv[6].toSint16() : -1;
+ int16 control = (argc > 7) ? argv[7].toSint16() : -1;
- case K_GRAPH_ADJUST_PRIORITY:
- // Seems to be only implemented for SCI0/SCI01 games
- debugC(2, kDebugLevelGraphics, "adjust_priority(%d, %d)", argv[1].toUint16(), argv[2].toUint16());
- g_sci->_gfxPorts->kernelGraphAdjustPriority(argv[1].toUint16(), argv[2].toUint16());
- break;
+ g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control);
+ return s->r_acc;
+}
- case K_GRAPH_SAVE_UPSCALEDHIRES_BOX:
- rect = kGraphCreateRect(x, y, x1, y1);
- return g_sci->_gfxPaint16->kernelGraphSaveUpscaledHiresBox(rect);
+reg_t kGraphUpdateBox(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ // argv[4] is the map (1 for visual, etc.)
+ // argc == 6 on upscaled hires
+ bool hiresMode = (argc > 5) ? true : false;
+ g_sci->_gfxPaint16->kernelGraphUpdateBox(rect, hiresMode);
+ return s->r_acc;
+}
- default:
- warning("Unsupported kGraph() operation %04x", argv[0].toSint16());
- }
+reg_t kGraphRedrawBox(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ g_sci->_gfxPaint16->kernelGraphRedrawBox(rect);
+ return s->r_acc;
+}
+// Seems to be only implemented for SCI0/SCI01 games
+reg_t kGraphAdjustPriority(EngineState *s, int argc, reg_t *argv) {
+ g_sci->_gfxPorts->kernelGraphAdjustPriority(argv[0].toUint16(), argv[1].toUint16());
return s->r_acc;
}
+reg_t kGraphSaveUpscaledHiresBox(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ return g_sci->_gfxPaint16->kernelGraphSaveUpscaledHiresBox(rect);
+}
+
reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
int16 textWidth, textHeight;
Common::String text = s->_segMan->getString(argv[1]);
@@ -337,13 +356,14 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
}
textWidth = dest[3].toUint16(); textHeight = dest[2].toUint16();
-
+
#ifdef ENABLE_SCI32
- if (g_sci->_gui32)
- g_sci->_gui32->textSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
- else
+ if (!g_sci->_gfxText16) {
+ // TODO: Implement this
+ textWidth = 0; textHeight = 0;
+ } else
#endif
- g_sci->_gui->textSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
+ g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d", text.c_str(), textWidth, textHeight);
dest[2] = make_reg(0, textHeight);
@@ -386,17 +406,16 @@ reg_t kCanBeHere(EngineState *s, int argc, reg_t *argv) {
reg_t curObject = argv[0];
reg_t listReference = (argc > 1) ? argv[1] : NULL_REG;
- bool canBeHere = g_sci->_gfxCompare->kernelCanBeHere(curObject, listReference);
- return make_reg(0, canBeHere);
+ reg_t canBeHere = g_sci->_gfxCompare->kernelCanBeHere(curObject, listReference);
+ return make_reg(0, canBeHere.isNull() ? 1 : 0);
}
-// kCantBeHere does the same thing as kCanBeHere, except that it returns the opposite result.
reg_t kCantBeHere(EngineState *s, int argc, reg_t *argv) {
reg_t curObject = argv[0];
reg_t listReference = (argc > 1) ? argv[1] : NULL_REG;
- bool canBeHere = g_sci->_gfxCompare->kernelCanBeHere(curObject, listReference);
- return make_reg(0, !canBeHere);
+ reg_t canBeHere = g_sci->_gfxCompare->kernelCanBeHere(curObject, listReference);
+ return canBeHere;
}
reg_t kIsItSkip(EngineState *s, int argc, reg_t *argv) {
@@ -437,7 +456,7 @@ reg_t kCelWide(EngineState *s, int argc, reg_t *argv) {
reg_t kNumLoops(EngineState *s, int argc, reg_t *argv) {
reg_t object = argv[0];
- GuiResourceId viewId = GET_SEL32V(s->_segMan, object, SELECTOR(view));
+ GuiResourceId viewId = readSelectorValue(s->_segMan, object, SELECTOR(view));
int16 loopCount;
loopCount = g_sci->_gfxCache->kernelViewGetLoopCount(viewId);
@@ -449,8 +468,8 @@ reg_t kNumLoops(EngineState *s, int argc, reg_t *argv) {
reg_t kNumCels(EngineState *s, int argc, reg_t *argv) {
reg_t object = argv[0];
- GuiResourceId viewId = GET_SEL32V(s->_segMan, object, SELECTOR(view));
- int16 loopNo = GET_SEL32V(s->_segMan, object, SELECTOR(loop));
+ GuiResourceId viewId = readSelectorValue(s->_segMan, object, SELECTOR(view));
+ int16 loopNo = readSelectorValue(s->_segMan, object, SELECTOR(loop));
int16 celCount;
celCount = g_sci->_gfxCache->kernelViewGetCelCount(viewId, loopNo);
@@ -522,14 +541,6 @@ reg_t kBaseSetter(EngineState *s, int argc, reg_t *argv) {
reg_t object = argv[0];
g_sci->_gfxCompare->kernelBaseSetter(object);
-
- // WORKAROUND for a problem in LSL1VGA. This allows the casino door to be opened,
- // till the actual problem is found
- if (s->_gameId == "lsl1sci" && s->currentRoomNumber() == 300) {
- int top = GET_SEL32V(s->_segMan, object, SELECTOR(brTop));
- PUT_SEL32V(s->_segMan, object, SELECTOR(brTop), top + 2);
- }
-
return s->r_acc;
}
@@ -539,64 +550,72 @@ reg_t kSetNowSeen(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
+// we are called on EGA/amiga games as well, this doesnt make sense.
+// doing this would actually break the system EGA/amiga palette
reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
- // we are called on EGA/amiga games as well, this doesnt make sense.
- // doing this would actually break the system EGA/amiga palette
- if (!g_sci->getResMan()->isVGA())
- return s->r_acc;
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
- switch (argv[0].toUint16()) {
- case 1: // Set resource palette
- if (argc==3) {
- GuiResourceId resourceId = argv[1].toUint16();
- bool force = argv[2].toUint16() == 2 ? true : false;
- g_sci->_gfxPalette->kernelSetFromResource(resourceId, force);
- } else {
- warning("kPalette(1) called with %d parameters", argc);
- }
- break;
- case 2: { // Set palette-flag(s)
- uint16 fromColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
- uint16 toColor = CLIP<uint16>(argv[2].toUint16(), 1, 255);
- uint16 flags = argv[3].toUint16();
+reg_t kPaletteSetFromResource(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isVGA()) {
+ GuiResourceId resourceId = argv[0].toUint16();
+ bool force = false;
+ if (argc == 2)
+ force = argv[1].toUint16() == 2 ? true : false;
+ g_sci->_gfxPalette->kernelSetFromResource(resourceId, force);
+ }
+ return s->r_acc;
+}
+
+reg_t kPaletteSetFlag(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isVGA()) {
+ uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
+ uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
+ uint16 flags = argv[2].toUint16();
g_sci->_gfxPalette->kernelSetFlag(fromColor, toColor, flags);
- break;
}
- case 3: { // Remove palette-flag(s)
- uint16 fromColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
- uint16 toColor = CLIP<uint16>(argv[2].toUint16(), 1, 255);
- uint16 flags = argv[3].toUint16();
+ return s->r_acc;
+}
+
+reg_t kPaletteUnsetFlag(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isVGA()) {
+ uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
+ uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
+ uint16 flags = argv[2].toUint16();
g_sci->_gfxPalette->kernelUnsetFlag(fromColor, toColor, flags);
- break;
}
- case 4: { // Set palette intensity
- switch (argc) {
- case 4:
- case 5: {
- uint16 fromColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
- uint16 toColor = CLIP<uint16>(argv[2].toUint16(), 1, 255);
- uint16 intensity = argv[3].toUint16();
- bool setPalette = (argc < 5) ? true : (argv[4].isNull()) ? true : false;
-
- g_sci->_gfxPalette->kernelSetIntensity(fromColor, toColor, intensity, setPalette);
- break;
- }
- default:
- warning("kPalette(4) called with %d parameters", argc);
- }
- break;
+ return s->r_acc;
+}
+
+reg_t kPaletteSetIntensity(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isVGA()) {
+ uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
+ uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
+ uint16 intensity = argv[2].toUint16();
+ bool setPalette = (argc < 4) ? true : (argv[3].isNull()) ? true : false;
+
+ g_sci->_gfxPalette->kernelSetIntensity(fromColor, toColor, intensity, setPalette);
}
- case 5: { // Find closest color
- uint16 r = argv[1].toUint16();
- uint16 g = argv[2].toUint16();
- uint16 b = argv[3].toUint16();
+ return s->r_acc;
+}
+reg_t kPaletteFindColor(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isVGA()) {
+ uint16 r = argv[0].toUint16();
+ uint16 g = argv[1].toUint16();
+ uint16 b = argv[2].toUint16();
return make_reg(0, g_sci->_gfxPalette->kernelFindColor(r, g, b));
}
- case 6: { // Animate
+ return NULL_REG;
+}
+
+reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isVGA()) {
int16 argNr;
bool paletteChanged = false;
- for (argNr = 1; argNr < argc; argNr += 3) {
+ for (argNr = 0; argNr < argc; argNr += 3) {
uint16 fromColor = argv[argNr].toUint16();
uint16 toColor = argv[argNr + 1].toUint16();
int16 speed = argv[argNr + 2].toSint16();
@@ -605,80 +624,82 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
}
if (paletteChanged)
g_sci->_gfxPalette->kernelAnimateSet();
- break;
- }
- case 7: { // Save palette to heap
- warning("kPalette(7), save palette to heap STUB");
- break;
- }
- case 8: { // Restore palette from heap
- warning("kPalette(8), set stored palette STUB");
- break;
}
- default:
- warning("kPalette(%d), not implemented", argv[0].toUint16());
+ return s->r_acc;
+}
+
+reg_t kPaletteSave(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isVGA()) {
+ return g_sci->_gfxPalette->kernelSave();
}
+ return NULL_REG;
+}
- return s->r_acc;
+reg_t kPaletteRestore(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isVGA()) {
+ g_sci->_gfxPalette->kernelRestore(argv[0]);
+ }
+ return argv[0];
}
-// This here is needed to make Pharkas work
reg_t kPalVary(EngineState *s, int argc, reg_t *argv) {
- uint16 operation = argv[0].toUint16();
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
- if (!g_sci->_gui)
- return s->r_acc;
+reg_t kPalVaryInit(EngineState *s, int argc, reg_t *argv) {
+ GuiResourceId paletteId = argv[0].toUint16();
+ uint16 ticks = argv[1].toUint16();
+ uint16 stepStop = argc >= 3 ? argv[2].toUint16() : 64;
+ uint16 direction = argc >= 4 ? argv[3].toUint16() : 1;
+ if (g_sci->_gfxPalette->kernelPalVaryInit(paletteId, ticks, stepStop, direction))
+ return SIGNAL_REG;
+ return NULL_REG;
+}
- switch (operation) {
- case 0: { // Init
- GuiResourceId paletteId;
- uint16 time;
- if (argc == 3) {
- paletteId = argv[1].toUint16();
- time = argv[2].toUint16();
- g_sci->_gfxPalette->startPalVary(paletteId, time);
- warning("kPalVary(init) called with paletteId = %d, time = %d", paletteId, time);
- } else {
- warning("kPalVary(init) called with unsupported argc %d", argc);
- }
- break;
- }
- case 1: { // Unknown
- warning("kPalVary(1) called with parameter %d (argc %d)", argv[1].toUint16(), argc);
- break;
- }
- case 3: { // DeInit
- if (argc == 1) {
- g_sci->_gfxPalette->stopPalVary();
- warning("kPalVary(deinit)");
- } else {
- warning("kPalVary(deinit) called with unsupported argc %d", argc);
- }
- break;
- }
- case 4: { // Unknown
- warning("kPalVary(4) called with parameter %d (argc %d)", argv[1].toUint16(), argc);
- break;
- }
- case 6: { // Pause
- bool pauseState;
- if (argc == 2) {
- pauseState = argv[1].isNull() ? false : true;
- g_sci->_gfxPalette->togglePalVary(pauseState);
- warning("kPalVary(pause) called with state = %d", pauseState);
- } else {
- warning("kPalVary(pause) called with unsupported argc %d", argc);
- }
- break;
- }
- default:
- warning("kPalVary(%d), not implemented (argc = %d)", operation, argc);
- }
+reg_t kPalVaryReverse(EngineState *s, int argc, reg_t *argv) {
+ int16 ticks = argc >= 1 ? argv[0].toUint16() : -1;
+ int16 stepStop = argc >= 2 ? argv[1].toUint16() : 0;
+ int16 direction = argc >= 3 ? argv[2].toSint16() : -1;
+
+ return make_reg(0, g_sci->_gfxPalette->kernelPalVaryReverse(ticks, stepStop, direction));
+}
+
+reg_t kPalVaryGetCurrentStep(EngineState *s, int argc, reg_t *argv) {
+ return make_reg(0, g_sci->_gfxPalette->kernelPalVaryGetCurrentStep());
+}
+
+reg_t kPalVaryDeinit(EngineState *s, int argc, reg_t *argv) {
+ g_sci->_gfxPalette->kernelPalVaryDeinit();
+ return NULL_REG;
+}
+
+reg_t kPalVaryChangeTarget(EngineState *s, int argc, reg_t *argv) {
+ GuiResourceId paletteId = argv[0].toUint16();
+ int16 currentStep = g_sci->_gfxPalette->kernelPalVaryChangeTarget(paletteId);
+ return make_reg(0, currentStep);
+}
+
+reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv) {
+ uint16 ticks = argv[0].toUint16();
+ g_sci->_gfxPalette->kernelPalVaryChangeTicks(ticks);
+ return NULL_REG;
+}
+
+reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv) {
+ bool pauseState = !argv[0].isNull();
+ g_sci->_gfxPalette->kernelPalVaryPause(pauseState);
+ return NULL_REG;
+}
+
+reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv) {
+ // Unknown (seems to be SCI32 exclusive)
return NULL_REG;
}
reg_t kAssertPalette(EngineState *s, int argc, reg_t *argv) {
- GuiResourceId paletteId = argv[1].toUint16();
+ GuiResourceId paletteId = argv[0].toUint16();
g_sci->_gfxPalette->kernelAssertPalette(paletteId);
return s->r_acc;
@@ -692,9 +713,9 @@ reg_t kPortrait(EngineState *s, int argc, reg_t *argv) {
case 0: { // load
if (argc == 2) {
Common::String resourceName = s->_segMan->getString(argv[1]);
- s->r_acc = g_sci->_gui->portraitLoad(resourceName);
+ s->r_acc = g_sci->_gfxPaint16->kernelPortraitLoad(resourceName);
} else {
- warning("kPortrait(loadResource) called with unsupported argc %d", argc);
+ error("kPortrait(loadResource) called with unsupported argc %d", argc);
}
break;
}
@@ -709,31 +730,33 @@ reg_t kPortrait(EngineState *s, int argc, reg_t *argv) {
uint seq = argv[8].toUint16() & 0xff;
// argv[9] is usually 0??!!
- g_sci->_gui->portraitShow(resourceName, position, resourceNum, noun, verb, cond, seq);
+ g_sci->_gfxPaint16->kernelPortraitShow(resourceName, position, resourceNum, noun, verb, cond, seq);
return SIGNAL_REG;
} else {
- warning("kPortrait(show) called with unsupported argc %d", argc);
+ error("kPortrait(show) called with unsupported argc %d", argc);
}
break;
}
case 2: { // unload
if (argc == 2) {
uint16 portraitId = argv[1].toUint16();
- g_sci->_gui->portraitUnload(portraitId);
+ g_sci->_gfxPaint16->kernelPortraitUnload(portraitId);
} else {
- warning("kPortrait(unload) called with unsupported argc %d", argc);
+ error("kPortrait(unload) called with unsupported argc %d", argc);
}
break;
}
default:
- warning("kPortrait(%d), not implemented (argc = %d)", operation, argc);
+ error("kPortrait(%d), not implemented (argc = %d)", operation, argc);
}
return s->r_acc;
}
-// Original top-left must stay on kControl rects, we adjust accordingly because sierra sci actually wont draw rects that
-// are upside down (example: jones, when challenging jones - one button is a duplicate and also has lower-right which is 0, 0)
+// Original top-left must stay on kControl rects, we adjust accordingly because
+// sierra sci actually wont draw rects that are upside down (example: jones,
+// when challenging jones - one button is a duplicate and also has lower-right
+// which is 0, 0)
Common::Rect kControlCreateRect(int16 x, int16 y, int16 x1, int16 y1) {
if (x > x1) x1 = x;
if (y > y1) y1 = y;
@@ -741,12 +764,12 @@ Common::Rect kControlCreateRect(int16 x, int16 y, int16 x1, int16 y1) {
}
void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
- int16 type = GET_SEL32V(s->_segMan, controlObject, SELECTOR(type));
- int16 style = GET_SEL32V(s->_segMan, controlObject, SELECTOR(state));
- int16 x = GET_SEL32V(s->_segMan, controlObject, SELECTOR(nsLeft));
- int16 y = GET_SEL32V(s->_segMan, controlObject, SELECTOR(nsTop));
- GuiResourceId fontId = GET_SEL32V(s->_segMan, controlObject, SELECTOR(font));
- reg_t textReference = GET_SEL32(s->_segMan, controlObject, SELECTOR(text));
+ int16 type = readSelectorValue(s->_segMan, controlObject, SELECTOR(type));
+ int16 style = readSelectorValue(s->_segMan, controlObject, SELECTOR(state));
+ int16 x = readSelectorValue(s->_segMan, controlObject, SELECTOR(nsLeft));
+ int16 y = readSelectorValue(s->_segMan, controlObject, SELECTOR(nsTop));
+ GuiResourceId fontId = readSelectorValue(s->_segMan, controlObject, SELECTOR(font));
+ reg_t textReference = readSelector(s->_segMan, controlObject, SELECTOR(text));
Common::String text;
Common::Rect rect;
TextAlignment alignment;
@@ -762,8 +785,8 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
bool isAlias = false;
rect = kControlCreateRect(x, y,
- GET_SEL32V(s->_segMan, controlObject, SELECTOR(nsRight)),
- GET_SEL32V(s->_segMan, controlObject, SELECTOR(nsBottom)));
+ readSelectorValue(s->_segMan, controlObject, SELECTOR(nsRight)),
+ readSelectorValue(s->_segMan, controlObject, SELECTOR(nsBottom)));
if (!textReference.isNull())
text = s->_segMan->getString(textReference);
@@ -775,32 +798,34 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
return;
case SCI_CONTROLS_TYPE_TEXT:
- alignment = GET_SEL32V(s->_segMan, controlObject, SELECTOR(mode));
+ alignment = readSelectorValue(s->_segMan, controlObject, SELECTOR(mode));
debugC(2, kDebugLevelGraphics, "drawing text %04x:%04x ('%s') to %d,%d, mode=%d", PRINT_REG(controlObject), text.c_str(), x, y, alignment);
g_sci->_gfxControls->kernelDrawText(rect, controlObject, g_sci->strSplit(text.c_str()).c_str(), fontId, alignment, style, hilite);
return;
case SCI_CONTROLS_TYPE_TEXTEDIT:
- mode = GET_SEL32V(s->_segMan, controlObject, SELECTOR(mode));
- maxChars = GET_SEL32V(s->_segMan, controlObject, SELECTOR(max));
- cursorPos = GET_SEL32V(s->_segMan, controlObject, SELECTOR(cursor));
+ mode = readSelectorValue(s->_segMan, controlObject, SELECTOR(mode));
+ maxChars = readSelectorValue(s->_segMan, controlObject, SELECTOR(max));
+ cursorPos = readSelectorValue(s->_segMan, controlObject, SELECTOR(cursor));
+ if (cursorPos > (int)text.size()) {
+ // if cursor is outside of text, adjust accordingly
+ cursorPos = text.size();
+ writeSelectorValue(s->_segMan, controlObject, SELECTOR(cursor), cursorPos);
+ }
debugC(2, kDebugLevelGraphics, "drawing edit control %04x:%04x (text %04x:%04x, '%s') to %d,%d", PRINT_REG(controlObject), PRINT_REG(textReference), text.c_str(), x, y);
g_sci->_gfxControls->kernelDrawTextEdit(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, mode, style, cursorPos, maxChars, hilite);
return;
case SCI_CONTROLS_TYPE_ICON:
- viewId = GET_SEL32V(s->_segMan, controlObject, SELECTOR(view));
+ viewId = readSelectorValue(s->_segMan, controlObject, SELECTOR(view));
{
- int l = GET_SEL32V(s->_segMan, controlObject, SELECTOR(loop));
+ int l = readSelectorValue(s->_segMan, controlObject, SELECTOR(loop));
loopNo = (l & 0x80) ? l - 256 : l;
- int c = GET_SEL32V(s->_segMan, controlObject, SELECTOR(cel));
+ int c = readSelectorValue(s->_segMan, controlObject, SELECTOR(cel));
celNo = (c & 0x80) ? c - 256 : c;
- // Game-specific: *ONLY* the jones EGA/VGA sierra interpreter contain code using priority selector
- // ALL other games use a hardcoded -1 (madness!)
- // We are detecting jones/talkie as "jones" as well, but the sierra interpreter of talkie doesnt have this
- // "hack". Hopefully it wont cause regressions (the code causes regressions if used against kq5/floppy)
- if (s->_gameId == "jones")
- priority = GET_SEL32V(s->_segMan, controlObject, SELECTOR(priority));
+ // Check if the control object specifies a priority selector (like in Jones)
+ if (lookupSelector(s->_segMan, controlObject, SELECTOR(priority), NULL, NULL) == kSelectorVariable)
+ priority = readSelectorValue(s->_segMan, controlObject, SELECTOR(priority));
else
priority = -1;
}
@@ -813,17 +838,17 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
if (type == SCI_CONTROLS_TYPE_LIST_ALIAS)
isAlias = true;
- maxChars = GET_SEL32V(s->_segMan, controlObject, SELECTOR(x)); // max chars per entry
- cursorOffset = GET_SEL32V(s->_segMan, controlObject, SELECTOR(cursor));
- if (g_sci->getKernel()->_selectorCache.topString != -1) {
+ maxChars = readSelectorValue(s->_segMan, controlObject, SELECTOR(x)); // max chars per entry
+ cursorOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(cursor));
+ if (SELECTOR(topString) != -1) {
// Games from early SCI1 onwards use topString
- upperOffset = GET_SEL32V(s->_segMan, controlObject, SELECTOR(topString));
+ upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(topString));
} else {
// Earlier games use lsTop or brTop
- if (lookup_selector(s->_segMan, controlObject, g_sci->getKernel()->_selectorCache.brTop, NULL, NULL) == kSelectorVariable)
- upperOffset = GET_SEL32V(s->_segMan, controlObject, SELECTOR(brTop));
+ if (lookupSelector(s->_segMan, controlObject, SELECTOR(brTop), NULL, NULL) == kSelectorVariable)
+ upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(brTop));
else
- upperOffset = GET_SEL32V(s->_segMan, controlObject, SELECTOR(lsTop));
+ upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(lsTop));
}
// Count string entries in NULL terminated string list
@@ -873,9 +898,40 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) {
// Disable the "Change Directory" button, as we don't allow the game engine to
// change the directory where saved games are placed
- if (objName == "changeDirI") {
- int state = GET_SEL32V(s->_segMan, controlObject, SELECTOR(state));
- PUT_SEL32V(s->_segMan, controlObject, SELECTOR(state), (state | SCI_CONTROLS_STYLE_DISABLED) & ~SCI_CONTROLS_STYLE_ENABLED);
+ // "changeDirItem" is used in the import windows of QFG2&3
+ if ((objName == "changeDirI") || (objName == "changeDirItem")) {
+ int state = readSelectorValue(s->_segMan, controlObject, SELECTOR(state));
+ writeSelectorValue(s->_segMan, controlObject, SELECTOR(state), (state | SCI_CONTROLS_STYLE_DISABLED) & ~SCI_CONTROLS_STYLE_ENABLED);
+ }
+ if (objName == "DEdit") {
+ reg_t textReference = readSelector(s->_segMan, controlObject, SELECTOR(text));
+ if (!textReference.isNull()) {
+ Common::String text = s->_segMan->getString(textReference);
+ if ((text == "a:hq1_hero.sav") || (text == "a:glory1.sav") || (text == "a:glory2.sav") || (text == "a:glory3.sav")) {
+ // Remove "a:" from hero quest / quest for glory export default filenames
+ text.deleteChar(0);
+ text.deleteChar(0);
+ s->_segMan->strcpy(textReference, text.c_str());
+ }
+ }
+ }
+ if (objName == "savedHeros") {
+ // Import of QfG character files dialog is shown
+ // display additional popup information before letting user use it
+ reg_t changeDirButton = s->_segMan->findObjectByName("changeDirItem");
+ if (!changeDirButton.isNull()) {
+ // check if checkDirButton is still enabled, in that case we are called the first time during that room
+ if (!(readSelectorValue(s->_segMan, changeDirButton, SELECTOR(state)) & SCI_CONTROLS_STYLE_DISABLED)) {
+ GUI::MessageDialog dialog("Characters saved inside ScummVM are shown "
+ "automatically. Character files saved in the original "
+ "interpreter need to be put inside ScummVM's saved games "
+ "directory and a prefix needs to be added depending on which "
+ "game it was saved in: 'qfg1-' for Quest for Glory 1, 'qfg2-' "
+ "for Quest for Glory 2. Example: 'qfg2-thief.sav'.",
+ "OK");
+ dialog.runModal();
+ }
+ }
}
_k_GenericDrawControl(s, controlObject, false);
@@ -894,7 +950,7 @@ reg_t kEditControl(EngineState *s, int argc, reg_t *argv) {
reg_t eventObject = argv[1];
if (!controlObject.isNull()) {
- int16 controlType = GET_SEL32V(s->_segMan, controlObject, SELECTOR(type));
+ int16 controlType = readSelectorValue(s->_segMan, controlObject, SELECTOR(type));
switch (controlType) {
case SCI_CONTROLS_TYPE_TEXTEDIT:
@@ -954,14 +1010,13 @@ reg_t kSetPort(EngineState *s, int argc, reg_t *argv) {
case 7:
initPriorityBandsFlag = true;
- case 4:
case 6:
picRect.top = argv[0].toSint16();
picRect.left = argv[1].toSint16();
picRect.bottom = argv[2].toSint16();
picRect.right = argv[3].toSint16();
- picTop = (argc >= 6) ? argv[4].toSint16() : 0;
- picLeft = (argc >= 6) ? argv[5].toSint16() : 0;
+ picTop = argv[4].toSint16();
+ picLeft = argv[5].toSint16();
g_sci->_gfxPorts->kernelSetPicWindow(picRect, picTop, picLeft, initPriorityBandsFlag);
break;
@@ -980,28 +1035,26 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) {
uint16 y = argv[4].toUint16();
int16 priority = (argc > 5) ? argv[5].toSint16() : -1;
uint16 paletteNo = (argc > 6) ? argv[6].toUint16() : 0;
- bool hiresMode = (argc > 7) ? true : false;
- reg_t upscaledHiresHandle = (argc > 7) ? argv[7] : NULL_REG;
-
- if ((s->_gameId == "freddypharkas") || (s->_gameId == "freddypharkas-demo")) {
- // WORKAROUND
- // Script 24 contains code that draws the game menu on screen. It uses a temp variable for setting priority that
- // is not set. in Sierra sci this happens to be 8250h. In our sci temporary variables are initialized thus we would
- // get 0 here resulting in broken menus.
- if ((viewId == 995) && (loopNo == 0) && (celNo == 0) && (priority == 0)) // game menu
- priority = 15;
- if ((viewId == 992) && (loopNo == 0) && (celNo == 0) && (priority == 0)) // quit game
- priority = 15;
- }
-
- if (s->_gameId == "laurabow2") {
- // WORKAROUND
- // see the one above
- if ((viewId == 995) && (priority == 0))
- priority = 15;
+ bool hiresMode = false;
+ reg_t upscaledHiresHandle = NULL_REG;
+ uint16 scaleX = 128;
+ uint16 scaleY = 128;
+
+ if (argc > 7) {
+ // this is either kq6 hires or scaling
+ if (paletteNo > 0) {
+ // it's scaling
+ scaleX = argv[6].toUint16();
+ scaleY = argv[7].toUint16();
+ paletteNo = 0;
+ } else {
+ // KQ6 hires
+ hiresMode = true;
+ upscaledHiresHandle = argv[7];
+ }
}
- g_sci->_gfxPaint16->kernelDrawCel(viewId, loopNo, celNo, x, y, priority, paletteNo, hiresMode, upscaledHiresHandle);
+ g_sci->_gfxPaint16->kernelDrawCel(viewId, loopNo, celNo, x, y, priority, paletteNo, scaleX, scaleY, hiresMode, upscaledHiresHandle);
return s->r_acc;
}
@@ -1043,10 +1096,6 @@ reg_t kAnimate(EngineState *s, int argc, reg_t *argv) {
reg_t castListReference = (argc > 0) ? argv[0] : NULL_REG;
bool cycle = (argc > 1) ? ((argv[1].toUint16()) ? true : false) : false;
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- // Take care of incoming events (kAnimate is called semi-regularly)
- process_sound_events(s);
-#endif
g_sci->_gfxAnimate->kernelAnimate(castListReference, cycle, argc, argv);
return s->r_acc;
@@ -1056,7 +1105,7 @@ reg_t kShakeScreen(EngineState *s, int argc, reg_t *argv) {
int16 shakeCount = (argc > 0) ? argv[0].toUint16() : 1;
int16 directions = (argc > 1) ? argv[1].toUint16() : 1;
- g_sci->_gfxPaint->kernelShakeScreen(shakeCount, directions);
+ g_sci->_gfxScreen->kernelShakeScreen(shakeCount, directions);
return s->r_acc;
}
@@ -1077,105 +1126,264 @@ reg_t kDisplay(EngineState *s, int argc, reg_t *argv) {
return g_sci->_gfxPaint16->kernelDisplay(g_sci->strSplit(text.c_str()).c_str(), argc, argv);
}
-reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
- // Hide the cursor if it's showing and then show it again if it was
- // previously visible.
- bool reshowCursor;
-
- reshowCursor = g_sci->_gfxCursor->isVisible();
- if (reshowCursor)
- g_sci->_gfxCursor->kernelHide();
-
- Graphics::VideoDecoder *videoDecoder = 0;
+reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv) {
+ // This call is used for KQ6's intro. It has one parameter, which is 1 when
+ // the intro begins, and 0 when it ends. It is suspected that this is
+ // actually a flag to enable video planar memory access, as the video
+ // decoder in KQ6 is specifically written for the planar memory model.
+ // Planar memory mode access was used for VGA "Mode X" (320x240 resolution,
+ // although the intro in KQ6 is 320x200).
+ // Refer to http://en.wikipedia.org/wiki/Mode_X
- if (argv[0].segment != 0) {
- Common::String filename = s->_segMan->getString(argv[0]);
+ //warning("STUB: SetVideoMode %d", argv[0].toUint16());
+ return s->r_acc;
+}
- if (g_sci->getPlatform() == Common::kPlatformMacintosh) {
- // Mac QuickTime
- // The only argument is the string for the video
- warning("TODO: Play QuickTime movie '%s'", filename.c_str());
- return s->r_acc;
- } else {
- // DOS SEQ
- // SEQ's are called with no subops, just the string and delay
- SeqDecoder *seqDecoder = new SeqDecoder();
- seqDecoder->setFrameDelay(argv[1].toUint16()); // Time between frames in ticks
- videoDecoder = seqDecoder;
-
- if (!videoDecoder->loadFile(filename)) {
- warning("Failed to open movie file %s", filename.c_str());
- delete videoDecoder;
- videoDecoder = 0;
- }
- }
- } else {
- // Windows AVI (Macintosh QuickTime? Need to check KQ6 Macintosh)
- // TODO: This appears to be some sort of subop. case 0 contains the string
- // for the video, so we'll just play it from there for now.
+// New calls for SCI11. Using those is only needed when using text-codes so that
+// one is able to change font and/or color multiple times during kDisplay and
+// kDrawControl
+reg_t kTextFonts(EngineState *s, int argc, reg_t *argv) {
+ g_sci->_gfxText16->kernelTextFonts(argc, argv);
+ return s->r_acc;
+}
+
+reg_t kTextColors(EngineState *s, int argc, reg_t *argv) {
+ g_sci->_gfxText16->kernelTextColors(argc, argv);
+ return s->r_acc;
+}
#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2_1) {
- // SCI2.1 always has argv[0] as 1, the rest of the arguments seem to
- // follow SCI1.1/2.
- if (argv[0].toUint16() != 1)
- error("SCI2.1 kShowMovie argv[0] not 1");
- argv++;
- argc--;
- }
-#endif
- switch (argv[0].toUint16()) {
- case 0: {
- Common::String filename = s->_segMan->getString(argv[1]);
- videoDecoder = new Graphics::AviDecoder(g_system->getMixer());
-
- if (!videoDecoder->loadFile(filename.c_str())) {
- warning("Failed to open movie file %s", filename.c_str());
- delete videoDecoder;
- videoDecoder = 0;
- }
- break;
- }
- default:
- warning("Unhandled SCI kShowMovie subop %d", argv[1].toUint16());
- }
- }
- if (videoDecoder) {
- uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2;
- uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2;
+reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) {
+ // Returns 0 if the screen width or height is less than 640 or 400,
+ // respectively.
+ if (g_system->getWidth() < 640 || g_system->getHeight() < 400)
+ return make_reg(0, 0);
- while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo()) {
- if (videoDecoder->needsUpdate()) {
- Graphics::Surface *frame = videoDecoder->decodeNextFrame();
- if (frame) {
- g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
+ return make_reg(0, 1);
+}
- if (videoDecoder->hasDirtyPalette())
- videoDecoder->setSystemPalette();
+// SCI32 variant, can't work like sci16 variants
+reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv) {
+// reg_t curObject = argv[0];
+// reg_t listReference = (argc > 1) ? argv[1] : NULL_REG;
+
+ return NULL_REG;
+}
- g_system->updateScreen();
- }
- }
+reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) {
+ reg_t viewObj = argv[0];
- Common::Event event;
- while (g_system->getEventManager()->pollEvent(event))
- ;
+ g_sci->_gfxFrameout->kernelAddScreenItem(viewObj);
+ return NULL_REG;
+}
- g_system->delayMillis(10);
- }
-
- delete videoDecoder;
- g_sci->_gfxScreen->kernelSyncWithFramebuffer();
- }
+reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv) {
+ //reg_t viewObj = argv[0];
+
+ //warning("kUpdateScreenItem, object %04x:%04x, view %d, loop %d, cel %d, pri %d", PRINT_REG(viewObj), viewId, loopNo, celNo, priority);
+ return NULL_REG;
+}
+
+reg_t kDeleteScreenItem(EngineState *s, int argc, reg_t *argv) {
+ reg_t viewObj = argv[0];
+
+ g_sci->_gfxFrameout->kernelDeleteScreenItem(viewObj);
+
+ /*
+ reg_t viewObj = argv[0];
+ uint16 viewId = readSelectorValue(s->_segMan, viewObj, SELECTOR(view));
+ int16 loopNo = readSelectorValue(s->_segMan, viewObj, SELECTOR(loop));
+ int16 celNo = readSelectorValue(s->_segMan, viewObj, SELECTOR(cel));
+ //int16 leftPos = 0;
+ //int16 topPos = 0;
+ int16 priority = readSelectorValue(s->_segMan, viewObj, SELECTOR(priority));
+ //int16 control = 0;
+ */
- if (reshowCursor)
- g_sci->_gfxCursor->kernelShow();
+ // TODO
+ //warning("kDeleteScreenItem, view %d, loop %d, cel %d, pri %d", viewId, loopNo, celNo, priority);
+ return NULL_REG;
+}
+
+reg_t kAddPlane(EngineState *s, int argc, reg_t *argv) {
+ reg_t planeObj = argv[0];
+
+ g_sci->_gfxFrameout->kernelAddPlane(planeObj);
+ return NULL_REG;
+}
+
+reg_t kDeletePlane(EngineState *s, int argc, reg_t *argv) {
+ reg_t planeObj = argv[0];
+
+ g_sci->_gfxFrameout->kernelDeletePlane(planeObj);
+ return NULL_REG;
+}
+
+reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv) {
+ reg_t planeObj = argv[0];
+
+ g_sci->_gfxFrameout->kernelUpdatePlane(planeObj);
return s->r_acc;
}
-#ifdef ENABLE_SCI32
+reg_t kRepaintPlane(EngineState *s, int argc, reg_t *argv) {
+ reg_t picObj = argv[0];
+
+ // TODO
+
+ warning("kRepaintPlane object %04x:%04x", PRINT_REG(picObj));
+ return NULL_REG;
+}
+
+reg_t kAddPicAt(EngineState *s, int argc, reg_t *argv) {
+ reg_t planeObj = argv[0];
+ GuiResourceId pictureId = argv[1].toUint16();
+ int16 forWidth = argv[2].toSint16();
+ // argv[3] seems to be 0 most of the time
+
+ g_sci->_gfxFrameout->kernelAddPicAt(planeObj, forWidth, pictureId);
+ return s->r_acc;
+}
+
+reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv) {
+ return make_reg(0, g_sci->_gfxFrameout->kernelGetHighPlanePri());
+}
+
+reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) {
+ // This kernel call likely seems to be doing the screen updates,
+ // as its called right after a view is updated
+
+ // TODO
+ g_sci->_gfxFrameout->kernelFrameout();
+
+ return NULL_REG;
+}
+
+reg_t kOnMe(EngineState *s, int argc, reg_t *argv) {
+ // Tests if the cursor is on the passed object
+
+ uint16 x = argv[0].toUint16();
+ uint16 y = argv[1].toUint16();
+ reg_t targetObject = argv[2];
+ uint16 illegalBits = argv[3].offset;
+ Common::Rect nsRect;
+
+ // we assume that x, y are local coordinates
+
+ // Get the bounding rectangle of the object
+ nsRect.left = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsLeft));
+ nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsTop));
+ nsRect.right = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsRight));
+ nsRect.bottom = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsBottom));
+
+ // nsRect top/left may be negative, adjust accordingly
+ Common::Rect checkRect = nsRect;
+ if (checkRect.top < 0)
+ checkRect.top = 0;
+ if (checkRect.left < 0)
+ checkRect.left = 0;
+
+ bool contained = checkRect.contains(x, y);
+ if (contained && illegalBits) {
+ // If illegalbits are set, we check the color of the pixel that got clicked on
+ // for now, we return false if the pixel is transparent
+ // although illegalBits may get differently set, don't know yet how this really works out
+ uint16 viewId = readSelectorValue(s->_segMan, targetObject, SELECTOR(view));
+ int16 loopNo = readSelectorValue(s->_segMan, targetObject, SELECTOR(loop));
+ int16 celNo = readSelectorValue(s->_segMan, targetObject, SELECTOR(cel));
+ if (g_sci->_gfxCompare->kernelIsItSkip(viewId, loopNo, celNo, Common::Point(x - nsRect.left, y - nsRect.top)))
+ contained = false;
+ }
+// these hacks shouldn't be needed anymore
+// uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x));
+// uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y));
+
+ // If top and left are negative, we need to adjust coordinates by
+ // the item's x and y (e.g. happens in GK1, day 1, with detective
+ // Mosely's hotspot in his office)
+
+// if (nsRect.left < 0)
+// nsRect.translate(itemX, 0);
+//
+// if (nsRect.top < 0)
+// nsRect.translate(0, itemY);
+
+// // HACK: nsLeft and nsTop can be invalid, so try and fix them here
+// // using x and y (e.g. with the inventory screen in GK1)
+// if (nsRect.left == itemY && nsRect.top == itemX) {
+// // Swap the values, as they're inversed (eh???)
+// nsRect.left = itemX;
+// nsRect.top = itemY;
+// }
+
+ return make_reg(0, contained);
+}
+
+reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) {
+ // Tests if the cursor is on the passed object, after adjusting the
+ // coordinates of the object according to the object's plane
+
+ uint16 x = argv[0].toUint16();
+ uint16 y = argv[1].toUint16();
+ reg_t targetObject = argv[2];
+ // TODO: argv[3] - it's usually 0
+ Common::Rect nsRect;
+
+ // Get the bounding rectangle of the object
+ nsRect.left = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsLeft));
+ nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsTop));
+ nsRect.right = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsRight));
+ nsRect.bottom = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsBottom));
+
+ // Get the object's plane
+#if 0
+ reg_t planeObject = readSelector(s->_segMan, targetObject, SELECTOR(plane));
+ if (!planeObject.isNull()) {
+ //uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x));
+ //uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y));
+ uint16 planeResY = readSelectorValue(s->_segMan, planeObject, SELECTOR(resY));
+ uint16 planeResX = readSelectorValue(s->_segMan, planeObject, SELECTOR(resX));
+ uint16 planeTop = readSelectorValue(s->_segMan, planeObject, SELECTOR(top));
+ uint16 planeLeft = readSelectorValue(s->_segMan, planeObject, SELECTOR(left));
+ planeTop = (planeTop * g_sci->_gfxScreen->getHeight()) / planeResY;
+ planeLeft = (planeLeft * g_sci->_gfxScreen->getWidth()) / planeResX;
+
+ // Adjust the bounding rectangle of the object by the object's
+ // actual X, Y coordinates
+ nsRect.top = ((nsRect.top * g_sci->_gfxScreen->getHeight()) / planeResY);
+ nsRect.left = ((nsRect.left * g_sci->_gfxScreen->getWidth()) / planeResX);
+ nsRect.bottom = ((nsRect.bottom * g_sci->_gfxScreen->getHeight()) / planeResY);
+ nsRect.right = ((nsRect.right * g_sci->_gfxScreen->getWidth()) / planeResX);
+
+ nsRect.translate(planeLeft, planeTop);
+ }
+#endif
+ //warning("kIsOnMe: (%d, %d) on object %04x:%04x, parameter %d", argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), argv[3].toUint16());
+
+ return make_reg(0, nsRect.contains(x, y));
+}
+
+reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) {
+ // TODO: argument 0 is usually 0, and arguments 1 and 2 are usually 1
+ switch (argv[0].toUint16()) {
+ case 0: {
+ if (argc != 4) {
+ warning("kCreateTextBitmap(0): expected 4 arguments, got %i", argc);
+ return NULL_REG;
+ }
+ reg_t object = argv[3];
+ Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text)));
+ break;
+ }
+ default:
+ warning("CreateTextBitmap(%d)", argv[0].toUint16());
+ }
+
+ return NULL_REG;
+}
+
reg_t kRobot(EngineState *s, int argc, reg_t *argv) {
int16 subop = argv[0].toUint16();
@@ -1188,8 +1396,15 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) {
int16 x = argv[4].toUint16();
int16 y = argv[5].toUint16();
warning("kRobot(init), id %d, obj %04x:%04x, flag %d, x=%d, y=%d", id, PRINT_REG(obj), flag, x, y);
+ GfxRobot *test = new GfxRobot(g_sci->getResMan(), g_sci->_gfxScreen, id);
+ test->draw();
+ delete test;
+
}
break;
+ case 1: // LSL6 hires (startup)
+ // TODO
+ return NULL_REG; // an integer is expected
case 4: { // start
int id = argv[1].toUint16();
warning("kRobot(start), id %d", id);
@@ -1205,31 +1420,7 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-#endif
-
-reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv) {
- // This call is used for KQ6's intro. It has one parameter, which is
- // 1 when the intro begins, and 0 when it ends. It is suspected that
- // this is actually a flag to enable video planar memory access, as
- // the video decoder in KQ6 is specifically written for the planar
- // memory model. Planar memory mode access was used for VGA "Mode X"
- // (320x240 resolution, although the intro in KQ6 is 320x200).
- // Refer to http://en.wikipedia.org/wiki/Mode_X
-
- //warning("STUB: SetVideoMode %d", argv[0].toUint16());
- return s->r_acc;
-}
-// New calls for SCI11. Using those is only needed when using text-codes so that one is able to change
-// font and/or color multiple times during kDisplay and kDrawControl
-reg_t kTextFonts(EngineState *s, int argc, reg_t *argv) {
- g_sci->_gui->textFonts(argc, argv);
- return s->r_acc;
-}
-
-reg_t kTextColors(EngineState *s, int argc, reg_t *argv) {
- g_sci->_gui->textColors(argc, argv);
- return s->r_acc;
-}
+#endif
} // End of namespace Sci
diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp
index c04454ca3d..93e95099f5 100644
--- a/engines/sci/engine/klists.cpp
+++ b/engines/sci/engine/klists.cpp
@@ -34,15 +34,20 @@ static bool isSaneNodePointer(SegManager *segMan, reg_t addr) {
reg_t prev = addr;
do {
- Node *node = segMan->lookupNode(addr);
+ Node *node = segMan->lookupNode(addr, false);
if (!node) {
- warning("isSaneNodePointer: Node at %04x:%04x wasn't found", PRINT_REG(addr));
+ if ((g_sci->getGameId() == GID_ICEMAN) && (g_sci->getEngineState()->currentRoomNumber() == 40)) {
+ // ICEMAN: when plotting course, unDrawLast is called by startPlot::changeState
+ // there is no previous entry so we get 0 in here
+ } else {
+ error("isSaneNodePointer: Node at %04x:%04x wasn't found", PRINT_REG(addr));
+ }
return false;
}
if (havePrev && node->pred != prev) {
- warning("isSaneNodePointer: Node at %04x:%04x points to invalid predecessor %04x:%04x (should be %04x:%04x)",
+ error("isSaneNodePointer: Node at %04x:%04x points to invalid predecessor %04x:%04x (should be %04x:%04x)",
PRINT_REG(addr), PRINT_REG(node->pred), PRINT_REG(prev));
//node->pred = prev; // fix the problem in the node
@@ -58,33 +63,33 @@ static bool isSaneNodePointer(SegManager *segMan, reg_t addr) {
}
static void checkListPointer(SegManager *segMan, reg_t addr) {
- List *l = segMan->lookupList(addr);
+ List *list = segMan->lookupList(addr);
- if (!l) {
- warning("isSaneListPointer (list %04x:%04x): The requested list wasn't found",
+ if (!list) {
+ error("checkListPointer (list %04x:%04x): The requested list wasn't found",
PRINT_REG(addr));
return;
}
- if (l->first.isNull() && l->last.isNull()) {
+ if (list->first.isNull() && list->last.isNull()) {
// Empty list is fine
- } else if (!l->first.isNull() && !l->last.isNull()) {
+ } else if (!list->first.isNull() && !list->last.isNull()) {
// Normal list
- Node *node_a = segMan->lookupNode(l->first);
- Node *node_z = segMan->lookupNode(l->last);
+ Node *node_a = segMan->lookupNode(list->first, false);
+ Node *node_z = segMan->lookupNode(list->last, false);
if (!node_a) {
- warning("isSaneListPointer (list %04x:%04x): missing first node", PRINT_REG(addr));
+ error("checkListPointer (list %04x:%04x): missing first node", PRINT_REG(addr));
return;
}
if (!node_z) {
- warning("isSaneListPointer (list %04x:%04x): missing last node", PRINT_REG(addr));
+ error("checkListPointer (list %04x:%04x): missing last node", PRINT_REG(addr));
return;
}
if (!node_a->pred.isNull()) {
- warning("isSaneListPointer (list %04x:%04x): First node of the list points to a predecessor node",
+ error("checkListPointer (list %04x:%04x): First node of the list points to a predecessor node",
PRINT_REG(addr));
//node_a->pred = NULL_REG; // fix the problem in the node
@@ -93,7 +98,7 @@ static void checkListPointer(SegManager *segMan, reg_t addr) {
}
if (!node_z->succ.isNull()) {
- warning("isSaneListPointer (list %04x:%04x): Last node of the list points to a successor node",
+ error("checkListPointer (list %04x:%04x): Last node of the list points to a successor node",
PRINT_REG(addr));
//node_z->succ = NULL_REG; // fix the problem in the node
@@ -101,84 +106,42 @@ static void checkListPointer(SegManager *segMan, reg_t addr) {
return;
}
- isSaneNodePointer(segMan, l->first);
+ isSaneNodePointer(segMan, list->first);
} else {
// Not sane list... it's missing pointers to the first or last element
- if (l->first.isNull())
- warning("isSaneListPointer (list %04x:%04x): missing pointer to first element",
+ if (list->first.isNull())
+ error("checkListPointer (list %04x:%04x): missing pointer to first element",
PRINT_REG(addr));
- if (l->last.isNull())
- warning("isSaneListPointer (list %04x:%04x): missing pointer to last element",
+ if (list->last.isNull())
+ error("checkListPointer (list %04x:%04x): missing pointer to last element",
PRINT_REG(addr));
}
}
reg_t kNewList(EngineState *s, int argc, reg_t *argv) {
- reg_t listbase;
- List *l;
- l = s->_segMan->allocateList(&listbase);
- l->first = l->last = NULL_REG;
- debugC(2, kDebugLevelNodes, "New listbase at %04x:%04x", PRINT_REG(listbase));
+ reg_t listRef;
+ List *list = s->_segMan->allocateList(&listRef);
+ list->first = list->last = NULL_REG;
+ debugC(2, kDebugLevelNodes, "New listRef at %04x:%04x", PRINT_REG(listRef));
- return listbase; // Return list base address
+ return listRef; // Return list base address
}
reg_t kDisposeList(EngineState *s, int argc, reg_t *argv) {
// This function is not needed in ScummVM. The garbage collector
// cleans up unused objects automatically
-#if 0
- List *l = s->_segMan->lookupList(argv[0]);
-
- if (!l) {
- // FIXME: This should be an error, but it's turned to a warning for now
- warning("Attempt to dispose non-list at %04x:%04x", PRINT_REG(argv[0]));
- return NULL_REG;
- }
-
- checkListPointer(s->_segMan, argv[0]);
-
- if (!l->first.isNull()) {
- reg_t n_addr = l->first;
-
- while (!n_addr.isNull()) { // Free all nodes
- Node *n = s->_segMan->lookupNode(n_addr);
- n_addr = n->succ;
-
- //s->_segMan->free_Node(n_addr); // TODO
- }
- }
-
- //s->_segMan->free_list(argv[0]); // TODO
-#endif
-
return s->r_acc;
}
-static reg_t _k_new_node(EngineState *s, reg_t value, reg_t key) {
- reg_t nodebase;
- Node *n = s->_segMan->allocateNode(&nodebase);
-
- if (!n) {
- error("[Kernel] Out of memory while creating a node");
- return NULL_REG;
- }
-
- n->pred = n->succ = NULL_REG;
- n->key = key;
- n->value = value;
-
- return nodebase;
-}
-
reg_t kNewNode(EngineState *s, int argc, reg_t *argv) {
+ reg_t nodeValue = argv[0];
+ // Some SCI32 games call this with 1 parameter (e.g. the demo of Phantasmagoria).
+ // Set the key to be the same as the value in this case
+ reg_t nodeKey = (argc == 2) ? argv[1] : argv[0];
+ s->r_acc = s->_segMan->newNode(nodeValue, nodeKey);
- if (argc == 1)
- s->r_acc = _k_new_node(s, argv[0], argv[0]);
- else
- s->r_acc = _k_new_node(s, argv[0], argv[1]);
-
- debugC(2, kDebugLevelNodes, "New nodebase at %04x:%04x", PRINT_REG(s->r_acc));
+ debugC(2, kDebugLevelNodes, "New nodeRef at %04x:%04x", PRINT_REG(s->r_acc));
return s->r_acc;
}
@@ -187,11 +150,11 @@ reg_t kFirstNode(EngineState *s, int argc, reg_t *argv) {
if (argv[0].isNull())
return NULL_REG;
- List *l = s->_segMan->lookupList(argv[0]);
+ List *list = s->_segMan->lookupList(argv[0]);
- if (l) {
+ if (list) {
checkListPointer(s->_segMan, argv[0]);
- return l->first;
+ return list->first;
} else {
return NULL_REG;
}
@@ -201,11 +164,11 @@ reg_t kLastNode(EngineState *s, int argc, reg_t *argv) {
if (argv[0].isNull())
return NULL_REG;
- List *l = s->_segMan->lookupList(argv[0]);
+ List *list = s->_segMan->lookupList(argv[0]);
- if (l) {
+ if (list) {
checkListPointer(s->_segMan, argv[0]);
- return l->last;
+ return list->last;
} else {
return NULL_REG;
}
@@ -215,56 +178,56 @@ reg_t kEmptyList(EngineState *s, int argc, reg_t *argv) {
if (argv[0].isNull())
return NULL_REG;
- List *l = s->_segMan->lookupList(argv[0]);
+ List *list = s->_segMan->lookupList(argv[0]);
checkListPointer(s->_segMan, argv[0]);
- return make_reg(0, ((l) ? l->first.isNull() : 0));
+ return make_reg(0, ((list) ? list->first.isNull() : 0));
}
-static void _k_add_to_front(EngineState *s, reg_t listbase, reg_t nodebase) {
- List *l = s->_segMan->lookupList(listbase);
- Node *new_n = s->_segMan->lookupNode(nodebase);
+static void addToFront(EngineState *s, reg_t listRef, reg_t nodeRef) {
+ List *list = s->_segMan->lookupList(listRef);
+ Node *newNode = s->_segMan->lookupNode(nodeRef);
- debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase));
+ debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef));
- // FIXME: This should be an error, but it's turned to a warning for now
- if (!new_n)
- warning("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase));
- checkListPointer(s->_segMan, listbase);
+ if (!newNode)
+ error("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef));
+ checkListPointer(s->_segMan, listRef);
+
+ newNode->pred = NULL_REG;
+ newNode->succ = list->first;
- new_n->succ = l->first;
- new_n->pred = NULL_REG;
// Set node to be the first and last node if it's the only node of the list
- if (l->first.isNull())
- l->last = nodebase;
+ if (list->first.isNull())
+ list->last = nodeRef;
else {
- Node *old_n = s->_segMan->lookupNode(l->first);
- old_n->pred = nodebase;
+ Node *oldNode = s->_segMan->lookupNode(list->first);
+ oldNode->pred = nodeRef;
}
- l->first = nodebase;
+ list->first = nodeRef;
}
-static void _k_add_to_end(EngineState *s, reg_t listbase, reg_t nodebase) {
- List *l = s->_segMan->lookupList(listbase);
- Node *new_n = s->_segMan->lookupNode(nodebase);
+static void addToEnd(EngineState *s, reg_t listRef, reg_t nodeRef) {
+ List *list = s->_segMan->lookupList(listRef);
+ Node *newNode = s->_segMan->lookupNode(nodeRef);
+
+ debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef));
- debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase));
+ if (!newNode)
+ error("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef));
+ checkListPointer(s->_segMan, listRef);
- // FIXME: This should be an error, but it's turned to a warning for now
- if (!new_n)
- warning("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase));
- checkListPointer(s->_segMan, listbase);
+ newNode->pred = list->last;
+ newNode->succ = NULL_REG;
- new_n->succ = NULL_REG;
- new_n->pred = l->last;
// Set node to be the first and last node if it's the only node of the list
- if (l->last.isNull())
- l->first = nodebase;
+ if (list->last.isNull())
+ list->first = nodeRef;
else {
- Node *old_n = s->_segMan->lookupNode(l->last);
- old_n->succ = nodebase;
+ Node *old_n = s->_segMan->lookupNode(list->last);
+ old_n->succ = nodeRef;
}
- l->last = nodebase;
+ list->last = nodeRef;
}
reg_t kNextNode(EngineState *s, int argc, reg_t *argv) {
@@ -292,28 +255,43 @@ reg_t kNodeValue(EngineState *s, int argc, reg_t *argv) {
}
reg_t kAddToFront(EngineState *s, int argc, reg_t *argv) {
- _k_add_to_front(s, argv[0], argv[1]);
+ addToFront(s, argv[0], argv[1]);
+
+ if (argc == 3)
+ s->_segMan->lookupNode(argv[1])->key = argv[2];
+
+ return s->r_acc;
+}
+
+reg_t kAddToEnd(EngineState *s, int argc, reg_t *argv) {
+ addToEnd(s, argv[0], argv[1]);
+
+ if (argc == 3)
+ s->_segMan->lookupNode(argv[1])->key = argv[2];
+
return s->r_acc;
}
reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) {
- List *l = s->_segMan->lookupList(argv[0]);
+ List *list = s->_segMan->lookupList(argv[0]);
Node *firstnode = argv[1].isNull() ? NULL : s->_segMan->lookupNode(argv[1]);
Node *newnode = s->_segMan->lookupNode(argv[2]);
checkListPointer(s->_segMan, argv[0]);
- // FIXME: This should be an error, but it's turned to a warning for now
if (!newnode) {
- warning("New 'node' %04x:%04x is not a node", PRINT_REG(argv[2]));
+ error("New 'node' %04x:%04x is not a node", PRINT_REG(argv[2]));
return NULL_REG;
}
- if (argc != 3) {
- warning("kAddAfter: Haven't got 3 arguments, aborting");
+ if (argc != 3 && argc != 4) {
+ error("kAddAfter: Haven't got 3 or 4 arguments, aborting");
return NULL_REG;
}
+ if (argc == 4)
+ newnode->key = argv[3];
+
if (firstnode) { // We're really appending after
reg_t oldnext = firstnode->succ;
@@ -323,22 +301,17 @@ reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) {
if (oldnext.isNull()) // Appended after last node?
// Set new node as last list node
- l->last = argv[2];
+ list->last = argv[2];
else
s->_segMan->lookupNode(oldnext)->pred = argv[2];
} else { // !firstnode
- _k_add_to_front(s, argv[0], argv[2]); // Set as initial list node
+ addToFront(s, argv[0], argv[2]); // Set as initial list node
}
return s->r_acc;
}
-reg_t kAddToEnd(EngineState *s, int argc, reg_t *argv) {
- _k_add_to_end(s, argv[0], argv[1]);
- return s->r_acc;
-}
-
reg_t kFindKey(EngineState *s, int argc, reg_t *argv) {
reg_t node_pos;
reg_t key = argv[1];
@@ -370,23 +343,27 @@ reg_t kFindKey(EngineState *s, int argc, reg_t *argv) {
reg_t kDeleteKey(EngineState *s, int argc, reg_t *argv) {
reg_t node_pos = kFindKey(s, 2, argv);
Node *n;
- List *l = s->_segMan->lookupList(argv[0]);
+ List *list = s->_segMan->lookupList(argv[0]);
if (node_pos.isNull())
return NULL_REG; // Signal failure
n = s->_segMan->lookupNode(node_pos);
- if (l->first == node_pos)
- l->first = n->succ;
- if (l->last == node_pos)
- l->last = n->pred;
+ if (list->first == node_pos)
+ list->first = n->succ;
+ if (list->last == node_pos)
+ list->last = n->pred;
if (!n->pred.isNull())
s->_segMan->lookupNode(n->pred)->succ = n->succ;
if (!n->succ.isNull())
s->_segMan->lookupNode(n->succ)->pred = n->pred;
- //s->_segMan->free_Node(node_pos); // TODO
+ // Erase references to the predecessor and successor nodes, as the game
+ // scripts could reference the node itself again.
+ // Happens in the intro of QFG1 and in Longbow, when exiting the cave.
+ n->pred = NULL_REG;
+ n->succ = NULL_REG;
return make_reg(0, 1); // Signal success
}
@@ -415,11 +392,9 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) {
reg_t dest = argv[1];
reg_t order_func = argv[2];
- int input_size = (int16)GET_SEL32V(segMan, source, SELECTOR(size));
- int i;
-
- reg_t input_data = GET_SEL32(segMan, source, SELECTOR(elements));
- reg_t output_data = GET_SEL32(segMan, dest, SELECTOR(elements));
+ int input_size = (int16)readSelectorValue(segMan, source, SELECTOR(size));
+ reg_t input_data = readSelector(segMan, source, SELECTOR(elements));
+ reg_t output_data = readSelector(segMan, dest, SELECTOR(elements));
List *list;
Node *node;
@@ -430,19 +405,20 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) {
if (output_data.isNull()) {
list = s->_segMan->allocateList(&output_data);
list->first = list->last = NULL_REG;
- PUT_SEL32(segMan, dest, SELECTOR(elements), output_data);
+ writeSelector(segMan, dest, SELECTOR(elements), output_data);
}
- PUT_SEL32V(segMan, dest, SELECTOR(size), input_size);
+ writeSelectorValue(segMan, dest, SELECTOR(size), input_size);
list = s->_segMan->lookupList(input_data);
node = s->_segMan->lookupNode(list->first);
sort_temp_t *temp_array = (sort_temp_t *)malloc(sizeof(sort_temp_t) * input_size);
- i = 0;
+ int i = 0;
while (node) {
- invoke_selector(INV_SEL(s, order_func, doit, kStopOnInvalidSelector), 1, node->value);
+ reg_t params[1] = { node->value };
+ invokeSelector(s, order_func, SELECTOR(doit), argc, argv, 1, params);
temp_array[i].key = node->key;
temp_array[i].value = node->value;
temp_array[i].order = s->r_acc;
@@ -453,8 +429,8 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) {
qsort(temp_array, input_size, sizeof(sort_temp_t), sort_temp_cmp);
for (i = 0;i < input_size;i++) {
- reg_t lNode = _k_new_node(s, temp_array[i].key, temp_array[i].value);
- _k_add_to_end(s, output_data, lNode);
+ reg_t lNode = s->_segMan->newNode(temp_array[i].value, temp_array[i].key);
+ addToEnd(s, output_data, lNode);
}
free(temp_array);
@@ -467,14 +443,14 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) {
reg_t kListAt(EngineState *s, int argc, reg_t *argv) {
if (argc != 2) {
- warning("kListAt called with %d parameters", argc);
+ error("kListAt called with %d parameters", argc);
return NULL_REG;
}
List *list = s->_segMan->lookupList(argv[0]);
reg_t curAddress = list->first;
if (list->first.isNull()) {
- warning("kListAt tried to reference empty list (%04x:%04x)", PRINT_REG(argv[0]));
+ error("kListAt tried to reference empty list (%04x:%04x)", PRINT_REG(argv[0]));
return NULL_REG;
}
Node *curNode = s->_segMan->lookupNode(curAddress);
@@ -533,15 +509,15 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) {
curObject = curNode->value;
// First, check if the target selector is a variable
- if (lookup_selector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
+ if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
// This can only happen with 3 params (list, target selector, variable)
if (argc != 3) {
- warning("kListEachElementDo: Attempted to modify a variable selector with %d params", argc);
+ error("kListEachElementDo: Attempted to modify a variable selector with %d params", argc);
} else {
- write_selector(s->_segMan, curObject, slc, argv[2]);
+ writeSelector(s->_segMan, curObject, slc, argv[2]);
}
} else {
- invoke_selector_argv(s, curObject, slc, kContinueOnInvalidSelector, argc, argv, argc - 2, argv + 2);
+ invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);
}
curNode = s->_segMan->lookupNode(nextNode);
@@ -566,11 +542,11 @@ reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv) {
curObject = curNode->value;
// First, check if the target selector is a variable
- if (lookup_selector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
+ if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
// Can this happen with variable selectors?
- warning("kListFirstTrue: Attempted to access a variable selector");
+ error("kListFirstTrue: Attempted to access a variable selector");
} else {
- invoke_selector_argv(s, curObject, slc, kContinueOnInvalidSelector, argc, argv, argc - 2, argv + 2);
+ invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);
// Check if the result is true
if (!s->r_acc.isNull())
@@ -600,11 +576,11 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) {
curObject = curNode->value;
// First, check if the target selector is a variable
- if (lookup_selector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
+ if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
// Can this happen with variable selectors?
- warning("kListAllTrue: Attempted to access a variable selector");
+ error("kListAllTrue: Attempted to access a variable selector");
} else {
- invoke_selector_argv(s, curObject, slc, kContinueOnInvalidSelector, argc, argv, argc - 2, argv + 2);
+ invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);
// Check if the result isn't true
if (s->r_acc.isNull())
@@ -617,65 +593,134 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-// In SCI2.1, all the list functions were merged in one
reg_t kList(EngineState *s, int argc, reg_t *argv) {
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
+
+reg_t kAddBefore(EngineState *s, int argc, reg_t *argv) {
+ error("Unimplemented function kAddBefore called");
+ return s->r_acc;
+}
+
+reg_t kMoveToFront(EngineState *s, int argc, reg_t *argv) {
+ error("Unimplemented function kMoveToFront called");
+ return s->r_acc;
+}
+
+reg_t kMoveToEnd(EngineState *s, int argc, reg_t *argv) {
+ error("Unimplemented function kMoveToEnd called");
+ return s->r_acc;
+}
+
+reg_t kArray(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
- case 0:
- return kNewList(s, argc - 1, argv + 1);
- case 1:
- return kDisposeList(s, argc - 1, argv + 1);
- case 2:
- return kNewNode(s, argc - 1, argv + 1);
- case 3:
- return kFirstNode(s, argc - 1, argv + 1);
- case 4:
- return kLastNode(s, argc - 1, argv + 1);
- case 5:
- return kEmptyList(s, argc - 1, argv + 1);
- case 6:
- return kNextNode(s, argc - 1, argv + 1);
- case 7:
- return kPrevNode(s, argc - 1, argv + 1);
- case 8:
- return kNodeValue(s, argc - 1, argv + 1);
- case 9:
- return kAddAfter(s, argc - 1, argv + 1);
- case 10:
- return kAddToFront(s, argc - 1, argv + 1);
- case 11:
- return kAddToEnd(s, argc - 1, argv + 1);
- case 12:
- warning("kList: unimplemented subfunction kAddBefore");
- //return kAddBefore(s, argc - 1, argv + 1);
- return NULL_REG;
- case 13:
- warning("kList: unimplemented subfunction kMoveToFront");
- //return kMoveToFront(s, argc - 1, argv + 1);
- return NULL_REG;
- case 14:
- warning("kList: unimplemented subfunction kMoveToEnd");
- //return kMoveToEnd(s, argc - 1, argv + 1);
- return NULL_REG;
- case 15:
- return kFindKey(s, argc - 1, argv + 1);
- case 16:
- return kDeleteKey(s, argc - 1, argv + 1);
- case 17:
- return kListAt(s, argc - 1, argv + 1);
- case 18:
- return kListIndexOf(s, argc - 1, argv + 1);
- case 19:
- return kListEachElementDo(s, argc - 1, argv + 1);
- case 20:
- return kListFirstTrue(s, argc - 1, argv + 1);
- case 21:
- return kListAllTrue(s, argc - 1, argv + 1);
- case 22:
- return kSort(s, argc - 1, argv + 1);
+ case 0: { // New
+ reg_t arrayHandle;
+ SciArray<reg_t> *array = s->_segMan->allocateArray(&arrayHandle);
+ array->setType(argv[2].toUint16());
+ array->setSize(argv[1].toUint16());
+ return arrayHandle;
+ }
+ case 1: { // Size
+ SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
+ return make_reg(0, array->getSize());
+ }
+ case 2: { // At (return value at an index)
+ SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
+ return array->getValue(argv[2].toUint16());
+ }
+ case 3: { // Atput (put value at an index)
+ SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
+
+ uint32 index = argv[2].toUint16();
+ uint32 count = argc - 3;
+
+ if (index + count > 65535)
+ break;
+
+ if (array->getSize() < index + count)
+ array->setSize(index + count);
+
+ for (uint16 i = 0; i < count; i++)
+ array->setValue(i + index, argv[i + 3]);
+
+ return argv[1]; // We also have to return the handle
+ }
+ case 4: // Free
+ // Freeing of arrays is handled by the garbage collector
+ return s->r_acc;
+ case 5: { // Fill
+ SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
+ uint16 index = argv[2].toUint16();
+
+ // A count of -1 means fill the rest of the array
+ uint16 count = argv[3].toSint16() == -1 ? array->getSize() - index : argv[3].toUint16();
+ uint16 arraySize = array->getSize();
+
+ if (arraySize < index + count)
+ array->setSize(index + count);
+
+ for (uint16 i = 0; i < count; i++)
+ array->setValue(i + index, argv[4]);
+
+ return argv[1];
+ }
+ case 6: { // Cpy
+ if (s->_segMan->getSegmentObj(argv[1].segment)->getType() != SEG_TYPE_ARRAY ||
+ s->_segMan->getSegmentObj(argv[3].segment)->getType() != SEG_TYPE_ARRAY) {
+ // Happens in the RAMA demo
+ warning("kArray(Cpy): Request to copy a segment which isn't an array, ignoring");
+ return NULL_REG;
+ }
+
+ SciArray<reg_t> *array1 = s->_segMan->lookupArray(argv[1]);
+ SciArray<reg_t> *array2 = s->_segMan->lookupArray(argv[3]);
+ uint32 index1 = argv[2].toUint16();
+ uint32 index2 = argv[4].toUint16();
+
+ // The original engine ignores bad copies too
+ if (index2 > array2->getSize())
+ break;
+
+ // A count of -1 means fill the rest of the array
+ uint32 count = argv[5].toSint16() == -1 ? array2->getSize() - index2 : argv[5].toUint16();
+
+ if (array1->getSize() < index1 + count)
+ array1->setSize(index1 + count);
+
+ for (uint16 i = 0; i < count; i++)
+ array1->setValue(i + index1, array2->getValue(i + index2));
+
+ return argv[1];
+ }
+ case 7: // Cmp
+ // Not implemented in SSCI
+ return s->r_acc;
+ case 8: { // Dup
+ SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
+ reg_t arrayHandle;
+ SciArray<reg_t> *dupArray = s->_segMan->allocateArray(&arrayHandle);
+
+ dupArray->setType(array->getType());
+ dupArray->setSize(array->getSize());
+
+ for (uint32 i = 0; i < array->getSize(); i++)
+ dupArray->setValue(i, array->getValue(i));
+
+ return arrayHandle;
+ }
+ case 9: // Getdata
+ if (!s->_segMan->isHeapObject(argv[1]))
+ return argv[1];
+
+ return readSelector(s->_segMan, argv[1], SELECTOR(data));
default:
- warning("kList: Unhandled case %d", argv[0].toUint16());
- return NULL_REG;
+ error("Unknown kArray subop %d", argv[0].toUint16());
}
+
+ return NULL_REG;
}
#endif
diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp
index dbf317860f..f3769b653b 100644
--- a/engines/sci/engine/kmath.cpp
+++ b/engines/sci/engine/kmath.cpp
@@ -29,16 +29,40 @@
namespace Sci {
reg_t kRandom(EngineState *s, int argc, reg_t *argv) {
- int fromNumber = argv[0].toUint16();
- int toNumber = argv[1].toUint16();
- double randomNumber = fromNumber + ((toNumber + 1.0 - fromNumber) * (rand() / (RAND_MAX + 1.0)));
- return make_reg(0, (int)randomNumber);
+ switch (argc) {
+ case 1: // set seed to argv[0]
+ // SCI0/SCI01 just reset the seed to 0 instead of using argv[0] at all
+ return NULL_REG;
+
+ case 2: { // get random number
+ int fromNumber = argv[0].toUint16();
+ int toNumber = argv[1].toUint16();
+
+ // TODO/CHECKME: It is propbably not required to check whether
+ // toNumber is greater than fromNumber, at least not when one
+ // goes by their names, but let us be on the safe side and
+ // allow toNumber to be smaller than fromNumber too.
+ if (fromNumber > toNumber)
+ SWAP(fromNumber, toNumber);
+
+ const uint diff = (uint)(toNumber - fromNumber);
+
+ const int randomNumber = fromNumber + (int)g_sci->getRNG().getRandomNumber(diff);
+ return make_reg(0, randomNumber);
+ }
+
+ case 3: // get seed
+ // SCI0/01 did not support this at all
+ // Actually we would have to return the previous seed
+ error("kRandom: scripts asked for previous seed");
+ break;
+
+ default:
+ error("kRandom: unsupported argc");
+ }
}
reg_t kAbs(EngineState *s, int argc, reg_t *argv) {
- // This is a hack, but so is the code in Hoyle1 that needs it.
- if (argv[0].segment)
- return make_reg(0, 0x3e9); // Yes people, this is an object
return make_reg(0, abs(argv[0].toSint16()));
}
@@ -112,7 +136,7 @@ reg_t kCosDiv(EngineState *s, int argc, reg_t *argv) {
double cosval = cos(angle * PI / 180.0);
if ((cosval < 0.0001) && (cosval > -0.0001)) {
- warning("kCosDiv: Attempted division by zero");
+ error("kCosDiv: Attempted division by zero");
return SIGNAL_REG;
} else
return make_reg(0, (int16)(value / cosval));
@@ -124,7 +148,7 @@ reg_t kSinDiv(EngineState *s, int argc, reg_t *argv) {
double sinval = sin(angle * PI / 180.0);
if ((sinval < 0.0001) && (sinval > -0.0001)) {
- warning("kSinDiv: Attempted division by zero");
+ error("kSinDiv: Attempted division by zero");
return SIGNAL_REG;
} else
return make_reg(0, (int16)(value / sinval));
@@ -136,7 +160,7 @@ reg_t kTimesTan(EngineState *s, int argc, reg_t *argv) {
param -= 90;
if ((param % 90) == 0) {
- warning("kTimesTan: Attempted tan(pi/2)");
+ error("kTimesTan: Attempted tan(pi/2)");
return SIGNAL_REG;
} else
return make_reg(0, (int16) - (tan(param * PI / 180.0) * scale));
@@ -147,10 +171,28 @@ reg_t kTimesCot(EngineState *s, int argc, reg_t *argv) {
int scale = (argc > 1) ? argv[1].toSint16() : 1;
if ((param % 90) == 0) {
- warning("kTimesCot: Attempted tan(pi/2)");
+ error("kTimesCot: Attempted tan(pi/2)");
return SIGNAL_REG;
} else
return make_reg(0, (int16)(tan(param * PI / 180.0) * scale));
}
+#ifdef ENABLE_SCI32
+
+reg_t kMulDiv(EngineState *s, int argc, reg_t *argv) {
+ int16 multiplicant = argv[0].toSint16();
+ int16 multiplier = argv[1].toSint16();
+ int16 denominator = argv[2].toSint16();
+
+ // Sanity check...
+ if (!denominator) {
+ error("kMulDiv: attempt to divide by zero (%d * %d / %d", multiplicant, multiplier, denominator);
+ return NULL_REG;
+ }
+
+ return make_reg(0, multiplicant * multiplier / denominator);
+}
+
+#endif
+
} // End of namespace Sci
diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp
index a5f2f01297..c8a6e03556 100644
--- a/engines/sci/engine/kmenu.cpp
+++ b/engines/sci/engine/kmenu.cpp
@@ -27,7 +27,6 @@
#include "sci/resource.h"
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
-#include "sci/graphics/gui.h"
#include "sci/graphics/cursor.h"
#include "sci/graphics/menu.h"
@@ -74,7 +73,7 @@ reg_t kDrawStatus(EngineState *s, int argc, reg_t *argv) {
int16 colorBack = (argc > 2) ? argv[2].toSint16() : g_sci->getResMan()->isVGA() ? 255 : 15;
if (!textReference.isNull()) {
- // Sometimes this is called without giving text, if thats the case dont process it
+ // Sometimes this is called without giving text, if thats the case dont process it.
text = s->_segMan->getString(textReference);
g_sci->_gfxMenu->kernelDrawStatus(g_sci->strSplit(text.c_str(), NULL).c_str(), colorPen, colorBack);
@@ -91,10 +90,9 @@ reg_t kDrawMenuBar(EngineState *s, int argc, reg_t *argv) {
reg_t kMenuSelect(EngineState *s, int argc, reg_t *argv) {
reg_t eventObject = argv[0];
- //bool pauseSound = argc > 1 ? (argv[1].isNull() ? false : true) : false;
+ bool pauseSound = argc > 1 ? (argv[1].isNull() ? false : true) : true;
- // TODO: pauseSound implementation
- return g_sci->_gfxMenu->kernelSelect(eventObject);
+ return g_sci->_gfxMenu->kernelSelect(eventObject, pauseSound);
}
} // End of namespace Sci
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
index 450dca3770..fbe20410de 100644
--- a/engines/sci/engine/kmisc.cpp
+++ b/engines/sci/engine/kmisc.cpp
@@ -31,17 +31,14 @@
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
#include "sci/engine/gc.h"
-#include "sci/graphics/gui.h"
+#include "sci/graphics/maciconbar.h"
namespace Sci {
reg_t kRestartGame(EngineState *s, int argc, reg_t *argv) {
- s->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW;
- s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE; // This appears to help
+ s->shrinkStackToBase();
- shrink_execution_stack(s, s->execution_stack_base + 1);
-
- script_abort_flag = 1; // Force vm to abort ASAP
+ s->abortScriptProcessing = kAbortRestartGame; // Force vm to abort ASAP
return NULL_REG;
}
@@ -49,47 +46,40 @@ reg_t kRestartGame(EngineState *s, int argc, reg_t *argv) {
** Returns the restarting_flag in acc
*/
reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) {
- s->r_acc = make_reg(0, (s->restarting_flags & SCI_GAME_WAS_RESTARTED));
+ s->r_acc = make_reg(0, s->gameIsRestarting);
if (argc) { // Only happens during replay
if (!argv[0].toUint16()) // Set restarting flag
- s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED;
+ s->gameIsRestarting = GAMEISRESTARTING_NONE;
}
uint32 neededSleep = 30;
- // WORKAROUND:
- // LSL3 calculates a machinespeed variable during game startup (right after the filthy questions)
- // This one would go through w/o throttling resulting in having to do 1000 pushups or something
- // Another way of handling this would be delaying incrementing of "machineSpeed" selector
- if (s->_gameId == "lsl3" && s->currentRoomNumber() == 290)
- s->_throttleTrigger = true;
- if (s->_gameId == "iceman" && s->currentRoomNumber() == 27) {
- s->_throttleTrigger = true;
- neededSleep = 60;
- }
-
- if (s->_throttleTrigger) {
- // Some games seem to get the duration of main loop initially and then switch of animations for the whole game
- // based on that (qfg2, iceman). We are now running full speed initially to avoid that.
- // It seems like we dont need to do that anymore
- //if (s->_throttleCounter < 50) {
- // s->_throttleCounter++;
- // return s->r_acc;
- //}
-
- uint32 curTime = g_system->getMillis();
- uint32 duration = curTime - s->_throttleLastTime;
-
- if (duration < neededSleep) {
- s->_event->sleep(neededSleep - duration);
- s->_throttleLastTime = g_system->getMillis();
- } else {
- s->_throttleLastTime = curTime;
+ // WORKAROUNDS:
+ switch (g_sci->getGameId()) {
+ case GID_LSL3:
+ // LSL3 calculates a machinespeed variable during game startup
+ // (right after the filthy questions). This one would go through w/o
+ // throttling resulting in having to do 1000 pushups or something. Another
+ // way of handling this would be delaying incrementing of "machineSpeed"
+ // selector.
+ if (s->currentRoomNumber() == 290)
+ s->_throttleTrigger = true;
+ break;
+ case GID_ICEMAN:
+ // In ICEMAN the submarine control room is not animating much, so it runs way too fast
+ // we calm it down even more otherwise especially fighting against other submarines
+ // is almost impossible
+ if (s->currentRoomNumber() == 27) {
+ s->_throttleTrigger = true;
+ neededSleep = 60;
}
- s->_throttleTrigger = false;
+ break;
+ default:
+ break;
}
+ s->speedThrottler(neededSleep);
return s->r_acc;
}
@@ -106,7 +96,11 @@ enum kMemoryInfoFunc {
};
reg_t kMemoryInfo(EngineState *s, int argc, reg_t *argv) {
- const uint16 size = 0x7fff; // Must not be 0xffff, or some memory calculations will overflow
+ // The free heap size returned must not be 0xffff, or some memory
+ // calculations will overflow. Crazy Nick's games handle up to 32746
+ // bytes (0x7fea), otherwise they throw a warning that the memory is
+ // fragmented
+ const uint16 size = 0x7fea;
switch (argv[0].offset) {
case K_MEMORYINFO_LARGEST_HEAP_BLOCK:
@@ -120,7 +114,7 @@ reg_t kMemoryInfo(EngineState *s, int argc, reg_t *argv) {
return make_reg(0, size);
default:
- warning("Unknown MemoryInfo operation: %04x", argv[0].offset);
+ error("Unknown MemoryInfo operation: %04x", argv[0].offset);
}
return NULL_REG;
@@ -172,16 +166,16 @@ reg_t kFlushResources(EngineState *s, int argc, reg_t *argv) {
reg_t kSetDebug(EngineState *s, int argc, reg_t *argv) {
printf("Debug mode activated\n");
- g_debugState.seeking = kDebugSeekNothing;
- g_debugState.runningStep = 0;
+ g_sci->_debugState.seeking = kDebugSeekNothing;
+ g_sci->_debugState.runningStep = 0;
return s->r_acc;
}
enum {
- K_NEW_GETTIME_TICKS = 0,
- K_NEW_GETTIME_TIME_12HOUR = 1,
- K_NEW_GETTIME_TIME_24HOUR = 2,
- K_NEW_GETTIME_DATE = 3
+ KGETTIME_TICKS = 0,
+ KGETTIME_TIME_12HOUR = 1,
+ KGETTIME_TIME_24HOUR = 2,
+ KGETTIME_DATE = 3
};
reg_t kGetTime(EngineState *s, int argc, reg_t *argv) {
@@ -190,32 +184,32 @@ reg_t kGetTime(EngineState *s, int argc, reg_t *argv) {
int retval = 0; // Avoid spurious warning
g_system->getTimeAndDate(loc_time);
- elapsedTime = g_system->getMillis() - s->game_start_time;
+ elapsedTime = g_system->getMillis() - s->gameStartTime;
int mode = (argc > 0) ? argv[0].toUint16() : 0;
if (getSciVersion() <= SCI_VERSION_0_LATE && mode > 1)
- warning("kGetTime called in SCI0 with mode %d (expected 0 or 1)", mode);
+ error("kGetTime called in SCI0 with mode %d (expected 0 or 1)", mode);
switch (mode) {
- case K_NEW_GETTIME_TICKS :
+ case KGETTIME_TICKS :
retval = elapsedTime * 60 / 1000;
debugC(2, kDebugLevelTime, "GetTime(elapsed) returns %d", retval);
break;
- case K_NEW_GETTIME_TIME_12HOUR :
+ case KGETTIME_TIME_12HOUR :
retval = ((loc_time.tm_hour % 12) << 12) | (loc_time.tm_min << 6) | (loc_time.tm_sec);
debugC(2, kDebugLevelTime, "GetTime(12h) returns %d", retval);
break;
- case K_NEW_GETTIME_TIME_24HOUR :
+ case KGETTIME_TIME_24HOUR :
retval = (loc_time.tm_hour << 11) | (loc_time.tm_min << 5) | (loc_time.tm_sec >> 1);
debugC(2, kDebugLevelTime, "GetTime(24h) returns %d", retval);
break;
- case K_NEW_GETTIME_DATE :
+ case KGETTIME_DATE :
retval = loc_time.tm_mday | ((loc_time.tm_mon + 1) << 5) | (((loc_time.tm_year + 1900) & 0x7f) << 9);
debugC(2, kDebugLevelTime, "GetTime(date) returns %d", retval);
break;
default:
- warning("Attempt to use unknown GetTime mode %d", mode);
+ error("Attempt to use unknown GetTime mode %d", mode);
break;
}
@@ -233,17 +227,32 @@ enum {
reg_t kMemory(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
- case K_MEMORY_ALLOCATE_CRITICAL :
- if (!s->_segMan->allocDynmem(argv[1].toUint16(), "kMemory() critical", &s->r_acc)) {
+ case K_MEMORY_ALLOCATE_CRITICAL: {
+ int byteCount = argv[1].toUint16();
+ // WORKAROUND: pq3 (multilingual) when plotting crimes - allocates the
+ // returned bytes from kStrLen on "W" and "E" and wants to put a
+ // string in there, which doesn't fit of course. That's why we allocate
+ // one byte more all the time inside that room
+ if (g_sci->getGameId() == GID_PQ3) {
+ if (s->currentRoomNumber() == 202)
+ byteCount++;
+ }
+ if (!s->_segMan->allocDynmem(byteCount, "kMemory() critical", &s->r_acc)) {
error("Critical heap allocation failed");
}
break;
- case K_MEMORY_ALLOCATE_NONCRITICAL :
+ }
+ case K_MEMORY_ALLOCATE_NONCRITICAL:
s->_segMan->allocDynmem(argv[1].toUint16(), "kMemory() non-critical", &s->r_acc);
break;
case K_MEMORY_FREE :
- if (s->_segMan->freeDynmem(argv[1])) {
- error("Attempt to kMemory::free() non-dynmem pointer %04x:%04x", PRINT_REG(argv[1]));
+ if (!s->_segMan->freeDynmem(argv[1])) {
+ if (g_sci->getGameId() == GID_QFG1VGA) {
+ // Ignore script bug in QFG1VGA, when closing any conversation dialog with esc
+ } else {
+ // Usually, the result of a script bug. Non-critical
+ warning("Attempt to kMemory::free() non-dynmem pointer %04x:%04x", PRINT_REG(argv[1]));
+ }
}
break;
case K_MEMORY_MEMCPY : {
@@ -252,11 +261,16 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) {
break;
}
case K_MEMORY_PEEK : {
+ if (!argv[1].segment) {
+ // This occurs in KQ5CD when interacting with certain objects
+ warning("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1]));
+ return s->r_acc;
+ }
+
SegmentRef ref = s->_segMan->dereference(argv[1]);
if (!ref.isValid() || ref.maxSize < 2) {
- // This occurs in KQ5CD when interacting with certain objects
- warning("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1]));
+ error("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1]));
return s->r_acc;
}
if (ref.isRaw)
@@ -272,7 +286,7 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) {
SegmentRef ref = s->_segMan->dereference(argv[1]);
if (!ref.isValid() || ref.maxSize < 2) {
- warning("Attempt to poke invalid memory at %04x:%04x", PRINT_REG(argv[1]));
+ error("Attempt to poke invalid memory at %04x:%04x", PRINT_REG(argv[1]));
return s->r_acc;
}
@@ -298,9 +312,12 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) {
reg_t kIconBar(EngineState *s, int argc, reg_t *argv) {
// TODO...
- if (argv[0].toUint16() == 4 && argv[1].toUint16() == 0)
+ if (argv[0].toUint16() == 4 && argv[1].toUint16() == 0) {
for (int i = 0; i < argv[2].toUint16(); i++)
- warning("kIconBar: Icon Object %d = %04x:%04x", i, PRINT_REG(argv[i + 3]));
+ g_sci->_gfxMacIconBar->addIcon(argv[i + 3]);
+
+ g_sci->_gfxMacIconBar->drawIcons();
+ }
// Other calls seem to handle selecting/deselecting them
@@ -327,11 +344,12 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) {
bool isWindows = g_sci->getPlatform() == Common::kPlatformWindows;
if (argc == 0 && getSciVersion() < SCI_VERSION_2) {
- // This is called in KQ5CD with no parameters, where it seems to do some graphics
- // driver check. This kernel function didn't have subfunctions then. If 0 is
- // returned, the game functions normally, otherwise all the animations show up
- // like a slideshow (e.g. in the intro). So we return 0. However, the behavior
- // changed for kPlatform with no parameters in SCI32.
+ // This is called in KQ5CD with no parameters, where it seems to do some
+ // graphics driver check. This kernel function didn't have subfunctions
+ // then. If 0 is returned, the game functions normally, otherwise all
+ // the animations show up like a slideshow (e.g. in the intro). So we
+ // return 0. However, the behavior changed for kPlatform with no
+ // parameters in SCI32.
return NULL_REG;
}
@@ -363,10 +381,53 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) {
case kPlatformIsItWindows:
return make_reg(0, isWindows);
default:
- warning("Unsupported kPlatform operation %d", operation);
+ error("Unsupported kPlatform operation %d", operation);
+ }
+
+ return NULL_REG;
+}
+
+reg_t kEmpty(EngineState *s, int argc, reg_t *argv) {
+ // Placeholder for empty kernel functions which are still called from the
+ // engine scripts (like the empty kSetSynonyms function in SCI1.1). This
+ // differs from dummy functions because it does nothing and never throws a
+ // warning when it is called.
+ return s->r_acc;
+}
+
+reg_t kStub(EngineState *s, int argc, reg_t *argv) {
+ Kernel *kernel = g_sci->getKernel();
+ int kernelCallNr = -1;
+
+ Common::List<ExecStack>::iterator callIterator = s->_executionStack.end();
+ if (callIterator != s->_executionStack.begin()) {
+ callIterator--;
+ ExecStack lastCall = *callIterator;
+ kernelCallNr = lastCall.debugSelector;
}
+ Common::String warningMsg = "Dummy function k" + kernel->getKernelName(kernelCallNr) +
+ Common::String::printf("[%x]", kernelCallNr) +
+ " invoked. Params: " +
+ Common::String::printf("%d", argc) + " (";
+
+ for (int i = 0; i < argc; i++) {
+ warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i]));
+ warningMsg += (i == argc - 1 ? ")" : ", ");
+ }
+
+ warning("%s", warningMsg.c_str());
+ return s->r_acc;
+}
+
+reg_t kStubNull(EngineState *s, int argc, reg_t *argv) {
+ kStub(s, argc, argv);
return NULL_REG;
}
+reg_t kDummy(EngineState *s, int argc, reg_t *argv) {
+ kStub(s, argc, argv);
+ error("Kernel function was called, which was considered to be unused - see log for details");
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp
index fcaf0d7ea0..5c23539bf8 100644
--- a/engines/sci/engine/kmovement.cpp
+++ b/engines/sci/engine/kmovement.cpp
@@ -30,45 +30,47 @@
#include "sci/engine/selector.h"
#include "sci/engine/kernel.h"
#include "sci/graphics/animate.h"
+#include "sci/graphics/screen.h"
namespace Sci {
-/*
-Compute "velocity" vector (xStep,yStep)=(vx,vy) for a jump from (0,0) to (dx,dy), with gravity gy.
-The gravity is assumed to be non-negative.
-
-If this was ordinary continuous physics, we would compute the desired (floating point!)
-velocity vector (vx,vy) as follows, under the assumption that vx and vy are linearly correlated
-by some constant factor c, i.e. vy = c * vx:
- dx = t * vx
- dy = t * vy + gy * t^2 / 2
-=> dy = c * dx + gy * (dx/vx)^2 / 2
-=> |vx| = sqrt( gy * dx^2 / (2 * (dy - c * dx)) )
-Here, the sign of vx must be chosen equal to the sign of dx, obviously.
-
-Clearly, this square root only makes sense in our context if the denominator is positive,
-or equivalently, (dy - c * dx) must be positive. For simplicity and by symmetry
-along the x-axis, we assume dx to be positive for all computations, and only adjust for
-its sign in the end. Switching the sign of c appropriately, we set tmp := (dy + c * dx)
-and compute c so that this term becomes positive.
-
-Remark #1: If the jump is straight up, i.e. dx == 0, then we should not assume the above
-linear correlation vy = c * vx of the velocities (as vx will be 0, but vy shouldn't be,
-unless we drop).
-
-
-Remark #2: We are actually in a discrete setup. The motion is computed iteratively: each iteration,
-we add vx and vy to the position, then add gy to vy. So the real formula is the following
-(where t is ideally close to an int):
-
- dx = t * vx
- dy = t * vy + gy * t*(t-1) / 2
-
-But the solution resulting from that is a lot more complicated, so we use the above approximation instead.
-
-Still, what we compute in the end is of course not a real velocity anymore, but an integer approximation,
-used in an iterative stepping algorithm
-*/
+/**
+ * Compute "velocity" vector (xStep,yStep)=(vx,vy) for a jump from (0,0) to
+ * (dx,dy), with gravity constant gy. The gravity is assumed to be non-negative.
+ *
+ * If this was ordinary continuous physics, we would compute the desired
+ * (floating point!) velocity vector (vx,vy) as follows, under the assumption
+ * that vx and vy are linearly correlated by a constant c, i.e., vy = c * vx:
+ * dx = t * vx
+ * dy = t * vy + gy * t^2 / 2
+ * => dy = c * dx + gy * (dx/vx)^2 / 2
+ * => |vx| = sqrt( gy * dx^2 / (2 * (dy - c * dx)) )
+ * Here, the sign of vx must be chosen equal to the sign of dx, obviously.
+ *
+ * This square root only makes sense in our context if the denominator is
+ * positive, or equivalently, (dy - c * dx) must be positive. For simplicity
+ * and by symmetry along the x-axis, we assume dx to be positive for all
+ * computations, and only adjust for its sign in the end. Switching the sign of
+ * c appropriately, we set tmp := (dy + c * dx) and compute c so that this term
+ * becomes positive.
+ *
+ * Remark #1: If the jump is straight up, i.e. dx == 0, then we should not
+ * assume the above linear correlation vy = c * vx of the velocities (as vx
+ * will be 0, but vy shouldn't be, unless we drop down).
+ *
+ * Remark #2: We are actually in a discrete setup. The motion is computed
+ * iteratively: each iteration, we add vx and vy to the position, then add gy
+ * to vy. So the real formula is the following (where t ideally is close to an int):
+ *
+ * dx = t * vx
+ * dy = t * vy + gy * t*(t-1) / 2
+ *
+ * But the solution resulting from that is a lot more complicated, so we use
+ * the above approximation instead.
+ *
+ * Still, what we compute in the end is of course not a real velocity anymore,
+ * but an integer approximation, used in an iterative stepping algorithm.
+ */
reg_t kSetJump(EngineState *s, int argc, reg_t *argv) {
SegManager *segMan = s->_segMan;
// Input data
@@ -115,7 +117,7 @@ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) {
//tmp = dx * 3 / 2; // ALMOST the resulting value, except for obvious rounding issues
// FIXME: Where is the 3 coming from? Maybe they hard/coded, by "accident", that usually gy=3 ?
- // Then this choice of will make t equal to roughly sqrt(dx)
+ // Then this choice of scalar will make t equal to roughly sqrt(dx)
}
}
// POST: c >= 1
@@ -158,8 +160,8 @@ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) {
debugC(2, kDebugLevelBresen, "SetJump for object at %04x:%04x", PRINT_REG(object));
debugC(2, kDebugLevelBresen, "xStep: %d, yStep: %d", vx, vy);
- PUT_SEL32V(segMan, object, SELECTOR(xStep), vx);
- PUT_SEL32V(segMan, object, SELECTOR(yStep), vy);
+ writeSelectorValue(segMan, object, SELECTOR(xStep), vx);
+ writeSelectorValue(segMan, object, SELECTOR(yStep), vy);
return s->r_acc;
}
@@ -168,9 +170,9 @@ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) {
#define _K_BRESEN_AXIS_Y 1
static void initialize_bresen(SegManager *segMan, int argc, reg_t *argv, reg_t mover, int step_factor, int deltax, int deltay) {
- reg_t client = GET_SEL32(segMan, mover, SELECTOR(client));
- int stepx = (int16)GET_SEL32V(segMan, client, SELECTOR(xStep)) * step_factor;
- int stepy = (int16)GET_SEL32V(segMan, client, SELECTOR(yStep)) * step_factor;
+ reg_t client = readSelector(segMan, mover, SELECTOR(client));
+ int stepx = (int16)readSelectorValue(segMan, client, SELECTOR(xStep)) * step_factor;
+ int stepy = (int16)readSelectorValue(segMan, client, SELECTOR(yStep)) * step_factor;
int numsteps_x = stepx ? (abs(deltax) + stepx - 1) / stepx : 0;
int numsteps_y = stepy ? (abs(deltay) + stepy - 1) / stepy : 0;
int bdi, i1;
@@ -191,15 +193,15 @@ static void initialize_bresen(SegManager *segMan, int argc, reg_t *argv, reg_t m
/* if (abs(deltax) > abs(deltay)) {*/ // Bresenham on y
if (numsteps_y < numsteps_x) {
- PUT_SEL32V(segMan, mover, SELECTOR(b_xAxis), _K_BRESEN_AXIS_Y);
- PUT_SEL32V(segMan, mover, SELECTOR(b_incr), (deltay < 0) ? -1 : 1);
+ writeSelectorValue(segMan, mover, SELECTOR(b_xAxis), _K_BRESEN_AXIS_Y);
+ writeSelectorValue(segMan, mover, SELECTOR(b_incr), (deltay < 0) ? -1 : 1);
//i1 = 2 * (abs(deltay) - abs(deltay_step * numsteps)) * abs(deltax_step);
//bdi = -abs(deltax);
i1 = 2 * (abs(deltay) - abs(deltay_step * (numsteps - 1))) * abs(deltax_step);
bdi = -abs(deltax);
} else { // Bresenham on x
- PUT_SEL32V(segMan, mover, SELECTOR(b_xAxis), _K_BRESEN_AXIS_X);
- PUT_SEL32V(segMan, mover, SELECTOR(b_incr), (deltax < 0) ? -1 : 1);
+ writeSelectorValue(segMan, mover, SELECTOR(b_xAxis), _K_BRESEN_AXIS_X);
+ writeSelectorValue(segMan, mover, SELECTOR(b_incr), (deltax < 0) ? -1 : 1);
//i1= 2 * (abs(deltax) - abs(deltax_step * numsteps)) * abs(deltay_step);
//bdi = -abs(deltay);
i1 = 2 * (abs(deltax) - abs(deltax_step * (numsteps - 1))) * abs(deltay_step);
@@ -207,26 +209,26 @@ static void initialize_bresen(SegManager *segMan, int argc, reg_t *argv, reg_t m
}
- PUT_SEL32V(segMan, mover, SELECTOR(dx), deltax_step);
- PUT_SEL32V(segMan, mover, SELECTOR(dy), deltay_step);
+ writeSelectorValue(segMan, mover, SELECTOR(dx), deltax_step);
+ writeSelectorValue(segMan, mover, SELECTOR(dy), deltay_step);
debugC(2, kDebugLevelBresen, "Init bresen for mover %04x:%04x: d=(%d,%d)", PRINT_REG(mover), deltax, deltay);
debugC(2, kDebugLevelBresen, " steps=%d, mv=(%d, %d), i1= %d, i2=%d",
numsteps, deltax_step, deltay_step, i1, bdi*2);
- //PUT_SEL32V(segMan, mover, SELECTOR(b_movCnt), numsteps); // Needed for HQ1/Ogre?
- PUT_SEL32V(segMan, mover, SELECTOR(b_di), bdi);
- PUT_SEL32V(segMan, mover, SELECTOR(b_i1), i1);
- PUT_SEL32V(segMan, mover, SELECTOR(b_i2), bdi * 2);
+ //writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), numsteps); // Needed for HQ1/Ogre?
+ writeSelectorValue(segMan, mover, SELECTOR(b_di), bdi);
+ writeSelectorValue(segMan, mover, SELECTOR(b_i1), i1);
+ writeSelectorValue(segMan, mover, SELECTOR(b_i2), bdi * 2);
}
reg_t kInitBresen(EngineState *s, int argc, reg_t *argv) {
SegManager *segMan = s->_segMan;
reg_t mover = argv[0];
- reg_t client = GET_SEL32(segMan, mover, SELECTOR(client));
+ reg_t client = readSelector(segMan, mover, SELECTOR(client));
- int deltax = (int16)GET_SEL32V(segMan, mover, SELECTOR(x)) - (int16)GET_SEL32V(segMan, client, SELECTOR(x));
- int deltay = (int16)GET_SEL32V(segMan, mover, SELECTOR(y)) - (int16)GET_SEL32V(segMan, client, SELECTOR(y));
+ int deltax = (int16)readSelectorValue(segMan, mover, SELECTOR(x)) - (int16)readSelectorValue(segMan, client, SELECTOR(x));
+ int deltay = (int16)readSelectorValue(segMan, mover, SELECTOR(y)) - (int16)readSelectorValue(segMan, client, SELECTOR(y));
int step_factor = (argc < 1) ? argv[1].toUint16() : 1;
initialize_bresen(s->_segMan, argc, argv, mover, step_factor, deltax, deltay);
@@ -240,42 +242,51 @@ reg_t kInitBresen(EngineState *s, int argc, reg_t *argv) {
reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
SegManager *segMan = s->_segMan;
reg_t mover = argv[0];
- reg_t client = GET_SEL32(segMan, mover, SELECTOR(client));
+ reg_t client = readSelector(segMan, mover, SELECTOR(client));
- int x = (int16)GET_SEL32V(segMan, client, SELECTOR(x));
- int y = (int16)GET_SEL32V(segMan, client, SELECTOR(y));
+ int x = (int16)readSelectorValue(segMan, client, SELECTOR(x));
+ int y = (int16)readSelectorValue(segMan, client, SELECTOR(y));
int oldx, oldy, destx, desty, dx, dy, bdi, bi1, bi2, movcnt, bdelta, axis;
- uint16 signal = GET_SEL32V(segMan, client, SELECTOR(signal));
+ uint16 signal = readSelectorValue(segMan, client, SELECTOR(signal));
int completed = 0;
- int max_movcnt = GET_SEL32V(segMan, client, SELECTOR(moveSpeed));
+ int max_movcnt = readSelectorValue(segMan, client, SELECTOR(moveSpeed));
if (getSciVersion() > SCI_VERSION_01)
signal &= ~kSignalHitObstacle;
- PUT_SEL32(segMan, client, SELECTOR(signal), make_reg(0, signal)); // This is a NOP for SCI0
+ writeSelector(segMan, client, SELECTOR(signal), make_reg(0, signal)); // This is a NOP for SCI0
oldx = x;
oldy = y;
- destx = (int16)GET_SEL32V(segMan, mover, SELECTOR(x));
- desty = (int16)GET_SEL32V(segMan, mover, SELECTOR(y));
- dx = (int16)GET_SEL32V(segMan, mover, SELECTOR(dx));
- dy = (int16)GET_SEL32V(segMan, mover, SELECTOR(dy));
- bdi = (int16)GET_SEL32V(segMan, mover, SELECTOR(b_di));
- bi1 = (int16)GET_SEL32V(segMan, mover, SELECTOR(b_i1));
- bi2 = (int16)GET_SEL32V(segMan, mover, SELECTOR(b_i2));
- movcnt = GET_SEL32V(segMan, mover, SELECTOR(b_movCnt));
- bdelta = (int16)GET_SEL32V(segMan, mover, SELECTOR(b_incr));
- axis = (int16)GET_SEL32V(segMan, mover, SELECTOR(b_xAxis));
+ destx = (int16)readSelectorValue(segMan, mover, SELECTOR(x));
+ desty = (int16)readSelectorValue(segMan, mover, SELECTOR(y));
+ dx = (int16)readSelectorValue(segMan, mover, SELECTOR(dx));
+ dy = (int16)readSelectorValue(segMan, mover, SELECTOR(dy));
+ bdi = (int16)readSelectorValue(segMan, mover, SELECTOR(b_di));
+ bi1 = (int16)readSelectorValue(segMan, mover, SELECTOR(b_i1));
+ bi2 = (int16)readSelectorValue(segMan, mover, SELECTOR(b_i2));
+ movcnt = readSelectorValue(segMan, mover, SELECTOR(b_movCnt));
+ bdelta = (int16)readSelectorValue(segMan, mover, SELECTOR(b_incr));
+ axis = (int16)readSelectorValue(segMan, mover, SELECTOR(b_xAxis));
+
+ if ((getSciVersion() >= SCI_VERSION_1_LATE)) {
+ // Mixed-Up Fairy Tales has no xLast/yLast selectors
+ if (SELECTOR(xLast) != -1) {
+ // save last position into mover
+ writeSelectorValue(segMan, mover, SELECTOR(xLast), x);
+ writeSelectorValue(segMan, mover, SELECTOR(yLast), y);
+ }
+ }
//printf("movecnt %d, move speed %d\n", movcnt, max_movcnt);
if (g_sci->_features->handleMoveCount()) {
if (max_movcnt > movcnt) {
++movcnt;
- PUT_SEL32V(segMan, mover, SELECTOR(b_movCnt), movcnt); // Needed for HQ1/Ogre?
+ writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), movcnt); // Needed for HQ1/Ogre?
return NULL_REG;
} else {
movcnt = 0;
- PUT_SEL32V(segMan, mover, SELECTOR(b_movCnt), movcnt); // Needed for HQ1/Ogre?
+ writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), movcnt); // Needed for HQ1/Ogre?
}
}
@@ -288,7 +299,7 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
dy += bdelta;
}
- PUT_SEL32V(segMan, mover, SELECTOR(b_di), bdi);
+ writeSelectorValue(segMan, mover, SELECTOR(b_di), bdi);
x += dx;
y += dy;
@@ -303,6 +314,7 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
|| ((y == desty) && (abs(dy) >= abs(dx))) /* Moving fast, reached? */
))) {
// Whew... in short: If we have reached or passed our target position
+
x = destx;
y = desty;
completed = 1;
@@ -310,34 +322,46 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
debugC(2, kDebugLevelBresen, "Finished mover %04x:%04x", PRINT_REG(mover));
}
- PUT_SEL32V(segMan, client, SELECTOR(x), x);
- PUT_SEL32V(segMan, client, SELECTOR(y), y);
+ writeSelectorValue(segMan, client, SELECTOR(x), x);
+ writeSelectorValue(segMan, client, SELECTOR(y), y);
debugC(2, kDebugLevelBresen, "New data: (x,y)=(%d,%d), di=%d", x, y, bdi);
- if (g_sci->getKernel()->_selectorCache.cantBeHere != -1) {
- invoke_selector(INV_SEL(s, client, cantBeHere, kStopOnInvalidSelector), 0);
- s->r_acc = make_reg(0, !s->r_acc.offset);
+ bool collision = false;
+ reg_t cantBeHere = NULL_REG;
+
+ if (SELECTOR(cantBeHere) != -1) {
+ // adding this here for hoyle 3 to get happy. CantBeHere is a dummy in hoyle 3 and acc is != 0 so we would
+ // get a collision otherwise
+ s->r_acc = NULL_REG;
+ invokeSelector(s, client, SELECTOR(cantBeHere), argc, argv);
+ if (!s->r_acc.isNull())
+ collision = true;
+ cantBeHere = s->r_acc;
} else {
- invoke_selector(INV_SEL(s, client, canBeHere, kStopOnInvalidSelector), 0);
+ invokeSelector(s, client, SELECTOR(canBeHere), argc, argv);
+ if (s->r_acc.isNull())
+ collision = true;
}
- if (!s->r_acc.offset) { // Contains the return value
- signal = GET_SEL32V(segMan, client, SELECTOR(signal));
+ if (collision) {
+ signal = readSelectorValue(segMan, client, SELECTOR(signal));
- PUT_SEL32V(segMan, client, SELECTOR(x), oldx);
- PUT_SEL32V(segMan, client, SELECTOR(y), oldy);
- PUT_SEL32V(segMan, client, SELECTOR(signal), (signal | kSignalHitObstacle));
+ writeSelectorValue(segMan, client, SELECTOR(x), oldx);
+ writeSelectorValue(segMan, client, SELECTOR(y), oldy);
+ writeSelectorValue(segMan, client, SELECTOR(signal), (signal | kSignalHitObstacle));
debugC(2, kDebugLevelBresen, "Finished mover %04x:%04x by collision", PRINT_REG(mover));
- completed = 1;
+ // We shall not set completed in this case, sierra sci also doesn't do it
+ // if we set call .moveDone in those cases qfg1 vga gate at the castle and lsl1 casino door will not work
}
- // FIXME: find out why iceman needs this and we ask for version > SCI01
- if ((getSciVersion() > SCI_VERSION_01) || (s->_gameId == "iceman"))
+ if ((getSciVersion() >= SCI_VERSION_1_EGA))
if (completed)
- invoke_selector(INV_SEL(s, mover, moveDone, kStopOnInvalidSelector), 0);
+ invokeSelector(s, mover, SELECTOR(moveDone), argc, argv);
+ if (SELECTOR(cantBeHere) != -1)
+ return cantBeHere;
return make_reg(0, completed);
}
@@ -374,59 +398,52 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) {
s->r_acc = SIGNAL_REG;
if (!s->_segMan->isHeapObject(avoider)) {
- warning("DoAvoider() where avoider %04x:%04x is not an object", PRINT_REG(avoider));
+ error("DoAvoider() where avoider %04x:%04x is not an object", PRINT_REG(avoider));
return NULL_REG;
}
- client = GET_SEL32(segMan, avoider, SELECTOR(client));
+ client = readSelector(segMan, avoider, SELECTOR(client));
if (!s->_segMan->isHeapObject(client)) {
- warning("DoAvoider() where client %04x:%04x is not an object", PRINT_REG(client));
+ error("DoAvoider() where client %04x:%04x is not an object", PRINT_REG(client));
return NULL_REG;
}
- looper = GET_SEL32(segMan, client, SELECTOR(looper));
- mover = GET_SEL32(segMan, client, SELECTOR(mover));
+ looper = readSelector(segMan, client, SELECTOR(looper));
+ mover = readSelector(segMan, client, SELECTOR(mover));
if (!s->_segMan->isHeapObject(mover)) {
if (mover.segment) {
- warning("DoAvoider() where mover %04x:%04x is not an object", PRINT_REG(mover));
+ error("DoAvoider() where mover %04x:%04x is not an object", PRINT_REG(mover));
}
return s->r_acc;
}
- destx = GET_SEL32V(segMan, mover, SELECTOR(x));
- desty = GET_SEL32V(segMan, mover, SELECTOR(y));
+ destx = readSelectorValue(segMan, mover, SELECTOR(x));
+ desty = readSelectorValue(segMan, mover, SELECTOR(y));
debugC(2, kDebugLevelBresen, "Doing avoider %04x:%04x (dest=%d,%d)", PRINT_REG(avoider), destx, desty);
- if (invoke_selector(INV_SEL(s, mover, doit, kContinueOnInvalidSelector) , 0)) {
- error("Mover %04x:%04x of avoider %04x:%04x doesn't have a doit() funcselector", PRINT_REG(mover), PRINT_REG(avoider));
- return NULL_REG;
- }
+ invokeSelector(s, mover, SELECTOR(doit), argc, argv);
- mover = GET_SEL32(segMan, client, SELECTOR(mover));
+ mover = readSelector(segMan, client, SELECTOR(mover));
if (!mover.segment) // Mover has been disposed?
return s->r_acc; // Return gracefully.
- if (invoke_selector(INV_SEL(s, client, isBlocked, kContinueOnInvalidSelector) , 0)) {
- error("Client %04x:%04x of avoider %04x:%04x doesn't"
- " have an isBlocked() funcselector", PRINT_REG(client), PRINT_REG(avoider));
- return NULL_REG;
- }
+ invokeSelector(s, client, SELECTOR(isBlocked), argc, argv);
- dx = destx - GET_SEL32V(segMan, client, SELECTOR(x));
- dy = desty - GET_SEL32V(segMan, client, SELECTOR(y));
+ dx = destx - readSelectorValue(segMan, client, SELECTOR(x));
+ dy = desty - readSelectorValue(segMan, client, SELECTOR(y));
angle = getAngle(dx, dy);
debugC(2, kDebugLevelBresen, "Movement (%d,%d), angle %d is %sblocked", dx, dy, angle, (s->r_acc.offset) ? " " : "not ");
if (s->r_acc.offset) { // isBlocked() returned non-zero
- int rotation = (rand() & 1) ? 45 : (360 - 45); // Clockwise/counterclockwise
- int oldx = GET_SEL32V(segMan, client, SELECTOR(x));
- int oldy = GET_SEL32V(segMan, client, SELECTOR(y));
- int xstep = GET_SEL32V(segMan, client, SELECTOR(xStep));
- int ystep = GET_SEL32V(segMan, client, SELECTOR(yStep));
+ int rotation = (g_sci->getRNG().getRandomBit() == 1) ? 45 : (360 - 45); // Clockwise/counterclockwise
+ int oldx = readSelectorValue(segMan, client, SELECTOR(x));
+ int oldy = readSelectorValue(segMan, client, SELECTOR(y));
+ int xstep = readSelectorValue(segMan, client, SELECTOR(xStep));
+ int ystep = readSelectorValue(segMan, client, SELECTOR(yStep));
int moves;
debugC(2, kDebugLevelBresen, " avoider %04x:%04x", PRINT_REG(avoider));
@@ -435,23 +452,19 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) {
int move_x = (int)(sin(angle * PI / 180.0) * (xstep));
int move_y = (int)(-cos(angle * PI / 180.0) * (ystep));
- PUT_SEL32V(segMan, client, SELECTOR(x), oldx + move_x);
- PUT_SEL32V(segMan, client, SELECTOR(y), oldy + move_y);
+ writeSelectorValue(segMan, client, SELECTOR(x), oldx + move_x);
+ writeSelectorValue(segMan, client, SELECTOR(y), oldy + move_y);
debugC(2, kDebugLevelBresen, "Pos (%d,%d): Trying angle %d; delta=(%d,%d)", oldx, oldy, angle, move_x, move_y);
- if (invoke_selector(INV_SEL(s, client, canBeHere, kContinueOnInvalidSelector) , 0)) {
- error("Client %04x:%04x of avoider %04x:%04x doesn't"
- " have a canBeHere() funcselector", PRINT_REG(client), PRINT_REG(avoider));
- return NULL_REG;
- }
+ invokeSelector(s, client, SELECTOR(canBeHere), argc, argv);
- PUT_SEL32V(segMan, client, SELECTOR(x), oldx);
- PUT_SEL32V(segMan, client, SELECTOR(y), oldy);
+ writeSelectorValue(segMan, client, SELECTOR(x), oldx);
+ writeSelectorValue(segMan, client, SELECTOR(y), oldy);
if (s->r_acc.offset) { // We can be here
debugC(2, kDebugLevelBresen, "Success");
- PUT_SEL32V(segMan, client, SELECTOR(heading), angle);
+ writeSelectorValue(segMan, client, SELECTOR(heading), angle);
return make_reg(0, angle);
}
@@ -462,23 +475,22 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) {
angle -= 360;
}
- warning("DoAvoider failed for avoider %04x:%04x", PRINT_REG(avoider));
+ error("DoAvoider failed for avoider %04x:%04x", PRINT_REG(avoider));
} else {
- int heading = GET_SEL32V(segMan, client, SELECTOR(heading));
+ int heading = readSelectorValue(segMan, client, SELECTOR(heading));
if (heading == -1)
return s->r_acc; // No change
- PUT_SEL32V(segMan, client, SELECTOR(heading), angle);
+ writeSelectorValue(segMan, client, SELECTOR(heading), angle);
s->r_acc = make_reg(0, angle);
+ reg_t params[2] = { make_reg(0, angle), client };
+
if (looper.segment) {
- if (invoke_selector(INV_SEL(s, looper, doit, kContinueOnInvalidSelector), 2, angle, client)) {
- error("Looper %04x:%04x of avoider %04x:%04x doesn't"
- " have a doit() funcselector", PRINT_REG(looper), PRINT_REG(avoider));
- } else
- return s->r_acc;
+ invokeSelector(s, looper, SELECTOR(doit), argc, argv, 2, params);
+ return s->r_acc;
} else {
// No looper? Fall back to DirLoop
_k_dirloop(client, (uint16)angle, s, argc, argv);
diff --git a/engines/sci/engine/kparse.cpp b/engines/sci/engine/kparse.cpp
index 0254d21642..552e425906 100644
--- a/engines/sci/engine/kparse.cpp
+++ b/engines/sci/engine/kparse.cpp
@@ -31,6 +31,8 @@
#include "sci/engine/message.h"
#include "sci/engine/kernel.h"
+//#define DEBUG_PARSER
+
namespace Sci {
/*************************************************************/
@@ -42,6 +44,7 @@ reg_t kSaid(EngineState *s, int argc, reg_t *argv) {
reg_t heap_said_block = argv[0];
byte *said_block;
int new_lastmatch;
+ Vocabulary *voc = g_sci->getVocabulary();
#ifdef DEBUG_PARSER
const int debug_parser = 1;
#else
@@ -59,11 +62,11 @@ reg_t kSaid(EngineState *s, int argc, reg_t *argv) {
}
#ifdef DEBUG_PARSER
- debugC(2, kDebugLevelParser, "Said block:", 0);
- s->_voc->decipherSaidBlock(said_block);
+ printf("Said block: ");
+ g_sci->getVocabulary()->debugDecipherSaidBlock(said_block);
#endif
- if (s->_voc->parser_event.isNull() || (GET_SEL32V(s->_segMan, s->_voc->parser_event, SELECTOR(claimed)))) {
+ if (voc->parser_event.isNull() || (readSelectorValue(s->_segMan, voc->parser_event, SELECTOR(claimed)))) {
return NULL_REG;
}
@@ -77,7 +80,7 @@ reg_t kSaid(EngineState *s, int argc, reg_t *argv) {
s->r_acc = make_reg(0, 1);
if (new_lastmatch != SAID_PARTIAL_MATCH)
- PUT_SEL32V(s->_segMan, s->_voc->parser_event, SELECTOR(claimed), 1);
+ writeSelectorValue(s->_segMan, voc->parser_event, SELECTOR(claimed), 1);
} else {
return NULL_REG;
@@ -92,20 +95,21 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) {
char *error;
ResultWordList words;
reg_t event = argv[1];
- Vocabulary *voc = s->_voc;
-
- s->_voc->parser_event = event;
+ g_sci->checkVocabularySwitch();
+ Vocabulary *voc = g_sci->getVocabulary();
+ voc->parser_event = event;
+ reg_t params[2] = { voc->parser_base, stringpos };
bool res = voc->tokenizeString(words, string.c_str(), &error);
- s->_voc->parserIsValid = false; /* not valid */
+ voc->parserIsValid = false; /* not valid */
if (res && !words.empty()) {
- s->_voc->synonymizeTokens(words);
+ voc->synonymizeTokens(words);
s->r_acc = make_reg(0, 1);
#ifdef DEBUG_PARSER
- debugC(2, kDebugLevelParser, "Parsed to the following blocks:", 0);
+ debugC(2, kDebugLevelParser, "Parsed to the following blocks:");
for (ResultWordList::const_iterator i = words.begin(); i != words.end(); ++i)
debugC(2, kDebugLevelParser, " Type[%04x] Group[%04x]", i->_class, i->_group);
@@ -115,32 +119,32 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) {
if (syntax_fail) {
s->r_acc = make_reg(0, 1);
- PUT_SEL32V(segMan, event, SELECTOR(claimed), 1);
+ writeSelectorValue(segMan, event, SELECTOR(claimed), 1);
- invoke_selector(INV_SEL(s, s->_gameObj, syntaxFail, kStopOnInvalidSelector), 2, s->_voc->parser_base, stringpos);
+ invokeSelector(s, g_sci->getGameObject(), SELECTOR(syntaxFail), argc, argv, 2, params);
/* Issue warning */
debugC(2, kDebugLevelParser, "Tree building failed");
} else {
- s->_voc->parserIsValid = true;
- PUT_SEL32V(segMan, event, SELECTOR(claimed), 0);
+ voc->parserIsValid = true;
+ writeSelectorValue(segMan, event, SELECTOR(claimed), 0);
#ifdef DEBUG_PARSER
- s->_voc->dumpParseTree();
+ voc->dumpParseTree();
#endif
}
} else {
s->r_acc = make_reg(0, 0);
- PUT_SEL32V(segMan, event, SELECTOR(claimed), 1);
+ writeSelectorValue(segMan, event, SELECTOR(claimed), 1);
if (error) {
- s->_segMan->strcpy(s->_voc->parser_base, error);
+ s->_segMan->strcpy(voc->parser_base, error);
debugC(2, kDebugLevelParser, "Word unknown: %s", error);
/* Issue warning: */
- invoke_selector(INV_SEL(s, s->_gameObj, wordFail, kStopOnInvalidSelector), 2, s->_voc->parser_base, stringpos);
+ invokeSelector(s, g_sci->getGameObject(), SELECTOR(wordFail), argc, argv, 2, params);
free(error);
return make_reg(0, 1); /* Tell them that it didn't work */
}
@@ -156,28 +160,29 @@ reg_t kSetSynonyms(EngineState *s, int argc, reg_t *argv) {
Node *node;
int script;
int numSynonyms = 0;
+ Vocabulary *voc = g_sci->getVocabulary();
// Only SCI0-SCI1 EGA games had a parser. In newer versions, this is a stub
if (getSciVersion() > SCI_VERSION_1_EGA)
return s->r_acc;
- s->_voc->clearSynonyms();
+ voc->clearSynonyms();
- list = s->_segMan->lookupList(GET_SEL32(segMan, object, SELECTOR(elements)));
+ list = s->_segMan->lookupList(readSelector(segMan, object, SELECTOR(elements)));
node = s->_segMan->lookupNode(list->first);
while (node) {
reg_t objpos = node->value;
int seg;
- script = GET_SEL32V(segMan, objpos, SELECTOR(number));
+ script = readSelectorValue(segMan, objpos, SELECTOR(number));
seg = s->_segMan->getScriptSegment(script);
if (seg > 0)
numSynonyms = s->_segMan->getScript(seg)->getSynonymsNr();
if (numSynonyms) {
- byte *synonyms = s->_segMan->getScript(seg)->getSynonyms();
+ const byte *synonyms = s->_segMan->getScript(seg)->getSynonyms();
if (synonyms) {
debugC(2, kDebugLevelParser, "Setting %d synonyms for script.%d",
@@ -193,7 +198,7 @@ reg_t kSetSynonyms(EngineState *s, int argc, reg_t *argv) {
synonym_t tmp;
tmp.replaceant = (int16)READ_LE_UINT16(synonyms + i * 4);
tmp.replacement = (int16)READ_LE_UINT16(synonyms + i * 4 + 2);
- s->_voc->addSynonym(tmp);
+ voc->addSynonym(tmp);
}
} else
warning("Synonyms of script.%03d were requested, but script is not available", script);
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index 25d967c247..07d0a31f0b 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -265,7 +265,8 @@ struct PathfindingState {
static Common::Point read_point(SegManager *segMan, reg_t list, int offset) {
SegmentRef list_r = segMan->dereference(list);
if (!list_r.isValid() || list_r.skipByte) {
- warning("read_point(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(list));
+ // If this happens, then the code below will probably go OOB and crash
+ error("read_point(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(list));
}
Common::Point point;
@@ -337,15 +338,15 @@ static void draw_point(EngineState *s, Common::Point p, int start, int width, in
static void draw_polygon(EngineState *s, reg_t polygon, int width, int height) {
SegManager *segMan = s->_segMan;
- reg_t points = GET_SEL32(segMan, polygon, SELECTOR(points));
+ reg_t points = readSelector(segMan, polygon, SELECTOR(points));
#ifdef ENABLE_SCI32
if (segMan->isHeapObject(points))
- points = GET_SEL32(segMan, points, SELECTOR(data));
+ points = readSelector(segMan, points, SELECTOR(data));
#endif
- int size = GET_SEL32V(segMan, polygon, SELECTOR(size));
- int type = GET_SEL32V(segMan, polygon, SELECTOR(type));
+ int size = readSelectorValue(segMan, polygon, SELECTOR(size));
+ int type = readSelectorValue(segMan, polygon, SELECTOR(type));
Common::Point first, prev;
int i;
@@ -386,15 +387,15 @@ static void draw_input(EngineState *s, reg_t poly_list, Common::Point start, Com
}
static void print_polygon(SegManager *segMan, reg_t polygon) {
- reg_t points = GET_SEL32(segMan, polygon, SELECTOR(points));
+ reg_t points = readSelector(segMan, polygon, SELECTOR(points));
#ifdef ENABLE_SCI32
if (segMan->isHeapObject(points))
- points = GET_SEL32(segMan, points, SELECTOR(data));
+ points = readSelector(segMan, points, SELECTOR(data));
#endif
- int size = GET_SEL32V(segMan, polygon, SELECTOR(size));
- int type = GET_SEL32V(segMan, polygon, SELECTOR(type));
+ int size = readSelectorValue(segMan, polygon, SELECTOR(size));
+ int type = readSelectorValue(segMan, polygon, SELECTOR(type));
int i;
Common::Point point;
@@ -436,33 +437,41 @@ static void print_input(EngineState *s, reg_t poly_list, Common::Point start, Co
}
}
+/**
+ * Computes the area of a triangle
+ * Parameters: (const Common::Point &) a, b, c: The points of the triangle
+ * Returns : (int) The area multiplied by two
+ */
static int area(const Common::Point &a, const Common::Point &b, const Common::Point &c) {
- // Computes the area of a triangle
- // Parameters: (const Common::Point &) a, b, c: The points of the triangle
- // Returns : (int) The area multiplied by two
return (b.x - a.x) * (a.y - c.y) - (c.x - a.x) * (a.y - b.y);
}
+/**
+ * Determines whether or not a point is to the left of a directed line
+ * Parameters: (const Common::Point &) a, b: The directed line (a, b)
+ * (const Common::Point &) c: The query point
+ * Returns : (int) true if c is to the left of (a, b), false otherwise
+ */
static bool left(const Common::Point &a, const Common::Point &b, const Common::Point &c) {
- // Determines whether or not a point is to the left of a directed line
- // Parameters: (const Common::Point &) a, b: The directed line (a, b)
- // (const Common::Point &) c: The query point
- // Returns : (int) true if c is to the left of (a, b), false otherwise
return area(a, b, c) > 0;
}
+/**
+ * Determines whether or not three points are collinear
+ * Parameters: (const Common::Point &) a, b, c: The three points
+ * Returns : (int) true if a, b, and c are collinear, false otherwise
+ */
static bool collinear(const Common::Point &a, const Common::Point &b, const Common::Point &c) {
- // Determines whether or not three points are collinear
- // Parameters: (const Common::Point &) a, b, c: The three points
- // Returns : (int) true if a, b, and c are collinear, false otherwise
return area(a, b, c) == 0;
}
+/**
+ * Determines whether or not a point lies on a line segment
+ * Parameters: (const Common::Point &) a, b: The line segment (a, b)
+ * (const Common::Point &) c: The query point
+ * Returns : (int) true if c lies on (a, b), false otherwise
+ */
static bool between(const Common::Point &a, const Common::Point &b, const Common::Point &c) {
- // Determines whether or not a point lies on a line segment
- // Parameters: (const Common::Point &) a, b: The line segment (a, b)
- // (const Common::Point &) c: The query point
- // Returns : (int) true if c lies on (a, b), false otherwise
if (!collinear(a, b, c))
return false;
@@ -473,25 +482,29 @@ static bool between(const Common::Point &a, const Common::Point &b, const Common
return ((a.y <= c.y) && (c.y <= b.y)) || ((a.y >= c.y) && (c.y >= b.y));
}
+/**
+ * Determines whether or not two line segments properly intersect
+ * Parameters: (const Common::Point &) a, b: The line segment (a, b)
+ * (const Common::Point &) c, d: The line segment (c, d)
+ * Returns : (int) true if (a, b) properly intersects (c, d), false otherwise
+ */
static bool intersect_proper(const Common::Point &a, const Common::Point &b, const Common::Point &c, const Common::Point &d) {
- // Determines whether or not two line segments properly intersect
- // Parameters: (const Common::Point &) a, b: The line segment (a, b)
- // (const Common::Point &) c, d: The line segment (c, d)
- // Returns : (int) true if (a, b) properly intersects (c, d), false otherwise
int ab = (left(a, b, c) && left(b, a, d)) || (left(a, b, d) && left(b, a, c));
int cd = (left(c, d, a) && left(d, c, b)) || (left(c, d, b) && left(d, c, a));
return ab && cd;
}
+/**
+ * Polygon containment test
+ * Parameters: (const Common::Point &) p: The point
+ * (Polygon *) polygon: The polygon
+ * Returns : (int) CONT_INSIDE if p is strictly contained in polygon,
+ * CONT_ON_EDGE if p lies on an edge of polygon,
+ * CONT_OUTSIDE otherwise
+ * Number of ray crossing left and right
+ */
static int contained(const Common::Point &p, Polygon *polygon) {
- // Polygon containment test
- // Parameters: (const Common::Point &) p: The point
- // (Polygon *) polygon: The polygon
- // Returns : (int) CONT_INSIDE if p is strictly contained in polygon,
- // CONT_ON_EDGE if p lies on an edge of polygon,
- // CONT_OUTSIDE otherwise
- // Number of ray crossing left and right
int lcross = 0, rcross = 0;
Vertex *vertex;
@@ -549,10 +562,12 @@ static int contained(const Common::Point &p, Polygon *polygon) {
return CONT_OUTSIDE;
}
+/**
+ * Computes polygon area
+ * Parameters: (Polygon *) polygon: The polygon
+ * Returns : (int) The area multiplied by two
+ */
static int polygon_area(Polygon *polygon) {
- // Computes polygon area
- // Parameters: (Polygon *) polygon: The polygon
- // Returns : (int) The area multiplied by two
Vertex *first = polygon->vertices.first();
Vertex *v;
int size = 0;
@@ -567,11 +582,13 @@ static int polygon_area(Polygon *polygon) {
return size;
}
+/**
+ * Fixes the vertex order of a polygon if incorrect. Contained access
+ * polygons should have their vertices ordered clockwise, all other types
+ * anti-clockwise
+ * Parameters: (Polygon *) polygon: The polygon
+ */
static void fix_vertex_order(Polygon *polygon) {
- // Fixes the vertex order of a polygon if incorrect. Contained access
- // polygons should have their vertices ordered clockwise, all other types
- // anti-clockwise
- // Parameters: (Polygon *) polygon: The polygon
int area = polygon_area(polygon);
// When the polygon area is positive the vertices are ordered
@@ -584,13 +601,15 @@ static void fix_vertex_order(Polygon *polygon) {
}
}
+/**
+ * Determines whether or not a line from a point to a vertex intersects the
+ * interior of the polygon, locally at that vertex
+ * Parameters: (Common::Point) p: The point
+ * (Vertex *) vertex: The vertex
+ * Returns : (int) 1 if the line (p, vertex->v) intersects the interior of
+ * the polygon, locally at the vertex. 0 otherwise
+ */
static int inside(const Common::Point &p, Vertex *vertex) {
- // Determines whether or not a line from a point to a vertex intersects the
- // interior of the polygon, locally at that vertex
- // Parameters: (Common::Point) p: The point
- // (Vertex *) vertex: The vertex
- // Returns : (int) 1 if the line (p, vertex->v) intersects the interior of
- // the polygon, locally at the vertex. 0 otherwise
// Check that it's not a single-vertex polygon
if (VERTEX_HAS_EDGES(vertex)) {
const Common::Point &prev = CLIST_PREV(vertex)->v;
@@ -655,28 +674,34 @@ static VertexList *visible_vertices(PathfindingState *s, Vertex *vertex_cur) {
return visVerts;
}
+/**
+ * Determines if a point lies on the screen border
+ * Parameters: (const Common::Point &) p: The point
+ * Returns : (int) true if p lies on the screen border, false otherwise
+ */
bool PathfindingState::pointOnScreenBorder(const Common::Point &p) {
- // Determines if a point lies on the screen border
- // Parameters: (const Common::Point &) p: The point
- // Returns : (int) true if p lies on the screen border, false otherwise
return (p.x == 0) || (p.x == _width - 1) || (p.y == 0) || (p.y == _height - 1);
}
+/**
+ * Determines if an edge lies on the screen border
+ * Parameters: (const Common::Point &) p, q: The edge (p, q)
+ * Returns : (int) true if (p, q) lies on the screen border, false otherwise
+ */
bool PathfindingState::edgeOnScreenBorder(const Common::Point &p, const Common::Point &q) {
- // Determines if an edge lies on the screen border
- // Parameters: (const Common::Point &) p, q: The edge (p, q)
- // Returns : (int) true if (p, q) lies on the screen border, false otherwise
return ((p.x == 0 && q.x == 0) || (p.y == 0 && q.y == 0)
|| ((p.x == _width - 1) && (q.x == _width - 1))
|| ((p.y == _height - 1) && (q.y == _height - 1)));
}
+/**
+ * Searches for a nearby point that is not contained in a polygon
+ * Parameters: (FloatPoint) f: The pointf to search nearby
+ * (Polygon *) polygon: The polygon
+ * Returns : (int) PF_OK on success, PF_FATAL otherwise
+ * (Common::Point) *ret: The non-contained point on success
+ */
static int find_free_point(FloatPoint f, Polygon *polygon, Common::Point *ret) {
- // Searches for a nearby point that is not contained in a polygon
- // Parameters: (FloatPoint) f: The pointf to search nearby
- // (Polygon *) polygon: The polygon
- // Returns : (int) PF_OK on success, PF_FATAL otherwise
- // (Common::Point) *ret: The non-contained point on success
Common::Point p;
// Try nearest point first
@@ -706,12 +731,14 @@ static int find_free_point(FloatPoint f, Polygon *polygon, Common::Point *ret) {
return PF_OK;
}
+/**
+ * Computes the near point of a point contained in a polygon
+ * Parameters: (const Common::Point &) p: The point
+ * (Polygon *) polygon: The polygon
+ * Returns : (int) PF_OK on success, PF_FATAL otherwise
+ * (Common::Point) *ret: The near point of p in polygon on success
+ */
int PathfindingState::findNearPoint(const Common::Point &p, Polygon *polygon, Common::Point *ret) {
- // Computes the near point of a point contained in a polygon
- // Parameters: (const Common::Point &) p: The point
- // (Polygon *) polygon: The polygon
- // Returns : (int) PF_OK on success, PF_FATAL otherwise
- // (Common::Point) *ret: The near point of p in polygon on success
Vertex *vertex;
FloatPoint near_p;
uint32 dist = HUGE_DISTANCE;
@@ -751,13 +778,15 @@ int PathfindingState::findNearPoint(const Common::Point &p, Polygon *polygon, Co
return find_free_point(near_p, polygon, ret);
}
+/**
+ * Computes the intersection point of a line segment and an edge (not
+ * including the vertices themselves)
+ * Parameters: (const Common::Point &) a, b: The line segment (a, b)
+ * (Vertex *) vertex: The first vertex of the edge
+ * Returns : (int) FP_OK on success, PF_ERROR otherwise
+ * (FloatPoint) *ret: The intersection point
+ */
static int intersection(const Common::Point &a, const Common::Point &b, Vertex *vertex, FloatPoint *ret) {
- // Computes the intersection point of a line segment and an edge (not
- // including the vertices themselves)
- // Parameters: (const Common::Point &) a, b: The line segment (a, b)
- // (Vertex *) vertex: The first vertex of the edge
- // Returns : (int) FP_OK on success, PF_ERROR otherwise
- // (FloatPoint) *ret: The intersection point
// Parameters of parametric equations
float s, t;
// Numerator and denominator of equations
@@ -790,16 +819,18 @@ static int intersection(const Common::Point &a, const Common::Point &b, Vertex *
return PF_ERROR;
}
+/**
+ * Computes the nearest intersection point of a line segment and the polygon
+ * set. Intersection points that are reached from the inside of a polygon
+ * are ignored as are improper intersections which do not obstruct
+ * visibility
+ * Parameters: (PathfindingState *) s: The pathfinding state
+ * (const Common::Point &) p, q: The line segment (p, q)
+ * Returns : (int) PF_OK on success, PF_ERROR when no intersections were
+ * found, PF_FATAL otherwise
+ * (Common::Point) *ret: On success, the closest intersection point
+ */
static int nearest_intersection(PathfindingState *s, const Common::Point &p, const Common::Point &q, Common::Point *ret) {
- // Computes the nearest intersection point of a line segment and the polygon
- // set. Intersection points that are reached from the inside of a polygon
- // are ignored as are improper intersections which do not obstruct
- // visibility
- // Parameters: (PathfindingState *) s: The pathfinding state
- // (const Common::Point &) p, q: The line segment (p, q)
- // Returns : (int) PF_OK on success, PF_ERROR when no intersections were
- // found, PF_FATAL otherwise
- // (Common::Point) *ret: On success, the closest intersection point
Polygon *polygon = 0;
FloatPoint isec;
Polygon *ipolygon = 0;
@@ -903,9 +934,11 @@ static Common::Point *fixup_start_point(PathfindingState *s, const Common::Point
case POLY_NEAREST_ACCESS:
if (cont == CONT_INSIDE) {
if (s->_prependPoint != NULL) {
- // We shouldn't get here twice
+ // We shouldn't get here twice.
+ // We need to break in this case, otherwise we'll end in an infinite
+ // loop.
warning("AvoidPath: start point is contained in multiple polygons");
- continue;
+ break;
}
if (s->findNearPoint(start, (*it), new_start) != PF_OK) {
@@ -914,7 +947,7 @@ static Common::Point *fixup_start_point(PathfindingState *s, const Common::Point
}
if ((type == POLY_BARRED_ACCESS) || (type == POLY_CONTAINED_ACCESS))
- warning("AvoidPath: start position at unreachable location");
+ debugC(2, kDebugLevelAvoidPath, "AvoidPath: start position at unreachable location");
// The original start position is in an invalid location, so we
// use the moved point and add the original one to the final path
@@ -957,9 +990,14 @@ static Common::Point *fixup_end_point(PathfindingState *s, const Common::Point &
case POLY_NEAREST_ACCESS:
if (cont != CONT_OUTSIDE) {
if (s->_appendPoint != NULL) {
- // We shouldn't get here twice
+ // We shouldn't get here twice.
+ // Happens in LB2CD, inside the speakeasy when walking from the
+ // speakeasy (room 310) into the bathroom (room 320), after having
+ // consulted the notebook (bug #3036299).
+ // We need to break in this case, otherwise we'll end in an infinite
+ // loop.
warning("AvoidPath: end point is contained in multiple polygons");
- continue;
+ break;
}
// The original end position is in an invalid location, so we move the point
@@ -981,14 +1019,16 @@ static Common::Point *fixup_end_point(PathfindingState *s, const Common::Point &
return new_end;
}
+/**
+ * Merges a point into the polygon set. A new vertex is allocated for this
+ * point, unless a matching vertex already exists. If the point is on an
+ * already existing edge that edge is split up into two edges connected by
+ * the new vertex
+ * Parameters: (PathfindingState *) s: The pathfinding state
+ * (const Common::Point &) v: The point to merge
+ * Returns : (Vertex *) The vertex corresponding to v
+ */
static Vertex *merge_point(PathfindingState *s, const Common::Point &v) {
- // Merges a point into the polygon set. A new vertex is allocated for this
- // point, unless a matching vertex already exists. If the point is on an
- // already existing edge that edge is split up into two edges connected by
- // the new vertex
- // Parameters: (PathfindingState *) s: The pathfinding state
- // (const Common::Point &) v: The point to merge
- // Returns : (Vertex *) The vertex corresponding to v
Vertex *vertex;
Vertex *v_new;
Polygon *polygon;
@@ -1029,20 +1069,22 @@ static Vertex *merge_point(PathfindingState *s, const Common::Point &v) {
return v_new;
}
+/**
+ * Converts an SCI polygon into a Polygon
+ * Parameters: (EngineState *) s: The game state
+ * (reg_t) polygon: The SCI polygon to convert
+ * Returns : (Polygon *) The converted polygon, or NULL on error
+ */
static Polygon *convert_polygon(EngineState *s, reg_t polygon) {
- // Converts an SCI polygon into a Polygon
- // Parameters: (EngineState *) s: The game state
- // (reg_t) polygon: The SCI polygon to convert
- // Returns : (Polygon *) The converted polygon, or NULL on error
SegManager *segMan = s->_segMan;
int i;
- reg_t points = GET_SEL32(segMan, polygon, SELECTOR(points));
- int size = GET_SEL32V(segMan, polygon, SELECTOR(size));
+ reg_t points = readSelector(segMan, polygon, SELECTOR(points));
+ int size = readSelectorValue(segMan, polygon, SELECTOR(size));
#ifdef ENABLE_SCI32
// SCI32 stores the actual points in the data property of points (in a new array)
if (segMan->isHeapObject(points))
- points = GET_SEL32(segMan, points, SELECTOR(data));
+ points = readSelector(segMan, points, SELECTOR(data));
#endif
if (size == 0) {
@@ -1050,13 +1092,13 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) {
return NULL;
}
- Polygon *poly = new Polygon(GET_SEL32V(segMan, polygon, SELECTOR(type)));
+ Polygon *poly = new Polygon(readSelectorValue(segMan, polygon, SELECTOR(type)));
int skip = 0;
// WORKAROUND: broken polygon in lsl1sci, room 350, after opening elevator
// Polygon has 17 points but size is set to 19
- if ((size == 19) && (s->_gameId == "lsl1sci")) {
+ if ((size == 19) && g_sci->getGameId() == GID_LSL1) {
if ((s->currentRoomNumber() == 350)
&& (read_point(segMan, points, 18) == Common::Point(108, 137))) {
debug(1, "Applying fix for broken polygon in lsl1sci, room 350");
@@ -1074,11 +1116,13 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) {
return poly;
}
+/**
+ * Changes the polygon list for optimization level 0 (used for keyboard
+ * support). Totally accessible polygons are removed and near-point
+ * accessible polygons are changed into totally accessible polygons.
+ * Parameters: (PathfindingState *) s: The pathfinding state
+ */
static void change_polygons_opt_0(PathfindingState *s) {
- // Changes the polygon list for optimization level 0 (used for keyboard
- // support). Totally accessible polygons are removed and near-point
- // accessible polygons are changed into totally accessible polygons.
- // Parameters: (PathfindingState *) s: The pathfinding state
PolygonList::iterator it = s->polygons.begin();
while (it != s->polygons.end()) {
@@ -1096,15 +1140,17 @@ static void change_polygons_opt_0(PathfindingState *s) {
}
}
+/**
+ * Converts the SCI input data for pathfinding
+ * Parameters: (EngineState *) s: The game state
+ * (reg_t) poly_list: Polygon list
+ * (Common::Point) start: The start point
+ * (Common::Point) end: The end point
+ * (int) opt: Optimization level (0, 1 or 2)
+ * Returns : (PathfindingState *) On success a newly allocated pathfinding state,
+ * NULL otherwise
+ */
static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Common::Point start, Common::Point end, int width, int height, int opt) {
- // Converts the SCI input data for pathfinding
- // Parameters: (EngineState *) s: The game state
- // (reg_t) poly_list: Polygon list
- // (Common::Point) start: The start point
- // (Common::Point) end: The end point
- // (int) opt: Optimization level (0, 1 or 2)
- // Returns : (PathfindingState *) On success a newly allocated pathfinding state,
- // NULL otherwise
SegManager *segMan = s->_segMan;
Polygon *polygon;
int err;
@@ -1121,7 +1167,7 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co
if (polygon) {
pf_s->polygons.push_back(polygon);
- count += GET_SEL32V(segMan, node->value, SELECTOR(size));
+ count += readSelectorValue(segMan, node->value, SELECTOR(size));
}
node = s->_segMan->lookupNode(node->succ);
@@ -1174,7 +1220,7 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co
// WORKAROUND LSL5 room 660. Priority glitch due to us choosing a different path
// than SSCI. Happens when Patti walks to the control room.
- if ((s->_gameId == "lsl5") && (s->currentRoomNumber() == 660) && (Common::Point(67, 131) == *new_start) && (Common::Point(229, 101) == *new_end)) {
+ if (g_sci->getGameId() == GID_LSL5 && (s->currentRoomNumber() == 660) && (Common::Point(67, 131) == *new_start) && (Common::Point(229, 101) == *new_end)) {
debug(1, "[avoidpath] Applying fix for priority problem in LSL5, room 660");
pf_s->_prependPoint = new_start;
new_start = new Common::Point(77, 107);
@@ -1277,7 +1323,7 @@ static void AStar(PathfindingState *s) {
}
if (openSet.empty())
- warning("[avoidpath] End point (%i, %i) is unreachable", s->vertex_end->v.x, s->vertex_end->v.y);
+ debugC(2, kDebugLevelAvoidPath, "AvoidPath: End point (%i, %i) is unreachable", s->vertex_end->v.x, s->vertex_end->v.y);
}
static reg_t allocateOutputArray(SegManager *segMan, int size) {
@@ -1297,11 +1343,13 @@ static reg_t allocateOutputArray(SegManager *segMan, int size) {
return addr;
}
+/**
+ * Stores the final path in newly allocated dynmem
+ * Parameters: (PathfindingState *) p: The pathfinding state
+ * (EngineState *) s: The game state
+ * Returns : (reg_t) Pointer to dynmem containing path
+ */
static reg_t output_path(PathfindingState *p, EngineState *s) {
- // Stores the final path in newly allocated dynmem
- // Parameters: (PathfindingState *) p: The pathfinding state
- // (EngineState *) s: The game state
- // Returns : (reg_t) Pointer to dynmem containing path
int path_len = 0;
reg_t output;
Vertex *vertex = p->vertex_end;
@@ -1394,7 +1442,7 @@ reg_t kAvoidPath(EngineState *s, int argc, reg_t *argv) {
if (argc < 7)
error("[avoidpath] Not enough arguments");
- poly_list = (!argv[4].isNull() ? GET_SEL32(s->_segMan, argv[4], SELECTOR(elements)) : NULL_REG);
+ poly_list = (!argv[4].isNull() ? readSelector(s->_segMan, argv[4], SELECTOR(elements)) : NULL_REG);
width = argv[5].toUint16();
height = argv[6].toUint16();
if (argc > 7)
@@ -1694,4 +1742,49 @@ reg_t kIntersections(EngineState *s, int argc, reg_t *argv) {
}
}
+/**
+ * This is a quite rare kernel function. An example of when it's called
+ * is in QFG1VGA, after killing any monster.
+ */
+reg_t kMergePoly(EngineState *s, int argc, reg_t *argv) {
+#if 0
+ // 3 parameters: raw polygon data, polygon list, list size
+ reg_t polygonData = argv[0];
+ List *list = s->_segMan->lookupList(argv[1]);
+ Node *node = s->_segMan->lookupNode(list->first);
+ // List size is not needed
+
+ Polygon *polygon;
+ int count = 0;
+
+ while (node) {
+ polygon = convert_polygon(s, node->value);
+
+ if (polygon) {
+ count += readSelectorValue(s->_segMan, node->value, SELECTOR(size));
+ }
+
+ node = s->_segMan->lookupNode(node->succ);
+ }
+#endif
+
+ // TODO: actually merge the polygon. We return an empty polygon for now.
+ // In QFG1VGA, you can walk over enemy bodies after killing them, since
+ // this is a stub.
+ reg_t output = allocateOutputArray(s->_segMan, 1);
+ SegmentRef arrayRef = s->_segMan->dereference(output);
+ writePoint(arrayRef, 0, Common::Point(POLY_LAST_POINT, POLY_LAST_POINT));
+ warning("Stub: kMergePoly");
+ return output;
+}
+
+#ifdef ENABLE_SCI32
+
+reg_t kInPolygon(EngineState *s, int argc, reg_t *argv) {
+ // kAvoidPath already implements this
+ return kAvoidPath(s, argc, argv);
+}
+
+#endif
+
} // End of namespace Sci
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index ba29f64966..a5501c160f 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -25,16 +25,20 @@
#include "sci/sci.h"
#include "sci/resource.h"
+#include "sci/engine/seg_manager.h"
+#include "sci/engine/script.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
#include "sci/engine/kernel.h"
+#include "common/file.h"
+
namespace Sci {
// Loads arbitrary resources of type 'restype' with resource numbers 'resnrs'
// This implementation ignores all resource numbers except the first one.
reg_t kLoad(EngineState *s, int argc, reg_t *argv) {
- int restype = argv[0].toUint16();
+ ResourceType restype = g_sci->getResMan()->convertResType(argv[0].toUint16());
int resnr = argv[1].toUint16();
// Request to dynamically allocate hunk memory for later use
@@ -44,9 +48,32 @@ reg_t kLoad(EngineState *s, int argc, reg_t *argv) {
return make_reg(0, ((restype << 11) | resnr)); // Return the resource identifier as handle
}
+// Unloads an arbitrary resource of type 'restype' with resource numbber 'resnr'
+// behaviour of this call didn't change between sci0->sci1.1 parameter wise, which means getting called with
+// 1 or 3+ parameters is not right according to sierra sci
+reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) {
+ if (argc >= 2) {
+ ResourceType restype = g_sci->getResMan()->convertResType(argv[0].toUint16());
+ reg_t resnr = argv[1];
+
+ // WORKAROUND for a broken script in room 320 in Castle of Dr. Brain.
+ // Script 377 tries to free the hunk memory allocated for the saved area
+ // (underbits) beneath the pop up window, which results in having the
+ // window stay on screen even when it's closed. Ignore this request here.
+ if (restype == kResourceTypeMemory && g_sci->getGameId() == GID_CASTLEBRAIN &&
+ s->currentRoomNumber() == 320)
+ return s->r_acc;
+
+ if (restype == kResourceTypeMemory)
+ s->_segMan->freeHunkEntry(resnr);
+ }
+
+ return s->r_acc;
+}
+
reg_t kLock(EngineState *s, int argc, reg_t *argv) {
int state = argc > 2 ? argv[2].toUint16() : 1;
- ResourceType type = (ResourceType)(argv[0].toUint16() & 0x7f);
+ ResourceType type = g_sci->getResMan()->convertResType(argv[0].toUint16());
ResourceId id = ResourceId(type, argv[1].toUint16());
Resource *which;
@@ -56,42 +83,48 @@ reg_t kLock(EngineState *s, int argc, reg_t *argv) {
g_sci->getResMan()->findResource(id, 1);
break;
case 0 :
- which = g_sci->getResMan()->findResource(id, 0);
-
- if (which)
- g_sci->getResMan()->unlockResource(which);
- else {
- if (id.type == kResourceTypeInvalid)
- warning("[resMan] Attempt to unlock resource %i of invalid type %i", id.number, type);
- else
- warning("[resMan] Attempt to unlock non-existant resource %s", id.toString().c_str());
+ if (id.getNumber() == 0xFFFF) {
+ // Unlock all resources of the requested type
+ Common::List<ResourceId> *resources = g_sci->getResMan()->listResources(type);
+ Common::List<ResourceId>::iterator itr = resources->begin();
+
+ while (itr != resources->end()) {
+ Resource *res = g_sci->getResMan()->testResource(*itr);
+ if (res->isLocked())
+ g_sci->getResMan()->unlockResource(res);
+ ++itr;
+ }
+
+ delete resources;
+ } else {
+ which = g_sci->getResMan()->findResource(id, 0);
+
+ if (which)
+ g_sci->getResMan()->unlockResource(which);
+ else {
+ if (id.getType() == kResourceTypeInvalid)
+ warning("[resMan] Attempt to unlock resource %i of invalid type %i", id.getNumber(), type);
+ else
+ // Happens in CD games (e.g. LSL6CD) with the message
+ // resource. It isn't fatal, and it's usually caused
+ // by leftover scripts.
+ debugC(2, kDebugLevelResMan, "[resMan] Attempt to unlock non-existant resource %s", id.toString().c_str());
+ }
}
break;
}
return s->r_acc;
}
-// Unloads an arbitrary resource of type 'restype' with resource numbber 'resnr'
-reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) {
- if (argc >= 2) {
- int restype = argv[0].toUint16();
- reg_t resnr = argv[1];
-
- if (restype == kResourceTypeMemory)
- s->_segMan->freeHunkEntry(resnr);
-
- if (argc > 2)
- warning("kUnload called with more than 2 parameters (%d)", argc);
- } else {
- warning("kUnload called with less than 2 parameters (%d) - ignoring", argc);
- }
-
- return s->r_acc;
-}
-
reg_t kResCheck(EngineState *s, int argc, reg_t *argv) {
Resource *res = NULL;
- ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f);
+ ResourceType restype = g_sci->getResMan()->convertResType(argv[0].toUint16());
+
+ if (restype == kResourceTypeVMD) {
+ char fileName[10];
+ sprintf(fileName, "%d.vmd", argv[1].toUint16());
+ return make_reg(0, Common::File::exists(fileName));
+ }
if ((restype == kResourceTypeAudio36) || (restype == kResourceTypeSync36)) {
if (argc >= 6) {
@@ -111,7 +144,7 @@ reg_t kResCheck(EngineState *s, int argc, reg_t *argv) {
reg_t kClone(EngineState *s, int argc, reg_t *argv) {
reg_t parent_addr = argv[0];
- Object *parent_obj = s->_segMan->getObject(parent_addr);
+ const Object *parent_obj = s->_segMan->getObject(parent_addr);
reg_t clone_addr;
Clone *clone_obj; // same as Object*
@@ -132,7 +165,7 @@ reg_t kClone(EngineState *s, int argc, reg_t *argv) {
*clone_obj = *parent_obj;
// Mark as clone
- clone_obj->setInfoSelector(make_reg(0, SCRIPT_INFO_CLONE));
+ clone_obj->markAsClone();
clone_obj->setSpeciesSelector(clone_obj->getPos());
if (parent_obj->isClass())
clone_obj->setSuperClassSelector(parent_obj->getPos());
@@ -154,25 +187,11 @@ reg_t kDisposeClone(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
- if (victim_obj->getInfoSelector().offset != SCRIPT_INFO_CLONE) {
- //warning("Attempt to dispose something other than a clone at %04x", offset);
+ if (!victim_obj->isClone()) {
// SCI silently ignores this behaviour; some games actually depend on it
return s->r_acc;
}
- // QFG3 clears clones with underbits set
- //if (GET_SEL32V(victim_addr, underBits))
- // warning("Clone %04x:%04x was cleared with underBits set", PRINT_REG(victim_addr));
-
-#if 0
- if (s->dyn_views) { // Free any widget associated with the clone
- GfxWidget *widget = gfxw_set_id(gfxw_remove_ID(s->dyn_views, offset), GFXW_NO_ID);
-
- if (widget && s->bg_widgets)
- s->bg_widgets->add(GFXWC(s->bg_widgets), widget);
- }
-#endif
-
victim_obj->markAsFreed();
return s->r_acc;
@@ -181,7 +200,7 @@ reg_t kDisposeClone(EngineState *s, int argc, reg_t *argv) {
// Returns script dispatch address index in the supplied script
reg_t kScriptID(EngineState *s, int argc, reg_t *argv) {
int script = argv[0].toUint16();
- int index = (argc > 1) ? argv[1].toUint16() : 0;
+ uint16 index = (argc > 1) ? argv[1].toUint16() : 0;
if (argv[0].segment)
return argv[0];
@@ -193,27 +212,36 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) {
Script *scr = s->_segMan->getScript(scriptSeg);
- if (!scr->_numExports) {
- // FIXME: Is this fatal? This occurs in SQ4CD
- warning("Script 0x%x does not have a dispatch table", script);
+ if (!scr->getExportsNr()) {
+ // This is normal. Some scripts don't have a dispatch (exports) table,
+ // and this call is probably used to load them in memory, ignoring
+ // the return value. If only one argument is passed, this call is done
+ // only to load the script in memory. Thus, don't show any warning,
+ // as no return value is expected. If an export is requested, then
+ // it will most certainly fail with OOB access.
+ if (argc == 2)
+ error("Script 0x%x does not have a dispatch table and export %d "
+ "was requested from it", script, index);
return NULL_REG;
}
- if (index > scr->_numExports) {
- error("Dispatch index too big: %d > %d", index, scr->_numExports);
+ if (index > scr->getExportsNr()) {
+ error("Dispatch index too big: %d > %d", index, scr->getExportsNr());
return NULL_REG;
}
- return make_reg(scriptSeg, scr->validateExportFunc(index));
+ uint16 address = scr->validateExportFunc(index);
+
+ // Point to the heap for SCI1.1+ games
+ if (getSciVersion() >= SCI_VERSION_1_1)
+ address += scr->getScriptSize();
+
+ return make_reg(scriptSeg, address);
}
reg_t kDisposeScript(EngineState *s, int argc, reg_t *argv) {
int script = argv[0].offset;
- // Work around QfG1 graveyard bug
- if (argv[0].segment)
- return s->r_acc;
-
SegmentId id = s->_segMan->getScriptSegment(script);
Script *scr = s->_segMan->getScriptIfLoaded(id);
if (scr) {
@@ -221,13 +249,13 @@ reg_t kDisposeScript(EngineState *s, int argc, reg_t *argv) {
scr->setLockers(1);
}
- script_uninstantiate(s->_segMan, script);
+ s->_segMan->uninstantiateScript(script);
if (argc != 2) {
return s->r_acc;
} else {
- // This exists in the KQ5CD and GK1 interpreter. We know it is used when GK1 starts
- // up, before the Sierra logo.
+ // This exists in the KQ5CD and GK1 interpreter. We know it is used
+ // when GK1 starts up, before the Sierra logo.
warning("kDisposeScript called with 2 parameters, still untested");
return argv[1];
}
@@ -244,7 +272,7 @@ reg_t kRespondsTo(EngineState *s, int argc, reg_t *argv) {
reg_t obj = argv[0];
int selector = argv[1].toUint16();
- return make_reg(0, s->_segMan->isHeapObject(obj) && lookup_selector(s->_segMan, obj, selector, NULL, NULL) != kSelectorNone);
+ return make_reg(0, s->_segMan->isHeapObject(obj) && lookupSelector(s->_segMan, obj, selector, NULL, NULL) != kSelectorNone);
}
} // End of namespace Sci
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index 367a89005c..2f00cd7da2 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -39,12 +39,39 @@ namespace Sci {
* Used for synthesized music playback
*/
reg_t kDoSound(EngineState *s, int argc, reg_t *argv) {
- return s->_soundCmd->parseCommand(argc, argv, s->r_acc);
+ if (!s)
+ return make_reg(0, g_sci->_features->detectDoSoundType());
+ error("not supposed to call this");
}
+#define CREATE_DOSOUND_FORWARD(_name_) reg_t k##_name_(EngineState *s, int argc, reg_t *argv) { return g_sci->_soundCmd->k##_name_(argc, argv, s->r_acc); }
+
+CREATE_DOSOUND_FORWARD(DoSoundInit)
+CREATE_DOSOUND_FORWARD(DoSoundPlay)
+CREATE_DOSOUND_FORWARD(DoSoundRestore)
+CREATE_DOSOUND_FORWARD(DoSoundDispose)
+CREATE_DOSOUND_FORWARD(DoSoundMute)
+CREATE_DOSOUND_FORWARD(DoSoundStop)
+CREATE_DOSOUND_FORWARD(DoSoundStopAll)
+CREATE_DOSOUND_FORWARD(DoSoundPause)
+CREATE_DOSOUND_FORWARD(DoSoundResumeAfterRestore)
+CREATE_DOSOUND_FORWARD(DoSoundMasterVolume)
+CREATE_DOSOUND_FORWARD(DoSoundUpdate)
+CREATE_DOSOUND_FORWARD(DoSoundFade)
+CREATE_DOSOUND_FORWARD(DoSoundGetPolyphony)
+CREATE_DOSOUND_FORWARD(DoSoundUpdateCues)
+CREATE_DOSOUND_FORWARD(DoSoundSendMidi)
+CREATE_DOSOUND_FORWARD(DoSoundReverb)
+CREATE_DOSOUND_FORWARD(DoSoundSetHold)
+CREATE_DOSOUND_FORWARD(DoSoundDummy)
+CREATE_DOSOUND_FORWARD(DoSoundGetAudioCapability)
+CREATE_DOSOUND_FORWARD(DoSoundSuspend)
+CREATE_DOSOUND_FORWARD(DoSoundSetVolume)
+CREATE_DOSOUND_FORWARD(DoSoundSetPriority)
+CREATE_DOSOUND_FORWARD(DoSoundSetLoop)
+
reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
- case kSciAudioWPlay:
case kSciAudioPlay: {
if (argc < 2)
return NULL_REG;
@@ -72,6 +99,7 @@ reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) {
break;
case kSciAudioPosition:
return make_reg(0, g_sci->_audio->audioCdPosition());
+ case kSciAudioWPlay: // CD Audio can't be preloaded
case kSciAudioRate: // No need to set the audio rate
case kSciAudioVolume: // The speech setting isn't used by CD Audio
case kSciAudioLanguage: // No need to set the language
@@ -80,7 +108,7 @@ reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) {
// Init
return make_reg(0, 1);
default:
- warning("kCdDoAudio: Unhandled case %d", argv[0].toUint16());
+ error("kCdDoAudio: Unhandled case %d", argv[0].toUint16());
}
return s->r_acc;
@@ -110,8 +138,10 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) {
number = argv[1].toUint16();
} else if (argc == 6 || argc == 8) {
module = argv[1].toUint16();
- number = ((argv[2].toUint16() & 0xff) << 24) | ((argv[3].toUint16() & 0xff) << 16) |
- ((argv[4].toUint16() & 0xff) << 8) | (argv[5].toUint16() & 0xff);
+ number = ((argv[2].toUint16() & 0xff) << 24) |
+ ((argv[3].toUint16() & 0xff) << 16) |
+ ((argv[4].toUint16() & 0xff) << 8) |
+ (argv[5].toUint16() & 0xff);
if (argc == 8)
warning("kDoAudio: Play called with SQ6 extra parameters");
} else {
@@ -119,46 +149,92 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) {
return NULL_REG;
}
- return make_reg(0, g_sci->_audio->startAudio(module, number)); // return sample length in ticks
+ debugC(2, kDebugLevelSound, "kDoAudio: play sample %d, module %d", number, module);
+
+ // return sample length in ticks
+ if (argv[0].toUint16() == kSciAudioWPlay)
+ return make_reg(0, g_sci->_audio->wPlayAudio(module, number));
+ else
+ return make_reg(0, g_sci->_audio->startAudio(module, number));
}
case kSciAudioStop:
+ debugC(2, kDebugLevelSound, "kDoAudio: stop");
g_sci->_audio->stopAudio();
break;
case kSciAudioPause:
+ debugC(2, kDebugLevelSound, "kDoAudio: pause");
g_sci->_audio->pauseAudio();
break;
case kSciAudioResume:
+ debugC(2, kDebugLevelSound, "kDoAudio: resume");
g_sci->_audio->resumeAudio();
break;
case kSciAudioPosition:
+ //debugC(2, kDebugLevelSound, "kDoAudio: get position"); // too verbose
return make_reg(0, g_sci->_audio->getAudioPosition());
case kSciAudioRate:
+ debugC(2, kDebugLevelSound, "kDoAudio: set audio rate to %d", argv[1].toUint16());
g_sci->_audio->setAudioRate(argv[1].toUint16());
break;
case kSciAudioVolume: {
int16 volume = argv[1].toUint16();
volume = CLIP<int16>(volume, 0, AUDIO_VOLUME_MAX);
+ debugC(2, kDebugLevelSound, "kDoAudio: set volume to %d", volume);
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2_1) {
+ int16 volumePrev = mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 2;
+ volumePrev = CLIP<int16>(volumePrev, 0, AUDIO_VOLUME_MAX);
+ mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume * 2);
+ return make_reg(0, volumePrev);
+ } else
+#endif
mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume * 2);
- break;
}
case kSciAudioLanguage:
// In SCI1.1: tests for digital audio support
- if (getSciVersion() == SCI_VERSION_1_1)
+ if (getSciVersion() == SCI_VERSION_1_1) {
+ debugC(2, kDebugLevelSound, "kDoAudio: audio capability test");
return make_reg(0, 1);
- else {
+ } else {
int16 language = argv[1].toSint16();
+ debugC(2, kDebugLevelSound, "kDoAudio: set language to %d", language);
if (language != -1)
g_sci->getResMan()->setAudioLanguage(language);
- return make_reg(0, g_sci->getSciLanguage());
+ kLanguage kLang = g_sci->getSciLanguage();
+ g_sci->setSciLanguage(kLang);
+
+ return make_reg(0, kLang);
}
break;
case kSciAudioCD:
- return kDoCdAudio(s, argc - 1, argv + 1);
- // TODO: There are 3 more functions used in Freddy Pharkas (11, 12 and 13) and new within sierra sci
- // Details currently unknown
- // kDoAudio sits at seg026:038C
+
+ if (getSciVersion() <= SCI_VERSION_1_1) {
+ debugC(2, kDebugLevelSound, "kDoAudio: CD audio subop");
+ return kDoCdAudio(s, argc - 1, argv + 1);
+#ifdef ENABLE_SCI32
+ } else {
+ // TODO: This isn't CD Audio in SCI32 anymore
+ warning("kDoAudio: Unhandled case 10, %d extra arguments passed", argc - 1);
+ break;
+#endif
+ }
+
+ // 3 new subops in Pharkas. kDoAudio in Pharkas sits at seg026:038C
+ case 11:
+ // Not sure where this is used yet
+ warning("kDoAudio: Unhandled case 11, %d extra arguments passed", argc - 1);
+ break;
+ case 12:
+ // Seems to be some sort of audio sync, used in Pharkas. Silenced the
+ // warning due to the high level of spam it produces. (takes no params)
+ //warning("kDoAudio: Unhandled case 12, %d extra arguments passed", argc - 1);
+ break;
+ case 13:
+ // Used in Pharkas whenever a speech sample starts (takes no params)
+ //warning("kDoAudio: Unhandled case 13, %d extra arguments passed", argc - 1);
+ break;
default:
warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1);
}
@@ -195,7 +271,7 @@ reg_t kDoSync(EngineState *s, int argc, reg_t *argv) {
g_sci->_audio->stopSoundSync();
break;
default:
- warning("DoSync: Unhandled subfunction %d", argv[0].toUint16());
+ error("DoSync: Unhandled subfunction %d", argv[0].toUint16());
}
return s->r_acc;
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 426c682e11..9254bce9c1 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -115,12 +115,14 @@ reg_t kStrAt(EngineState *s, int argc, reg_t *argv) {
if (argc > 2) { /* Request to modify this char */
tmp.offset &= 0xff00;
tmp.offset |= newvalue;
+ tmp.segment = 0;
}
} else {
value = tmp.offset >> 8;
if (argc > 2) { /* Request to modify this char */
tmp.offset &= 0x00ff;
tmp.offset |= newvalue << 8;
+ tmp.segment = 0;
}
}
}
@@ -138,10 +140,39 @@ reg_t kReadNumber(EngineState *s, int argc, reg_t *argv) {
while (isspace((unsigned char)*source))
source++; /* Skip whitespace */
- if (*source == '$') /* SCI uses this for hex numbers */
- return make_reg(0, (int16)strtol(source + 1, NULL, 16)); /* Hex */
- else
- return make_reg(0, (int16)strtol(source, NULL, 10)); /* Force decimal */
+ int16 result = 0;
+
+ if (*source == '$') {
+ // Hexadecimal input
+ result = (int16)strtol(source + 1, NULL, 16);
+ } else {
+ // Decimal input. We can not use strtol/atoi in here, because while
+ // Sierra used atoi, it was a non standard compliant atoi, that didn't
+ // do clipping. In SQ4 we get the door code in here and that's even
+ // larger than uint32!
+ if (*source == '-') {
+ result = -1;
+ source++;
+ }
+ while (*source) {
+ if ((*source < '0') || (*source > '9')) {
+ // Sierra's atoi stopped processing at anything which is not
+ // a digit. Sometimes the input has a trailing space, that's
+ // fine (example: lsl3)
+ if (*source != ' ') {
+ // TODO: this happens in lsl5 right in the intro -> we get '1' '3' 0xCD 0xCD 0xCD 0xCD 0xCD
+ // find out why this happens and fix it
+ warning("Invalid character in kReadNumber input");
+ }
+ break;
+ }
+ result *= 10;
+ result += *source - 0x30;
+ source++;
+ }
+ }
+
+ return make_reg(0, result);
}
@@ -241,7 +272,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
#ifdef ENABLE_SCI32
// If the string is a string object, get to the actual string in the data selector
if (s->_segMan->isObject(reg))
- reg = GET_SEL32(s->_segMan, reg, SELECTOR(data));
+ reg = readSelector(s->_segMan, reg, SELECTOR(data));
#endif
Common::String tempsource = (reg == NULL_REG) ? "" : g_sci->getKernel()->lookupText(reg,
@@ -397,15 +428,16 @@ reg_t kGetFarText(EngineState *s, int argc, reg_t *argv) {
seeker = (char *)textres->data;
- // The second parameter (counter) determines the number of the string inside the text
- // resource.
+ // The second parameter (counter) determines the number of the string
+ // inside the text resource.
while (counter--) {
while (*seeker++)
;
}
- // If the third argument is NULL, allocate memory for the destination. This occurs in
- // SCI1 Mac games. The memory will later be freed by the game's scripts.
+ // If the third argument is NULL, allocate memory for the destination. This
+ // occurs in SCI1 Mac games. The memory will later be freed by the game's
+ // scripts.
if (argv[2] == NULL_REG)
s->_segMan->allocDynmem(strlen(seeker) + 1, "Mac FarText", &argv[2]);
@@ -534,8 +566,8 @@ reg_t kMessage(EngineState *s, int argc, reg_t *argv) {
}
reg_t kSetQuitStr(EngineState *s, int argc, reg_t *argv) {
- Common::String quitStr = s->_segMan->getString(argv[0]);
- debug("Setting quit string to '%s'", quitStr.c_str());
+ //Common::String quitStr = s->_segMan->getString(argv[0]);
+ //debug("Setting quit string to '%s'", quitStr.c_str());
return s->r_acc;
}
@@ -552,11 +584,201 @@ reg_t kStrSplit(EngineState *s, int argc, reg_t *argv) {
// Make sure target buffer is large enough
SegmentRef buf_r = s->_segMan->dereference(argv[0]);
if (!buf_r.isValid() || buf_r.maxSize < (int)str.size() + 1) {
- warning("StrSplit: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(argv[0]), str.size() + 1, str.c_str());
+ warning("StrSplit: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'",
+ PRINT_REG(argv[0]), str.size() + 1, str.c_str());
return NULL_REG;
}
s->_segMan->strcpy(argv[0], str.c_str());
return argv[0];
}
+#ifdef ENABLE_SCI32
+
+reg_t kText(EngineState *s, int argc, reg_t *argv) {
+ switch (argv[0].toUint16()) {
+ case 0:
+ return kTextSize(s, argc - 1, argv + 1);
+ default:
+ // TODO: Other subops here too, perhaps kTextColors and kTextFonts
+ warning("kText(%d)", argv[0].toUint16());
+ break;
+ }
+
+ return s->r_acc;
+}
+
+reg_t kString(EngineState *s, int argc, reg_t *argv) {
+ switch (argv[0].toUint16()) {
+ case 0: { // New
+ reg_t stringHandle;
+ SciString *string = s->_segMan->allocateString(&stringHandle);
+ string->setSize(argv[1].toUint16());
+
+ // Make sure the first character is a null character
+ if (string->getSize() > 0)
+ string->setValue(0, 0);
+
+ return stringHandle;
+ }
+ case 1: // Size
+ return make_reg(0, s->_segMan->getString(argv[1]).size());
+ case 2: { // At (return value at an index)
+ if (argv[1].segment == s->_segMan->getStringSegmentId())
+ return make_reg(0, s->_segMan->lookupString(argv[1])->getRawData()[argv[2].toUint16()]);
+
+ return make_reg(0, s->_segMan->getString(argv[1])[argv[2].toUint16()]);
+ }
+ case 3: { // Atput (put value at an index)
+ SciString *string = s->_segMan->lookupString(argv[1]);
+
+ uint32 index = argv[2].toUint16();
+ uint32 count = argc - 3;
+
+ if (index + count > 65535)
+ break;
+
+ if (string->getSize() < index + count)
+ string->setSize(index + count);
+
+ for (uint16 i = 0; i < count; i++)
+ string->setValue(i + index, argv[i + 3].toUint16());
+
+ return argv[1]; // We also have to return the handle
+ }
+ case 4: // Free
+ // Freeing of strings is handled by the garbage collector
+ return s->r_acc;
+ case 5: { // Fill
+ SciString *string = s->_segMan->lookupString(argv[1]);
+ uint16 index = argv[2].toUint16();
+
+ // A count of -1 means fill the rest of the array
+ uint16 count = argv[3].toSint16() == -1 ? string->getSize() - index : argv[3].toUint16();
+ uint16 stringSize = string->getSize();
+
+ if (stringSize < index + count)
+ string->setSize(index + count);
+
+ for (uint16 i = 0; i < count; i++)
+ string->setValue(i + index, argv[4].toUint16());
+
+ return argv[1];
+ }
+ case 6: { // Cpy
+ const char *string2 = 0;
+ uint32 string2Size = 0;
+
+ if (argv[3].segment == s->_segMan->getStringSegmentId()) {
+ SciString *string = s->_segMan->lookupString(argv[3]);
+ string2 = string->getRawData();
+ string2Size = string->getSize();
+ } else {
+ Common::String string = s->_segMan->getString(argv[3]);
+ string2 = string.c_str();
+ string2Size = string.size() + 1;
+ }
+
+ uint32 index1 = argv[2].toUint16();
+ uint32 index2 = argv[4].toUint16();
+
+ // The original engine ignores bad copies too
+ if (index2 > string2Size)
+ break;
+
+ // A count of -1 means fill the rest of the array
+ uint32 count = argv[5].toSint16() == -1 ? string2Size - index2 + 1 : argv[5].toUint16();
+
+ // We have a special case here for argv[1] being a system string
+ if (argv[1].segment == s->_segMan->getSysStringsSegment()) {
+ // Resize if necessary
+ const uint16 sysStringId = argv[1].toUint16();
+ SystemString *sysString = s->_segMan->getSystemString(sysStringId);
+ assert(sysString);
+ if ((uint32)sysString->_maxSize < index1 + count) {
+ free(sysString->_value);
+ sysString->_maxSize = index1 + count;
+ sysString->_value = (char *)calloc(index1 + count, sizeof(char));
+ }
+
+ strncpy(sysString->_value + index1, string2 + index2, count);
+ } else {
+ SciString *string1 = s->_segMan->lookupString(argv[1]);
+
+ if (string1->getSize() < index1 + count)
+ string1->setSize(index1 + count);
+
+ // Note: We're accessing from c_str() here because the
+ // string's size ignores the trailing 0 and therefore
+ // triggers an assert when doing string2[i + index2].
+ for (uint16 i = 0; i < count; i++)
+ string1->setValue(i + index1, string2[i + index2]);
+ }
+
+ } return argv[1];
+ case 7: { // Cmp
+ Common::String string1 = argv[1].isNull() ? "" : s->_segMan->getString(argv[1]);
+ Common::String string2 = argv[2].isNull() ? "" : s->_segMan->getString(argv[2]);
+
+ if (argc == 4) // Strncmp
+ return make_reg(0, strncmp(string1.c_str(), string2.c_str(), argv[3].toUint16()));
+ else // Strcmp
+ return make_reg(0, strcmp(string1.c_str(), string2.c_str()));
+ }
+ case 8: { // Dup
+ const char *rawString = 0;
+ uint32 size = 0;
+
+ if (argv[1].segment == s->_segMan->getStringSegmentId()) {
+ SciString *string = s->_segMan->lookupString(argv[1]);
+ rawString = string->getRawData();
+ size = string->getSize();
+ } else {
+ Common::String string = s->_segMan->getString(argv[1]);
+ rawString = string.c_str();
+ size = string.size() + 1;
+ }
+
+ reg_t stringHandle;
+ SciString *dupString = s->_segMan->allocateString(&stringHandle);
+ dupString->setSize(size);
+
+ for (uint32 i = 0; i < size; i++)
+ dupString->setValue(i, rawString[i]);
+
+ return stringHandle;
+ }
+ case 9: // Getdata
+ if (!s->_segMan->isHeapObject(argv[1]))
+ return argv[1];
+
+ return readSelector(s->_segMan, argv[1], SELECTOR(data));
+ case 10: // Stringlen
+ return make_reg(0, s->_segMan->strlen(argv[1]));
+ case 11: { // Printf
+ reg_t stringHandle;
+ s->_segMan->allocateString(&stringHandle);
+
+ reg_t *adjustedArgs = new reg_t[argc];
+ adjustedArgs[0] = stringHandle;
+ memcpy(&adjustedArgs[1], argv + 1, (argc - 1) * sizeof(reg_t));
+
+ kFormat(s, argc, adjustedArgs);
+ delete[] adjustedArgs;
+ return stringHandle;
+ }
+ case 12: // Printf Buf
+ return kFormat(s, argc - 1, argv + 1);
+ case 13: { // atoi
+ Common::String string = s->_segMan->getString(argv[1]);
+ return make_reg(0, (uint16)atoi(string.c_str()));
+ }
+ default:
+ error("Unknown kString subop %d", argv[0].toUint16());
+ }
+
+ return NULL_REG;
+}
+
+#endif
+
} // End of namespace Sci
diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
new file mode 100644
index 0000000000..ac6cfb6835
--- /dev/null
+++ b/engines/sci/engine/kvideo.cpp
@@ -0,0 +1,306 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "engines/util.h"
+#include "sci/engine/state.h"
+#include "sci/graphics/helpers.h"
+#include "sci/graphics/cursor.h"
+#include "sci/graphics/palette.h"
+#include "sci/graphics/screen.h"
+#include "graphics/cursorman.h"
+#include "graphics/video/avi_decoder.h"
+#include "graphics/video/qt_decoder.h"
+#include "sci/video/seq_decoder.h"
+#ifdef ENABLE_SCI32
+#include "graphics/video/coktel_decoder.h"
+#endif
+
+namespace Sci {
+
+void playVideo(Graphics::VideoDecoder *videoDecoder) {
+ if (!videoDecoder)
+ return;
+
+ byte *scaleBuffer = 0;
+ uint16 width = videoDecoder->getWidth();
+ uint16 height = videoDecoder->getHeight();
+ uint16 screenWidth = g_system->getWidth();
+ uint16 screenHeight = g_system->getHeight();
+
+ if (screenWidth == 640 && width <= 320 && height <= 240) {
+ assert(videoDecoder->getPixelFormat().bytesPerPixel == 1);
+ width *= 2;
+ height *= 2;
+ scaleBuffer = new byte[width * height];
+ }
+
+ uint16 x = (screenWidth - width) / 2;
+ uint16 y = (screenHeight - height) / 2;
+ bool skipVideo = false;
+
+ if (videoDecoder->hasDirtyPalette())
+ videoDecoder->setSystemPalette();
+
+ while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) {
+ if (videoDecoder->needsUpdate()) {
+ Graphics::Surface *frame = videoDecoder->decodeNextFrame();
+ if (frame) {
+ if (scaleBuffer) {
+ // TODO: Probably should do aspect ratio correction in e.g. GK1 Windows
+ g_sci->_gfxScreen->scale2x((byte *)frame->pixels, scaleBuffer, videoDecoder->getWidth(), videoDecoder->getHeight());
+ g_system->copyRectToScreen(scaleBuffer, width, x, y, width, height);
+ } else
+ g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, width, height);
+
+ if (videoDecoder->hasDirtyPalette())
+ videoDecoder->setSystemPalette();
+
+ g_system->updateScreen();
+ }
+ }
+
+ Common::Event event;
+ while (g_system->getEventManager()->pollEvent(event)) {
+ if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
+ skipVideo = true;
+ }
+
+ g_system->delayMillis(10);
+ }
+
+ delete[] scaleBuffer;
+ delete videoDecoder;
+}
+
+reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
+ // Hide the cursor if it's showing and then show it again if it was
+ // previously visible.
+ bool reshowCursor = g_sci->_gfxCursor->isVisible();
+ if (reshowCursor)
+ g_sci->_gfxCursor->kernelHide();
+
+ uint16 screenWidth = g_system->getWidth();
+ uint16 screenHeight = g_system->getHeight();
+
+ Graphics::VideoDecoder *videoDecoder = 0;
+
+ if (argv[0].segment != 0) {
+ Common::String filename = s->_segMan->getString(argv[0]);
+
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh) {
+ // Mac QuickTime
+ // The only argument is the string for the video
+
+ // HACK: Switch to 16bpp graphics for Cinepak.
+ initGraphics(screenWidth, screenHeight, screenWidth > 320, NULL);
+
+ if (g_system->getScreenFormat().bytesPerPixel == 1) {
+ error("This video requires >8bpp color to be displayed, but could not switch to RGB color mode.");
+ return NULL_REG;
+ }
+
+ videoDecoder = new Graphics::QuickTimeDecoder();
+ if (!videoDecoder->loadFile(filename))
+ error("Could not open '%s'", filename.c_str());
+ } else {
+ // DOS SEQ
+ // SEQ's are called with no subops, just the string and delay
+ SeqDecoder *seqDecoder = new SeqDecoder();
+ seqDecoder->setFrameDelay(argv[1].toUint16()); // Time between frames in ticks
+ videoDecoder = seqDecoder;
+
+ if (!videoDecoder->loadFile(filename)) {
+ warning("Failed to open movie file %s", filename.c_str());
+ delete videoDecoder;
+ videoDecoder = 0;
+ }
+ }
+ } else {
+ // Windows AVI
+ // TODO: This appears to be some sort of subop. case 0 contains the string
+ // for the video, so we'll just play it from there for now.
+
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2_1) {
+ // SCI2.1 always has argv[0] as 1, the rest of the arguments seem to
+ // follow SCI1.1/2.
+ if (argv[0].toUint16() != 1)
+ error("SCI2.1 kShowMovie argv[0] not 1");
+ argv++;
+ argc--;
+ }
+#endif
+ switch (argv[0].toUint16()) {
+ case 0: {
+ Common::String filename = s->_segMan->getString(argv[1]);
+ videoDecoder = new Graphics::AviDecoder(g_system->getMixer());
+
+ if (!videoDecoder->loadFile(filename.c_str())) {
+ warning("Failed to open movie file %s", filename.c_str());
+ delete videoDecoder;
+ videoDecoder = 0;
+ }
+ break;
+ }
+ default:
+ warning("Unhandled SCI kShowMovie subop %d", argv[1].toUint16());
+ }
+ }
+
+ if (videoDecoder) {
+ playVideo(videoDecoder);
+
+ // HACK: Switch back to 8bpp if we played a QuickTime video.
+ // We also won't be copying the screen to the SCI screen...
+ if (g_system->getScreenFormat().bytesPerPixel != 1)
+ initGraphics(screenWidth, screenHeight, screenWidth > 320);
+ else {
+ g_sci->_gfxScreen->kernelSyncWithFramebuffer();
+ g_sci->_gfxPalette->kernelSyncScreenPalette();
+ }
+ }
+
+ if (reshowCursor)
+ g_sci->_gfxCursor->kernelShow();
+
+ return s->r_acc;
+}
+
+#ifdef ENABLE_SCI32
+
+reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) {
+ uint16 operation = argv[0].toUint16();
+ Graphics::VideoDecoder *videoDecoder = 0;
+ bool reshowCursor = g_sci->_gfxCursor->isVisible();
+ Common::String fileName, warningMsg;
+
+ switch (operation) {
+ case 0: // init
+ // This is actually meant to init the video file, but we play it instead
+ fileName = s->_segMan->derefString(argv[1]);
+ // TODO: argv[2] (usually null). When it exists, it points to an "Event" object,
+ // that holds no data initially (e.g. in the intro of Phantasmagoria 1 demo).
+ // Perhaps it's meant for syncing
+ if (argv[2] != NULL_REG)
+ warning("kPlayVMD: third parameter isn't 0 (it's %04x:%04x - %s)", PRINT_REG(argv[2]), s->_segMan->getObjectName(argv[2]));
+
+ videoDecoder = new Graphics::VMDDecoder(g_system->getMixer());
+
+ if (!videoDecoder->loadFile(fileName)) {
+ warning("Could not open VMD %s", fileName.c_str());
+ break;
+ }
+
+ if (reshowCursor)
+ g_sci->_gfxCursor->kernelHide();
+
+ playVideo(videoDecoder);
+
+ if (reshowCursor)
+ g_sci->_gfxCursor->kernelShow();
+ break;
+ case 1:
+ {
+ // Set VMD parameters. Called with a maximum of 6 parameters:
+ //
+ // x, y, flags, gammaBoost, gammaFirst, gammaLast
+ //
+ // Flags are as follows:
+ // bit 0 doubled
+ // bit 1 "drop frames"?
+ // bit 2 insert black lines
+ // bit 3 unknown
+ // bit 4 gamma correction
+ // bit 5 hold black frame
+ // bit 6 hold last frame
+ // bit 7 unknown
+ // bit 8 stretch
+
+ // gammaBoost boosts palette colors in the range gammaFirst to
+ // gammaLast, but only if bit 4 in flags is set. Percent value such that
+ // 0% = no amplification These three parameters are optional if bit 4 is
+ // clear. Also note that the x, y parameters play subtle games if used
+ // with subfx 21. The subtleness has to do with creation of temporary
+ // planes and positioning relative to such planes.
+
+ int flags = argv[3].offset;
+ Common::String flagspec;
+
+ if (argc > 3) {
+ if (flags & 1)
+ flagspec += "doubled ";
+ if (flags & 2)
+ flagspec += "dropframes ";
+ if (flags & 4)
+ flagspec += "blacklines ";
+ if (flags & 8)
+ flagspec += "bit3 ";
+ if (flags & 16)
+ flagspec += "gammaboost ";
+ if (flags & 32)
+ flagspec += "holdblack ";
+ if (flags & 64)
+ flagspec += "holdlast ";
+ if (flags & 128)
+ flagspec += "bit7 ";
+ if (flags & 256)
+ flagspec += "stretch";
+
+ warning("VMDFlags: %s", flagspec.c_str());
+ }
+
+ warning("x, y: %d, %d", argv[1].offset, argv[2].offset);
+
+ if (argc > 4 && flags & 16)
+ warning("gammaBoost: %d%% between palette entries %d and %d", argv[4].offset, argv[5].offset, argv[6].offset);
+ break;
+ }
+ case 6:
+ // Play, perhaps? Or stop? This is the last call made, and takes no extra parameters
+ case 14:
+ // Takes an additional integer parameter (e.g. 3)
+ case 16:
+ // Takes an additional parameter, usually 0
+ case 21:
+ // Looks to be setting the video size and position. Called with 4 extra integer
+ // parameters (e.g. 86, 41, 235, 106)
+ default:
+ warningMsg = Common::String::printf("PlayVMD - unsupported subop %d. Params: %d (", operation, argc);
+
+ for (int i = 0; i < argc; i++) {
+ warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i]));
+ warningMsg += (i == argc - 1 ? ")" : ", ");
+ }
+
+ warning("%s", warningMsg.c_str());
+ break;
+ }
+
+ return s->r_acc;
+}
+
+#endif
+
+} // End of namespace Sci
diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp
index 07f8792471..6e1b326c4f 100644
--- a/engines/sci/engine/message.cpp
+++ b/engines/sci/engine/message.cpp
@@ -161,11 +161,13 @@ bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &re
reader = new MessageReaderV4(res->data, res->size);
break;
default:
- warning("Message: unsupported resource version %d", version);
+ error("Message: unsupported resource version %d", version);
return false;
}
if (!reader->init()) {
+ delete reader;
+
warning("Message: failed to read resource header");
return false;
}
@@ -180,6 +182,7 @@ bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &re
continue;
}
+ delete reader;
return false;
}
@@ -193,6 +196,7 @@ bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &re
}
}
+ delete reader;
return true;
}
}
@@ -259,7 +263,7 @@ void MessageState::popCursorStack() {
if (!_cursorStackStack.empty())
_cursorStack = _cursorStackStack.pop();
else
- warning("Message: attempt to pop from empty stack");
+ error("Message: attempt to pop from empty stack");
}
int MessageState::hexDigitToInt(char h) {
@@ -330,7 +334,8 @@ bool MessageState::stringStage(Common::String &outstr, const Common::String &inS
}
// If we find a lowercase character or a digit, it's not a stage direction
- if (((inStr[i] >= 'a') && (inStr[i] <= 'z')) || ((inStr[i] >= '0') && (inStr[i] <= '9')))
+ // SCI32 seems to support having digits in stage directions
+ if (((inStr[i] >= 'a') && (inStr[i] <= 'z')) || ((inStr[i] >= '0') && (inStr[i] <= '9') && (getSciVersion() < SCI_VERSION_2)))
return false;
}
@@ -379,7 +384,14 @@ void MessageState::outputString(reg_t buf, const Common::String &str) {
if ((unsigned)buffer_r.maxSize >= str.size() + 1) {
_segMan->strcpy(buf, str.c_str());
} else {
- warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(buf), str.size() + 1, str.c_str());
+ // LSL6 sets an exit text here, but the buffer size allocated
+ // is too small. Don't display a warning in this case, as we
+ // don't use the exit text anyway - bug report #3035533
+ if (g_sci->getGameId() == GID_LSL6 && str.hasPrefix("\r\n(c) 1993 Sierra On-Line, Inc")) {
+ // LSL6 buggy exit text, don't show warning
+ } else {
+ warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(buf), str.size() + 1, str.c_str());
+ }
// Set buffer to empty string if possible
if (buffer_r.maxSize > 0)
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index fef2b9a19e..dfc41cc56a 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -33,24 +33,19 @@
#include "sci/event.h"
#include "sci/engine/features.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/message.h"
#include "sci/engine/savegame.h"
+#include "sci/engine/selector.h"
#include "sci/engine/vm_types.h"
#include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS
-#include "sci/graphics/gui.h"
+#include "sci/graphics/palette.h"
#include "sci/graphics/ports.h"
#include "sci/sound/audio.h"
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-#include "sci/sound/iterator/core.h"
-#include "sci/sound/iterator/iterator.h"
-#else
#include "sci/sound/music.h"
-#endif
-#ifdef ENABLE_SCI32
-#include "sci/graphics/gui32.h"
-#endif
+#include "gui/message.h"
namespace Sci {
@@ -58,106 +53,8 @@ namespace Sci {
#define VER(x) Common::Serializer::Version(x)
-// OBSOLETE: This const is used for backward compatibility only.
-const uint32 INTMAPPER_MAGIC_KEY = 0xDEADBEEF;
-
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-// from ksound.cpp:
-SongIterator *build_iterator(ResourceManager *resMan, int song_nr, SongIteratorType type, songit_id_t id);
-#endif
-
-
#pragma mark -
-// TODO: Many of the following sync_*() methods should be turned into member funcs
-// of the classes they are syncing.
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-static void sync_songlib(Common::Serializer &s, SongLibrary &obj);
-#endif
-
-static void sync_reg_t(Common::Serializer &s, reg_t &obj) {
- s.syncAsUint16LE(obj.segment);
- s.syncAsUint16LE(obj.offset);
-}
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-static void syncSong(Common::Serializer &s, Song &obj) {
- s.syncAsSint32LE(obj._handle);
- s.syncAsSint32LE(obj._resourceNum);
- s.syncAsSint32LE(obj._priority);
- s.syncAsSint32LE(obj._status);
- s.syncAsSint32LE(obj._restoreBehavior);
- s.syncAsSint32LE(obj._restoreTime);
- s.syncAsSint32LE(obj._loops);
- s.syncAsSint32LE(obj._hold);
-
- if (s.isLoading()) {
- obj._it = 0;
- obj._delay = 0;
- obj._next = 0;
- obj._nextPlaying = 0;
- obj._nextStopping = 0;
- }
-}
-#else
-
-#define DEFROBNICATE_HANDLE(handle) (make_reg((handle >> 16) & 0xffff, handle & 0xffff))
-
-void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) {
- if (s.getVersion() < 14) {
- // Old sound system data. This data is only loaded, never saved (as we're never
- // saving in the older version format)
- uint32 handle = 0;
- s.syncAsSint32LE(handle);
- soundObj = DEFROBNICATE_HANDLE(handle);
- s.syncAsSint32LE(resourceId);
- s.syncAsSint32LE(priority);
- s.syncAsSint32LE(status);
- s.skip(4); // restoreBehavior
- uint32 restoreTime = 0;
- s.syncAsSint32LE(restoreTime);
- ticker = restoreTime * 60 / 1000;
- s.syncAsSint32LE(loop);
- s.syncAsSint32LE(hold);
- // volume and dataInc will be synced from the sound objects
- // when the sound list is reconstructed in gamestate_restore()
- volume = MUSIC_VOLUME_MAX;
- dataInc = 0;
- // No fading info
- fadeTo = 0;
- fadeStep = 0;
- fadeTicker = 0;
- fadeTickerStep = 0;
- } else {
- // A bit more optimized saving
- sync_reg_t(s, soundObj);
- s.syncAsSint16LE(resourceId);
- s.syncAsSint16LE(dataInc);
- s.syncAsSint16LE(ticker);
- s.syncAsSint16LE(signal, VER(17));
- s.syncAsByte(priority);
- s.syncAsSint16LE(loop, VER(17));
- s.syncAsByte(volume);
- s.syncAsByte(hold, VER(17));
- s.syncAsByte(fadeTo);
- s.syncAsSint16LE(fadeStep);
- s.syncAsSint32LE(fadeTicker);
- s.syncAsSint32LE(fadeTickerStep);
- s.syncAsByte(status);
- }
-
- // pMidiParser and pStreamAud will be initialized when the
- // sound list is reconstructed in gamestate_restore()
- if (s.isLoading()) {
- soundRes = 0;
- pMidiParser = 0;
- pStreamAud = 0;
- }
-}
-#endif
-
// Experimental hack: Use syncWithSerializer to sync. By default, this assume
// the object to be synced is a subclass of Serializable and thus tries to invoke
// the saveLoadWithSerializer() method. But it is possible to specialize this
@@ -217,31 +114,19 @@ void syncArray(Common::Serializer &s, Common::Array<T> &arr) {
template <>
void syncWithSerializer(Common::Serializer &s, reg_t &obj) {
- sync_reg_t(s, obj);
+ s.syncAsUint16LE(obj.segment);
+ s.syncAsUint16LE(obj.offset);
}
void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
- s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be reserved_id
- s.skip(4, VER(9), VER(18)); // OBSOLETE: Used to be _exportsAreWide
- s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be gc_mark_bits
+ if (s.isLoading())
+ resetSegMan();
+
+ s.skip(4, VER(14), VER(18)); // OBSOLETE: Used to be _exportsAreWide
if (s.isLoading()) {
// Reset _scriptSegMap, to be restored below
_scriptSegMap.clear();
-
- if (s.getVersion() <= 9) {
- // OBSOLETE: Skip over the old id_seg_map when loading (we now
- // regenerate the equivalent data, in _scriptSegMap, from scratch).
-
- s.skip(4); // base_value
- while (true) {
- uint32 key = 0;
- s.syncAsSint32LE(key);
- if (key == INTMAPPER_MAGIC_KEY)
- break;
- s.skip(4); // idx
- }
- }
}
@@ -257,57 +142,38 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
// If we were saving and mobj == 0, or if we are loading and this is an
// entry marked as empty -> skip to next
- if (type == SEG_TYPE_INVALID) {
+ if (type == SEG_TYPE_INVALID)
continue;
- }
-
- s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be _segManagerId
// Don't save or load HunkTable segments
- if (type == SEG_TYPE_HUNK) {
+ if (type == SEG_TYPE_HUNK)
continue;
- }
- // Handle the OBSOLETE type SEG_TYPE_STRING_FRAG -- just ignore it
- if (s.isLoading() && type == SEG_TYPE_STRING_FRAG) {
- continue;
- }
-
-
- if (s.isLoading()) {
+ if (s.isLoading())
mobj = SegmentObj::createSegmentObj(type);
- }
+
assert(mobj);
// Let the object sync custom data
mobj->saveLoadWithSerializer(s);
// If we are loading a script, hook it up in the script->segment map.
- if (s.isLoading() && type == SEG_TYPE_SCRIPT) {
- _scriptSegMap[((Script *)mobj)->_nr] = i;
- }
+ if (s.isLoading() && type == SEG_TYPE_SCRIPT)
+ _scriptSegMap[((Script *)mobj)->getScriptNumber()] = i;
}
- s.syncAsSint32LE(Clones_seg_id);
- s.syncAsSint32LE(Lists_seg_id);
- s.syncAsSint32LE(Nodes_seg_id);
-}
-
-static void sync_SegManagerPtr(Common::Serializer &s, SegManager *&obj) {
- s.skip(1, VER(9), VER(9)); // obsolete: used to be a flag indicating if we got sci11 or not
+ s.syncAsSint32LE(_clonesSegId);
+ s.syncAsSint32LE(_listsSegId);
+ s.syncAsSint32LE(_nodesSegId);
- if (s.isLoading())
- obj->resetSegMan();
-
- obj->saveLoadWithSerializer(s);
+ syncArray<Class>(s, _classTable);
}
-
template <>
void syncWithSerializer(Common::Serializer &s, Class &obj) {
s.syncAsSint32LE(obj.script);
- sync_reg_t(s, obj.reg);
+ syncWithSerializer(s, obj.reg);
}
static void sync_SavegameMetadata(Common::Serializer &s, SavegameMetadata &obj) {
@@ -318,60 +184,29 @@ static void sync_SavegameMetadata(Common::Serializer &s, SavegameMetadata &obj)
s.syncVersion(CURRENT_SAVEGAME_VERSION);
obj.savegame_version = s.getVersion();
s.syncString(obj.game_version);
- s.skip(4, VER(9), VER(9)); // obsolete: used to be game version
s.syncAsSint32LE(obj.savegame_date);
s.syncAsSint32LE(obj.savegame_time);
+ if (s.getVersion() < 22) {
+ obj.game_object_offset = 0;
+ obj.script0_size = 0;
+ } else {
+ s.syncAsUint16LE(obj.game_object_offset);
+ s.syncAsUint16LE(obj.script0_size);
+ }
}
void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
- s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be savegame_version
-
Common::String tmp;
- s.syncString(tmp); // OBSOLETE: Used to be game_version
- s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be version
-
- // OBSOLETE: Saved menus. Skip all of the saved data
- if (s.getVersion() < 14) {
- int totalMenus = 0;
- s.syncAsUint32LE(totalMenus);
-
- // Now iterate through the obsolete saved menu data
- for (int i = 0; i < totalMenus; i++) {
- s.syncString(tmp); // OBSOLETE: Used to be _title
- s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be _titleWidth
- s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be _width
-
- int menuLength = 0;
- s.syncAsUint32LE(menuLength);
-
- for (int j = 0; j < menuLength; j++) {
- s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be _type
- s.syncString(tmp); // OBSOLETE: Used to be _keytext
- s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be keytext_size
-
- s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be _flags
- s.skip(64, VER(12), VER(12)); // OBSOLETE: Used to be MENU_SAID_SPEC_SIZE
- s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be _saidPos
- s.syncString(tmp); // OBSOLETE: Used to be _text
- s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be _textPos
- s.skip(4 * 4, VER(12), VER(12)); // OBSOLETE: Used to be _modifiers, _key, _enabled and _tag
- }
- }
- }
-
- s.skip(4, VER(12), VER(12)); // obsolete: used to be status_bar_foreground
- s.skip(4, VER(12), VER(12)); // obsolete: used to be status_bar_background
+ s.syncString(tmp, VER(14), VER(23)); // OBSOLETE: Used to be game_version
- if (s.getVersion() >= 13 && g_sci->_gui) {
- // Save/Load picPort as well (cause sierra sci also does this)
+ if (getSciVersion() <= SCI_VERSION_1_1) {
+ // Save/Load picPort as well for SCI0-SCI1.1. Necessary for Castle of Dr. Brain,
+ // as the picPort has been changed when loading during the intro
int16 picPortTop, picPortLeft;
Common::Rect picPortRect;
- if (s.isSaving()) {
- // FIXME: _gfxPorts is 0 when using SCI32 code
- assert(g_sci->_gfxPorts);
+ if (s.isSaving())
picPortRect = g_sci->_gfxPorts->kernelGetPicWindow(picPortTop, picPortLeft);
- }
s.syncAsSint16LE(picPortRect.top);
s.syncAsSint16LE(picPortRect.left);
@@ -379,17 +214,15 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint16LE(picPortRect.right);
s.syncAsSint16LE(picPortTop);
s.syncAsSint16LE(picPortLeft);
- }
- sync_SegManagerPtr(s, _segMan);
+ if (s.isLoading())
+ g_sci->_gfxPorts->kernelSetPicWindow(picPortRect, picPortTop, picPortLeft, false);
+ }
- syncArray<Class>(s, _segMan->_classtable);
+ _segMan->saveLoadWithSerializer(s);
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- sync_songlib(s, _sound._songlib);
-#else
- _soundCmd->syncPlayList(s);
-#endif
+ g_sci->_soundCmd->syncPlayList(s);
+ g_sci->_gfxPalette->saveLoadWithSerializer(s);
}
void LocalVariables::saveLoadWithSerializer(Common::Serializer &s) {
@@ -400,8 +233,7 @@ void LocalVariables::saveLoadWithSerializer(Common::Serializer &s) {
void Object::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint32LE(_flags);
- sync_reg_t(s, _pos);
- s.skip(4, VER(9), VER(12)); // OBSOLETE: Used to be variable_names_nr
+ syncWithSerializer(s, _pos);
s.syncAsSint32LE(_methodCount); // that's actually a uint16
syncArray<reg_t>(s, _variables);
@@ -418,18 +250,18 @@ template <>
void syncWithSerializer(Common::Serializer &s, Table<List>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
- sync_reg_t(s, obj.first);
- sync_reg_t(s, obj.last);
+ syncWithSerializer(s, obj.first);
+ syncWithSerializer(s, obj.last);
}
template <>
void syncWithSerializer(Common::Serializer &s, Table<Node>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
- sync_reg_t(s, obj.pred);
- sync_reg_t(s, obj.succ);
- sync_reg_t(s, obj.key);
- sync_reg_t(s, obj.value);
+ syncWithSerializer(s, obj.pred);
+ syncWithSerializer(s, obj.succ);
+ syncWithSerializer(s, obj.key);
+ syncWithSerializer(s, obj.value);
}
#ifdef ENABLE_SCI32
@@ -463,7 +295,7 @@ void syncWithSerializer(Common::Serializer &s, Table<SciArray<reg_t> >::Entry &o
if (s.isSaving())
value = obj.getValue(i);
- sync_reg_t(s, value);
+ syncWithSerializer(s, value);
if (s.isLoading())
obj.setValue(i, value);
@@ -524,25 +356,15 @@ void HunkTable::saveLoadWithSerializer(Common::Serializer &s) {
void Script::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint32LE(_nr);
- s.syncAsUint32LE(_bufSize);
- s.syncAsUint32LE(_scriptSize);
- s.syncAsUint32LE(_heapSize);
-
- if (s.getVersion() <= 10) {
- assert((s.isLoading()));
- // OBSOLETE: Skip over the old _objIndices data when loading
- s.skip(4); // base_value
- while (true) {
- uint32 key = 0;
- s.syncAsSint32LE(key);
- if (key == INTMAPPER_MAGIC_KEY)
- break;
- s.skip(4); // idx
- }
- }
- s.syncAsSint32LE(_numExports);
- s.syncAsSint32LE(_numSynonyms);
+ if (s.isLoading())
+ init(_nr, g_sci->getResMan());
+ s.skip(4, VER(14), VER(22)); // OBSOLETE: Used to be _bufSize
+ s.skip(4, VER(14), VER(22)); // OBSOLETE: Used to be _scriptSize
+ s.skip(4, VER(14), VER(22)); // OBSOLETE: Used to be _heapSize
+
+ s.skip(4, VER(14), VER(19)); // OBSOLETE: Used to be _numExports
+ s.skip(4, VER(14), VER(19)); // OBSOLETE: Used to be _numSynonyms
s.syncAsSint32LE(_lockers);
// Sync _objects. This is a hashmap, and we use the following on disk format:
@@ -559,18 +381,18 @@ void Script::saveLoadWithSerializer(Common::Serializer &s) {
_objects.clear();
Object tmp;
for (uint i = 0; i < numObjs; ++i) {
- syncWithSerializer<Object>(s, tmp);
+ syncWithSerializer(s, tmp);
_objects[tmp.getPos().offset] = tmp;
}
} else {
ObjMap::iterator it;
const ObjMap::iterator end = _objects.end();
for (it = _objects.begin(); it != end; ++it) {
- syncWithSerializer<Object>(s, it->_value);
+ syncWithSerializer(s, it->_value);
}
}
- s.syncAsSint32LE(_localsOffset);
+ s.skip(4, VER(14), VER(20)); // OBSOLETE: Used to be _localsOffset
s.syncAsSint32LE(_localsSegment);
s.syncAsSint32LE(_markedAsDeleted);
@@ -615,37 +437,13 @@ void DynMem::saveLoadWithSerializer(Common::Serializer &s) {
void DataStack::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsUint32LE(_capacity);
if (s.isLoading()) {
- //free(entries);
+ free(_entries);
_entries = (reg_t *)calloc(_capacity, sizeof(reg_t));
}
}
#pragma mark -
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-static void sync_songlib(Common::Serializer &s, SongLibrary &obj) {
- int songcount = 0;
- if (s.isSaving())
- songcount = obj.countSongs();
- s.syncAsUint32LE(songcount);
-
- if (s.isLoading()) {
- obj._lib = 0;
- while (songcount--) {
- Song *newsong = new Song;
- syncSong(s, *newsong);
- obj.addSong(newsong);
- }
- } else {
- Song *seeker = obj._lib;
- while (seeker) {
- seeker->_restoreTime = seeker->_it->getTimepos();
- syncSong(s, *seeker);
- seeker = seeker->_next;
- }
- }
-}
-#else
void SciMusic::saveLoadWithSerializer(Common::Serializer &s) {
// Sync song lib data. When loading, the actual song lib will be initialized
// afterwards in gamestate_restore()
@@ -694,7 +492,52 @@ void SciMusic::saveLoadWithSerializer(Common::Serializer &s) {
}
}
}
-#endif
+
+void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) {
+ syncWithSerializer(s, soundObj);
+ s.syncAsSint16LE(resourceId);
+ s.syncAsSint16LE(dataInc);
+ s.syncAsSint16LE(ticker);
+ s.syncAsSint16LE(signal, VER(17));
+ s.syncAsByte(priority);
+ s.syncAsSint16LE(loop, VER(17));
+ s.syncAsByte(volume);
+ s.syncAsByte(hold, VER(17));
+ s.syncAsByte(fadeTo);
+ s.syncAsSint16LE(fadeStep);
+ s.syncAsSint32LE(fadeTicker);
+ s.syncAsSint32LE(fadeTickerStep);
+ s.syncAsByte(status);
+
+ // pMidiParser and pStreamAud will be initialized when the
+ // sound list is reconstructed in gamestate_restore()
+ if (s.isLoading()) {
+ soundRes = 0;
+ pMidiParser = 0;
+ pStreamAud = 0;
+ }
+}
+
+void SoundCommandParser::syncPlayList(Common::Serializer &s) {
+ _music->saveLoadWithSerializer(s);
+}
+
+void SoundCommandParser::reconstructPlayList(int savegame_version) {
+ Common::StackLock lock(_music->_mutex);
+
+ const MusicList::iterator end = _music->getPlayListEnd();
+ for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) {
+ if ((*i)->resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, (*i)->resourceId))) {
+ (*i)->soundRes = new SoundResource((*i)->resourceId, _resMan, _soundVersion);
+ _music->soundInitSnd(*i);
+ } else {
+ (*i)->soundRes = 0;
+ }
+ if ((*i)->status == kSoundPlaying) {
+ processPlaySound((*i)->soundObj);
+ }
+ }
+}
#ifdef ENABLE_SCI32
void ArrayTable::saveLoadWithSerializer(Common::Serializer &ser) {
@@ -712,211 +555,153 @@ void StringTable::saveLoadWithSerializer(Common::Serializer &ser) {
}
#endif
-#pragma mark -
-
-
-int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename, const char *version) {
- TimeDate curTime;
- g_system->getTimeAndDate(curTime);
-
- SavegameMetadata meta;
- meta.savegame_version = CURRENT_SAVEGAME_VERSION;
- meta.savegame_name = savename;
- meta.game_version = version;
- meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF);
- meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF);
-
- if (s->execution_stack_base) {
- warning("Cannot save from below kernel function");
- return 1;
+void GfxPalette::palVarySaveLoadPalette(Common::Serializer &s, Palette *palette) {
+ s.syncBytes(palette->mapping, 256);
+ s.syncAsUint32LE(palette->timestamp);
+ for (int i = 0; i < 256; i++) {
+ s.syncAsByte(palette->colors[i].used);
+ s.syncAsByte(palette->colors[i].r);
+ s.syncAsByte(palette->colors[i].g);
+ s.syncAsByte(palette->colors[i].b);
}
-
-/*
- if (s->sound_server) {
- if ((s->sound_server->save)(s, dirname)) {
- warning("Saving failed for the sound subsystem");
- //chdir("..");
- return 1;
- }
- }
-*/
- Common::Serializer ser(0, fh);
- sync_SavegameMetadata(ser, meta);
- Graphics::saveThumbnail(*fh);
- s->saveLoadWithSerializer(ser); // FIXME: Error handling?
-
- return 0;
+ s.syncBytes(palette->intensity, 256);
}
-static byte *find_unique_script_block(EngineState *s, byte *buf, int type) {
- bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
-
- if (oldScriptHeader)
- buf += 2;
-
- do {
- int seeker_type = READ_LE_UINT16(buf);
+void GfxPalette::saveLoadWithSerializer(Common::Serializer &s) {
+ if (s.getVersion() < 24)
+ return;
- if (seeker_type == 0) break;
- if (seeker_type == type) return buf;
+ if (s.isLoading() && _palVaryResourceId != -1)
+ palVaryRemoveTimer();
- int seeker_size = READ_LE_UINT16(buf + 2);
- assert(seeker_size > 0);
- buf += seeker_size;
- } while (1);
+ s.syncAsSint32LE(_palVaryResourceId);
+ if (_palVaryResourceId != -1) {
+ palVarySaveLoadPalette(s, &_palVaryOriginPalette);
+ palVarySaveLoadPalette(s, &_palVaryTargetPalette);
+ s.syncAsSint16LE(_palVaryStep);
+ s.syncAsSint16LE(_palVaryStepStop);
+ s.syncAsSint16LE(_palVaryDirection);
+ s.syncAsUint16LE(_palVaryTicks);
+ s.syncAsSint32LE(_palVaryPaused);
+ }
- return NULL;
+ if (s.isLoading() && _palVaryResourceId != -1) {
+ _palVarySignal = 0;
+ palVaryInstallTimer();
+ }
}
-// TODO: This should probably be turned into an EngineState or DataStack method.
-static void reconstruct_stack(EngineState *retval) {
- SegmentId stack_seg = retval->_segMan->findSegmentByType(SEG_TYPE_STACK);
- DataStack *stack = (DataStack *)(retval->_segMan->_heap[stack_seg]);
-
- retval->stack_base = stack->_entries;
- retval->stack_top = stack->_entries + stack->_capacity;
+void SegManager::reconstructStack(EngineState *s) {
+ DataStack *stack = (DataStack *)(_heap[findSegmentByType(SEG_TYPE_STACK)]);
+ s->stack_base = stack->_entries;
+ s->stack_top = s->stack_base + stack->_capacity;
}
-static void load_script(EngineState *s, Script *scr) {
- scr->_buf = (byte *)malloc(scr->_bufSize);
- assert(scr->_buf);
-
- Resource *script = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, scr->_nr), 0);
- assert(script != 0);
-
- assert(scr->_bufSize >= script->size);
- memcpy(scr->_buf, script->data, script->size);
-
- if (getSciVersion() >= SCI_VERSION_1_1) {
- Resource *heap = g_sci->getResMan()->findResource(ResourceId(kResourceTypeHeap, scr->_nr), 0);
- assert(heap != 0);
-
- scr->_heapStart = scr->_buf + scr->_scriptSize;
-
- assert(scr->_bufSize - scr->_scriptSize <= heap->size);
- memcpy(scr->_heapStart, heap->data, heap->size);
- }
-}
-
-// TODO: Move thie function to a more appropriate place, such as vm.cpp or script.cpp
+// TODO: Move this function to a more appropriate place, such as vm.cpp or script.cpp
void SegManager::reconstructScripts(EngineState *s) {
uint i;
- SegmentObj *mobj;
for (i = 0; i < _heap.size(); i++) {
- mobj = _heap[i];
- if (!mobj || mobj->getType() != SEG_TYPE_SCRIPT)
+ if (!_heap[i] || _heap[i]->getType() != SEG_TYPE_SCRIPT)
continue;
- Script *scr = (Script *)mobj;
-
- // FIXME: Unify this code with script_instantiate_* ?
- load_script(s, scr);
+ Script *scr = (Script *)_heap[i];
+ scr->load(g_sci->getResMan());
scr->_localsBlock = (scr->_localsSegment == 0) ? NULL : (LocalVariables *)(_heap[scr->_localsSegment]);
- if (getSciVersion() >= SCI_VERSION_1_1) {
- scr->_exportTable = 0;
- scr->_synonyms = 0;
- if (READ_LE_UINT16(scr->_buf + 6) > 0) {
- scr->setExportTableOffset(6);
- s->_segMan->scriptRelocateExportsSci11(i);
- }
- } else {
- scr->_exportTable = (uint16 *) find_unique_script_block(s, scr->_buf, SCI_OBJ_EXPORTS);
- scr->_synonyms = find_unique_script_block(s, scr->_buf, SCI_OBJ_SYNONYMS);
- scr->_exportTable += 3;
- }
- scr->_codeBlocks.clear();
- ObjMap::iterator it;
- const ObjMap::iterator end = scr->_objects.end();
- for (it = scr->_objects.begin(); it != end; ++it) {
- byte *data = scr->_buf + it->_value.getPos().offset;
- it->_value._baseObj = data;
- }
+ for (ObjMap::iterator it = scr->_objects.begin(); it != scr->_objects.end(); ++it)
+ it->_value._baseObj = scr->getBuf(it->_value.getPos().offset);
}
for (i = 0; i < _heap.size(); i++) {
- mobj = _heap[i];
- if (!mobj || mobj->getType() != SEG_TYPE_SCRIPT)
+ if (!_heap[i] || _heap[i]->getType() != SEG_TYPE_SCRIPT)
continue;
- Script *scr = (Script *)mobj;
+ Script *scr = (Script *)_heap[i];
- // FIXME: Unify this code with Script::scriptObjInit ?
- ObjMap::iterator it;
- const ObjMap::iterator end = scr->_objects.end();
- for (it = scr->_objects.begin(); it != end; ++it) {
- byte *data = scr->_buf + it->_value.getPos().offset;
+ for (ObjMap::iterator it = scr->_objects.begin(); it != scr->_objects.end(); ++it) {
+ reg_t addr = it->_value.getPos();
+ Object *obj = scr->scriptObjInit(addr, false);
- if (getSciVersion() >= SCI_VERSION_1_1) {
- uint16 *funct_area = (uint16 *)(scr->_buf + READ_LE_UINT16( data + 6 ));
- uint16 *prop_area = (uint16 *)(scr->_buf + READ_LE_UINT16( data + 4 ));
+ if (getSciVersion() < SCI_VERSION_1_1) {
+ if (!obj->initBaseObject(this, addr, false)) {
+ // TODO/FIXME: This should not be happening at all. It might indicate a possible issue
+ // with the garbage collector. It happens for example in LSL5 (German, perhaps English too).
+ warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
+ scr->scriptObjRemove(addr);
+ }
+ }
+ }
+ }
+}
- it->_value._baseMethod = funct_area;
- it->_value._baseVars = prop_area;
- } else {
- int funct_area = READ_LE_UINT16(data + SCRIPT_FUNCTAREAPTR_OFFSET);
- Object *_baseObj;
+void SegManager::reconstructClones() {
+ for (uint i = 0; i < _heap.size(); i++) {
+ SegmentObj *mobj = _heap[i];
+ if (mobj && mobj->getType() == SEG_TYPE_CLONES) {
+ CloneTable *ct = (CloneTable *)mobj;
- _baseObj = s->_segMan->getObject(it->_value.getSpeciesSelector());
+ for (uint j = 0; j < ct->_table.size(); j++) {
+ // Check if the clone entry is used
+ uint entryNum = (uint)ct->first_free;
+ bool isUsed = true;
+ while (entryNum != ((uint) CloneTable::HEAPENTRY_INVALID)) {
+ if (entryNum == j) {
+ isUsed = false;
+ break;
+ }
+ entryNum = ct->_table[entryNum].next_free;
+ }
- if (!_baseObj) {
- warning("Object without a base class: Script %d, index %d (reg address %04x:%04x",
- scr->_nr, i, PRINT_REG(it->_value.getSpeciesSelector()));
+ if (!isUsed)
continue;
- }
- it->_value.setVarCount(_baseObj->getVarCount());
- it->_value._baseObj = _baseObj->_baseObj;
- it->_value._baseMethod = (uint16 *)(data + funct_area);
- it->_value._baseVars = (uint16 *)(data + it->_value.getVarCount() * 2 + SCRIPT_SELECTOR_OFFSET);
- }
- }
- }
+ CloneTable::Entry &seeker = ct->_table[j];
+ const Object *baseObj = getObject(seeker.getSpeciesSelector());
+ seeker.cloneFromObject(baseObj);
+ if (!baseObj) {
+ // Can happen when loading some KQ6 savegames
+ warning("Clone entry without a base class: %d", j);
+ }
+ } // end for
+ } // end if
+ } // end for
}
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-static void reconstruct_sounds(EngineState *s) {
- Song *seeker;
- SongIteratorType it_type;
-
- if (getSciVersion() > SCI_VERSION_01)
- it_type = SCI_SONG_ITERATOR_TYPE_SCI1;
- else
- it_type = SCI_SONG_ITERATOR_TYPE_SCI0;
-
- seeker = s->_sound._songlib._lib;
-
- while (seeker) {
- SongIterator *base, *ff = 0;
- int oldstatus;
- SongIterator::Message msg;
-
- base = ff = build_iterator(g_sci->getResMan(), seeker->_resourceNum, it_type, seeker->_handle);
- if (seeker->_restoreBehavior == RESTORE_BEHAVIOR_CONTINUE)
- ff = new_fast_forward_iterator(base, seeker->_restoreTime);
- ff->init();
-
- msg = SongIterator::Message(seeker->_handle, SIMSG_SET_LOOPS(seeker->_loops));
- songit_handle_message(&ff, msg);
- msg = SongIterator::Message(seeker->_handle, SIMSG_SET_HOLD(seeker->_hold));
- songit_handle_message(&ff, msg);
-
- oldstatus = seeker->_status;
- seeker->_status = SOUND_STATUS_STOPPED;
- seeker->_it = ff;
- s->_sound.sfx_song_set_status(seeker->_handle, oldstatus);
- seeker = seeker->_next;
+
+#pragma mark -
+
+
+bool gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename, const char *version) {
+ TimeDate curTime;
+ g_system->getTimeAndDate(curTime);
+
+ SavegameMetadata meta;
+ meta.savegame_version = CURRENT_SAVEGAME_VERSION;
+ meta.savegame_name = savename;
+ meta.game_version = version;
+ meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF);
+ meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF);
+
+ Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false);
+ meta.script0_size = script0->size;
+ meta.game_object_offset = g_sci->getGameObject().offset;
+
+ // Checking here again
+ if (s->executionStackBase) {
+ warning("Cannot save from below kernel function");
+ return false;
}
+
+ Common::Serializer ser(0, fh);
+ sync_SavegameMetadata(ser, meta);
+ Graphics::saveThumbnail(*fh);
+ s->saveLoadWithSerializer(ser); // FIXME: Error handling?
+
+ return true;
}
-#endif
void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
- EngineState *retval;
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- SongLibrary temp;
-#endif
-
SavegameMetadata meta;
Common::Serializer ser(fh, 0);
@@ -929,104 +714,65 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
if ((meta.savegame_version < MINIMUM_SAVEGAME_VERSION) ||
(meta.savegame_version > CURRENT_SAVEGAME_VERSION)) {
+ /*
if (meta.savegame_version < MINIMUM_SAVEGAME_VERSION)
- warning("Old savegame version detected- can't load");
+ warning("Old savegame version detected, unable to load it");
else
- warning("Savegame version is %d- maximum supported is %0d", meta.savegame_version, CURRENT_SAVEGAME_VERSION);
+ warning("Savegame version is %d, maximum supported is %0d", meta.savegame_version, CURRENT_SAVEGAME_VERSION);
+ */
+
+ GUI::MessageDialog dialog("The format of this saved game is obsolete, unable to load it", "OK");
+ dialog.runModal();
s->r_acc = make_reg(0, 1); // signal failure
return;
}
- if (meta.savegame_version >= 12) {
- // We don't need the thumbnail here, so just read it and discard it
- Graphics::Surface *thumbnail = new Graphics::Surface();
- assert(thumbnail);
- Graphics::loadThumbnail(*fh, *thumbnail);
- delete thumbnail;
- thumbnail = 0;
- }
-
- // Create a new EngineState object
- retval = new EngineState(s->_voc, s->_segMan);
- retval->_event = s->_event;
-
- // Copy some old data
- retval->_soundCmd = s->_soundCmd;
+ if (meta.game_object_offset > 0 && meta.script0_size > 0) {
+ Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false);
+ if (script0->size != meta.script0_size || g_sci->getGameObject().offset != meta.game_object_offset) {
+ //warning("This saved game was created with a different version of the game, unable to load it");
- // Copy memory segment
- retval->_memorySegmentSize = s->_memorySegmentSize;
- memcpy(retval->_memorySegment, s->_memorySegment, s->_memorySegmentSize);
+ GUI::MessageDialog dialog("This saved game was created with a different version of the game, unable to load it", "OK");
+ dialog.runModal();
- retval->saveLoadWithSerializer(ser); // FIXME: Error handling?
+ s->r_acc = make_reg(0, 1); // signal failure
+ return;
+ }
+ }
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- s->_sound.sfx_exit();
-#endif
+ // We don't need the thumbnail here, so just read it and discard it
+ Graphics::skipThumbnail(*fh);
- // Set exec stack base to zero
- retval->execution_stack_base = 0;
+ s->reset(true);
+ s->saveLoadWithSerializer(ser); // FIXME: Error handling?
// Now copy all current state information
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- temp = retval->_sound._songlib;
- retval->_sound.sfx_init(g_sci->getResMan(), s->sfx_init_flags, g_sci->_features->detectDoSoundType());
- retval->sfx_init_flags = s->sfx_init_flags;
- retval->_sound._songlib.freeSounds();
- retval->_sound._songlib = temp;
- retval->_soundCmd->updateSfxState(&retval->_sound);
-#endif
-
- reconstruct_stack(retval);
- retval->_segMan->reconstructScripts(retval);
- retval->_segMan->reconstructClones();
- retval->_gameObj = s->_gameObj;
- retval->script_000 = retval->_segMan->getScript(retval->_segMan->getScriptSegment(0, SCRIPT_GET_DONT_LOAD));
- retval->gc_countdown = GC_INTERVAL - 1;
- retval->sys_strings_segment = retval->_segMan->findSegmentByType(SEG_TYPE_SYS_STRINGS);
- retval->sys_strings = (SystemStrings *)(retval->_segMan->_heap[retval->sys_strings_segment]);
+ s->_segMan->reconstructStack(s);
+ s->_segMan->reconstructScripts(s);
+ s->_segMan->reconstructClones();
+ s->initGlobals();
+ s->gcCountDown = GC_INTERVAL - 1;
// Time state:
- retval->last_wait_time = g_system->getMillis();
- retval->game_start_time = g_system->getMillis();
-
- // static parser information:
+ s->lastWaitTime = g_system->getMillis();
+ s->gameStartTime = g_system->getMillis();
+ s->_screenUpdateTime = g_system->getMillis();
- if (retval->_voc)
- retval->_voc->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE);
+ if (g_sci->_gfxPorts)
+ g_sci->_gfxPorts->reset();
- retval->successor = NULL;
- retval->_gameId = s->_gameId;
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- retval->_sound._it = NULL;
- retval->_sound._flags = s->_sound._flags;
- retval->_sound._song = NULL;
- retval->_sound._suspended = s->_sound._suspended;
- reconstruct_sounds(retval);
-#else
- retval->_soundCmd->reconstructPlayList(meta.savegame_version);
-#endif
+ g_sci->_soundCmd->reconstructPlayList(meta.savegame_version);
// Message state:
- retval->_msgState = new MessageState(retval->_segMan);
-
-#ifdef ENABLE_SCI32
- if (g_sci->_gui32) {
- g_sci->_gui32->init();
- } else {
-#endif
- g_sci->_gui->resetEngineState(retval);
- g_sci->_gui->init(g_sci->_features->usesOldGfxFunctions());
-#ifdef ENABLE_SCI32
- }
-#endif
+ delete s->_msgState;
+ s->_msgState = new MessageState(s->_segMan);
+ s->abortScriptProcessing = kAbortLoadGame;
- s->successor = retval; // Set successor
- script_abort_flag = 2; // Abort current game with replay
- shrink_execution_stack(s, s->execution_stack_base + 1);
+ // signal restored game to game scripts
+ s->gameIsRestarting = GAMEISRESTARTING_RESTORE;
}
bool get_savegame_metadata(Common::SeekableReadStream *stream, SavegameMetadata *meta) {
diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h
index bad79fca27..fc254ba33d 100644
--- a/engines/sci/engine/savegame.h
+++ b/engines/sci/engine/savegame.h
@@ -36,8 +36,8 @@ namespace Sci {
struct EngineState;
enum {
- CURRENT_SAVEGAME_VERSION = 19,
- MINIMUM_SAVEGAME_VERSION = 9
+ CURRENT_SAVEGAME_VERSION = 24,
+ MINIMUM_SAVEGAME_VERSION = 14
};
// Savegame metadata
@@ -47,6 +47,8 @@ struct SavegameMetadata {
Common::String game_version;
int savegame_date;
int savegame_time;
+ uint16 game_object_offset;
+ uint16 script0_size;
};
@@ -57,7 +59,7 @@ struct SavegameMetadata {
* @param savename The description of the savegame
* @return 0 on success, 1 otherwise
*/
-int gamestate_save(EngineState *s, Common::WriteStream *save, const char *savename, const char *version);
+bool gamestate_save(EngineState *s, Common::WriteStream *save, const char *savename, const char *version);
/**
* Restores a game state from a directory.
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 85a07f0efc..3ba550adf9 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -35,567 +35,578 @@
namespace Sci {
-#define END Script_None
-
-opcode_format g_opcode_formats[128][4] = {
- /*00*/
- {Script_None}, {Script_None}, {Script_None}, {Script_None},
- /*04*/
- {Script_None}, {Script_None}, {Script_None}, {Script_None},
- /*08*/
- {Script_None}, {Script_None}, {Script_None}, {Script_None},
- /*0C*/
- {Script_None}, {Script_None}, {Script_None}, {Script_None},
- /*10*/
- {Script_None}, {Script_None}, {Script_None}, {Script_None},
- /*14*/
- {Script_None}, {Script_None}, {Script_None}, {Script_SRelative, END},
- /*18*/
- {Script_SRelative, END}, {Script_SRelative, END}, {Script_SVariable, END}, {Script_None},
- /*1C*/
- {Script_SVariable, END}, {Script_None}, {Script_None}, {Script_Variable, END},
- /*20*/
- {Script_SRelative, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_SVariable, Script_Byte, END},
- /*24 (24=ret)*/
- {Script_End}, {Script_Byte, END}, {Script_Invalid}, {Script_Invalid},
- /*28*/
- {Script_Variable, END}, {Script_Invalid}, {Script_Byte, END}, {Script_Variable, Script_Byte, END},
- /*2C*/
- {Script_SVariable, END}, {Script_SVariable, Script_Variable, END}, {Script_None}, {Script_Invalid},
- /*30*/
- {Script_None}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END},
- /*34*/
- {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END},
- /*38*/
- {Script_Property, END}, {Script_SRelative, END}, {Script_SRelative, END}, {Script_None},
- /*3C*/
- {Script_None}, {Script_None}, {Script_None}, {Script_Word},
- /*40-4F*/
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- /*50-5F*/
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- /*60-6F*/
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- /*70-7F*/
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END},
- {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}
-};
-#undef END
-
-// TODO: script_adjust_opcode_formats should probably be part of the
-// constructor (?) of a VirtualMachine or a ScriptManager class.
-void script_adjust_opcode_formats(EngineState *s) {
- // TODO: Check that this is correct
- if (g_sci->_features->detectLofsType() != SCI_VERSION_0_EARLY) {
- g_opcode_formats[op_lofsa][0] = Script_Offset;
- g_opcode_formats[op_lofss][0] = Script_Offset;
- }
+Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) {
+ _nr = 0;
+ _buf = NULL;
+ _bufSize = 0;
+ _scriptSize = 0;
+ _heapSize = 0;
+
+ _synonyms = NULL;
+ _heapStart = NULL;
+ _exportTable = NULL;
+
+ _localsOffset = 0;
+ _localsSegment = 0;
+ _localsBlock = NULL;
+ _localsCount = 0;
+
+ _markedAsDeleted = false;
+}
+
+Script::~Script() {
+ freeScript();
+}
+
+void Script::freeScript() {
+ free(_buf);
+ _buf = NULL;
+ _bufSize = 0;
-#ifdef ENABLE_SCI32
- // In SCI32, some arguments are now words instead of bytes
- if (getSciVersion() >= SCI_VERSION_2) {
- g_opcode_formats[op_calle][2] = Script_Word;
- g_opcode_formats[op_callk][1] = Script_Word;
- g_opcode_formats[op_super][1] = Script_Word;
- g_opcode_formats[op_send][0] = Script_Word;
- g_opcode_formats[op_self][0] = Script_Word;
- g_opcode_formats[op_call][1] = Script_Word;
- g_opcode_formats[op_callb][1] = Script_Word;
+ _objects.clear();
+}
+
+void Script::init(int script_nr, ResourceManager *resMan) {
+ Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
+
+ _localsOffset = 0;
+ _localsBlock = NULL;
+ _localsCount = 0;
+
+ _markedAsDeleted = false;
+
+ _nr = script_nr;
+ _buf = 0;
+ _heapStart = 0;
+
+ _scriptSize = script->size;
+ _bufSize = script->size;
+ _heapSize = 0;
+
+ _lockers = 1;
+
+ if (getSciVersion() == SCI_VERSION_0_EARLY) {
+ _bufSize += READ_LE_UINT16(script->data) * 2;
+ } else if (getSciVersion() >= SCI_VERSION_1_1) {
+ // In SCI11, the heap was in a separate space from the script. We append
+ // it to the end of the script, and adjust addressing accordingly.
+ // However, since we address the heap with a 16-bit pointer, the
+ // combined size of the stack and the heap must be 64KB. So far this has
+ // worked for SCI11, SCI2 and SCI21 games. SCI3 games use a different
+ // script format, and theoretically they can exceed the 64KB boundary
+ // using relocation.
+ Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
+ _bufSize += heap->size;
+ _heapSize = heap->size;
+
+ // Ensure that the start of the heap resource can be word-aligned.
+ if (script->size & 2) {
+ _bufSize++;
+ _scriptSize++;
+ }
+
+ // As mentioned above, the script and the heap together should not exceed 64KB
+ if (script->size + heap->size > 65535)
+ error("Script and heap sizes combined exceed 64K. This means a fundamental "
+ "design bug was made regarding SCI1.1 and newer games.\n"
+ "Please report this error to the ScummVM team");
}
-#endif
}
-void SegManager::createClassTable() {
- Resource *vocab996 = _resMan->findResource(ResourceId(kResourceTypeVocab, 996), 1);
+void Script::load(ResourceManager *resMan) {
+ Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0);
+ assert(script != 0);
- if (!vocab996)
- error("SegManager: failed to open vocab 996");
+ _buf = (byte *)malloc(_bufSize);
+ assert(_buf);
- int totalClasses = vocab996->size >> 2;
- _classtable.resize(totalClasses);
+ assert(_bufSize >= script->size);
+ memcpy(_buf, script->data, script->size);
- for (uint16 classNr = 0; classNr < totalClasses; classNr++) {
- uint16 scriptNr = READ_SCI11ENDIAN_UINT16(vocab996->data + classNr * 4 + 2);
+ // Check scripts for matching signatures and patch those, if found
+ matchSignatureAndPatch(_nr, _buf, script->size);
- _classtable[classNr].reg = NULL_REG;
- _classtable[classNr].script = scriptNr;
- }
+ if (getSciVersion() >= SCI_VERSION_1_1) {
+ Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0);
+ assert(heap != 0);
- _resMan->unlockResource(vocab996);
-}
+ _heapStart = _buf + _scriptSize;
-reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller) {
- if (classnr == 0xffff)
- return NULL_REG;
+ assert(_bufSize - _scriptSize <= heap->size);
+ memcpy(_heapStart, heap->data, heap->size);
+ }
- if (classnr < 0 || (int)_classtable.size() <= classnr || _classtable[classnr].script < 0) {
- error("[VM] Attempt to dereference class %x, which doesn't exist (max %x)", classnr, _classtable.size());
- return NULL_REG;
+ _exportTable = 0;
+ _numExports = 0;
+ _synonyms = 0;
+ _numSynonyms = 0;
+
+ if (getSciVersion() >= SCI_VERSION_1_1) {
+ if (READ_LE_UINT16(_buf + 1 + 5) > 0) { // does the script have an export table?
+ _exportTable = (const uint16 *)(_buf + 1 + 5 + 2);
+ _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1);
+ }
+ _localsOffset = _scriptSize + 4;
+ _localsCount = READ_SCI11ENDIAN_UINT16(_buf + _localsOffset - 2);
} else {
- Class *the_class = &_classtable[classnr];
- if (!the_class->reg.segment) {
- getScriptSegment(the_class->script, lock);
+ _exportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS);
+ if (_exportTable) {
+ _numExports = READ_SCI11ENDIAN_UINT16(_exportTable + 1);
+ _exportTable += 3; // skip header plus 2 bytes (_exportTable is a uint16 pointer)
+ }
+ _synonyms = findBlock(SCI_OBJ_SYNONYMS);
+ if (_synonyms) {
+ _numSynonyms = READ_SCI11ENDIAN_UINT16(_synonyms + 2) / 4;
+ _synonyms += 4; // skip header
+ }
+ const byte* localsBlock = findBlock(SCI_OBJ_LOCALVARS);
+ if (localsBlock) {
+ _localsOffset = localsBlock - _buf + 4;
+ _localsCount = (READ_LE_UINT16(_buf + _localsOffset - 2) - 4) >> 1; // half block size
+ }
+ }
- if (!the_class->reg.segment) {
- error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;", classnr, the_class->script, the_class->script);
- return NULL_REG;
- }
- } else
- if (caller.segment != the_class->reg.segment)
- getScript(the_class->reg.segment)->incrementLockers();
+ if (getSciVersion() > SCI_VERSION_0_EARLY) {
+ // Does the script actually have locals? If not, set the locals offset to 0
+ if (!_localsCount)
+ _localsOffset = 0;
- return the_class->reg;
+ if (_localsOffset + _localsCount * 2 + 1 >= (int)_bufSize) {
+ error("Locals extend beyond end of script: offset %04x, count %d vs size %d", _localsOffset, _localsCount, _bufSize);
+ _localsCount = (_bufSize - _localsOffset) >> 1;
+ }
+ } else {
+ // Old script block. There won't be a localvar block in this case.
+ // Instead, the script starts with a 16 bit int specifying the
+ // number of locals we need; these are then allocated and zeroed.
+ _localsCount = READ_LE_UINT16(_buf);
+ _localsOffset = -_localsCount * 2; // Make sure it's invalid
}
}
-void SegManager::scriptInitialiseLocalsZero(SegmentId seg, int count) {
- Script *scr = getScript(seg);
-
- scr->_localsOffset = -count * 2; // Make sure it's invalid
+Object *Script::getObject(uint16 offset) {
+ if (_objects.contains(offset))
+ return &_objects[offset];
+ else
+ return 0;
+}
- LocalVariables *locals = allocLocalsSegment(scr, count);
- if (locals) {
- for (int i = 0; i < count; i++)
- locals->_locals[i] = NULL_REG;
- }
+const Object *Script::getObject(uint16 offset) const {
+ if (_objects.contains(offset))
+ return &_objects[offset];
+ else
+ return 0;
}
-void SegManager::scriptInitialiseLocals(reg_t location) {
- Script *scr = getScript(location.segment);
- unsigned int count;
+Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) {
+ if (getSciVersion() < SCI_VERSION_1_1 && fullObjectInit)
+ obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET)
- VERIFY(location.offset + 1 < (uint16)scr->_bufSize, "Locals beyond end of script\n");
+ VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n");
- if (getSciVersion() >= SCI_VERSION_1_1)
- count = READ_SCI11ENDIAN_UINT16(scr->_buf + location.offset - 2);
- else
- count = (READ_LE_UINT16(scr->_buf + location.offset - 2) - 4) >> 1;
- // half block size
+ VERIFY(obj_pos.offset + kOffsetFunctionArea < (int)_bufSize, "Function area pointer stored beyond end of script\n");
- scr->_localsOffset = location.offset;
+ // Get the object at the specified position and init it. This will
+ // automatically "allocate" space for it in the _objects map if necessary.
+ Object *obj = &_objects[obj_pos.offset];
+ obj->init(_buf, obj_pos, fullObjectInit);
- if (!(location.offset + count * 2 + 1 < scr->_bufSize)) {
- warning("Locals extend beyond end of script: offset %04x, count %x vs size %x", location.offset, count, (uint)scr->_bufSize);
- count = (scr->_bufSize - location.offset) >> 1;
- }
+ return obj;
+}
- LocalVariables *locals = allocLocalsSegment(scr, count);
- if (locals) {
- uint i;
- byte *base = (byte *)(scr->_buf + location.offset);
+void Script::scriptObjRemove(reg_t obj_pos) {
+ if (getSciVersion() < SCI_VERSION_1_1)
+ obj_pos.offset += 8;
- for (i = 0; i < count; i++)
- locals->_locals[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(base + i * 2));
- }
+ _objects.erase(obj_pos.toUint16());
}
-void SegManager::scriptRelocateExportsSci11(SegmentId seg) {
- Script *scr = getScript(seg);
- for (int i = 0; i < scr->_numExports; i++) {
- /* We are forced to use an ugly heuristic here to distinguish function
- exports from object/class exports. The former kind points into the
- script resource, the latter into the heap resource. */
- uint16 location = READ_SCI11ENDIAN_UINT16((byte *)(scr->_exportTable + i));
+// This helper function is used by Script::relocateLocal and Object::relocate
+// Duplicate in segment.cpp and script.cpp
+static bool relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location, size_t scriptSize) {
+ int rel = location - block_location;
- if ((location < scr->_heapSize - 1) && (READ_SCI11ENDIAN_UINT16(scr->_heapStart + location) == SCRIPT_OBJECT_MAGIC_NUMBER)) {
- WRITE_SCI11ENDIAN_UINT16((byte *)(scr->_exportTable + i), location + scr->_heapStart - scr->_buf);
- } else {
- // Otherwise it's probably a function export,
- // and we don't need to do anything.
- }
+ if (rel < 0)
+ return false;
+
+ uint idx = rel >> 1;
+
+ if (idx >= block.size())
+ return false;
+
+ if (rel & 1) {
+ error("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location);
+ return false;
}
+ block[idx].segment = segment; // Perform relocation
+ if (getSciVersion() >= SCI_VERSION_1_1)
+ block[idx].offset += scriptSize;
+
+ return true;
}
-void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) {
- Script *scr = getScript(seg);
- byte *seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2;
+bool Script::relocateLocal(SegmentId segment, int location) {
+ if (_localsBlock)
+ return relocateBlock(_localsBlock->_locals, _localsOffset, segment, location, _scriptSize);
+ else
+ return false;
+}
- while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) {
- if (READ_SCI11ENDIAN_UINT16(seeker + 14) & SCRIPT_INFO_CLASS) {
- int classpos = seeker - scr->_buf;
- int species = READ_SCI11ENDIAN_UINT16(seeker + 10);
-
- if (species < 0 || species >= (int)_classtable.size()) {
- error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d",
- species, species, _classtable.size(), scr->_nr);
- return;
- }
+void Script::relocate(reg_t block) {
+ const byte *heap = _buf;
+ uint16 heapSize = (uint16)_bufSize;
+ uint16 heapOffset = 0;
- _classtable[species].reg.segment = seg;
- _classtable[species].reg.offset = classpos;
- }
- seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2;
+ if (getSciVersion() >= SCI_VERSION_1_1) {
+ heap = _heapStart;
+ heapSize = (uint16)_heapSize;
+ heapOffset = _scriptSize;
}
- seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2;
- while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) {
- reg_t reg;
- Object *obj;
-
- reg.segment = seg;
- reg.offset = seeker - scr->_buf;
- obj = scr->scriptObjInit(reg);
-
-#if 0
- if (obj->_variables[5].offset != 0xffff) {
- obj->_variables[5] = INST_LOOKUP_CLASS(obj->_variables[5].offset);
- baseObj = getObject(obj->_variables[5]);
- obj->variable_names_nr = baseObj->variables_nr;
- obj->_baseObj = baseObj->_baseObj;
+ VERIFY(block.offset < (uint16)heapSize && READ_SCI11ENDIAN_UINT16(heap + block.offset) * 2 + block.offset < (uint16)heapSize,
+ "Relocation block outside of script\n");
+
+ int count = READ_SCI11ENDIAN_UINT16(heap + block.offset);
+ int exportIndex = 0;
+ int pos = 0;
+
+ for (int i = 0; i < count; i++) {
+ pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset;
+ // This occurs in SCI01/SCI1 games where usually one export value is
+ // zero. It seems that in this situation, we should skip the export and
+ // move to the next one, though the total count of valid exports remains
+ // the same
+ if (!pos) {
+ exportIndex++;
+ pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset;
+ if (!pos)
+ error("Script::relocate(): Consecutive zero exports found");
}
-#endif
- // Copy base from species class, as we need its selector IDs
- obj->setSuperClassSelector(
- getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG));
-
- // Set the -classScript- selector to the script number.
- // FIXME: As this selector is filled in at run-time, it is likely
- // that it is supposed to hold a pointer. The Obj::isKindOf method
- // uses this selector together with -propDict- to compare classes.
- // For the purpose of Obj::isKindOf, using the script number appears
- // to be sufficient.
- obj->setClassScriptSelector(make_reg(0, scr->_nr));
+ // In SCI0-SCI1, script local variables, objects and code are relocated.
+ // We only relocate locals and objects here, and ignore relocation of
+ // code blocks. In SCI1.1 and newer versions, only locals and objects
+ // are relocated.
+ if (!relocateLocal(block.segment, pos)) {
+ // Not a local? It's probably an object or code block. If it's an object, relocate it.
+ const ObjMap::iterator end = _objects.end();
+ for (ObjMap::iterator it = _objects.begin(); it != end; ++it)
+ if (it->_value.relocate(block.segment, pos, _scriptSize))
+ break;
+ }
- seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2;
+ exportIndex++;
}
}
+void Script::incrementLockers() {
+ _lockers++;
+}
+void Script::decrementLockers() {
+ if (_lockers > 0)
+ _lockers--;
+}
-int script_instantiate_common(ResourceManager *resMan, SegManager *segMan, int script_nr, Resource **script, Resource **heap, int *was_new) {
- *was_new = 1;
+int Script::getLockers() const {
+ return _lockers;
+}
- *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
- if (getSciVersion() >= SCI_VERSION_1_1)
- *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
+void Script::setLockers(int lockers) {
+ _lockers = lockers;
+}
- if (!*script || (getSciVersion() >= SCI_VERSION_1_1 && !heap)) {
- warning("Script 0x%x requested but not found", script_nr);
- if (getSciVersion() >= SCI_VERSION_1_1) {
- if (*heap)
- warning("Inconsistency: heap resource WAS found");
- else if (*script)
- warning("Inconsistency: script resource WAS found");
- }
+uint16 Script::validateExportFunc(int pubfunct) {
+ bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE);
+
+ if (_numExports <= pubfunct) {
+ error("validateExportFunc(): pubfunct is invalid");
return 0;
}
- SegmentId seg_id = segMan->getScriptSegment(script_nr);
- Script *scr = segMan->getScriptIfLoaded(seg_id);
- if (scr) {
- if (!scr->isMarkedAsDeleted()) {
- scr->incrementLockers();
- return seg_id;
- } else {
- scr->freeScript();
- }
- } else {
- scr = segMan->allocateScript(script_nr, &seg_id);
- if (!scr) { // ALL YOUR SCRIPT BASE ARE BELONG TO US
- error("Not enough heap space for script size 0x%x of script 0x%x (Should this happen?)", (*script)->size, script_nr);
- return 0;
+ if (exportsAreWide)
+ pubfunct *= 2;
+ uint16 offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct);
+ VERIFY(offset < _bufSize, "invalid export function pointer");
+
+ if (offset == 0) {
+ // Check if the game has a second export table (e.g. script 912 in Camelot)
+ // Fixes bug #3039785
+ const uint16 *secondExportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS, 0);
+
+ if (secondExportTable) {
+ secondExportTable += 3; // skip header plus 2 bytes (secondExportTable is a uint16 pointer)
+ offset = READ_SCI11ENDIAN_UINT16(secondExportTable + pubfunct);
+ VERIFY(offset < _bufSize, "invalid export function pointer");
}
}
- scr->init(script_nr, resMan);
-
- reg_t reg;
- reg.segment = seg_id;
- reg.offset = 0;
+ return offset;
+}
- // Set heap position (beyond the size word)
- scr->setLockers(1);
- scr->setExportTableOffset(0);
- scr->setSynonymsOffset(0);
- scr->setSynonymsNr(0);
+byte *Script::findBlock(int type, int skipBlockIndex) {
+ byte *buf = _buf;
+ bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
+ int blockIndex = 0;
- *was_new = 0;
+ if (oldScriptHeader)
+ buf += 2;
- return seg_id;
-}
+ do {
+ int seekerType = READ_LE_UINT16(buf);
-#define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : segMan->getClassAddress(id, SCRIPT_GET_LOCK, addr))
+ if (seekerType == 0)
+ break;
+ if (seekerType == type && blockIndex != skipBlockIndex)
+ return buf;
-int script_instantiate_sci0(ResourceManager *resMan, SegManager *segMan, int script_nr) {
- int objType;
- uint32 objLength = 0;
- int relocation = -1;
- Resource *script;
- int was_new;
- bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
- const int seg_id = script_instantiate_common(resMan, segMan, script_nr, &script, NULL, &was_new);
- uint16 curOffset = oldScriptHeader ? 2 : 0;
+ int seekerSize = READ_LE_UINT16(buf + 2);
+ assert(seekerSize > 0);
+ buf += seekerSize;
+ blockIndex++;
+ } while (1);
- if (was_new)
- return seg_id;
+ return NULL;
+}
- Script *scr = segMan->getScript(seg_id);
- scr->mcpyInOut(0, script->data, script->size);
+// memory operations
- if (oldScriptHeader) {
- // Old script block
- // There won't be a localvar block in this case
- // Instead, the script starts with a 16 bit int specifying the
- // number of locals we need; these are then allocated and zeroed.
- int locals_nr = READ_LE_UINT16(script->data);
- if (locals_nr)
- segMan->scriptInitialiseLocalsZero(seg_id, locals_nr);
+void Script::mcpyInOut(int dst, const void *src, size_t n) {
+ if (_buf) {
+ assert(dst + n <= _bufSize);
+ memcpy(_buf + dst, src, n);
}
+}
- // Now do a first pass through the script objects to find the
- // export table and local variable block
+bool Script::isValidOffset(uint16 offset) const {
+ return offset < _bufSize;
+}
- do {
- objType = scr->getHeap(curOffset);
- if (!objType)
- break;
+SegmentRef Script::dereference(reg_t pointer) {
+ if (pointer.offset > _bufSize) {
+ error("Script::dereference(): Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)",
+ PRINT_REG(pointer), (uint)_bufSize);
+ return SegmentRef();
+ }
- objLength = scr->getHeap(curOffset + 2);
+ SegmentRef ret;
+ ret.isRaw = true;
+ ret.maxSize = _bufSize - pointer.offset;
+ ret.raw = _buf + pointer.offset;
+ return ret;
+}
+
+void Script::initialiseLocals(SegManager *segMan) {
+ LocalVariables *locals = segMan->allocLocalsSegment(this);
+ if (locals) {
+ if (getSciVersion() > SCI_VERSION_0_EARLY) {
+ const byte *base = (const byte *)(_buf + getLocalsOffset());
- // This happens in some demos (e.g. the EcoQuest 1 demo). Not sure what is the
- // actual cause of it, but the scripts of these demos can't be loaded properly
- // and we're stuck forever in this loop, as objLength never changes
- if (!objLength) {
- warning("script_instantiate_sci0: objLength is 0, unable to parse script");
- return 0;
+ for (uint16 i = 0; i < getLocalsCount(); i++)
+ locals->_locals[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(base + i * 2));
+ } else {
+ // In SCI0 early, locals are set at run time, thus zero them all here
+ for (uint16 i = 0; i < getLocalsCount(); i++)
+ locals->_locals[i] = NULL_REG;
}
+ }
+}
- curOffset += 4; // skip header
+void Script::initialiseClasses(SegManager *segMan) {
+ const byte *seeker = 0;
+ uint16 mult = 0;
+
+ if (getSciVersion() >= SCI_VERSION_1_1) {
+ seeker = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2;
+ mult = 2;
+ } else {
+ seeker = findBlock(SCI_OBJ_CLASS);
+ mult = 1;
+ }
- switch (objType) {
- case SCI_OBJ_EXPORTS:
- scr->setExportTableOffset(curOffset);
- break;
- case SCI_OBJ_SYNONYMS:
- scr->setSynonymsOffset(curOffset);
- scr->setSynonymsNr((objLength) / 4);
- break;
- case SCI_OBJ_LOCALVARS:
- segMan->scriptInitialiseLocals(make_reg(seg_id, curOffset));
- break;
+ if (!seeker)
+ return;
- case SCI_OBJ_CLASS: {
- int classpos = curOffset - SCRIPT_OBJECT_MAGIC_OFFSET;
- int species = scr->getHeap(curOffset - SCRIPT_OBJECT_MAGIC_OFFSET + SCRIPT_SPECIES_OFFSET);
- if (species < 0 || species >= (int)segMan->_classtable.size()) {
- if (species == (int)segMan->_classtable.size()) {
- // Happens in the LSL2 demo
- warning("Applying workaround for an off-by-one invalid species access");
- segMan->_classtable.resize(segMan->_classtable.size() + 1);
- } else {
- warning("Invalid species %d(0x%x) not in interval "
- "[0,%d) while instantiating script %d\n",
- species, species, segMan->_classtable.size(),
- script_nr);
- return 0;
- }
- }
+ uint16 marker;
+ bool isClass;
+ uint16 classpos;
+ int16 species = 0;
- segMan->_classtable[species].reg.segment = seg_id;
- segMan->_classtable[species].reg.offset = classpos;
- // Set technical class position-- into the block allocated for it
- }
- break;
+ while (true) {
+ // In SCI0-SCI1, this is the segment type. In SCI11, it's a marker (0x1234)
+ marker = READ_SCI11ENDIAN_UINT16(seeker);
+ classpos = seeker - _buf;
- default:
+ if (!marker)
break;
+
+ if (getSciVersion() >= SCI_VERSION_1_1) {
+ isClass = (READ_SCI11ENDIAN_UINT16(seeker + 14) & kInfoFlagClass); // -info- selector
+ species = READ_SCI11ENDIAN_UINT16(seeker + 10);
+ } else {
+ isClass = (marker == SCI_OBJ_CLASS);
+ if (isClass)
+ species = READ_SCI11ENDIAN_UINT16(seeker + 12);
+ classpos += 12;
+ }
+
+ if (isClass) {
+ // WORKAROUNDs for off-by-one script errors
+ if (g_sci->getGameId() == GID_LSL2 && g_sci->isDemo() && species == (int)segMan->classTableSize())
+ segMan->resizeClassTable(segMan->classTableSize() + 1);
+ if (g_sci->getGameId() == GID_LSL3 && !g_sci->isDemo() && _nr == 500 && species == (int)segMan->classTableSize())
+ segMan->resizeClassTable(segMan->classTableSize() + 1);
+ if (g_sci->getGameId() == GID_SQ3 && !g_sci->isDemo() && _nr == 93 && species == (int)segMan->classTableSize())
+ segMan->resizeClassTable(segMan->classTableSize() + 1);
+ if (g_sci->getGameId() == GID_SQ3 && !g_sci->isDemo() && _nr == 99 && species == (int)segMan->classTableSize())
+ segMan->resizeClassTable(segMan->classTableSize() + 1);
+
+ if (species < 0 || species >= (int)segMan->classTableSize())
+ error("Invalid species %d(0x%x) unknown max %d(0x%x) while instantiating script %d\n",
+ species, species, segMan->classTableSize(), segMan->classTableSize(), _nr);
+
+ SegmentId segmentId = segMan->getScriptSegment(_nr);
+ segMan->setClassOffset(species, make_reg(segmentId, classpos));
}
- curOffset += objLength - 4;
- } while (objType != 0 && curOffset < script->size - 2);
+ seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * mult;
+ }
+}
- // And now a second pass to adjust objects and class pointers, and the general pointers
- objLength = 0;
- curOffset = oldScriptHeader ? 2 : 0;
+void Script::initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId) {
+ bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
+ const byte *seeker = _buf + (oldScriptHeader ? 2 : 0);
do {
- objType = scr->getHeap(curOffset);
+ uint16 objType = READ_SCI11ENDIAN_UINT16(seeker);
if (!objType)
break;
- objLength = scr->getHeap(curOffset + 2);
- curOffset += 4; // skip header
-
- reg_t addr = make_reg(seg_id, curOffset);
-
switch (objType) {
- case SCI_OBJ_CODE:
- scr->scriptAddCodeBlock(addr);
- break;
case SCI_OBJ_OBJECT:
- case SCI_OBJ_CLASS: { // object or class?
- Object *obj = scr->scriptObjInit(addr);
-
- // Instantiate the superclass, if neccessary
- obj->setSpeciesSelector(INST_LOOKUP_CLASS(obj->getSpeciesSelector().offset));
-
- Object *baseObj = segMan->getObject(obj->getSpeciesSelector());
-
- if (baseObj) {
- obj->setVarCount(baseObj->getVarCount());
- // Copy base from species class, as we need its selector IDs
- obj->_baseObj = baseObj->_baseObj;
-
- obj->setSuperClassSelector(INST_LOOKUP_CLASS(obj->getSuperClassSelector().offset));
- } else {
- warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
-
- scr->scriptObjRemove(addr);
+ case SCI_OBJ_CLASS:
+ {
+ reg_t addr = make_reg(segmentId, seeker - _buf + 4);
+ Object *obj = scriptObjInit(addr);
+ obj->initSpecies(segMan, addr);
+
+ if (!obj->initBaseObject(segMan, addr)) {
+ if (_nr == 202 && g_sci->getGameId() == GID_KQ5) {
+ // WORKAROUND: Script 202 of KQ5 French and German
+ // (perhaps Spanish too?) has an invalid object.
+ // This is non-fatal. Refer to bug #3035396.
+ } else {
+ error("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
+ }
+ scriptObjRemove(addr);
+ }
}
- } // if object or class
- break;
- case SCI_OBJ_POINTERS: // A relocation table
- relocation = addr.offset;
break;
default:
break;
}
- curOffset += objLength - 4;
- } while (objType != 0 && curOffset < script->size - 2);
-
- if (relocation >= 0)
- scr->scriptRelocate(make_reg(seg_id, relocation));
+ seeker += READ_SCI11ENDIAN_UINT16(seeker + 2);
+ } while ((uint32)(seeker - _buf) < getScriptSize() - 2);
- return seg_id; // instantiation successful
+ byte *relocationBlock = findBlock(SCI_OBJ_POINTERS);
+ if (relocationBlock)
+ relocate(make_reg(segmentId, relocationBlock - getBuf() + 4));
}
-int script_instantiate_sci11(ResourceManager *resMan, SegManager *segMan, int script_nr) {
- Resource *script, *heap;
- int _heapStart;
- reg_t reg;
- int was_new;
-
- const int seg_id = script_instantiate_common(resMan, segMan, script_nr, &script, &heap, &was_new);
+void Script::initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId) {
+ const byte *seeker = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2;
- if (was_new)
- return seg_id;
-
- Script *scr = segMan->getScript(seg_id);
-
- _heapStart = script->size;
- if (script->size & 2)
- _heapStart++;
-
- scr->mcpyInOut(0, script->data, script->size);
- scr->mcpyInOut(_heapStart, heap->data, heap->size);
-
- if (READ_SCI11ENDIAN_UINT16(script->data + 6) > 0)
- scr->setExportTableOffset(6);
+ while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) {
+ reg_t reg = make_reg(segmentId, seeker - _buf);
+ Object *obj = scriptObjInit(reg);
- reg.segment = seg_id;
- reg.offset = _heapStart + 4;
- segMan->scriptInitialiseLocals(reg);
+ // Copy base from species class, as we need its selector IDs
+ obj->setSuperClassSelector(
+ segMan->getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG));
+
+ // If object is instance, get -propDict- from class and set it for this
+ // object. This is needed for ::isMemberOf() to work.
+ // Example testcase - room 381 of sq4cd - if isMemberOf() doesn't work,
+ // talk-clicks on the robot will act like clicking on ego
+ if (!obj->isClass()) {
+ reg_t classObject = obj->getSuperClassSelector();
+ const Object *classObj = segMan->getObject(classObject);
+ obj->setPropDictSelector(classObj->getPropDictSelector());
+ }
- segMan->scriptRelocateExportsSci11(seg_id);
- segMan->scriptInitialiseObjectsSci11(seg_id);
+ // Set the -classScript- selector to the script number.
+ // FIXME: As this selector is filled in at run-time, it is likely
+ // that it is supposed to hold a pointer. The Obj::isKindOf method
+ // uses this selector together with -propDict- to compare classes.
+ // For the purpose of Obj::isKindOf, using the script number appears
+ // to be sufficient.
+ obj->setClassScriptSelector(make_reg(0, _nr));
- reg.offset = READ_SCI11ENDIAN_UINT16(heap->data);
- scr->heapRelocate(reg);
+ seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2;
+ }
- return seg_id;
+ relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(_heapStart)));
}
-int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr) {
- if (getSciVersion() >= SCI_VERSION_1_1)
- return script_instantiate_sci11(resMan, segMan, script_nr);
- else
- return script_instantiate_sci0(resMan, segMan, script_nr);
+reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) const {
+ addr.offset = 0;
+ return addr;
}
-void script_uninstantiate_sci0(SegManager *segMan, int script_nr, SegmentId seg) {
- bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
- reg_t reg = make_reg(seg, oldScriptHeader ? 2 : 0);
- int objType, objLength;
- Script *scr = segMan->getScript(seg);
-
- // Make a pass over the object in order uninstantiate all superclasses
- objLength = 0;
-
- do {
- reg.offset += objLength; // Step over the last checked object
-
- objType = scr->getHeap(reg.offset);
- if (!objType)
- break;
- objLength = scr->getHeap(reg.offset + 2); // use SEG_UGET_HEAP ??
-
- reg.offset += 4; // Step over header
-
- if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class?
- int superclass;
+void Script::freeAtAddress(SegManager *segMan, reg_t addr) {
+ /*
+ debugC(2, kDebugLevelGC, "[GC] Freeing script %04x:%04x", PRINT_REG(addr));
+ if (_localsSegment)
+ debugC(2, kDebugLevelGC, "[GC] Freeing locals %04x:0000", _localsSegment);
+ */
- reg.offset -= SCRIPT_OBJECT_MAGIC_OFFSET;
-
- superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass...
-
- if (superclass >= 0) {
- int superclass_script = segMan->_classtable[superclass].script;
-
- if (superclass_script == script_nr) {
- if (scr->getLockers())
- scr->decrementLockers(); // Decrease lockers if this is us ourselves
- } else
- script_uninstantiate(segMan, superclass_script);
- // Recurse to assure that the superclass lockers number gets decreased
- }
-
- reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET;
- } // if object or class
-
- reg.offset -= 4; // Step back on header
-
- } while (objType != 0);
+ if (_markedAsDeleted)
+ segMan->deallocateScript(_nr);
}
-void script_uninstantiate(SegManager *segMan, int script_nr) {
- SegmentId segment = segMan->getScriptSegment(script_nr);
- Script *scr = segMan->getScriptIfLoaded(segment);
+Common::Array<reg_t> Script::listAllDeallocatable(SegmentId segId) const {
+ const reg_t r = make_reg(segId, 0);
+ return Common::Array<reg_t>(&r, 1);
+}
- if (!scr) { // Is it already loaded?
- //warning("unloading script 0x%x requested although not loaded", script_nr);
- // This is perfectly valid SCI behaviour
- return;
+Common::Array<reg_t> Script::listAllOutgoingReferences(reg_t addr) const {
+ Common::Array<reg_t> tmp;
+ if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) {
+ const Object *obj = getObject(addr.offset);
+ if (obj) {
+ // Note all local variables, if we have a local variable environment
+ if (_localsSegment)
+ tmp.push_back(make_reg(_localsSegment, 0));
+
+ for (uint i = 0; i < obj->getVarCount(); i++)
+ tmp.push_back(obj->getVariable(i));
+ } else {
+ error("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr));
+ }
+ } else {
+ /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/
+ /* Happens e.g. when we're looking into strings */
}
+ return tmp;
+}
- scr->decrementLockers(); // One less locker
-
- if (scr->getLockers() > 0)
- return;
-
- // Free all classtable references to this script
- for (uint i = 0; i < segMan->_classtable.size(); i++)
- if (segMan->_classtable[i].reg.segment == segment)
- segMan->_classtable[i].reg = NULL_REG;
-
- if (getSciVersion() < SCI_VERSION_1_1)
- script_uninstantiate_sci0(segMan, script_nr, segment);
- // FIXME: Add proper script uninstantiation for SCI 1.1
-
- if (scr->getLockers())
- return; // if xxx.lockers > 0
+Common::Array<reg_t> Script::listObjectReferences() const {
+ Common::Array<reg_t> tmp;
- // Otherwise unload it completely
- // Explanation: I'm starting to believe that this work is done by SCI itself.
- scr->markDeleted();
+ // Locals, if present
+ if (_localsSegment)
+ tmp.push_back(make_reg(_localsSegment, 0));
- debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr);
+ // All objects (may be classes, may be indirectly reachable)
+ ObjMap::iterator it;
+ const ObjMap::iterator end = _objects.end();
+ for (it = _objects.begin(); it != end; ++it) {
+ tmp.push_back(it->_value.getPos());
+ }
- return;
+ return tmp;
}
-
} // End of namespace Sci
diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h
index e94e9f64e6..c60cc4b19f 100644
--- a/engines/sci/engine/script.h
+++ b/engines/sci/engine/script.h
@@ -27,13 +27,13 @@
#define SCI_ENGINE_SCRIPT_H
#include "common/str.h"
+#include "sci/engine/segment.h"
namespace Sci {
struct EngineState;
class ResourceManager;
-
-#define SCI_SCRIPTS_NR 1000
+struct SciScriptSignature;
enum ScriptObjectTypes {
SCI_OBJ_TERMINATOR,
@@ -49,160 +49,218 @@ enum ScriptObjectTypes {
SCI_OBJ_LOCALVARS
};
-// Opcode formats
-enum opcode_format {
- Script_Invalid = -1,
- Script_None = 0,
- Script_Byte,
- Script_SByte,
- Script_Word,
- Script_SWord,
- Script_Variable,
- Script_SVariable,
- Script_SRelative,
- Script_Property,
- Script_Global,
- Script_Local,
- Script_Temp,
- Script_Param,
- Script_Offset,
- Script_End
-};
+typedef Common::HashMap<uint16, Object> ObjMap;
-enum sci_opcodes {
- op_bnot = 0x00, // 000
- op_add = 0x01, // 001
- op_sub = 0x02, // 002
- op_mul = 0x03, // 003
- op_div = 0x04, // 004
- op_mod = 0x05, // 005
- op_shr = 0x06, // 006
- op_shl = 0x07, // 007
- op_xor = 0x08, // 008
- op_and = 0x09, // 009
- op_or = 0x0a, // 010
- op_neg = 0x0b, // 011
- op_not = 0x0c, // 012
- op_eq_ = 0x0d, // 013
- op_ne_ = 0x0e, // 014
- op_gt_ = 0x0f, // 015
- op_ge_ = 0x10, // 016
- op_lt_ = 0x11, // 017
- op_le_ = 0x12, // 018
- op_ugt_ = 0x13, // 019
- op_uge_ = 0x14, // 020
- op_ult_ = 0x15, // 021
- op_ule_ = 0x16, // 022
- op_bt = 0x17, // 023
- op_bnt = 0x18, // 024
- op_jmp = 0x19, // 025
- op_ldi = 0x1a, // 026
- op_push = 0x1b, // 027
- op_pushi = 0x1c, // 028
- op_toss = 0x1d, // 029
- op_dup = 0x1e, // 030
- op_link = 0x1f, // 031
- op_call = 0x20, // 032
- op_callk = 0x21, // 033
- op_callb = 0x22, // 034
- op_calle = 0x23, // 035
- op_ret = 0x24, // 036
- op_send = 0x25, // 037
- // dummy 0x26, // 038
- // dummy 0x27, // 039
- op_class = 0x28, // 040
- // dummy 0x29, // 041
- op_self = 0x2a, // 042
- op_super = 0x2b, // 043
- op_rest = 0x2c, // 044
- op_lea = 0x2d, // 045
- op_selfID = 0x2e, // 046
- // dummy 0x2f // 047
- op_pprev = 0x30, // 048
- op_pToa = 0x31, // 049
- op_aTop = 0x32, // 050
- op_pTos = 0x33, // 051
- op_sTop = 0x34, // 052
- op_ipToa = 0x35, // 053
- op_dpToa = 0x36, // 054
- op_ipTos = 0x37, // 055
- op_dpTos = 0x38, // 056
- op_lofsa = 0x39, // 057
- op_lofss = 0x3a, // 058
- op_push0 = 0x3b, // 059
- op_push1 = 0x3c, // 060
- op_push2 = 0x3d, // 061
- op_pushSelf = 0x3e, // 062
- op_line = 0x3f, // 063
- op_lag = 0x40, // 064
- op_lal = 0x41, // 065
- op_lat = 0x42, // 066
- op_lap = 0x43, // 067
- op_lsg = 0x44, // 068
- op_lsl = 0x45, // 069
- op_lst = 0x46, // 070
- op_lsp = 0x47, // 071
- op_lagi = 0x48, // 072
- op_lali = 0x49, // 073
- op_lati = 0x4a, // 074
- op_lapi = 0x4b, // 075
- op_lsgi = 0x4c, // 076
- op_lsli = 0x4d, // 077
- op_lsti = 0x4e, // 078
- op_lspi = 0x4f, // 079
- op_sag = 0x50, // 080
- op_sal = 0x51, // 081
- op_sat = 0x52, // 082
- op_sap = 0x53, // 083
- op_ssg = 0x54, // 084
- op_ssl = 0x55, // 085
- op_sst = 0x56, // 086
- op_ssp = 0x57, // 087
- op_sagi = 0x58, // 088
- op_sali = 0x59, // 089
- op_sati = 0x5a, // 090
- op_sapi = 0x5b, // 091
- op_ssgi = 0x5c, // 092
- op_ssli = 0x5d, // 093
- op_ssti = 0x5e, // 094
- op_sspi = 0x5f, // 095
- op_plusag = 0x60, // 096
- op_plusal = 0x61, // 097
- op_plusat = 0x62, // 098
- op_plusap = 0x63, // 099
- op_plussg = 0x64, // 100
- op_plussl = 0x65, // 101
- op_plusst = 0x66, // 102
- op_plussp = 0x67, // 103
- op_plusagi = 0x68, // 104
- op_plusali = 0x69, // 105
- op_plusati = 0x6a, // 106
- op_plusapi = 0x6b, // 107
- op_plussgi = 0x6c, // 108
- op_plussli = 0x6d, // 109
- op_plussti = 0x6e, // 110
- op_plusspi = 0x6f, // 111
- op_minusag = 0x70, // 112
- op_minusal = 0x71, // 113
- op_minusat = 0x72, // 114
- op_minusap = 0x73, // 115
- op_minussg = 0x74, // 116
- op_minussl = 0x75, // 117
- op_minusst = 0x76, // 118
- op_minussp = 0x77, // 119
- op_minusagi = 0x78, // 120
- op_minusali = 0x79, // 121
- op_minusati = 0x7a, // 122
- op_minusapi = 0x7b, // 123
- op_minussgi = 0x7c, // 124
- op_minussli = 0x7d, // 125
- op_minussti = 0x7e, // 126
- op_minusspi = 0x7f // 127
-};
+class Script : public SegmentObj {
+private:
+ int _nr; /**< Script number */
+ byte *_buf; /**< Static data buffer, or NULL if not used */
+ byte *_heapStart; /**< Start of heap if SCI1.1, NULL otherwise */
+
+ int _lockers; /**< Number of classes and objects that require this script */
+ size_t _scriptSize;
+ size_t _heapSize;
+ uint16 _bufSize;
+
+ const uint16 *_exportTable; /**< Abs. offset of the export table or 0 if not present */
+ uint16 _numExports; /**< Number of entries in the exports table */
+
+ const byte *_synonyms; /**< Synonyms block or 0 if not present*/
+ uint16 _numSynonyms; /**< Number of entries in the synonyms block */
+
+ int _localsOffset;
+ uint16 _localsCount;
+
+ bool _markedAsDeleted;
+
+public:
+ /**
+ * Table for objects, contains property variables.
+ * Indexed by the TODO offset.
+ */
+ ObjMap _objects;
+ SegmentId _localsSegment; /**< The local variable segment */
+ LocalVariables *_localsBlock;
+
+public:
+ int getLocalsOffset() const { return _localsOffset; }
+ uint16 getLocalsCount() const { return _localsCount; }
+
+ uint32 getScriptSize() const { return _scriptSize; }
+ uint32 getHeapSize() const { return _heapSize; }
+ uint32 getBufSize() const { return _bufSize; }
+ const byte *getBuf(uint offset = 0) const { return _buf + offset; }
+
+ int getScriptNumber() const { return _nr; }
+
+public:
+ Script();
+ ~Script();
+
+ void freeScript();
+ void init(int script_nr, ResourceManager *resMan);
+ void load(ResourceManager *resMan);
+
+ void matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize);
+ int32 findSignature(const SciScriptSignature *signature, const byte *scriptData, const uint32 scriptSize);
+ void applyPatch(const uint16 *patch, byte *scriptData, const uint32 scriptSize, int32 signatureOffset);
+
+ virtual bool isValidOffset(uint16 offset) const;
+ virtual SegmentRef dereference(reg_t pointer);
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const;
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
+ virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const;
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
+
+ /**
+ * Return a list of all references to objects in this script
+ * (and also to the locals segment, if any).
+ * Used by the garbage collector.
+ * @return a list of outgoing references within the object
+ */
+ Common::Array<reg_t> listObjectReferences() const;
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+
+ Object *getObject(uint16 offset);
+ const Object *getObject(uint16 offset) const;
+
+ /**
+ * Initializes an object within the segment manager
+ * @param obj_pos Location (segment, offset) of the object. It must
+ * point to the beginning of the script/class block
+ * (as opposed to what the VM considers to be the
+ * object location)
+ * @returns A newly created Object describing the object,
+ * stored within the relevant script
+ */
+ Object *scriptObjInit(reg_t obj_pos, bool fullObjectInit = true);
-extern opcode_format g_opcode_formats[128][4];
+ /**
+ * Removes a script object
+ * @param obj_pos Location (segment, offset) of the object.
+ */
+ void scriptObjRemove(reg_t obj_pos);
-void script_adjust_opcode_formats(EngineState *s);
+ /**
+ * Initializes the script's local variables
+ * @param segMan A reference to the segment manager
+ */
+ void initialiseLocals(SegManager *segMan);
+
+ /**
+ * Adds the script's classes to the segment manager's class table
+ * @param segMan A reference to the segment manager
+ */
+ void initialiseClasses(SegManager *segMan);
+
+ /**
+ * Initializes the script's objects (SCI0)
+ * @param segMan A reference to the segment manager
+ * @param segmentId The script's segment id
+ */
+ void initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId);
+
+ /**
+ * Initializes the script's objects (SCI1.1+)
+ * @param segMan A reference to the segment manager
+ * @param segmentId The script's segment id
+ */
+ void initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId);
+
+ // script lock operations
+
+ /** Increments the number of lockers of this script by one. */
+ void incrementLockers();
+
+ /** Decrements the number of lockers of this script by one. */
+ void decrementLockers();
+
+ /**
+ * Retrieves the number of locks held on this script.
+ * @return the number of locks held on the previously identified script
+ */
+ int getLockers() const;
+
+ /** Sets the number of locks held on this script. */
+ void setLockers(int lockers);
+
+ /**
+ * Retrieves a pointer to the exports of this script
+ * @return pointer to the exports.
+ */
+ const uint16 *getExportTable() const { return _exportTable; }
+
+ /**
+ * Retrieves the number of exports of script.
+ * @return the number of exports of this script
+ */
+ uint16 getExportsNr() const { return _numExports; }
+
+ /**
+ * Retrieves a pointer to the synonyms associated with this script
+ * @return pointer to the synonyms, in non-parsed format.
+ */
+ const byte *getSynonyms() const { return _synonyms; }
+
+ /**
+ * Retrieves the number of synonyms associated with this script.
+ * @return the number of synonyms associated with this script
+ */
+ uint16 getSynonymsNr() const { return _numSynonyms; }
+
+ /**
+ * Validate whether the specified public function is exported by
+ * the script in the specified segment.
+ * @param pubfunct Index of the function to validate
+ * @return NULL if the public function is invalid, its
+ * offset into the script's segment otherwise
+ */
+ uint16 validateExportFunc(int pubfunct);
+
+ /**
+ * Marks the script as deleted.
+ * This will not actually delete the script. If references remain present on the
+ * heap or the stack, the script will stay in memory in a quasi-deleted state until
+ * either unreachable (resulting in its eventual deletion) or reloaded (resulting
+ * in its data being updated).
+ */
+ void markDeleted() {
+ _markedAsDeleted = true;
+ }
+
+ /**
+ * Determines whether the script is marked as being deleted.
+ */
+ bool isMarkedAsDeleted() const {
+ return _markedAsDeleted;
+ }
+
+ /**
+ * Copies a byte string into a script's heap representation.
+ * @param dst script-relative offset of the destination area
+ * @param src pointer to the data source location
+ * @param n number of bytes to copy
+ */
+ void mcpyInOut(int dst, const void *src, size_t n);
+
+ /**
+ * Finds the pointer where a block of a specific type starts from
+ */
+ byte *findBlock(int type, int skipBlockIndex = -1);
+
+private:
+ /**
+ * Processes a relocation block witin a script
+ * This function is idempotent, but it must only be called after all
+ * objects have been instantiated, or a run-time error will occur.
+ * @param obj_pos Location (segment, offset) of the block
+ * @return Location of the relocation block
+ */
+ void relocate(reg_t block);
+
+ bool relocateLocal(SegmentId segment, int location);
+};
} // End of namespace Sci
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
new file mode 100644
index 0000000000..e5fcbf72c2
--- /dev/null
+++ b/engines/sci/engine/script_patches.cpp
@@ -0,0 +1,353 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/sci.h"
+#include "sci/engine/script.h"
+
+#include "common/util.h"
+
+namespace Sci {
+
+#define PATCH_END 0xFFFF
+#define PATCH_ADDTOOFFSET 0x8000
+#define PATCH_GETORIGINALBYTE 0x4000
+#define PATCH_MAGICDWORD(a, b, c, d) CONSTANT_LE_32(a | (b << 8) | (c << 16) | (d << 24))
+
+struct SciScriptSignature {
+ uint16 scriptNr;
+ const char *description;
+ uint32 magicDWord;
+ int magicOffset;
+ const byte *data;
+ const uint16 *patch;
+};
+
+// signatures are built like this:
+// - first a counter of the bytes that follow
+// - then the actual bytes that need to get matched
+// - then another counter of bytes (0 for EOS)
+// - if not EOS, an adjust offset and the actual bytes
+// - rinse and repeat
+
+
+// daySixBeignet::changeState is called when the cop goes out and sets cycles to 220.
+// this is not enough time to get to the door, so we patch that to 23 seconds
+const byte gk1SignatureDay6PoliceBeignet[] = {
+ 4,
+ 0x35, 0x04, // ldi 04
+ 0x1a, // eq?
+ 0x30, // bnt [next state check]
+ +2, 5, // [skip 2 bytes, offset of bnt]
+ 0x38, 0x93, 0x00, // pushi 93 (selector dispose)
+ 0x76, // push0
+ 0x72, // lofsa deskSarg
+ +2, 9, // [skip 2 bytes, offset of lofsa]
+ 0x4a, 0x04, 0x00, // send 04
+ 0x34, 0xdc, 0x00, // ldi 220
+ 0x65, 0x1a, // aTop cycles
+ 0x32, // jmp [end]
+ 0
+};
+
+const uint16 gk1PatchDay6PoliceBeignet[] = {
+ PATCH_ADDTOOFFSET | +16,
+ 0x34, 0x17, 0x00, // ldi 23
+ 0x65, 0x1c, // aTop seconds
+ PATCH_END
+};
+
+const byte gk1SignatureDay6PoliceSleep[] = {
+ 4,
+ 0x35, 0x08, // ldi 08
+ 0x1a, // eq?
+ 0x31, // bnt [next state check]
+ +1, 5, // [skip 1 byte, offset of bnt]
+ 0x34, 0xdc, 0x00, // ldi 220
+ 0x65, 0x1a, // aTop cycles
+ 0x32, // jmp [end]
+ 0
+};
+
+const uint16 gk1PatchDay6PoliceSleep[] = {
+ PATCH_ADDTOOFFSET | +5,
+ 0x34, 0x2a, 0x00, // ldi 42
+ 0x65, 0x1c, // aTop seconds
+ PATCH_END
+};
+
+// script, description, magic DWORD, adjust
+const SciScriptSignature gk1Signatures[] = {
+ { 230, "day 6 police beignet timer issue", PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65), -16, gk1SignatureDay6PoliceBeignet, gk1PatchDay6PoliceBeignet },
+ { 230, "day 6 police sleep timer issue", PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65), -5, gk1SignatureDay6PoliceSleep, gk1PatchDay6PoliceSleep },
+ { 0, NULL, 0, 0, NULL, NULL }
+};
+
+// this here gets called on entry and when going out of game windows
+// uEvt::port will not get changed after kDisposeWindow but a bit later, so
+// we would get an invalid port handle to a kSetPort call. We just patch in
+// resetting of the port selector. We destroy the stop/fade code in there,
+// it seems it isn't used at all in the game.
+const byte hoyle4SignaturePortFix[] = {
+ 28,
+ 0x39, 0x09, // pushi 09
+ 0x89, 0x0b, // lsg 0b
+ 0x39, 0x64, // pushi 64
+ 0x38, 0xc8, 0x00, // pushi 00c8
+ 0x38, 0x2c, 0x01, // pushi 012c
+ 0x38, 0x90, 0x01, // pushi 0190
+ 0x38, 0xf4, 0x01, // pushi 01f4
+ 0x38, 0x58, 0x02, // pushi 0258
+ 0x38, 0xbc, 0x02, // pushi 02bc
+ 0x38, 0x20, 0x03, // pushi 0320
+ 0x46, // calle [xxxx] [xxxx] [xx]
+ +5, 43, // [skip 5 bytes]
+ 0x30, 0x27, 0x00, // bnt 0027 -> end of routine
+ 0x87, 0x00, // lap 00
+ 0x30, 0x19, 0x00, // bnt 0019 -> fade out
+ 0x87, 0x01, // lap 01
+ 0x30, 0x14, 0x00, // bnt 0014 -> fade out
+ 0x38, 0xa7, 0x00, // pushi 00a7
+ 0x76, // push0
+ 0x80, 0x29, 0x01, // lag 0129
+ 0x4a, 0x04, // send 04 (song::stop)
+ 0x39, 0x27, // pushi 27
+ 0x78, // push1
+ 0x8f, 0x01, // lsp 01
+ 0x51, 0x54, // class 54
+ 0x4a, 0x06, // send 06 (PlaySong::play)
+ 0x33, 0x09, // jmp 09 -> end of routine
+ 0x38, 0xaa, 0x00, // pushi 00aa
+ 0x76, // push0
+ 0x80, 0x29, 0x01, // lag 0129
+ 0x4a, 0x04, // send 04
+ 0x48, // ret
+ 0
+};
+
+const uint16 hoyle4PatchPortFix[] = {
+ PATCH_ADDTOOFFSET | +33,
+ 0x38, 0x31, 0x01, // pushi 0131 (selector curEvent)
+ 0x76, // push0
+ 0x80, 0x50, 0x00, // lag 0050 (global var 80h, "User")
+ 0x4a, 0x04, // send 04 (read User::curEvent)
+
+ 0x38, 0x93, 0x00, // pushi 0093 (selector port)
+ 0x78, // push1
+ 0x76, // push0
+ 0x4a, 0x06, // send 06 (write 0 to that object::port)
+ 0x48, // ret
+ PATCH_END
+};
+
+// script, description, magic DWORD, adjust
+const SciScriptSignature hoyle4Signatures[] = {
+ { 0, "port fix when disposing windows", PATCH_MAGICDWORD(0x64, 0x38, 0xC8, 0x00), -5, hoyle4SignaturePortFix, hoyle4PatchPortFix },
+ { 0, NULL, 0, 0, NULL, NULL }
+};
+
+
+// this is called on every death dialog. Problem is at least the german
+// version of lsl6 gets title text that is far too long for the
+// available temp space resulting in temp space corruption
+// This patch moves the title text around, so this overflow
+// doesn't happen anymore. We would otherwise get a crash
+// calling for invalid views (this happens of course also
+// in sierra sci)
+const byte larry6SignatureDeathDialog[] = {
+ 7,
+ 0x3e, 0x33, 0x01, // link 0133 (offset 0x20)
+ 0x35, 0xff, // ldi ff
+ 0xa3, 0x00, // sal 00
+ +255, 0,
+ +255, 0,
+ +170, 12, // [skip 680 bytes]
+ 0x8f, 0x01, // lsp 01 (offset 0x2cf)
+ 0x7a, // push2
+ 0x5a, 0x04, 0x00, 0x0e, 0x01, // lea 0004 010e
+ 0x36, // push
+ 0x43, 0x7c, 0x0e, // kMessage[7c] 0e
+ +90, 10, // [skip 90 bytes]
+ 0x38, 0xd6, 0x00, // pushi 00d6 (offset 0x335)
+ 0x78, // push1
+ 0x5a, 0x04, 0x00, 0x0e, 0x01, // lea 0004 010e
+ 0x36, // push
+ +76, 11, // [skip 76 bytes]
+ 0x38, 0xcd, 0x00, // pushi 00cd (offset 0x38b)
+ 0x39, 0x03, // pushi 03
+ 0x5a, 0x04, 0x00, 0x0e, 0x01, // lea 0004 010e
+ 0x36,
+ 0
+};
+
+const uint16 larry6PatchDeathDialog[] = {
+ 0x3e, 0x00, 0x02, // link 0200
+ PATCH_ADDTOOFFSET | +687,
+ 0x5a, 0x04, 0x00, 0x40, 0x01, // lea 0004 0140
+ PATCH_ADDTOOFFSET | +98,
+ 0x5a, 0x04, 0x00, 0x40, 0x01, // lea 0004 0140
+ PATCH_ADDTOOFFSET | +82,
+ 0x5a, 0x04, 0x00, 0x40, 0x01, // lea 0004 0140
+ PATCH_END
+};
+
+// script, description, magic DWORD, adjust
+const SciScriptSignature larry6Signatures[] = {
+ { 82, "death dialog memory corruption", PATCH_MAGICDWORD(0x3e, 0x33, 0x01, 0x35), 0, larry6SignatureDeathDialog, larry6PatchDeathDialog },
+ { 0, NULL, 0, 0, NULL, NULL }
+};
+
+// It seems to scripts warp ego outside the screen somehow (or maybe kDoBresen?)
+// ego::mover is set to 0 and rm119::doit will crash in that case. This here
+// fixes part of the problem and actually checks ego::mover to be 0 and skips
+// TODO: this should get further investigated by waltervn and maybe properly
+// patched. For now ego will shortly disappear and reappear a bit after
+// this isn't good, but sierra sci also "crashed" (endless looped) so this
+// is at least better than the original code
+const byte sq5SignatureScrubbing[] = {
+ 19,
+ 0x18, // not
+ 0x31, 0x37, // bnt 37
+ 0x78, // push1 (selector x)
+ 0x76, // push0
+ 0x39, 0x38, // pushi 38 (selector mover)
+ 0x76, // push0
+ 0x81, 0x00, // lag 00
+ 0x4a, 0x04, // send 04 (read ego::mover)
+ 0x4a, 0x04, // send 04 (read ego::mover::x)
+ 0x36, // push
+ 0x34, 0xa0, 0x00, // ldi 00a0
+ 0x1c, // ne?
+ 0
+};
+
+const uint16 sq5PatchScrubbing[] = {
+ 0x18, // not
+ 0x31, 0x37, // bnt 37
+// 0x2f, 0x38, // bt 37 (would save another byte, isn't needed
+ 0x39, 0x38, // pushi 38 (selector mover)
+ 0x76, // push0
+ 0x81, 0x00, // lag 00
+ 0x4a, 0x04, // send 04 (read ego::mover)
+ 0x31, 0x2e, // bnt 2e (jump if ego::mover is 0)
+ 0x78, // push1 (selector x)
+ 0x76, // push0
+ 0x4a, 0x04, // send 04 (read ego::mover::x)
+ 0x39, 0xa0, // pushi a0 (saving 2 bytes)
+ 0x1c, // ne?
+ PATCH_END
+};
+
+// script, description, magic DWORD, adjust
+const SciScriptSignature sq5Signatures[] = {
+ { 119, "scrubbing send crash", PATCH_MAGICDWORD(0x18, 0x31, 0x37, 0x78), 0, sq5SignatureScrubbing, sq5PatchScrubbing },
+ { 0, NULL, 0, 0, NULL, NULL }
+};
+
+
+// will actually patch previously found signature area
+void Script::applyPatch(const uint16 *patch, byte *scriptData, const uint32 scriptSize, int32 signatureOffset) {
+ int32 offset = signatureOffset;
+ uint16 patchWord = *patch;
+
+ while (patchWord != PATCH_END) {
+ if (patchWord & PATCH_ADDTOOFFSET) {
+ offset += patchWord & ~PATCH_ADDTOOFFSET;
+ } else if (patchWord & PATCH_GETORIGINALBYTE) {
+ // TODO: implement this
+ } else {
+ scriptData[offset] = patchWord & 0xFF;
+ offset++;
+ }
+ patch++;
+ patchWord = *patch;
+ }
+}
+
+// will return -1 if no match was found, otherwise an offset to the start of the signature match
+int32 Script::findSignature(const SciScriptSignature *signature, const byte *scriptData, const uint32 scriptSize) {
+ if (scriptSize < 4) // we need to find a DWORD, so less than 4 bytes is not okay
+ return -1;
+
+ const uint32 magicDWord = signature->magicDWord; // is platform-specific BE/LE form, so that the later match will work
+ const uint32 searchLimit = scriptSize - 3;
+ uint32 DWordOffset = 0;
+ // first search for the magic DWORD
+ while (DWordOffset < searchLimit) {
+ if (magicDWord == *(const uint32 *)(scriptData + DWordOffset)) {
+ // magic DWORD found, check if actual signature matches
+ uint32 offset = DWordOffset + signature->magicOffset;
+ uint32 byteOffset = offset;
+ const byte *signatureData = signature->data;
+ byte matchAdjust = 1;
+ while (matchAdjust) {
+ byte matchBytesCount = *signatureData++;
+ if ((byteOffset + matchBytesCount) > scriptSize) // Out-Of-Bounds?
+ break;
+ if (memcmp(signatureData, &scriptData[byteOffset], matchBytesCount)) // Byte-Mismatch?
+ break;
+ // those bytes matched, adjust offsets accordingly
+ signatureData += matchBytesCount;
+ byteOffset += matchBytesCount;
+ // get offset...
+ matchAdjust = *signatureData++;
+ byteOffset += matchAdjust;
+ }
+ if (!matchAdjust) // all matches worked?
+ return offset;
+ }
+ DWordOffset++;
+ }
+ // nothing found
+ return -1;
+}
+
+void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) {
+ const SciScriptSignature *signatureTable = NULL;
+ if (g_sci->getGameId() == GID_GK1)
+ signatureTable = gk1Signatures;
+// hoyle4 now works due workaround inside GfxPorts
+// if (g_sci->getGameId() == GID_HOYLE4)
+// signatureTable = hoyle4Signatures;
+ if (g_sci->getGameId() == GID_LSL6)
+ signatureTable = larry6Signatures;
+ if (g_sci->getGameId() == GID_SQ5)
+ signatureTable = sq5Signatures;
+
+ if (signatureTable) {
+ while (signatureTable->data) {
+ if (scriptNr == signatureTable->scriptNr) {
+ int32 foundOffset = findSignature(signatureTable, scriptData, scriptSize);
+ if (foundOffset != -1) {
+ // found, so apply the patch
+ warning("matched %s on script %d offset %d", signatureTable->description, scriptNr, foundOffset);
+ applyPatch(signatureTable->patch, scriptData, scriptSize, foundOffset);
+ }
+ }
+ signatureTable++;
+ }
+ }
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 4b60626b2e..9c08526fbb 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -63,46 +63,11 @@ const char *opcodeNames[] = {
"-sli", "-sti", "-spi"
};
-extern const char *selector_name(EngineState *s, int selector);
-
-DebugState g_debugState;
-
-int propertyOffsetToId(SegManager *segMan, int prop_ofs, reg_t objp) {
- Object *obj = segMan->getObject(objp);
- byte *selectoroffset;
- int selectors;
-
- if (!obj) {
- warning("Applied propertyOffsetToId on non-object at %04x:%04x", PRINT_REG(objp));
- return -1;
- }
-
- selectors = obj->getVarCount();
-
- if (getSciVersion() < SCI_VERSION_1_1)
- selectoroffset = ((byte *)(obj->_baseObj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2;
- else {
- if (!(obj->getInfoSelector().offset & SCRIPT_INFO_CLASS)) {
- obj = segMan->getObject(obj->getSuperClassSelector());
- selectoroffset = (byte *)obj->_baseVars;
- } else
- selectoroffset = (byte *)obj->_baseVars;
- }
-
- if (prop_ofs < 0 || (prop_ofs >> 1) >= selectors) {
- warning("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d]) on object at %04x:%04x",
- prop_ofs, prop_ofs >> 1, selectors - 1, PRINT_REG(objp));
- return -1;
- }
-
- return READ_SCI11ENDIAN_UINT16(selectoroffset + prop_ofs);
-}
-
// Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered.
reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecode) {
SegmentObj *mobj = s->_segMan->getSegment(pos.segment, SEG_TYPE_SCRIPT);
Script *script_entity = NULL;
- byte *scr;
+ const byte *scr;
int scr_size;
reg_t retval = make_reg(pos.segment, pos.offset + 1);
uint16 param_value;
@@ -115,8 +80,8 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
} else
script_entity = (Script *)mobj;
- scr = script_entity->_buf;
- scr_size = script_entity->_bufSize;
+ scr = script_entity->getBuf();
+ scr_size = script_entity->getBufSize();
if (pos.offset >= scr_size) {
warning("Trying to disassemble beyond end of script");
@@ -221,51 +186,52 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
}
}
- if (pos == scriptState.xs->addr.pc) { // Extra information if debugging the current opcode
+ if (pos == s->xs->addr.pc) { // Extra information if debugging the current opcode
if ((opcode == op_pTos) || (opcode == op_sTop) || (opcode == op_pToa) || (opcode == op_aTop) ||
(opcode == op_dpToa) || (opcode == op_ipToa) || (opcode == op_dpTos) || (opcode == op_ipTos)) {
- int prop_ofs = scr[pos.offset + 1];
- int prop_id = propertyOffsetToId(s->_segMan, prop_ofs, scriptState.xs->objp);
-
- printf(" (%s)", selector_name(s, prop_id));
+ const Object *obj = s->_segMan->getObject(s->xs->objp);
+ if (!obj)
+ warning("Attempted to reference on non-object at %04x:%04x", PRINT_REG(s->xs->objp));
+ else
+ printf(" (%s)", g_sci->getKernel()->getSelectorName(obj->propertyOffsetToId(s->_segMan, scr[pos.offset + 1])).c_str());
}
}
printf("\n");
- if (pos == scriptState.xs->addr.pc) { // Extra information if debugging the current opcode
+ if (pos == s->xs->addr.pc) { // Extra information if debugging the current opcode
if (opcode == op_callk) {
- int stackframe = (scr[pos.offset + 2] >> 1) + (scriptState.restAdjust);
- int argc = ((scriptState.xs->sp)[- stackframe - 1]).offset;
+ int stackframe = (scr[pos.offset + 2] >> 1) + (s->restAdjust);
+ int argc = ((s->xs->sp)[- stackframe - 1]).offset;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
if (!oldScriptHeader)
- argc += (scriptState.restAdjust);
+ argc += (s->restAdjust);
printf(" Kernel params: (");
for (int j = 0; j < argc; j++) {
- printf("%04x:%04x", PRINT_REG((scriptState.xs->sp)[j - stackframe]));
+ printf("%04x:%04x", PRINT_REG((s->xs->sp)[j - stackframe]));
if (j + 1 < argc)
printf(", ");
}
printf(")\n");
} else if ((opcode == op_send) || (opcode == op_self)) {
- int restmod = scriptState.restAdjust;
+ int restmod = s->restAdjust;
int stackframe = (scr[pos.offset + 1] >> 1) + restmod;
- reg_t *sb = scriptState.xs->sp;
+ reg_t *sb = s->xs->sp;
uint16 selector;
reg_t fun_ref;
while (stackframe > 0) {
int argc = sb[- stackframe + 1].offset;
const char *name = NULL;
- reg_t called_obj_addr = scriptState.xs->objp;
+ reg_t called_obj_addr = s->xs->objp;
if (opcode == op_send)
called_obj_addr = s->r_acc;
else if (opcode == op_self)
- called_obj_addr = scriptState.xs->objp;
+ called_obj_addr = s->xs->objp;
selector = sb[- stackframe].offset;
@@ -274,9 +240,9 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
if (!name)
name = "<invalid>";
- printf(" %s::%s[", name, (selector > kernel->getSelectorNamesSize()) ? "<invalid>" : selector_name(s, selector));
+ printf(" %s::%s[", name, g_sci->getKernel()->getSelectorName(selector).c_str());
- switch (lookup_selector(s->_segMan, called_obj_addr, selector, 0, &fun_ref)) {
+ switch (lookupSelector(s->_segMan, called_obj_addr, selector, 0, &fun_ref)) {
case kSelectorMethod:
printf("FUNCT");
argc += restmod;
@@ -309,90 +275,76 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
}
-void script_debug(EngineState *s) {
- // Do we support a separate console?
+void SciEngine::scriptDebug() {
+ EngineState *s = _gamestate;
+ if (_debugState.seeking && !_debugState.breakpointWasHit) { // Are we looking for something special?
+ if (_debugState.seeking == kDebugSeekStepOver) {
+ // are we above seek-level? resume then
+ if (_debugState.seekLevel < (int)s->_executionStack.size())
+ return;
+ _debugState.seeking = kDebugSeekNothing;
+ }
-#if 0
- if (sci_debug_flags & _DEBUG_FLAG_LOGGING) {
- printf("%d: acc=%04x:%04x ", script_step_counter, PRINT_REG(s->r_acc));
- disassemble(s, scriptState.xs->addr.pc, 0, 1);
- if (scriptState.seeking == kDebugSeekGlobal)
- printf("Global %d (0x%x) = %04x:%04x\n", scriptState.seekSpecial,
- scriptState.seekSpecial, PRINT_REG(s->script_000->_localsBlock->_locals[scriptState.seekSpecial]));
- }
-#endif
+ if (_debugState.seeking != kDebugSeekNothing) {
+ const reg_t pc = s->xs->addr.pc;
+ SegmentObj *mobj = s->_segMan->getSegment(pc.segment, SEG_TYPE_SCRIPT);
+
+ if (mobj) {
+ Script *scr = (Script *)mobj;
+ const byte *code_buf = scr->getBuf();
+ int code_buf_size = scr->getBufSize();
+ int opcode = pc.offset >= code_buf_size ? 0 : code_buf[pc.offset];
+ int op = opcode >> 1;
+ int paramb1 = pc.offset + 1 >= code_buf_size ? 0 : code_buf[pc.offset + 1];
+ int paramf1 = (opcode & 1) ? paramb1 : (pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + pc.offset + 1));
+
+ switch (_debugState.seeking) {
+ case kDebugSeekSpecialCallk:
+ if (paramb1 != _debugState.seekSpecial)
+ return;
+
+ case kDebugSeekCallk:
+ if (op != op_callk)
+ return;
+ break;
-#if 0
- if (!g_debugState.debugging)
- return;
-#endif
-
- if (g_debugState.seeking && !g_debugState.breakpointWasHit) { // Are we looking for something special?
- SegmentObj *mobj = s->_segMan->getSegment(scriptState.xs->addr.pc.segment, SEG_TYPE_SCRIPT);
-
- if (mobj) {
- Script *scr = (Script *)mobj;
- byte *code_buf = scr->_buf;
- int code_buf_size = scr->_bufSize;
- int opcode = scriptState.xs->addr.pc.offset >= code_buf_size ? 0 : code_buf[scriptState.xs->addr.pc.offset];
- int op = opcode >> 1;
- int paramb1 = scriptState.xs->addr.pc.offset + 1 >= code_buf_size ? 0 : code_buf[scriptState.xs->addr.pc.offset + 1];
- int paramf1 = (opcode & 1) ? paramb1 : (scriptState.xs->addr.pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + scriptState.xs->addr.pc.offset + 1));
-
- switch (g_debugState.seeking) {
- case kDebugSeekSpecialCallk:
- if (paramb1 != g_debugState.seekSpecial)
- return;
-
- case kDebugSeekCallk: {
- if (op != op_callk)
- return;
- break;
- }
+ case kDebugSeekLevelRet:
+ if ((op != op_ret) || (_debugState.seekLevel < (int)s->_executionStack.size()-1))
+ return;
+ break;
- case kDebugSeekLevelRet: {
- if ((op != op_ret) || (g_debugState.seekLevel < (int)s->_executionStack.size()-1))
- return;
- break;
- }
+ case kDebugSeekGlobal:
+ if (op < op_sag)
+ return;
+ if ((op & 0x3) > 1)
+ return; // param or temp
+ if ((op & 0x3) && s->_executionStack.back().local_segment > 0)
+ return; // locals and not running in script.000
+ if (paramf1 != _debugState.seekSpecial)
+ return; // CORRECT global?
+ break;
- case kDebugSeekGlobal:
- if (op < op_sag)
- return;
- if ((op & 0x3) > 1)
- return; // param or temp
- if ((op & 0x3) && s->_executionStack.back().local_segment > 0)
- return; // locals and not running in script.000
- if (paramf1 != g_debugState.seekSpecial)
- return; // CORRECT global?
- break;
-
- case kDebugSeekSO:
- // FIXME: Unhandled?
- break;
-
- case kDebugSeekNothing:
- // We seek nothing, so just continue
- break;
- }
+ default:
+ break;
+ }
- g_debugState.seeking = kDebugSeekNothing;
- // OK, found whatever we were looking for
+ _debugState.seeking = kDebugSeekNothing;
+ }
}
+ // OK, found whatever we were looking for
}
- printf("Step #%d\n", script_step_counter);
- disassemble(s, scriptState.xs->addr.pc, 0, 1);
+ printf("Step #%d\n", s->scriptStepCounter);
+ disassemble(s, s->xs->addr.pc, 0, 1);
- if (g_debugState.runningStep) {
- g_debugState.runningStep--;
+ if (_debugState.runningStep) {
+ _debugState.runningStep--;
return;
}
- g_debugState.debugging = false;
+ _debugState.debugging = false;
- Console *con = ((Sci::SciEngine*)g_engine)->getSciDebugger();
- con->attach();
+ _console->attach();
}
void Kernel::dumpScriptObject(char *data, int seeker, int objsize) {
@@ -521,106 +473,57 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
dumpScriptObject((char *)script->data, seeker, objsize);
break;
- case SCI_OBJ_CODE: {
+ case SCI_OBJ_CODE:
printf("Code\n");
Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ break;
- case 3: {
+ case 3:
printf("<unknown>\n");
Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ break;
- case SCI_OBJ_SAID: {
+ case SCI_OBJ_SAID:
printf("Said\n");
Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
printf("%04x: ", seeker);
- while (seeker < _seeker) {
- unsigned char nextitem = script->data [seeker++];
- if (nextitem == 0xFF)
- printf("\n%04x: ", seeker);
- else if (nextitem >= 0xF0) {
- switch (nextitem) {
- case 0xf0:
- printf(", ");
- break;
- case 0xf1:
- printf("& ");
- break;
- case 0xf2:
- printf("/ ");
- break;
- case 0xf3:
- printf("( ");
- break;
- case 0xf4:
- printf(") ");
- break;
- case 0xf5:
- printf("[ ");
- break;
- case 0xf6:
- printf("] ");
- break;
- case 0xf7:
- printf("# ");
- break;
- case 0xf8:
- printf("< ");
- break;
- case 0xf9:
- printf("> ");
- break;
- }
- } else {
- nextitem = nextitem << 8 | script->data [seeker++];
- printf("%s[%03x] ", vocab->getAnyWordFromGroup(nextitem), nextitem);
- }
- }
+ vocab->debugDecipherSaidBlock(script->data + seeker);
printf("\n");
- }
- break;
+ break;
- case SCI_OBJ_STRINGS: {
+ case SCI_OBJ_STRINGS:
printf("Strings\n");
while (script->data [seeker]) {
printf("%04x: %s\n", seeker, script->data + seeker);
seeker += strlen((char *)script->data + seeker) + 1;
}
seeker++; // the ending zero byte
- };
- break;
+ break;
case SCI_OBJ_CLASS:
dumpScriptClass((char *)script->data, seeker, objsize);
break;
- case SCI_OBJ_EXPORTS: {
+ case SCI_OBJ_EXPORTS:
printf("Exports\n");
Common::hexdump((unsigned char *)script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ break;
- case SCI_OBJ_POINTERS: {
+ case SCI_OBJ_POINTERS:
printf("Pointers\n");
Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ break;
- case 9: {
+ case 9:
printf("<unknown>\n");
Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ break;
- case SCI_OBJ_LOCALVARS: {
+ case SCI_OBJ_LOCALVARS:
printf("Local vars\n");
Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ break;
default:
printf("Unsupported!\n");
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index b18d76e1a7..1fb37f458d 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -26,6 +26,7 @@
#include "sci/sci.h"
#include "sci/engine/seg_manager.h"
#include "sci/engine/state.h"
+#include "sci/engine/script.h"
namespace Sci {
@@ -39,14 +40,14 @@ enum {
SegManager::SegManager(ResourceManager *resMan) {
_heap.push_back(0);
- Clones_seg_id = 0;
- Lists_seg_id = 0;
- Nodes_seg_id = 0;
- Hunks_seg_id = 0;
+ _clonesSegId = 0;
+ _listsSegId = 0;
+ _nodesSegId = 0;
+ _hunksSegId = 0;
#ifdef ENABLE_SCI32
- Arrays_seg_id = 0;
- String_seg_id = 0;
+ _arraysSegId = 0;
+ _stringSegId = 0;
#endif
_resMan = resMan;
@@ -54,7 +55,6 @@ SegManager::SegManager(ResourceManager *resMan) {
createClassTable();
}
-// Destroy the object, free the memorys if allocated before
SegManager::~SegManager() {
resetSegMan();
}
@@ -71,27 +71,40 @@ void SegManager::resetSegMan() {
// And reinitialize
_heap.push_back(0);
- Clones_seg_id = 0;
- Lists_seg_id = 0;
- Nodes_seg_id = 0;
- Hunks_seg_id = 0;
+ _clonesSegId = 0;
+ _listsSegId = 0;
+ _nodesSegId = 0;
+ _hunksSegId = 0;
// Reinitialize class table
- _classtable.clear();
+ _classTable.clear();
createClassTable();
}
+void SegManager::initSysStrings() {
+ _sysStrings = (SystemStrings *)allocSegment(new SystemStrings(), &_sysStringsSegId);
+
+ // Allocate static buffer for savegame and CWD directories
+ SystemString *strSaveDir = getSystemString(SYS_STRING_SAVEDIR);
+ strSaveDir->_name = "savedir";
+ strSaveDir->_maxSize = MAX_SAVE_DIR_SIZE;
+ strSaveDir->_value = (char *)calloc(MAX_SAVE_DIR_SIZE, sizeof(char));
+ // Set the savegame dir (actually, we set it to a fake value,
+ // since we cannot let the game control where saves are stored)
+ ::strcpy(strSaveDir->_value, "");
+
+ // Allocate static buffer for the parser base
+ SystemString *strParserBase = getSystemString(SYS_STRING_PARSER_BASE);
+ strParserBase->_name = "parser-base";
+ strParserBase->_maxSize = MAX_PARSER_BASE;
+ strParserBase->_value = (char *)calloc(MAX_PARSER_BASE, sizeof(char));
+}
+
SegmentId SegManager::findFreeSegment() const {
- // FIXME: This is a very crude approach: We find a free segment id by scanning
- // from the start. This can be slow if the number of segments becomes large.
- // Optimizations are possible and easy, but I refrain from doing any until this
- // refactoring is complete.
- // One very simple yet probably effective approach would be to add
- // "int firstFreeSegment", which is updated when allocating/freeing segments.
- // There are some scenarios where it performs badly, but we should first check
- // whether those occur at all. If so, there are easy refinements that deal
- // with this. Finally, we could switch to a more elaborate scheme,
- // such as keeping track of all free segments. But I doubt this is necessary.
+ // The following is a very crude approach: We find a free segment id by
+ // scanning from the start. This can be slow if the number of segments
+ // becomes large. Optimizations are possible and easy, but I'll refrain
+ // from attempting any until we determine we actually need it.
uint seg = 1;
while (seg < _heap.size() && _heap[seg]) {
++seg;
@@ -144,7 +157,7 @@ int SegManager::deallocate(SegmentId seg, bool recursive) {
if (mobj->getType() == SEG_TYPE_SCRIPT) {
Script *scr = (Script *)mobj;
- _scriptSegMap.erase(scr->_nr);
+ _scriptSegMap.erase(scr->getScriptNumber());
if (recursive && scr->_localsSegment)
deallocate(scr->_localsSegment, recursive);
}
@@ -155,12 +168,12 @@ int SegManager::deallocate(SegmentId seg, bool recursive) {
return 1;
}
-bool SegManager::isHeapObject(reg_t pos) {
- Object *obj = getObject(pos);
+bool SegManager::isHeapObject(reg_t pos) const {
+ const Object *obj = getObject(pos);
if (obj == NULL || (obj && obj->isFreed()))
return false;
Script *scr = getScriptIfLoaded(pos.segment);
- return !(scr && scr->_markedAsDeleted);
+ return !(scr && scr->isMarkedAsDeleted());
}
void SegManager::deallocateScript(int script_nr) {
@@ -181,36 +194,36 @@ Script *SegManager::getScript(const SegmentId seg) {
return (Script *)_heap[seg];
}
-Script *SegManager::getScriptIfLoaded(const SegmentId seg) {
+Script *SegManager::getScriptIfLoaded(const SegmentId seg) const {
if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg] || _heap[seg]->getType() != SEG_TYPE_SCRIPT)
return 0;
return (Script *)_heap[seg];
}
-SegmentId SegManager::findSegmentByType(int type) {
+SegmentId SegManager::findSegmentByType(int type) const {
for (uint i = 0; i < _heap.size(); i++)
if (_heap[i] && _heap[i]->getType() == type)
return i;
return 0;
}
-SegmentObj *SegManager::getSegmentObj(SegmentId seg) {
+SegmentObj *SegManager::getSegmentObj(SegmentId seg) const {
if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg])
return 0;
return _heap[seg];
}
-SegmentType SegManager::getSegmentType(SegmentId seg) {
+SegmentType SegManager::getSegmentType(SegmentId seg) const {
if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg])
return SEG_TYPE_INVALID;
return _heap[seg]->getType();
}
-SegmentObj *SegManager::getSegment(SegmentId seg, SegmentType type) {
+SegmentObj *SegManager::getSegment(SegmentId seg, SegmentType type) const {
return getSegmentType(seg) == type ? _heap[seg] : NULL;
}
-Object *SegManager::getObject(reg_t pos) {
+Object *SegManager::getObject(reg_t pos) const {
SegmentObj *mobj = getSegmentObj(pos.segment);
Object *obj = NULL;
@@ -223,8 +236,8 @@ Object *SegManager::getObject(reg_t pos) {
warning("getObject(): Trying to get an invalid object");
} else if (mobj->getType() == SEG_TYPE_SCRIPT) {
Script *scr = (Script *)mobj;
- if (pos.offset <= scr->_bufSize && pos.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET
- && RAW_IS_OBJECT(scr->_buf + pos.offset)) {
+ if (pos.offset <= scr->getBufSize() && pos.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET
+ && RAW_IS_OBJECT(scr->getBuf(pos.offset))) {
obj = scr->getObject(pos.offset);
}
}
@@ -234,7 +247,7 @@ Object *SegManager::getObject(reg_t pos) {
}
const char *SegManager::getObjectName(reg_t pos) {
- Object *obj = getObject(pos);
+ const Object *obj = getObject(pos);
if (!obj)
return "<no such object>";
@@ -250,78 +263,55 @@ const char *SegManager::getObjectName(reg_t pos) {
}
reg_t SegManager::findObjectByName(const Common::String &name, int index) {
- reg_t retVal = NULL_REG;
+ Common::Array<reg_t> result;
+ uint i;
// Now all values are available; iterate over all objects.
- int timesFound = 0;
- for (uint i = 0; i < _heap.size(); i++) {
- SegmentObj *mobj = _heap[i];
- int idx = 0;
- int max_index = 0;
- ObjMap::iterator it;
- Script *scr = 0;
- CloneTable *ct = 0;
-
- if (mobj) {
- if (mobj->getType() == SEG_TYPE_SCRIPT) {
- scr = (Script *)mobj;
- max_index = scr->_objects.size();
- it = scr->_objects.begin();
- } else if (mobj->getType() == SEG_TYPE_CLONES) {
- ct = (CloneTable *)mobj;
- max_index = ct->_table.size();
- }
- }
+ for (i = 0; i < _heap.size(); i++) {
+ const SegmentObj *mobj = _heap[i];
+
+ if (!mobj)
+ continue;
- // It's a script or a clone table, scan all objects in it
- for (; idx < max_index; ++idx) {
- Object *obj = NULL;
- reg_t objpos;
- objpos.offset = 0;
- objpos.segment = i;
-
- if (mobj->getType() == SEG_TYPE_SCRIPT) {
- obj = &(it->_value);
- objpos.offset = obj->getPos().offset;
- ++it;
- } else if (mobj->getType() == SEG_TYPE_CLONES) {
+ reg_t objpos = make_reg(i, 0);
+
+ if (mobj->getType() == SEG_TYPE_SCRIPT) {
+ // It's a script, scan all objects in it
+ const Script *scr = (const Script *)mobj;
+ for (ObjMap::const_iterator it = scr->_objects.begin(); it != scr->_objects.end(); ++it) {
+ objpos.offset = it->_value.getPos().offset;
+ if (name == getObjectName(objpos))
+ result.push_back(objpos);
+ }
+ } else if (mobj->getType() == SEG_TYPE_CLONES) {
+ // It's clone table, scan all objects in it
+ const CloneTable *ct = (const CloneTable *)mobj;
+ for (uint idx = 0; idx < ct->_table.size(); ++idx) {
if (!ct->isValidEntry(idx))
continue;
- obj = &(ct->_table[idx]);
- objpos.offset = idx;
- }
- const char *objname = getObjectName(objpos);
- if (name == objname) {
- // Found a match!
- if ((index < 0) && (timesFound > 0)) {
- if (timesFound == 1) {
- // First time we realized the ambiguity
- printf("Ambiguous:\n");
- printf(" %3x: [%04x:%04x] %s\n", 0, PRINT_REG(retVal), name.c_str());
- }
- printf(" %3x: [%04x:%04x] %s\n", timesFound, PRINT_REG(objpos), name.c_str());
- }
- if (index < 0 || timesFound == index)
- retVal = objpos;
- ++timesFound;
+ objpos.offset = idx;
+ if (name == getObjectName(objpos))
+ result.push_back(objpos);
}
}
-
}
- if (!timesFound)
+ if (result.empty())
return NULL_REG;
- if (timesFound > 1 && index < 0) {
- printf("Ambiguous: Aborting.\n");
+ if (result.size() > 1 && index < 0) {
+ printf("Ambiguous:\n");
+ for (i = 0; i < result.size(); i++)
+ printf(" %3x: [%04x:%04x] %s\n", i, PRINT_REG(result[i]), name.c_str());
return NULL_REG; // Ambiguous
}
- if (timesFound <= index)
+ if (index < 0)
+ return result[0];
+ else if (result.size() <= (uint)index)
return NULL_REG; // Not found
-
- return retVal;
+ return result[index];
}
// validate the seg
@@ -348,7 +338,7 @@ SegmentId SegManager::getScriptSegment(int script_nr, ScriptLoadType load) {
SegmentId segment;
if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD)
- script_instantiate(_resMan, this, script_nr);
+ instantiateScript(script_nr);
segment = getScriptSegment(script_nr);
@@ -359,8 +349,8 @@ SegmentId SegManager::getScriptSegment(int script_nr, ScriptLoadType load) {
return segment;
}
-LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) {
- if (!count) { // No locals
+LocalVariables *SegManager::allocLocalsSegment(Script *scr) {
+ if (!scr->getLocalsCount()) { // No locals
scr->_localsSegment = 0;
scr->_localsBlock = NULL;
return NULL;
@@ -371,13 +361,13 @@ LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) {
locals = (LocalVariables *)_heap[scr->_localsSegment];
VERIFY(locals != NULL, "Re-used locals segment was NULL'd out");
VERIFY(locals->getType() == SEG_TYPE_LOCALS, "Re-used locals segment did not consist of local variables");
- VERIFY(locals->script_id == scr->_nr, "Re-used locals segment belonged to other script");
+ VERIFY(locals->script_id == scr->getScriptNumber(), "Re-used locals segment belonged to other script");
} else
locals = (LocalVariables *)allocSegment(new LocalVariables(), &scr->_localsSegment);
scr->_localsBlock = locals;
- locals->script_id = scr->_nr;
- locals->_locals.resize(count);
+ locals->script_id = scr->getScriptNumber();
+ locals->_locals.resize(scr->getLocalsCount());
return locals;
}
@@ -390,11 +380,13 @@ DataStack *SegManager::allocateStack(int size, SegmentId *segid) {
retval->_entries = (reg_t *)calloc(size, sizeof(reg_t));
retval->_capacity = size;
- return retval;
-}
+ // SSCI initializes the stack with "S" characters (uppercase S in SCI0-SCI1,
+ // lowercase s in SCI0 and SCI11) - probably stands for "stack"
+ byte filler = (getSciVersion() >= SCI_VERSION_01 && getSciVersion() <= SCI_VERSION_1_LATE) ? 'S' : 's';
+ for (int i = 0; i < size; i++)
+ retval->_entries[i] = make_reg(0, filler);
-SystemStrings *SegManager::allocateSysStrings(SegmentId *segid) {
- return (SystemStrings *)allocSegment(new SystemStrings(), segid);
+ return retval;
}
void SegManager::freeHunkEntry(reg_t addr) {
@@ -417,13 +409,13 @@ reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) {
HunkTable *table;
int offset;
- if (!Hunks_seg_id)
- allocSegment(new HunkTable(), &(Hunks_seg_id));
- table = (HunkTable *)_heap[Hunks_seg_id];
+ if (!_hunksSegId)
+ allocSegment(new HunkTable(), &(_hunksSegId));
+ table = (HunkTable *)_heap[_hunksSegId];
offset = table->allocEntry();
- reg_t addr = make_reg(Hunks_seg_id, offset);
+ reg_t addr = make_reg(_hunksSegId, offset);
Hunk *h = &(table->_table[offset]);
if (!h)
@@ -440,7 +432,7 @@ byte *SegManager::getHunkPointer(reg_t addr) {
HunkTable *ht = (HunkTable *)getSegment(addr.segment, SEG_TYPE_HUNK);
if (!ht || !ht->isValidEntry(addr.offset)) {
- warning("getHunkPointer() with invalid handle");
+ // Valid SCI behavior, e.g. when loading/quitting
return NULL;
}
@@ -451,61 +443,28 @@ Clone *SegManager::allocateClone(reg_t *addr) {
CloneTable *table;
int offset;
- if (!Clones_seg_id)
- table = (CloneTable *)allocSegment(new CloneTable(), &(Clones_seg_id));
+ if (!_clonesSegId)
+ table = (CloneTable *)allocSegment(new CloneTable(), &(_clonesSegId));
else
- table = (CloneTable *)_heap[Clones_seg_id];
+ table = (CloneTable *)_heap[_clonesSegId];
offset = table->allocEntry();
- *addr = make_reg(Clones_seg_id, offset);
+ *addr = make_reg(_clonesSegId, offset);
return &(table->_table[offset]);
}
-void SegManager::reconstructClones() {
- for (uint i = 0; i < _heap.size(); i++) {
- if (_heap[i]) {
- SegmentObj *mobj = _heap[i];
- if (mobj->getType() == SEG_TYPE_CLONES) {
- CloneTable *ct = (CloneTable *)mobj;
-
- for (uint j = 0; j < ct->_table.size(); j++) {
- // Check if the clone entry is used
- uint entryNum = (uint)ct->first_free;
- bool isUsed = true;
- while (entryNum != ((uint) CloneTable::HEAPENTRY_INVALID)) {
- if (entryNum == j) {
- isUsed = false;
- break;
- }
- entryNum = ct->_table[entryNum].next_free;
- }
-
- if (!isUsed)
- continue;
-
- CloneTable::Entry &seeker = ct->_table[j];
- Object *baseObj = getObject(seeker.getSpeciesSelector());
- seeker.cloneFromObject(baseObj);
- if (!baseObj)
- warning("Clone entry without a base class: %d", j);
- } // end for
- } // end if
- } // end if
- } // end for
-}
-
List *SegManager::allocateList(reg_t *addr) {
ListTable *table;
int offset;
- if (!Lists_seg_id)
- allocSegment(new ListTable(), &(Lists_seg_id));
- table = (ListTable *)_heap[Lists_seg_id];
+ if (!_listsSegId)
+ allocSegment(new ListTable(), &(_listsSegId));
+ table = (ListTable *)_heap[_listsSegId];
offset = table->allocEntry();
- *addr = make_reg(Lists_seg_id, offset);
+ *addr = make_reg(_listsSegId, offset);
return &(table->_table[offset]);
}
@@ -513,48 +472,60 @@ Node *SegManager::allocateNode(reg_t *addr) {
NodeTable *table;
int offset;
- if (!Nodes_seg_id)
- allocSegment(new NodeTable(), &(Nodes_seg_id));
- table = (NodeTable *)_heap[Nodes_seg_id];
+ if (!_nodesSegId)
+ allocSegment(new NodeTable(), &(_nodesSegId));
+ table = (NodeTable *)_heap[_nodesSegId];
offset = table->allocEntry();
- *addr = make_reg(Nodes_seg_id, offset);
+ *addr = make_reg(_nodesSegId, offset);
return &(table->_table[offset]);
}
+reg_t SegManager::newNode(reg_t value, reg_t key) {
+ reg_t nodeRef;
+ Node *n = allocateNode(&nodeRef);
+ n->pred = n->succ = NULL_REG;
+ n->key = key;
+ n->value = value;
+
+ return nodeRef;
+}
+
List *SegManager::lookupList(reg_t addr) {
if (getSegmentType(addr.segment) != SEG_TYPE_LISTS) {
- warning("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr));
+ error("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr));
return NULL;
}
ListTable *lt = (ListTable *)_heap[addr.segment];
if (!lt->isValidEntry(addr.offset)) {
- warning("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr));
+ error("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr));
return NULL;
}
return &(lt->_table[addr.offset]);
}
-Node *SegManager::lookupNode(reg_t addr) {
+Node *SegManager::lookupNode(reg_t addr, bool stopOnDiscarded) {
if (addr.isNull())
return NULL; // Non-error null
- if (getSegmentType(addr.segment) != SEG_TYPE_NODES) {
- // FIXME: This occurs right at the beginning of SQ4, when walking north from the first screen. It doesn't
- // seem to have any apparent ill-effects, though, so it's been changed to non-fatal, for now
- //error("%s, L%d: Attempt to use non-node %04x:%04x as list node", __FILE__, __LINE__, PRINT_REG(addr));
- warning("Attempt to use non-node %04x:%04x as list node", PRINT_REG(addr));
+ SegmentType type = getSegmentType(addr.segment);
+
+ if (type != SEG_TYPE_NODES) {
+ error("Attempt to use non-node %04x:%04x (type %d) as list node", PRINT_REG(addr), type);
return NULL;
}
NodeTable *nt = (NodeTable *)_heap[addr.segment];
if (!nt->isValidEntry(addr.offset)) {
- warning("Attempt to use non-node %04x:%04x as list node", PRINT_REG(addr));
+ if (!stopOnDiscarded)
+ return NULL;
+
+ error("Attempt to use invalid or discarded reference %04x:%04x as list node", PRINT_REG(addr));
return NULL;
}
@@ -582,7 +553,7 @@ static void *derefPtr(SegManager *segMan, reg_t pointer, int entries, bool wantR
if (ret.isRaw != wantRaw) {
warning("Dereferencing pointer %04x:%04x (type %d) which is %s, but expected %s", PRINT_REG(pointer),
- segMan->_heap[pointer.segment]->getType(),
+ segMan->getSegmentType(pointer.segment),
ret.isRaw ? "raw" : "not raw",
wantRaw ? "raw" : "not raw");
}
@@ -622,8 +593,12 @@ static inline char getChar(const SegmentRef &ref, uint offset) {
reg_t val = ref.reg[offset / 2];
+ // segment 0xFFFF means that the scripts are using uninitialized temp-variable space
+ // we can safely ignore this, if it isn't one of the first 2 chars.
+ // foreign lsl3 uses kFileIO(readraw) and then immediately uses kReadNumber right at the start
if (val.segment != 0)
- warning("Attempt to read character from non-raw data");
+ if (!((val.segment == 0xFFFF) && (offset > 1)))
+ warning("Attempt to read character from non-raw data");
return (offset & 1 ? val.offset >> 8 : val.offset & 0xff);
}
@@ -671,6 +646,14 @@ void SegManager::strncpy(reg_t dest, const char* src, size_t n) {
}
void SegManager::strncpy(reg_t dest, reg_t src, size_t n) {
+ if (src.isNull()) {
+ // Clear target string instead.
+ if (n > 0)
+ strcpy(dest, "");
+
+ return; // empty text
+ }
+
SegmentRef dest_r = dereference(dest);
const SegmentRef src_r = dereference(src);
if (!src_r.isValid()) {
@@ -798,6 +781,9 @@ void SegManager::memcpy(byte *dest, reg_t src, size_t n) {
}
size_t SegManager::strlen(reg_t str) {
+ if (str.isNull())
+ return 0; // empty text
+
SegmentRef str_r = dereference(str);
if (!str_r.isValid()) {
warning("Attempt to call strlen on invalid pointer %04x:%04x", PRINT_REG(str));
@@ -817,6 +803,9 @@ size_t SegManager::strlen(reg_t str) {
Common::String SegManager::getString(reg_t pointer, int entries) {
Common::String ret;
+ if (pointer.isNull())
+ return ret; // empty text
+
SegmentRef src_r = dereference(pointer);
if (!src_r.isValid()) {
warning("SegManager::getString(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer));
@@ -843,7 +832,6 @@ Common::String SegManager::getString(reg_t pointer, int entries) {
return ret;
}
-
byte *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) {
SegmentId seg;
SegmentObj *mobj = allocSegment(new DynMem(), &seg);
@@ -863,13 +851,13 @@ byte *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) {
return (byte *)(d._buf);
}
-int SegManager::freeDynmem(reg_t addr) {
+bool SegManager::freeDynmem(reg_t addr) {
if (addr.segment < 1 || addr.segment >= _heap.size() || !_heap[addr.segment] || _heap[addr.segment]->getType() != SEG_TYPE_DYNMEM)
- return 1; // error
+ return false; // error
deallocate(addr.segment, true);
- return 0; // OK
+ return true; // OK
}
#ifdef ENABLE_SCI32
@@ -877,14 +865,14 @@ SciArray<reg_t> *SegManager::allocateArray(reg_t *addr) {
ArrayTable *table;
int offset;
- if (!Arrays_seg_id) {
- table = (ArrayTable *)allocSegment(new ArrayTable(), &(Arrays_seg_id));
+ if (!_arraysSegId) {
+ table = (ArrayTable *)allocSegment(new ArrayTable(), &(_arraysSegId));
} else
- table = (ArrayTable *)_heap[Arrays_seg_id];
+ table = (ArrayTable *)_heap[_arraysSegId];
offset = table->allocEntry();
- *addr = make_reg(Arrays_seg_id, offset);
+ *addr = make_reg(_arraysSegId, offset);
return &(table->_table[offset]);
}
@@ -917,14 +905,14 @@ SciString *SegManager::allocateString(reg_t *addr) {
StringTable *table;
int offset;
- if (!String_seg_id) {
- table = (StringTable *)allocSegment(new StringTable(), &(String_seg_id));
+ if (!_stringSegId) {
+ table = (StringTable *)allocSegment(new StringTable(), &(_stringSegId));
} else
- table = (StringTable *)_heap[String_seg_id];
+ table = (StringTable *)_heap[_stringSegId];
offset = table->allocEntry();
- *addr = make_reg(String_seg_id, offset);
+ *addr = make_reg(_stringSegId, offset);
return &(table->_table[offset]);
}
@@ -955,4 +943,148 @@ void SegManager::freeString(reg_t addr) {
#endif
+void SegManager::createClassTable() {
+ Resource *vocab996 = _resMan->findResource(ResourceId(kResourceTypeVocab, 996), 1);
+
+ if (!vocab996)
+ error("SegManager: failed to open vocab 996");
+
+ int totalClasses = vocab996->size >> 2;
+ _classTable.resize(totalClasses);
+
+ for (uint16 classNr = 0; classNr < totalClasses; classNr++) {
+ uint16 scriptNr = READ_SCI11ENDIAN_UINT16(vocab996->data + classNr * 4 + 2);
+
+ _classTable[classNr].reg = NULL_REG;
+ _classTable[classNr].script = scriptNr;
+ }
+
+ _resMan->unlockResource(vocab996);
+}
+
+reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller) {
+ if (classnr == 0xffff)
+ return NULL_REG;
+
+ if (classnr < 0 || (int)_classTable.size() <= classnr || _classTable[classnr].script < 0) {
+ error("[VM] Attempt to dereference class %x, which doesn't exist (max %x)", classnr, _classTable.size());
+ return NULL_REG;
+ } else {
+ Class *the_class = &_classTable[classnr];
+ if (!the_class->reg.segment) {
+ getScriptSegment(the_class->script, lock);
+
+ if (!the_class->reg.segment) {
+ error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;", classnr, the_class->script, the_class->script);
+ return NULL_REG;
+ }
+ } else
+ if (caller.segment != the_class->reg.segment)
+ getScript(the_class->reg.segment)->incrementLockers();
+
+ return the_class->reg;
+ }
+}
+
+int SegManager::instantiateScript(int scriptNum) {
+ SegmentId segmentId = getScriptSegment(scriptNum);
+ Script *scr = getScriptIfLoaded(segmentId);
+ if (scr) {
+ if (!scr->isMarkedAsDeleted()) {
+ scr->incrementLockers();
+ return segmentId;
+ } else {
+ scr->freeScript();
+ }
+ } else {
+ scr = allocateScript(scriptNum, &segmentId);
+ }
+
+ scr->init(scriptNum, _resMan);
+ scr->load(_resMan);
+ scr->initialiseLocals(this);
+ scr->initialiseClasses(this);
+
+ if (getSciVersion() >= SCI_VERSION_1_1) {
+ scr->initialiseObjectsSci11(this, segmentId);
+ } else {
+ scr->initialiseObjectsSci0(this, segmentId);
+ }
+
+ return segmentId;
+}
+
+void SegManager::uninstantiateScript(int script_nr) {
+ SegmentId segmentId = getScriptSegment(script_nr);
+ Script *scr = getScriptIfLoaded(segmentId);
+
+ if (!scr) { // Is it already unloaded?
+ //warning("unloading script 0x%x requested although not loaded", script_nr);
+ // This is perfectly valid SCI behaviour
+ return;
+ }
+
+ scr->decrementLockers(); // One less locker
+
+ if (scr->getLockers() > 0)
+ return;
+
+ // Free all classtable references to this script
+ for (uint i = 0; i < classTableSize(); i++)
+ if (getClass(i).reg.segment == segmentId)
+ setClassOffset(i, NULL_REG);
+
+ if (getSciVersion() < SCI_VERSION_1_1)
+ uninstantiateScriptSci0(script_nr);
+ // FIXME: Add proper script uninstantiation for SCI 1.1
+
+ if (!scr->getLockers()) {
+ // The actual script deletion seems to be done by SCI scripts themselves
+ scr->markDeleted();
+ debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr);
+ }
+}
+
+void SegManager::uninstantiateScriptSci0(int script_nr) {
+ bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
+ SegmentId segmentId = getScriptSegment(script_nr);
+ Script *scr = getScript(segmentId);
+ reg_t reg = make_reg(segmentId, oldScriptHeader ? 2 : 0);
+ int objType, objLength = 0;
+
+ // Make a pass over the object in order uninstantiate all superclasses
+
+ do {
+ reg.offset += objLength; // Step over the last checked object
+
+ objType = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset));
+ if (!objType)
+ break;
+ objLength = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset + 2));
+
+ reg.offset += 4; // Step over header
+
+ if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class?
+ reg.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET)
+ int16 superclass = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset + 2));
+
+ if (superclass >= 0) {
+ int superclass_script = getClass(superclass).script;
+
+ if (superclass_script == script_nr) {
+ if (scr->getLockers())
+ scr->decrementLockers(); // Decrease lockers if this is us ourselves
+ } else
+ uninstantiateScript(superclass_script);
+ // Recurse to assure that the superclass lockers number gets decreased
+ }
+
+ reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET;
+ } // if object or class
+
+ reg.offset -= 4; // Step back on header
+
+ } while (objType != 0);
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index e8bbdbdb3f..59ac6f39b6 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -28,7 +28,9 @@
#include "common/scummsys.h"
#include "common/serializer.h"
+#include "sci/engine/script.h"
#include "sci/engine/vm.h"
+#include "sci/engine/vm_types.h"
#include "sci/engine/segment.h"
namespace Sci {
@@ -42,8 +44,6 @@ namespace Sci {
error("%s, line, %d, %s", __FILE__, __LINE__, msg); \
}
-
-
/**
* Parameters for getScriptSegment().
*/
@@ -53,6 +53,7 @@ enum ScriptLoadType {
SCRIPT_GET_LOCK = 3 /**< Load, if neccessary, and lock */
};
+class Script;
class SegManager : public Common::Serializable {
friend class Console;
@@ -96,6 +97,11 @@ public:
void reconstructScripts(EngineState *s);
/**
+ * Reconstructs the stack. Used when restoring saved games
+ */
+ void reconstructStack(EngineState *s);
+
+ /**
* Determines the segment occupied by a certain script, if any.
* @param script_nr Number of the script to look up
* @return The script's segment ID, or 0 on failure
@@ -111,12 +117,30 @@ public:
*/
SegmentId getScriptSegment(int script_nr, ScriptLoadType load);
- // TODO: document this
- reg_t lookupScriptExport(int script_nr, int export_index) {
- SegmentId seg = getScriptSegment(script_nr, SCRIPT_GET_DONT_LOAD);
- return make_reg(seg, getScript(seg)->validateExportFunc(export_index));
- }
+ /**
+ * Makes sure that a script and its superclasses get loaded to the heap.
+ * If the script already has been loaded, only the number of lockers is
+ * increased. All scripts containing superclasses of this script are loaded
+ * recursively as well, unless 'recursive' is set to zero. The
+ * complementary function is "uninstantiateScript()" below.
+ * @param[in] script_nr The script number to load
+ * @return The script's segment ID or 0 if out of heap
+ */
+ int instantiateScript(int script_nr);
+ /**
+ * Decreases the numer of lockers of a script and unloads it if that number
+ * reaches zero.
+ * This function will recursively unload scripts containing its
+ * superclasses, if those aren't locked by other scripts as well.
+ * @param[in] script_nr The script number that is requestet to be unloaded
+ */
+ void uninstantiateScript(int script_nr);
+
+private:
+ void uninstantiateScriptSci0(int script_nr);
+
+public:
// TODO: document this
reg_t getClassAddress(int classnr, ScriptLoadType lock, reg_t caller);
@@ -137,28 +161,7 @@ public:
* @param seg ID of the script segment to check for
* @return A pointer to the Script object, or NULL
*/
- Script *getScriptIfLoaded(SegmentId seg);
-
-
- // 1b. Script Initialisation
-
- // The set of functions below are intended
- // to be used during script instantiation,
- // i.e. loading and linking.
-
- /**
- * Initializes a script's local variable block
- * All variables are initialized to zero.
- * @param seg Segment containing the script to initialize
- * @param nr Number of local variables to allocate
- */
- void scriptInitialiseLocalsZero(SegmentId seg, int nr);
-
- /**
- * Initializes a script's local variable block according to a prototype
- * @param location Location to initialize from
- */
- void scriptInitialiseLocals(reg_t location);
+ Script *getScriptIfLoaded(SegmentId seg) const;
// 2. Clones
@@ -188,16 +191,11 @@ public:
// 5. System Strings
/**
- * Allocates a system string table
- * See also sys_string_acquire();
- * @param[in] segid Segment ID of the stack
- * @returns The physical stack
+ * Initializes the system string table.
*/
- SystemStrings *allocateSysStrings(SegmentId *segid);
+ void initSysStrings();
- // 5. System Strings
-
// 6, 7. Lists and Nodes
/**
@@ -215,6 +213,14 @@ public:
Node *allocateNode(reg_t *addr);
/**
+ * Allocate and initialize a new list node.
+ * @param[in] value The value to set the node to
+ * @param[in] key The key to set
+ * @return Pointer to the newly initialized list node
+ */
+ reg_t newNode(reg_t value, reg_t key);
+
+ /**
* Resolves a list pointer to a list.
* @param addr The address to resolve
* @return The list referenced, or NULL on error
@@ -226,7 +232,7 @@ public:
* @param addr The address to resolve
* @return The list node referenced, or NULL on error
*/
- Node *lookupNode(reg_t addr);
+ Node *lookupNode(reg_t addr, bool stopOnDiscarded = true);
// 8. Hunk Memory
@@ -268,7 +274,7 @@ public:
* Deallocates a piece of dynamic memory
* @param[in] addr Offset of the dynmem chunk to free
*/
- int freeDynmem(reg_t addr);
+ bool freeDynmem(reg_t addr);
// Generic Operations on Segments and Addresses
@@ -381,39 +387,39 @@ public:
* @param type The type of the segment to find
* @return The segment number, or -1 if the segment wasn't found
*/
- SegmentId findSegmentByType(int type);
+ SegmentId findSegmentByType(int type) const;
// TODO: document this
- SegmentObj *getSegmentObj(SegmentId seg);
+ SegmentObj *getSegmentObj(SegmentId seg) const;
// TODO: document this
- SegmentType getSegmentType(SegmentId seg);
+ SegmentType getSegmentType(SegmentId seg) const;
// TODO: document this
- SegmentObj *getSegment(SegmentId seg, SegmentType type);
+ SegmentObj *getSegment(SegmentId seg, SegmentType type) const;
/**
* Retrieves an object from the specified location
* @param[in] offset Location (segment, offset) of the object
* @return The object in question, or NULL if there is none
*/
- Object *getObject(reg_t pos);
+ Object *getObject(reg_t pos) const;
/**
* Checks whether a heap address contains an object
* @parm obj The address to check
* @return True if it is an object, false otherwise
*/
- bool isObject(reg_t obj) { return getObject(obj) != NULL; }
+ bool isObject(reg_t obj) const { return getObject(obj) != NULL; }
// TODO: document this
- bool isHeapObject(reg_t pos);
+ bool isHeapObject(reg_t pos) const;
/**
* Determines the name of an object
* @param[in] pos Location (segment, offset) of the object
* @return A name for that object, or a string describing an error
- * that occured while looking it up. The string is stored
+ * that occurred while looking it up. The string is stored
* in a static buffer and need not be freed (neither may
* it be modified).
*/
@@ -432,12 +438,27 @@ public:
*/
reg_t findObjectByName(const Common::String &name, int index = -1);
- void scriptRelocateExportsSci11(SegmentId seg);
- void scriptInitialiseObjectsSci11(SegmentId seg);
+ uint32 classTableSize() const { return _classTable.size(); }
+ Class getClass(int index) const { return _classTable[index]; }
+ void setClassOffset(int index, reg_t offset) { _classTable[index].reg = offset; }
+ void resizeClassTable(uint32 size) { _classTable.resize(size); }
-public: // TODO: make private
- Common::Array<SegmentObj *> _heap;
- Common::Array<Class> _classtable; /**< Table of all classes */
+ /**
+ * Obtains the system strings segment ID
+ */
+ SegmentId getSysStringsSegment() { return _sysStringsSegId; }
+
+ /**
+ * Get a pointer to the system string with the specified index,
+ * or NULL if that index is invalid.
+ *
+ * This method is currently only used by kString().
+ */
+ SystemString *getSystemString(uint idx) const {
+ if (idx >= SYS_STRINGS_MAX)
+ return NULL;
+ return &_sysStrings->_strings[idx];
+ }
#ifdef ENABLE_SCI32
SciArray<reg_t> *allocateArray(reg_t *addr);
@@ -446,28 +467,35 @@ public: // TODO: make private
SciString *allocateString(reg_t *addr);
SciString *lookupString(reg_t addr);
void freeString(reg_t addr);
- SegmentId getStringSegmentId() { return String_seg_id; }
+ SegmentId getStringSegmentId() { return _stringSegId; }
#endif
+ const Common::Array<SegmentObj *> &getSegments() const { return _heap; }
+
private:
+ Common::Array<SegmentObj *> _heap;
+ Common::Array<Class> _classTable; /**< Table of all classes */
/** Map script ids to segment ids. */
Common::HashMap<int, SegmentId> _scriptSegMap;
ResourceManager *_resMan;
- SegmentId Clones_seg_id; ///< ID of the (a) clones segment
- SegmentId Lists_seg_id; ///< ID of the (a) list segment
- SegmentId Nodes_seg_id; ///< ID of the (a) node segment
- SegmentId Hunks_seg_id; ///< ID of the (a) hunk segment
+ SegmentId _clonesSegId; ///< ID of the (a) clones segment
+ SegmentId _listsSegId; ///< ID of the (a) list segment
+ SegmentId _nodesSegId; ///< ID of the (a) node segment
+ SegmentId _hunksSegId; ///< ID of the (a) hunk segment
+
+ /* System strings */
+ SegmentId _sysStringsSegId;
+ SystemStrings *_sysStrings;
#ifdef ENABLE_SCI32
- SegmentId Arrays_seg_id;
- SegmentId String_seg_id;
+ SegmentId _arraysSegId;
+ SegmentId _stringSegId;
#endif
private:
SegmentObj *allocSegment(SegmentObj *mem, SegmentId *segid);
- LocalVariables *allocLocalsSegment(Script *scr, int count);
int deallocate(SegmentId seg, bool recursive);
void createClassTable();
@@ -480,6 +508,9 @@ private:
* 'seg' is a valid segment
*/
bool check(SegmentId seg);
+
+public:
+ LocalVariables *allocLocalsSegment(Script *scr);
};
} // End of namespace Sci
diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp
index ab1a68d165..b16dd5a5e5 100644
--- a/engines/sci/engine/segment.cpp
+++ b/engines/sci/engine/segment.cpp
@@ -27,6 +27,7 @@
#include "sci/sci.h"
#include "sci/engine/features.h"
+#include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS
#include "sci/engine/segment.h"
#include "sci/engine/seg_manager.h"
#include "sci/engine/state.h"
@@ -85,333 +86,72 @@ SegmentObj *SegmentObj::createSegmentObj(SegmentType type) {
return mem;
}
-Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) {
- _nr = 0;
- _buf = NULL;
- _bufSize = 0;
- _scriptSize = 0;
- _heapSize = 0;
-
- _synonyms = NULL;
- _heapStart = NULL;
- _exportTable = NULL;
-
- _localsOffset = 0;
- _localsSegment = 0;
- _localsBlock = NULL;
-
- _relocated = false;
- _markedAsDeleted = 0;
-}
-
-Script::~Script() {
- freeScript();
-}
-
-void Script::freeScript() {
- free(_buf);
- _buf = NULL;
- _bufSize = 0;
-
- _objects.clear();
- _codeBlocks.clear();
-}
-
-bool Script::init(int script_nr, ResourceManager *resMan) {
- setScriptSize(script_nr, resMan);
-
- _buf = (byte *)malloc(_bufSize);
-
- if (!_buf) {
- freeScript();
- warning("Not enough memory space for script size");
- _bufSize = 0;
- return false;
- }
-
- _localsOffset = 0;
- _localsBlock = NULL;
-
- _codeBlocks.clear();
-
- _relocated = false;
- _markedAsDeleted = false;
-
- _nr = script_nr;
-
- if (getSciVersion() >= SCI_VERSION_1_1)
- _heapStart = _buf + _scriptSize;
- else
- _heapStart = _buf;
-
- return true;
-}
-
-void Script::setScriptSize(int script_nr, ResourceManager *resMan) {
- Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
- Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
- bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
-
- _scriptSize = script->size;
- _heapSize = 0; // Set later
-
- if (!script || (getSciVersion() >= SCI_VERSION_1_1 && !heap)) {
- error("SegManager::setScriptSize: failed to load %s", !script ? "script" : "heap");
- }
- if (oldScriptHeader) {
- _bufSize = script->size + READ_LE_UINT16(script->data) * 2;
- //locals_size = READ_LE_UINT16(script->data) * 2;
- } else if (getSciVersion() < SCI_VERSION_1_1) {
- _bufSize = script->size;
- } else {
- _bufSize = script->size + heap->size;
- _heapSize = heap->size;
-
- // Ensure that the start of the heap resource can be word-aligned.
- if (script->size & 2) {
- _bufSize++;
- _scriptSize++;
- }
-
- if (_bufSize > 65535) {
- error("Script and heap sizes combined exceed 64K."
- "This means a fundamental design bug was made in SCI\n"
- "regarding SCI1.1 games.\nPlease report this so it can be"
- "fixed in the next major version");
- return;
- }
+const char *SegmentObj::getSegmentTypeName(SegmentType type) {
+ switch (type) {
+ case SEG_TYPE_SCRIPT:
+ return "script";
+ break;
+ case SEG_TYPE_CLONES:
+ return "clones";
+ break;
+ case SEG_TYPE_LOCALS:
+ return "locals";
+ break;
+ case SEG_TYPE_SYS_STRINGS:
+ return "strings";
+ break;
+ case SEG_TYPE_STACK:
+ return "stack";
+ break;
+ case SEG_TYPE_HUNK:
+ return "hunk";
+ break;
+ case SEG_TYPE_LISTS:
+ return "lists";
+ break;
+ case SEG_TYPE_NODES:
+ return "nodes";
+ break;
+ case SEG_TYPE_DYNMEM:
+ return "dynmem";
+ break;
+#ifdef ENABLE_SCI32
+ case SEG_TYPE_ARRAY:
+ return "array";
+ break;
+ case SEG_TYPE_STRING:
+ return "string";
+ break;
+#endif
+ default:
+ error("Unknown SegmentObj type %d", type);
+ break;
}
+ return NULL;
}
-Object *Script::allocateObject(uint16 offset) {
- return &_objects[offset];
-}
-
-Object *Script::getObject(uint16 offset) {
- if (_objects.contains(offset))
- return &_objects[offset];
- else
- return 0;
-}
-
-Object *Script::scriptObjInit(reg_t obj_pos) {
- Object *obj;
-
- if (getSciVersion() < SCI_VERSION_1_1)
- obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET)
-
- VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n");
-
- obj = allocateObject(obj_pos.offset);
-
- VERIFY(obj_pos.offset + SCRIPT_FUNCTAREAPTR_OFFSET < (int)_bufSize, "Function area pointer stored beyond end of script\n");
-
- obj->init(_buf, obj_pos);
-
- return obj;
-}
-
-void Script::scriptObjRemove(reg_t obj_pos) {
- if (getSciVersion() < SCI_VERSION_1_1)
- obj_pos.offset += 8;
-
- _objects.erase(obj_pos.toUint16());
-}
-
-int Script::relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location) {
+// This helper function is used by Script::relocateLocal and Object::relocate
+// Duplicate in segment.cpp and script.cpp
+static bool relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location, size_t scriptSize) {
int rel = location - block_location;
if (rel < 0)
- return 0;
+ return false;
uint idx = rel >> 1;
if (idx >= block.size())
- return 0;
+ return false;
if (rel & 1) {
- warning("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location);
- return 0;
+ error("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location);
+ return false;
}
block[idx].segment = segment; // Perform relocation
if (getSciVersion() >= SCI_VERSION_1_1)
- block[idx].offset += _scriptSize;
-
- return 1;
-}
-
-int Script::relocateLocal(SegmentId segment, int location) {
- if (_localsBlock)
- return relocateBlock(_localsBlock->_locals, _localsOffset, segment, location);
- else
- return 0; // No hands, no cookies
-}
-
-int Script::relocateObject(Object &obj, SegmentId segment, int location) {
- return relocateBlock(obj._variables, obj.getPos().offset, segment, location);
-}
-
-void Script::scriptAddCodeBlock(reg_t location) {
- CodeBlock cb;
- cb.pos = location;
- cb.size = READ_SCI11ENDIAN_UINT16(_buf + location.offset - 2);
- _codeBlocks.push_back(cb);
-}
-
-void Script::scriptRelocate(reg_t block) {
- VERIFY(block.offset < (uint16)_bufSize && READ_SCI11ENDIAN_UINT16(_buf + block.offset) * 2 + block.offset < (uint16)_bufSize,
- "Relocation block outside of script\n");
-
- int count = READ_SCI11ENDIAN_UINT16(_buf + block.offset);
-
- for (int i = 0; i <= count; i++) {
- int pos = READ_SCI11ENDIAN_UINT16(_buf + block.offset + 2 + (i * 2));
- if (!pos)
- continue; // FIXME: A hack pending investigation
-
- if (!relocateLocal(block.segment, pos)) {
- bool done = false;
- uint k;
-
- ObjMap::iterator it;
- const ObjMap::iterator end = _objects.end();
- for (it = _objects.begin(); !done && it != end; ++it) {
- if (relocateObject(it->_value, block.segment, pos))
- done = true;
- }
-
- for (k = 0; !done && k < _codeBlocks.size(); k++) {
- if (pos >= _codeBlocks[k].pos.offset &&
- pos < _codeBlocks[k].pos.offset + _codeBlocks[k].size)
- done = true;
- }
-
- if (!done) {
- printf("While processing relocation block %04x:%04x:\n", PRINT_REG(block));
- printf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count);
- if (_localsBlock)
- printf("- locals: %d at %04x\n", _localsBlock->_locals.size(), _localsOffset);
- else
- printf("- No locals\n");
- for (it = _objects.begin(), k = 0; it != end; ++it, ++k)
- printf("- obj#%d at %04x w/ %d vars\n", k, it->_value.getPos().offset, it->_value.getVarCount());
- // SQ3 script 71 has broken relocation entries.
- printf("Trying to continue anyway...\n");
- }
- }
- }
-}
-
-void Script::heapRelocate(reg_t block) {
- VERIFY(block.offset < (uint16)_heapSize && READ_SCI11ENDIAN_UINT16(_heapStart + block.offset) * 2 + block.offset < (uint16)_bufSize,
- "Relocation block outside of script\n");
-
- if (_relocated)
- return;
- _relocated = true;
- int count = READ_SCI11ENDIAN_UINT16(_heapStart + block.offset);
-
- for (int i = 0; i < count; i++) {
- int pos = READ_SCI11ENDIAN_UINT16(_heapStart + block.offset + 2 + (i * 2)) + _scriptSize;
-
- if (!relocateLocal(block.segment, pos)) {
- bool done = false;
- uint k;
-
- ObjMap::iterator it;
- const ObjMap::iterator end = _objects.end();
- for (it = _objects.begin(); !done && it != end; ++it) {
- if (relocateObject(it->_value, block.segment, pos))
- done = true;
- }
-
- if (!done) {
- printf("While processing relocation block %04x:%04x:\n", PRINT_REG(block));
- printf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count);
- if (_localsBlock)
- printf("- locals: %d at %04x\n", _localsBlock->_locals.size(), _localsOffset);
- else
- printf("- No locals\n");
- for (it = _objects.begin(), k = 0; it != end; ++it, ++k)
- printf("- obj#%d at %04x w/ %d vars\n", k, it->_value.getPos().offset, it->_value.getVarCount());
- error("Breakpoint in %s, line %d", __FILE__, __LINE__);
- }
- }
- }
-}
-
-void Script::incrementLockers() {
- _lockers++;
-}
-
-void Script::decrementLockers() {
- if (_lockers > 0)
- _lockers--;
-}
+ block[idx].offset += scriptSize;
-int Script::getLockers() const {
- return _lockers;
-}
-
-void Script::setLockers(int lockers) {
- _lockers = lockers;
-}
-
-void Script::setExportTableOffset(int offset) {
- if (offset) {
- _exportTable = (uint16 *)(_buf + offset + 2);
- _numExports = READ_SCI11ENDIAN_UINT16((byte *)(_exportTable - 1));
- } else {
- _exportTable = NULL;
- _numExports = 0;
- }
-}
-
-uint16 Script::validateExportFunc(int pubfunct) {
- bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE);
-
- if (_numExports <= pubfunct) {
- warning("validateExportFunc(): pubfunct is invalid");
- return 0;
- }
-
- if (exportsAreWide)
- pubfunct *= 2;
- uint16 offset = READ_SCI11ENDIAN_UINT16((byte *)(_exportTable + pubfunct));
- VERIFY(offset < _bufSize, "invalid export function pointer");
-
- return offset;
-}
-
-void Script::setSynonymsOffset(int offset) {
- _synonyms = _buf + offset;
-}
-
-byte *Script::getSynonyms() const {
- return _synonyms;
-}
-
-void Script::setSynonymsNr(int n) {
- _numSynonyms = n;
-}
-
-int Script::getSynonymsNr() const {
- return _numSynonyms;
-}
-
-// memory operations
-
-void Script::mcpyInOut(int dst, const void *src, size_t n) {
- if (_buf) {
- assert(dst + n <= _bufSize);
- memcpy(_buf + dst, src, n);
- }
-}
-
-int16 Script::getHeap(uint16 offset) const {
- assert(offset + 1 < (int)_bufSize);
- return READ_SCI11ENDIAN_UINT16(_buf + offset);
-// return (_buf[offset] | (_buf[offset+1]) << 8);
+ return true;
}
SegmentRef SegmentObj::dereference(reg_t pointer) {
@@ -420,23 +160,6 @@ SegmentRef SegmentObj::dereference(reg_t pointer) {
return SegmentRef();
}
-bool Script::isValidOffset(uint16 offset) const {
- return offset < _bufSize;
-}
-
-SegmentRef Script::dereference(reg_t pointer) {
- if (pointer.offset > _bufSize) {
- warning("Script::dereference(): Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)",
- PRINT_REG(pointer), (uint)_bufSize);
- return SegmentRef();
- }
-
- SegmentRef ret;
- ret.isRaw = true;
- ret.maxSize = _bufSize - pointer.offset;
- ret.raw = _buf + pointer.offset;
- return ret;
-}
bool LocalVariables::isValidOffset(uint16 offset) const {
return offset < _locals.size() * 2;
@@ -455,7 +178,16 @@ SegmentRef LocalVariables::dereference(reg_t pointer) {
if (ret.maxSize > 0) {
ret.reg = &_locals[pointer.offset / 2];
} else {
- warning("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer));
+ if ((g_sci->getEngineState()->currentRoomNumber() == 660 || g_sci->getEngineState()->currentRoomNumber() == 660)
+ && g_sci->getGameId() == GID_LAURABOW2) {
+ // Happens in two places during the intro of LB2CD, both from kMemory(peek):
+ // - room 160: Heap 160 has 83 local variables (0-82), and the game
+ // asks for variables at indices 83 - 90 too.
+ // - room 220: Heap 220 has 114 local variables (0-113), and the
+ // game asks for variables at indices 114-120 too.
+ } else {
+ error("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer));
+ }
ret.reg = 0;
}
return ret;
@@ -502,84 +234,45 @@ SegmentRef SystemStrings::dereference(reg_t pointer) {
if (isValidOffset(pointer.offset))
ret.raw = (byte *)(_strings[pointer.offset]._value);
else {
- // This occurs in KQ5CD when interacting with certain objects
- warning("SystemStrings::dereference(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer));
- }
-
- return ret;
-}
-
-
-//-------------------- script --------------------
-reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) {
- addr.offset = 0;
- return addr;
-}
-
-void Script::freeAtAddress(SegManager *segMan, reg_t addr) {
- /*
- debugC(2, kDebugLevelGC, "[GC] Freeing script %04x:%04x", PRINT_REG(addr));
- if (_localsSegment)
- debugC(2, kDebugLevelGC, "[GC] Freeing locals %04x:0000", _localsSegment);
- */
-
- if (_markedAsDeleted)
- segMan->deallocateScript(_nr);
-}
-
-void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
- (*note)(param, make_reg(segId, 0));
-}
-
-void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) {
- if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) {
- Object *obj = getObject(addr.offset);
- if (obj) {
- // Note all local variables, if we have a local variable environment
- if (_localsSegment)
- (*note)(param, make_reg(_localsSegment, 0));
-
- for (uint i = 0; i < obj->getVarCount(); i++)
- (*note)(param, obj->getVariable(i));
+ if (g_sci->getGameId() == GID_KQ5) {
+ // This occurs in KQ5CD when interacting with certain objects
} else {
- warning("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr));
+ error("SystemStrings::dereference(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer));
}
- } else {
- /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/
- /* Happens e.g. when we're looking into strings */
}
+
+ return ret;
}
//-------------------- clones --------------------
-void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) {
- Clone *clone;
-
+Common::Array<reg_t> CloneTable::listAllOutgoingReferences(reg_t addr) const {
+ Common::Array<reg_t> tmp;
// assert(addr.segment == _segId);
if (!isValidEntry(addr.offset)) {
error("Unexpected request for outgoing references from clone at %04x:%04x", PRINT_REG(addr));
}
- clone = &(_table[addr.offset]);
+ const Clone *clone = &(_table[addr.offset]);
// Emit all member variables (including references to the 'super' delegate)
for (uint i = 0; i < clone->getVarCount(); i++)
- (*note)(param, clone->getVariable(i));
+ tmp.push_back(clone->getVariable(i));
// Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals.
- (*note)(param, clone->getPos());
+ tmp.push_back(clone->getPos());
//debugC(2, kDebugLevelGC, "[GC] Reporting clone-pos %04x:%04x", PRINT_REG(clone->pos));
+
+ return tmp;
}
void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) {
#ifdef GC_DEBUG
- Object *victim_obj;
+ // assert(addr.segment == _segId);
-// assert(addr.segment == _segId);
-
- victim_obj = &(_table[addr.offset]);
+ Object *victim_obj = &(_table[addr.offset]);
if (!(victim_obj->_flags & OBJECT_FLAG_FREED))
warning("[GC] Clone %04x:%04x not reachable and not freed (freeing now)", PRINT_REG(addr));
@@ -597,7 +290,7 @@ void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) {
//-------------------- locals --------------------
-reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) {
+reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) const {
// Reference the owning script
SegmentId owner_seg = segMan->getScriptSegment(script_id);
@@ -606,25 +299,31 @@ reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) {
return make_reg(owner_seg, 0);
}
-void LocalVariables::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) {
+Common::Array<reg_t> LocalVariables::listAllOutgoingReferences(reg_t addr) const {
+ Common::Array<reg_t> tmp;
// assert(addr.segment == _segId);
for (uint i = 0; i < _locals.size(); i++)
- (*note)(param, _locals[i]);
+ tmp.push_back(_locals[i]);
+
+ return tmp;
}
//-------------------- stack --------------------
-reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) {
+reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) const {
addr.offset = 0;
return addr;
}
-void DataStack::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) {
+Common::Array<reg_t> DataStack::listAllOutgoingReferences(reg_t object) const {
+ Common::Array<reg_t> tmp;
fprintf(stderr, "Emitting %d stack entries\n", _capacity);
for (int i = 0; i < _capacity; i++)
- (*note)(param, _entries[i]);
+ tmp.push_back(_entries[i]);
fprintf(stderr, "DONE");
+
+ return tmp;
}
@@ -633,18 +332,20 @@ void ListTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
freeEntry(sub_addr.offset);
}
-void ListTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) {
+Common::Array<reg_t> ListTable::listAllOutgoingReferences(reg_t addr) const {
+ Common::Array<reg_t> tmp;
if (!isValidEntry(addr.offset)) {
- warning("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
- return;
+ error("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
}
- List *list = &(_table[addr.offset]);
+ const List *list = &(_table[addr.offset]);
- note(param, list->first);
- note(param, list->last);
+ tmp.push_back(list->first);
+ tmp.push_back(list->last);
// We could probably get away with just one of them, but
// let's be conservative here.
+
+ return tmp;
}
@@ -653,19 +354,21 @@ void NodeTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
freeEntry(sub_addr.offset);
}
-void NodeTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) {
+Common::Array<reg_t> NodeTable::listAllOutgoingReferences(reg_t addr) const {
+ Common::Array<reg_t> tmp;
if (!isValidEntry(addr.offset)) {
- warning("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
- return;
+ error("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
}
- Node *node = &(_table[addr.offset]);
+ const Node *node = &(_table[addr.offset]);
// We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us
// to walk around from any given node
- note(param, node->pred);
- note(param, node->succ);
- note(param, node->key);
- note(param, node->value);
+ tmp.push_back(node->pred);
+ tmp.push_back(node->succ);
+ tmp.push_back(node->key);
+ tmp.push_back(node->value);
+
+ return tmp;
}
@@ -673,22 +376,45 @@ void NodeTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback
//-------------------- object ----------------------------
-Object *Object::getClass(SegManager *segMan) {
+void Object::init(byte *buf, reg_t obj_pos, bool initVariables) {
+ byte *data = buf + obj_pos.offset;
+ _baseObj = data;
+ _pos = obj_pos;
+
+ if (getSciVersion() < SCI_VERSION_1_1) {
+ _variables.resize(READ_LE_UINT16(data + kOffsetSelectorCounter));
+ _baseVars = (const uint16 *)(_baseObj + _variables.size() * 2);
+ _baseMethod = (const uint16 *)(data + READ_LE_UINT16(data + kOffsetFunctionArea));
+ _methodCount = READ_LE_UINT16(_baseMethod - 1);
+ } else {
+ _variables.resize(READ_SCI11ENDIAN_UINT16(data + 2));
+ _baseVars = (const uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 4));
+ _baseMethod = (const uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 6));
+ _methodCount = READ_SCI11ENDIAN_UINT16(_baseMethod);
+ }
+
+ if (initVariables) {
+ for (uint i = 0; i < _variables.size(); i++)
+ _variables[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(data + (i * 2)));
+ }
+}
+
+const Object *Object::getClass(SegManager *segMan) const {
return isClass() ? this : segMan->getObject(getSuperClassSelector());
}
-int Object::locateVarSelector(SegManager *segMan, Selector slc) {
- byte *buf;
+int Object::locateVarSelector(SegManager *segMan, Selector slc) const {
+ const byte *buf;
uint varnum;
if (getSciVersion() < SCI_VERSION_1_1) {
varnum = getVarCount();
- int selector_name_offset = varnum * 2 + SCRIPT_SELECTOR_OFFSET;
+ int selector_name_offset = varnum * 2 + kOffsetSelectorSegment;
buf = _baseObj + selector_name_offset;
} else {
- Object *obj = getClass(segMan);
+ const Object *obj = getClass(segMan);
varnum = obj->getVariable(1).toUint16();
- buf = (byte *)obj->_baseVars;
+ buf = (const byte *)obj->_baseVars;
}
for (uint i = 0; i < varnum; i++)
@@ -698,15 +424,74 @@ int Object::locateVarSelector(SegManager *segMan, Selector slc) {
return -1; // Failed
}
+bool Object::relocate(SegmentId segment, int location, size_t scriptSize) {
+ return relocateBlock(_variables, getPos().offset, segment, location, scriptSize);
+}
+
+int Object::propertyOffsetToId(SegManager *segMan, int propertyOffset) const {
+ int selectors = getVarCount();
+
+ if (propertyOffset < 0 || (propertyOffset >> 1) >= selectors) {
+ error("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d])",
+ propertyOffset, propertyOffset >> 1, selectors - 1);
+ return -1;
+ }
+
+ if (getSciVersion() < SCI_VERSION_1_1) {
+ const byte *selectoroffset = ((const byte *)(_baseObj)) + kOffsetSelectorSegment + selectors * 2;
+ return READ_SCI11ENDIAN_UINT16(selectoroffset + propertyOffset);
+ } else {
+ const Object *obj = this;
+ if (!isClass())
+ obj = segMan->getObject(getSuperClassSelector());
+
+ return READ_SCI11ENDIAN_UINT16((const byte *)obj->_baseVars + propertyOffset);
+ }
+}
+
+void Object::initSpecies(SegManager *segMan, reg_t addr) {
+ uint16 speciesOffset = getSpeciesSelector().offset;
+
+ if (speciesOffset == 0xffff) // -1
+ setSpeciesSelector(NULL_REG); // no species
+ else
+ setSpeciesSelector(segMan->getClassAddress(speciesOffset, SCRIPT_GET_LOCK, addr));
+}
+
+void Object::initSuperClass(SegManager *segMan, reg_t addr) {
+ uint16 superClassOffset = getSuperClassSelector().offset;
+
+ if (superClassOffset == 0xffff) // -1
+ setSuperClassSelector(NULL_REG); // no superclass
+ else
+ setSuperClassSelector(segMan->getClassAddress(superClassOffset, SCRIPT_GET_LOCK, addr));
+}
+
+bool Object::initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClass) {
+ const Object *baseObj = segMan->getObject(getSpeciesSelector());
+
+ if (baseObj) {
+ _variables.resize(baseObj->getVarCount());
+ // Copy base from species class, as we need its selector IDs
+ _baseObj = baseObj->_baseObj;
+ if (doInitSuperClass)
+ initSuperClass(segMan, addr);
+ return true;
+ }
+
+ return false;
+}
+
//-------------------- dynamic memory --------------------
-reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) {
+reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) const {
addr.offset = 0;
return addr;
}
-void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
- (*note)(param, make_reg(segId, 0));
+Common::Array<reg_t> DynMem::listAllDeallocatable(SegmentId segId) const {
+ const reg_t r = make_reg(segId, 0);
+ return Common::Array<reg_t>(&r, 1);
}
#ifdef ENABLE_SCI32
@@ -724,22 +509,24 @@ void ArrayTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
freeEntry(sub_addr.offset);
}
-void ArrayTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) {
+Common::Array<reg_t> ArrayTable::listAllOutgoingReferences(reg_t addr) const {
+ Common::Array<reg_t> tmp;
if (!isValidEntry(addr.offset)) {
- warning("Invalid array referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
- return;
+ error("Invalid array referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
}
- SciArray<reg_t> *array = &(_table[addr.offset]);
+ const SciArray<reg_t> *array = &(_table[addr.offset]);
for (uint32 i = 0; i < array->getSize(); i++) {
reg_t value = array->getValue(i);
if (value.segment != 0)
- note(param, value);
+ tmp.push_back(value);
}
+
+ return tmp;
}
-Common::String SciString::toString() {
+Common::String SciString::toString() const {
if (_type != 3)
error("SciString::toString(): Array is not a string");
@@ -750,7 +537,7 @@ Common::String SciString::toString() {
return string;
}
-void SciString::fromString(Common::String string) {
+void SciString::fromString(const Common::String &string) {
if (_type != 3)
error("SciString::fromString(): Array is not a string");
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index 1089ada475..c8cb4cd203 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -67,7 +67,7 @@ enum SegmentType {
SEG_TYPE_NODES = 7,
SEG_TYPE_HUNK = 8,
SEG_TYPE_DYNMEM = 9,
- SEG_TYPE_STRING_FRAG = 10, // obsolete, we keep it to be able to load old saves
+ // 10 used to be string fragments, now obsolete
#ifdef ENABLE_SCI32
SEG_TYPE_ARRAY = 11,
@@ -80,10 +80,9 @@ enum SegmentType {
struct SegmentObj : public Common::Serializable {
SegmentType _type;
- typedef void (*NoteCallback)(void *param, reg_t addr); // FIXME: Bad choice of name
-
public:
static SegmentObj *createSegmentObj(SegmentType type);
+ static const char *getSegmentTypeName(SegmentType type);
public:
SegmentObj(SegmentType type) : _type(type) {}
@@ -106,40 +105,44 @@ public:
/**
* Finds the canonic address associated with sub_reg.
+ * Used by the garbage collector.
*
* For each valid address a, there exists a canonic address c(a) such that c(a) = c(c(a)).
* This address "governs" a in the sense that deallocating c(a) will deallocate a.
*
* @param sub_addr base address whose canonic address is to be found
*/
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) { return sub_addr; }
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const { return sub_addr; }
/**
* Deallocates all memory associated with the specified address.
+ * Used by the garbage collector.
* @param sub_addr address (within the given segment) to deallocate
*/
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {}
/**
- * Iterates over and reports all addresses within the current segment.
- * @param note Invoked for each address on which free_at_address() makes sense
- * @param param parameter passed to 'note'
+ * Iterates over and reports all addresses within the segment.
+ * Used by the garbage collector.
+ * @return a list of addresses within the segment
*/
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {}
+ virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const {
+ return Common::Array<reg_t>();
+ }
/**
* Iterates over all references reachable from the specified object.
- * @param object object (within the current segment) to analyse
- * @param param parameter passed to 'note'
- * @param note Invoked for each outgoing reference within the object
- * Note: This function may also choose to report numbers (segment 0) as adresses
+ * Used by the garbage collector.
+ * @param object object (within the current segment) to analyse
+ * @return a list of outgoing references within the object
+ *
+ * @note This function may also choose to report numbers (segment 0) as adresses
*/
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) {}
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const {
+ return Common::Array<reg_t>();
+ }
};
-
-struct IntMapper;
-
enum {
SYS_STRINGS_MAX = 4,
@@ -194,8 +197,8 @@ public:
virtual bool isValidOffset(uint16 offset) const;
virtual SegmentRef dereference(reg_t pointer);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const;
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -205,6 +208,22 @@ enum {
OBJECT_FLAG_FREED = (1 << 0)
};
+enum infoSelectorFlags {
+ kInfoFlagClone = 0x0001,
+ kInfoFlagClass = 0x8000
+};
+
+enum ObjectOffsets {
+ kOffsetLocalVariables = -6,
+ kOffsetFunctionArea = -4,
+ kOffsetSelectorCounter = -2,
+ kOffsetSelectorSegment = 0,
+ kOffsetInfoSelectorSci0 = 4,
+ kOffsetNamePointerSci0 = 6,
+ kOffsetInfoSelectorSci11 = 14,
+ kOffsetNamePointerSci11 = 16
+};
+
class Object {
public:
Object() {
@@ -214,31 +233,34 @@ public:
~Object() { }
- reg_t getSpeciesSelector() { return _variables[_offset]; }
+ reg_t getSpeciesSelector() const { return _variables[_offset]; }
void setSpeciesSelector(reg_t value) { _variables[_offset] = value; }
- reg_t getSuperClassSelector() { return _variables[_offset + 1]; }
+ reg_t getSuperClassSelector() const { return _variables[_offset + 1]; }
void setSuperClassSelector(reg_t value) { _variables[_offset + 1] = value; }
- reg_t getInfoSelector() { return _variables[_offset + 2]; }
- void setInfoSelector(reg_t value) { _variables[_offset + 2] = value; }
+ reg_t getInfoSelector() const { return _variables[_offset + 2]; }
+ void setInfoSelector(reg_t value) { _variables[_offset + 2] = value; }
+
+ reg_t getNameSelector() const { return _variables[_offset + 3]; }
+ void setNameSelector(reg_t value) { _variables[_offset + 3] = value; }
- reg_t getNameSelector() { return _variables[_offset + 3]; }
- void setNameSelector(reg_t value) { _variables[_offset + 3] = value; }
+ reg_t getPropDictSelector() const { return _variables[2]; }
+ void setPropDictSelector(reg_t value) { _variables[2] = value; }
- reg_t getClassScriptSelector() { return _variables[4]; }
+ reg_t getClassScriptSelector() const { return _variables[4]; }
void setClassScriptSelector(reg_t value) { _variables[4] = value; }
- Selector getVarSelector(uint16 i) { return READ_SCI11ENDIAN_UINT16(_baseVars + i); }
+ Selector getVarSelector(uint16 i) const { return READ_SCI11ENDIAN_UINT16(_baseVars + i); }
- reg_t getFunction(uint16 i) {
+ reg_t getFunction(uint16 i) const {
uint16 offset = (getSciVersion() < SCI_VERSION_1_1) ? _methodCount + 1 + i : i * 2 + 2;
- return make_reg(_pos.segment, READ_SCI11ENDIAN_UINT16((byte *) (_baseMethod + offset)));
+ return make_reg(_pos.segment, READ_SCI11ENDIAN_UINT16(_baseMethod + offset));
}
- Selector getFuncSelector(uint16 i) {
+ Selector getFuncSelector(uint16 i) const {
uint16 offset = (getSciVersion() < SCI_VERSION_1_1) ? i : i * 2 + 1;
- return READ_SCI11ENDIAN_UINT16((byte *) (_baseMethod + offset));
+ return READ_SCI11ENDIAN_UINT16(_baseMethod + offset);
}
/**
@@ -247,7 +269,7 @@ public:
* superclasses, i.e. failure may be returned even if one of the
* superclasses defines the funcselector
*/
- int funcSelectorPosition(Selector sel) {
+ int funcSelectorPosition(Selector sel) const {
for (uint i = 0; i < _methodCount; i++)
if (getFuncSelector(i) == sel)
return i;
@@ -256,260 +278,60 @@ public:
}
/**
- * Determines if the object explicitly defines slc as a varselector
- * Returns -1 if not found
+ * Determines if the object explicitly defines slc as a varselector.
+ * Returns -1 if not found.
*/
- int locateVarSelector(SegManager *segMan, Selector slc);
+ int locateVarSelector(SegManager *segMan, Selector slc) const;
- bool isClass() { return (getInfoSelector().offset & SCRIPT_INFO_CLASS); }
- Object *getClass(SegManager *segMan);
+ bool isClass() const { return (getInfoSelector().offset & kInfoFlagClass); }
+ const Object *getClass(SegManager *segMan) const;
- void markAsFreed() { _flags |= OBJECT_FLAG_FREED; }
- bool isFreed() { return _flags & OBJECT_FLAG_FREED; }
-
- void setVarCount(uint size) { _variables.resize(size); }
- uint getVarCount() { return _variables.size(); }
+ void markAsClone() { setInfoSelector(make_reg(0, kInfoFlagClone)); }
+ bool isClone() const { return (getInfoSelector().offset & kInfoFlagClone); }
- void init(byte *buf, reg_t obj_pos) {
- byte *data = (byte *)(buf + obj_pos.offset);
- _baseObj = data;
- _pos = obj_pos;
+ void markAsFreed() { _flags |= OBJECT_FLAG_FREED; }
+ bool isFreed() const { return _flags & OBJECT_FLAG_FREED; }
- if (getSciVersion() < SCI_VERSION_1_1) {
- _variables.resize(READ_LE_UINT16(data + SCRIPT_SELECTORCTR_OFFSET));
- _baseVars = (uint16 *)(_baseObj + _variables.size() * 2);
- _baseMethod = (uint16 *)(data + READ_LE_UINT16(data + SCRIPT_FUNCTAREAPTR_OFFSET));
- _methodCount = READ_LE_UINT16(_baseMethod - 1);
- } else {
- _variables.resize(READ_SCI11ENDIAN_UINT16(data + 2));
- _baseVars = (uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 4));
- _baseMethod = (uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 6));
- _methodCount = READ_SCI11ENDIAN_UINT16(_baseMethod);
- }
+ uint getVarCount() const { return _variables.size(); }
- for (uint i = 0; i < _variables.size(); i++)
- _variables[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(data + (i * 2)));
- }
+ void init(byte *buf, reg_t obj_pos, bool initVariables = true);
- reg_t getVariable(uint var) { return _variables[var]; }
+ reg_t getVariable(uint var) const { return _variables[var]; }
+ reg_t &getVariableRef(uint var) { return _variables[var]; }
- uint16 getMethodCount() { return _methodCount; }
- reg_t getPos() { return _pos; }
+ uint16 getMethodCount() const { return _methodCount; }
+ reg_t getPos() const { return _pos; }
void saveLoadWithSerializer(Common::Serializer &ser);
- void cloneFromObject(Object *obj) {
+ void cloneFromObject(const Object *obj) {
_baseObj = obj ? obj->_baseObj : NULL;
_baseMethod = obj ? obj->_baseMethod : NULL;
_baseVars = obj ? obj->_baseVars : NULL;
}
- // TODO: make private
- Common::Array<reg_t> _variables;
- byte *_baseObj; /**< base + object offset within base */
- uint16 *_baseVars; /**< Pointer to the varselector area for this object */
- uint16 *_baseMethod; /**< Pointer to the method selector area for this object */
-
-private:
- uint16 _methodCount;
- int _flags;
- uint16 _offset;
- reg_t _pos; /**< Object offset within its script; for clones, this is their base */
-};
+ bool relocate(SegmentId segment, int location, size_t scriptSize);
-struct CodeBlock {
- reg_t pos;
- int size;
-};
+ int propertyOffsetToId(SegManager *segMan, int propertyOffset) const;
-typedef Common::HashMap<uint16, Object> ObjMap;
-
-class Script : public SegmentObj {
-public:
- int _nr; /**< Script number */
- byte *_buf; /**< Static data buffer, or NULL if not used */
- size_t _bufSize;
- size_t _scriptSize;
- size_t _heapSize;
-
- byte *_heapStart; /**< Start of heap if SCI1.1, NULL otherwise */
-
- uint16 *_exportTable; /**< Abs. offset of the export table or 0 if not present */
- int _numExports; /**< Number of entries in the exports table */
-
- byte *_synonyms; /**< Synonyms block or 0 if not present*/
- int _numSynonyms; /**< Number of entries in the synonyms block */
-
-protected:
- int _lockers; /**< Number of classes and objects that require this script */
-
-public:
- /**
- * Table for objects, contains property variables.
- * Indexed by the TODO offset.
- */
- ObjMap _objects;
-
- int _localsOffset;
- SegmentId _localsSegment; /**< The local variable segment */
- LocalVariables *_localsBlock;
-
- Common::Array<CodeBlock> _codeBlocks;
- bool _relocated;
- bool _markedAsDeleted;
+ void initSpecies(SegManager *segMan, reg_t addr);
+ void initSuperClass(SegManager *segMan, reg_t addr);
+ bool initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClass = true);
+ // TODO: make private
+ // Only SegManager::reconstructScripts() is left needing direct access to these
public:
- Script();
- ~Script();
-
- void freeScript();
- bool init(int script_nr, ResourceManager *resMan);
-
- virtual bool isValidOffset(uint16 offset) const;
- virtual SegmentRef dereference(reg_t pointer);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-
- Object *allocateObject(uint16 offset);
- Object *getObject(uint16 offset);
-
- /**
- * Informs the segment manager that a code block must be relocated
- * @param location Start of block to relocate
- */
- void scriptAddCodeBlock(reg_t location);
-
- /**
- * Initializes an object within the segment manager
- * @param obj_pos Location (segment, offset) of the object. It must
- * point to the beginning of the script/class block
- * (as opposed to what the VM considers to be the
- * object location)
- * @returns A newly created Object describing the object,
- * stored within the relevant script
- */
- Object *scriptObjInit(reg_t obj_pos);
-
- /**
- * Removes a script object
- * @param obj_pos Location (segment, offset) of the object.
- */
- void scriptObjRemove(reg_t obj_pos);
-
- /**
- * Processes a relocation block witin a script
- * This function is idempotent, but it must only be called after all
- * objects have been instantiated, or a run-time error will occur.
- * @param obj_pos Location (segment, offset) of the block
- * @return Location of the relocation block
- */
- void scriptRelocate(reg_t block);
-
- void heapRelocate(reg_t block);
+ const byte *_baseObj; /**< base + object offset within base */
private:
- int relocateLocal(SegmentId segment, int location);
- int relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location);
- int relocateObject(Object &obj, SegmentId segment, int location);
-
-public:
- // script lock operations
-
- /** Increments the number of lockers of this script by one. */
- void incrementLockers();
-
- /** Decrements the number of lockers of this script by one. */
- void decrementLockers();
-
- /**
- * Retrieves the number of locks held on this script.
- * @return the number of locks held on the previously identified script
- */
- int getLockers() const;
+ const uint16 *_baseVars; /**< Pointer to the varselector area for this object */
+ const uint16 *_baseMethod; /**< Pointer to the method selector area for this object */
- /** Sets the number of locks held on this script. */
- void setLockers(int lockers);
-
- /**
- * Retrieves a pointer to the synonyms associated with this script
- * @return pointer to the synonyms, in non-parsed format.
- */
- byte *getSynonyms() const;
-
- /**
- * Retrieves the number of synonyms associated with this script.
- * @return the number of synonyms associated with this script
- */
- int getSynonymsNr() const;
-
- /**
- * Sets the script-relative offset of the exports table.
- * @param offset script-relative exports table offset
- */
- void setExportTableOffset(int offset);
-
- /**
- * Validate whether the specified public function is exported by
- * the script in the specified segment.
- * @param pubfunct Index of the function to validate
- * @return NULL if the public function is invalid, its
- * offset into the script's segment otherwise
- */
- uint16 validateExportFunc(int pubfunct);
-
- /**
- * Sets the script-relative offset of the synonyms associated with this script.
- * @param offset script-relative offset of the synonyms block
- */
- void setSynonymsOffset(int offset);
-
- /**
- * Sets the number of synonyms associated with this script,
- * @param nr number of synonyms, as to be stored within the script
- */
- void setSynonymsNr(int nr);
-
-
- /**
- * Marks the script as deleted.
- * This will not actually delete the script. If references remain present on the
- * heap or the stack, the script will stay in memory in a quasi-deleted state until
- * either unreachable (resulting in its eventual deletion) or reloaded (resulting
- * in its data being updated).
- */
- void markDeleted() {
- _markedAsDeleted = true;
- }
-
- /**
- * Determines whether the script is marked as being deleted.
- */
- bool isMarkedAsDeleted() const {
- return _markedAsDeleted;
- }
-
- /**
- * Copies a byte string into a script's heap representation.
- * @param dst script-relative offset of the destination area
- * @param src pointer to the data source location
- * @param n number of bytes to copy
- */
- void mcpyInOut(int dst, const void *src, size_t n);
-
-
- /**
- * Retrieves a 16 bit value from within a script's heap representation.
- * @param offset offset to read from
- * @return the value read from the specified location
- */
- int16 getHeap(uint16 offset) const;
-
-private:
- void setScriptSize(int script_nr, ResourceManager *resMan);
+ Common::Array<reg_t> _variables;
+ uint16 _methodCount;
+ int _flags;
+ uint16 _offset;
+ reg_t _pos; /**< Object offset within its script; for clones, this is their base */
};
/** Data stack */
@@ -529,8 +351,8 @@ public:
virtual bool isValidOffset(uint16 offset) const;
virtual SegmentRef dereference(reg_t pointer);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const;
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -618,10 +440,12 @@ public:
entries_used--;
}
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
+ virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const {
+ Common::Array<reg_t> tmp;
for (uint i = 0; i < _table.size(); i++)
if (isValidEntry(i))
- (*note)(param, make_reg(segId, i));
+ tmp.push_back(make_reg(segId, i));
+ return tmp;
}
};
@@ -631,7 +455,7 @@ struct CloneTable : public Table<Clone> {
CloneTable() : Table<Clone>(SEG_TYPE_CLONES) {}
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -642,7 +466,7 @@ struct NodeTable : public Table<Node> {
NodeTable() : Table<Node>(SEG_TYPE_NODES) {}
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -653,7 +477,7 @@ struct ListTable : public Table<List> {
ListTable() : Table<List>(SEG_TYPE_LISTS) {}
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -666,7 +490,10 @@ struct HunkTable : public Table<Hunk> {
virtual void freeEntry(int idx) {
Table<Hunk>::freeEntry(idx);
+ if (!_table[idx].mem)
+ warning("Attempt to free an already freed hunk");
free(_table[idx].mem);
+ _table[idx].mem = 0;
}
virtual void saveLoadWithSerializer(Common::Serializer &ser);
@@ -688,8 +515,8 @@ public:
virtual bool isValidOffset(uint16 offset) const;
virtual SegmentRef dereference(reg_t pointer);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const;
+ virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -782,7 +609,7 @@ public:
_size = _actualSize = size;
}
- T getValue(uint16 index) {
+ T getValue(uint16 index) const {
if (index >= _size)
error("SciArray::getValue(): %d is out of bounds (%d)", index, _size);
@@ -796,9 +623,10 @@ public:
_data[index] = value;
}
- byte getType() { return _type; }
- uint32 getSize() { return _size; }
+ byte getType() const { return _type; }
+ uint32 getSize() const { return _size; }
T *getRawData() { return _data; }
+ const T *getRawData() const { return _data; }
protected:
int8 _type;
@@ -814,15 +642,15 @@ public:
// We overload destroy to ensure the string type is 3 after destroying
void destroy() { SciArray<char>::destroy(); _type = 3; }
- Common::String toString();
- void fromString(Common::String string);
+ Common::String toString() const;
+ void fromString(const Common::String &string);
};
struct ArrayTable : public Table<SciArray<reg_t> > {
ArrayTable() : Table<SciArray<reg_t> >(SEG_TYPE_ARRAY) {}
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
void saveLoadWithSerializer(Common::Serializer &ser);
SegmentRef dereference(reg_t pointer);
diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp
index e226c4b574..f99a41e088 100644
--- a/engines/sci/engine/selector.cpp
+++ b/engines/sci/engine/selector.cpp
@@ -24,6 +24,7 @@
*/
#include "sci/sci.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
@@ -103,6 +104,8 @@ void Kernel::mapSelectors() {
FIND_SELECTOR2(b_incr, "b-incr");
FIND_SELECTOR(xStep);
FIND_SELECTOR(yStep);
+ FIND_SELECTOR(xLast);
+ FIND_SELECTOR(yLast);
FIND_SELECTOR(moveSpeed);
FIND_SELECTOR(canBeHere); // cantBeHere
FIND_SELECTOR(heading);
@@ -153,11 +156,15 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(subtitleLang);
FIND_SELECTOR(parseLang);
FIND_SELECTOR(overlay);
- FIND_SELECTOR(setCursor);
FIND_SELECTOR(topString);
FIND_SELECTOR(scaleSignal);
FIND_SELECTOR(scaleX);
FIND_SELECTOR(scaleY);
+ FIND_SELECTOR(maxScale);
+ FIND_SELECTOR(vanishingX);
+ FIND_SELECTOR(vanishingY);
+ FIND_SELECTOR(iconIndex);
+ FIND_SELECTOR(port);
#ifdef ENABLE_SCI32
FIND_SELECTOR(data);
@@ -172,58 +179,60 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(dimmed);
FIND_SELECTOR(fore);
FIND_SELECTOR(back);
+ FIND_SELECTOR(fixPriority);
+ FIND_SELECTOR(mirrored);
+ FIND_SELECTOR(useInsetRect);
+ FIND_SELECTOR(inTop);
+ FIND_SELECTOR(inLeft);
+ FIND_SELECTOR(inBottom);
+ FIND_SELECTOR(inRight);
#endif
}
-reg_t read_selector(SegManager *segMan, reg_t object, Selector selector_id) {
+reg_t readSelector(SegManager *segMan, reg_t object, Selector selectorId) {
ObjVarRef address;
- if (lookup_selector(segMan, object, selector_id, &address, NULL) != kSelectorVariable)
+ if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable)
return NULL_REG;
else
return *address.getPointer(segMan);
}
-void write_selector(SegManager *segMan, reg_t object, Selector selector_id, reg_t value) {
+void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t value) {
ObjVarRef address;
- if ((selector_id < 0) || (selector_id > (int)g_sci->getKernel()->getSelectorNamesSize())) {
- warning("Attempt to write to invalid selector %d of"
- " object at %04x:%04x.", selector_id, PRINT_REG(object));
+ if ((selectorId < 0) || (selectorId > (int)g_sci->getKernel()->getSelectorNamesSize())) {
+ error("Attempt to write to invalid selector %d of"
+ " object at %04x:%04x.", selectorId, PRINT_REG(object));
return;
}
- if (lookup_selector(segMan, object, selector_id, &address, NULL) != kSelectorVariable)
- warning("Selector '%s' of object at %04x:%04x could not be"
- " written to", g_sci->getKernel()->getSelectorName(selector_id).c_str(), PRINT_REG(object));
+ if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable)
+ error("Selector '%s' of object at %04x:%04x could not be"
+ " written to", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object));
else
*address.getPointer(segMan) = value;
}
-int invoke_selector_argv(EngineState *s, reg_t object, int selector_id, SelectorInvocation noinvalid,
+void invokeSelector(EngineState *s, reg_t object, int selectorId,
int k_argc, StackPtr k_argp, int argc, const reg_t *argv) {
int i;
int framesize = 2 + 1 * argc;
- reg_t address;
int slc_type;
StackPtr stackframe = k_argp + k_argc;
- stackframe[0] = make_reg(0, selector_id); // The selector we want to call
+ stackframe[0] = make_reg(0, selectorId); // The selector we want to call
stackframe[1] = make_reg(0, argc); // Argument count
- slc_type = lookup_selector(s->_segMan, object, selector_id, NULL, &address);
+ slc_type = lookupSelector(s->_segMan, object, selectorId, NULL, NULL);
if (slc_type == kSelectorNone) {
- warning("Selector '%s' of object at %04x:%04x could not be invoked",
- g_sci->getKernel()->getSelectorName(selector_id).c_str(), PRINT_REG(object));
- if (noinvalid == kStopOnInvalidSelector)
- error("[Kernel] Not recoverable: VM was halted");
- return 1;
+ error("Selector '%s' of object at %04x:%04x could not be invoked",
+ g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object));
}
if (slc_type == kSelectorVariable) {
- warning("Attempting to invoke variable selector %s of object %04x:%04x",
- g_sci->getKernel()->getSelectorName(selector_id).c_str(), PRINT_REG(object));
- return 0;
+ error("Attempting to invoke variable selector %s of object %04x:%04x",
+ g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object));
}
for (i = 0; i < argc; i++)
@@ -237,43 +246,25 @@ int invoke_selector_argv(EngineState *s, reg_t object, int selector_id, Selector
xstack->sp += argc + 2;
xstack->fp += argc + 2;
- run_vm(s, false); // Start a new vm
-
- return 0;
-}
-
-int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvocation noinvalid,
- int k_argc, StackPtr k_argp, int argc, ...) {
- va_list argp;
- reg_t *args = new reg_t[argc];
-
- va_start(argp, argc);
- for (int i = 0; i < argc; i++)
- args[i] = va_arg(argp, reg_t);
- va_end(argp);
-
- int retval = invoke_selector_argv(s, object, selector_id, noinvalid, k_argc, k_argp, argc, args);
-
- delete[] args;
- return retval;
+ run_vm(s); // Start a new vm
}
-SelectorType lookup_selector(SegManager *segMan, reg_t obj_location, Selector selector_id, ObjVarRef *varp, reg_t *fptr) {
- Object *obj = segMan->getObject(obj_location);
+SelectorType lookupSelector(SegManager *segMan, reg_t obj_location, Selector selectorId, ObjVarRef *varp, reg_t *fptr) {
+ const Object *obj = segMan->getObject(obj_location);
int index;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
// Early SCI versions used the LSB in the selector ID as a read/write
// toggle, meaning that we must remove it for selector lookup.
if (oldScriptHeader)
- selector_id &= ~1;
+ selectorId &= ~1;
if (!obj) {
- error("lookup_selector(): Attempt to send to non-object or invalid script. Address was %04x:%04x",
+ error("lookupSelector(): Attempt to send to non-object or invalid script. Address was %04x:%04x",
PRINT_REG(obj_location));
}
- index = obj->locateVarSelector(segMan, selector_id);
+ index = obj->locateVarSelector(segMan, selectorId);
if (index >= 0) {
// Found it as a variable
@@ -285,7 +276,7 @@ SelectorType lookup_selector(SegManager *segMan, reg_t obj_location, Selector se
} else {
// Check if it's a method, with recursive lookup in superclasses
while (obj) {
- index = obj->funcSelectorPosition(selector_id);
+ index = obj->funcSelectorPosition(selectorId);
if (index >= 0) {
if (fptr)
*fptr = obj->getFunction(index);
@@ -300,7 +291,7 @@ SelectorType lookup_selector(SegManager *segMan, reg_t obj_location, Selector se
}
-// return _lookup_selector_function(segMan, obj, selector_id, fptr);
+// return _lookupSelector_function(segMan, obj, selectorId, fptr);
}
} // End of namespace Sci
diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h
index 70eeb34d93..00e795c1b9 100644
--- a/engines/sci/engine/selector.h
+++ b/engines/sci/engine/selector.h
@@ -30,24 +30,133 @@
#include "sci/engine/vm_types.h" // for reg_t
#include "sci/engine/vm.h"
-#include "sci/engine/kernel.h" // for Kernel::_selectorCache
namespace Sci {
-
-/******************** Selector functionality ********************/
-
-enum SelectorInvocation {
- kStopOnInvalidSelector = 0,
- kContinueOnInvalidSelector = 1
+/** Contains selector IDs for a few selected selectors */
+struct SelectorCache {
+ SelectorCache() {
+ memset(this, 0, sizeof(*this));
+ }
+
+ // Statically defined selectors, (almost the) same in all SCI versions
+ Selector y;
+ Selector x;
+ Selector view, loop, cel; ///< Description of a specific image
+ Selector underBits; ///< Used by the graphics subroutines to store backupped BG pic data
+ Selector nsTop, nsLeft, nsBottom, nsRight; ///< View boundaries ('now seen')
+ Selector lsTop, lsLeft, lsBottom, lsRight; ///< Used by Animate() subfunctions and scroll list controls
+ Selector signal; ///< Used by Animate() to control a view's behaviour
+ Selector illegalBits; ///< Used by CanBeHere
+ Selector brTop, brLeft, brBottom, brRight; ///< Bounding Rectangle
+ // name, key, time
+ Selector text; ///< Used by controls
+ Selector elements; ///< Used by SetSynonyms()
+ // color, back
+ Selector mode; ///< Used by text controls (-> DrawControl())
+ // style
+ Selector state, font, type;///< Used by controls
+ // window
+ Selector cursor, max; ///< Used by EditControl
+ // mark, who
+ Selector message; ///< Used by GetEvent
+ // edit
+ Selector play; ///< Play function (first function to be called)
+ Selector number;
+ Selector handle; ///< Replaced by nodePtr in SCI1+
+ Selector nodePtr; ///< Replaces handle in SCI1+
+ Selector client; ///< The object that wants to be moved
+ Selector dx, dy; ///< Deltas
+ Selector b_movCnt, b_i1, b_i2, b_di, b_xAxis, b_incr; ///< Various Bresenham vars
+ Selector xStep, yStep; ///< BR adjustments
+ Selector xLast, yLast; ///< BR last position of client
+ Selector moveSpeed; ///< Used for DoBresen
+ Selector canBeHere; ///< Funcselector: Checks for movement validity in SCI0
+ Selector heading, mover; ///< Used in DoAvoider
+ Selector doit; ///< Called (!) by the Animate() system call
+ Selector isBlocked, looper; ///< Used in DoAvoider
+ Selector priority;
+ Selector modifiers; ///< Used by GetEvent
+ Selector replay; ///< Replay function
+ // setPri, at, next, done, width
+ Selector wordFail, syntaxFail; ///< Used by Parse()
+ // semanticFail, pragmaFail
+ // said
+ Selector claimed; ///< Used generally by the event mechanism
+ // value, save, restore, title, button, icon, draw
+ Selector delete_; ///< Called by Animate() to dispose a view object
+ Selector z;
+
+ // SCI1+ static selectors
+ Selector parseLang;
+ Selector printLang; ///< Used for i18n
+ Selector subtitleLang;
+ Selector size;
+ Selector points; ///< Used by AvoidPath()
+ Selector palette;
+ Selector dataInc;
+ // handle (in SCI1)
+ Selector min; ///< SMPTE time format
+ Selector sec;
+ Selector frame;
+ Selector vol;
+ Selector pri;
+ // perform
+ Selector moveDone; ///< used for DoBresen
+
+ // SCI1 selectors which have been moved a bit in SCI1.1, but otherwise static
+ Selector cantBeHere; ///< Checks for movement avoidance in SCI1+. Replaces canBeHere
+ Selector topString; ///< SCI1 scroll lists use this instead of lsTop
+ Selector flags;
+
+ // SCI1+ audio sync related selectors, not static. They're used for lip syncing in
+ // CD talkie games
+ Selector syncCue; ///< Used by DoSync()
+ Selector syncTime;
+
+ // SCI1.1 specific selectors
+ Selector scaleSignal; //< Used by kAnimate() for cel scaling (SCI1.1+)
+ Selector scaleX, scaleY; ///< SCI1.1 view scaling
+ Selector maxScale; ///< SCI1.1 view scaling, limit for cel, when using global scaling
+ Selector vanishingX; ///< SCI1.1 view scaling, used by global scaling
+ Selector vanishingY; ///< SCI1.1 view scaling, used by global scaling
+
+ // Used for auto detection purposes
+ Selector overlay; ///< Used to determine if a game is using old gfx functions or not
+
+ // SCI1.1 Mac icon bar selectors
+ Selector iconIndex; ///< Used to index icon bar objects
+
+ Selector port; // used by a hoyle 4 workaround
+
+#ifdef ENABLE_SCI32
+ Selector data; // Used by Array()/String()
+ Selector picture; // Used to hold the picture ID for SCI32 pictures
+
+ Selector plane;
+ Selector top;
+ Selector left;
+ Selector bottom;
+ Selector right;
+ Selector resX;
+ Selector resY;
+
+ Selector fore;
+ Selector back;
+ Selector dimmed;
+
+ Selector fixPriority;
+ Selector mirrored;
+
+ Selector useInsetRect;
+ Selector inTop, inLeft, inBottom, inRight;
+#endif
};
-
/**
* Map a selector name to a selector id. Shortcut for accessing the selector cache.
*/
#define SELECTOR(_slc_) (g_sci->getKernel()->_selectorCache._slc_)
-//#define SELECTOR(_slc_) _slc_
/**
* Retrieves a selector from an object.
@@ -58,8 +167,8 @@ enum SelectorInvocation {
* This macro halts on error. 'selector' must be a selector name registered in vm.h's
* SelectorCache and mapped in script.cpp.
*/
-#define GET_SEL32(segMan, _obj_, _slc_) read_selector(segMan, _obj_, _slc_)
-#define GET_SEL32V(segMan, _obj_, _slc_) (GET_SEL32(segMan, _obj_, _slc_).offset)
+reg_t readSelector(SegManager *segMan, reg_t object, Selector selectorId);
+#define readSelectorValue(segMan, _obj_, _slc_) (readSelector(segMan, _obj_, _slc_).offset)
/**
* Writes a selector value to an object.
@@ -70,26 +179,14 @@ enum SelectorInvocation {
* This macro halts on error. 'selector' must be a selector name registered in vm.h's
* SelectorCache and mapped in script.cpp.
*/
-#define PUT_SEL32(segMan, _obj_, _slc_, _val_) write_selector(segMan, _obj_, _slc_, _val_)
-#define PUT_SEL32V(segMan, _obj_, _slc_, _val_) PUT_SEL32(segMan, _obj_, _slc_, make_reg(0, _val_))
-
+void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t value);
+#define writeSelectorValue(segMan, _obj_, _slc_, _val_) writeSelector(segMan, _obj_, _slc_, make_reg(0, _val_))
/**
- * Kludge for use with invoke_selector(). Used for compatibility with compilers
- * that cannot handle vararg macros.
+ * Invokes a selector from an object.
*/
-#define INV_SEL(s, _object_, _selector_, _noinvalid_) \
- s, _object_, g_sci->getKernel()->_selectorCache._selector_, _noinvalid_, argc, argv
-
-
-reg_t read_selector(SegManager *segMan, reg_t object, Selector selector_id);
-void write_selector(SegManager *segMan, reg_t object, Selector selector_id, reg_t value);
-int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvocation noinvalid,
- int k_argc, StackPtr k_argp, int argc, ...);
-int invoke_selector_argv(EngineState *s, reg_t object, int selector_id, SelectorInvocation noinvalid,
- int k_argc, StackPtr k_argp, int argc, const reg_t *argv);
-
-
+void invokeSelector(EngineState *s, reg_t object, int selectorId,
+ int k_argc, StackPtr k_argp, int argc = 0, const reg_t *argv = 0);
} // End of namespace Sci
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index bd78639c77..a069344d61 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -29,6 +29,7 @@
#include "sci/debug.h" // for g_debug_sleeptime_factor
#include "sci/event.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
#include "sci/engine/vm.h"
@@ -69,70 +70,102 @@ static const uint16 s_halfWidthSJISMap[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-EngineState::EngineState(Vocabulary *voc, SegManager *segMan)
-: _voc(voc), _segMan(segMan), _dirseeker() {
+EngineState::EngineState(SegManager *segMan)
+: _segMan(segMan), _dirseeker() {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- sfx_init_flags = 0;
-#endif
+ reset(false);
+}
- restarting_flags = 0;
+EngineState::~EngineState() {
+ delete _msgState;
+}
- last_wait_time = 0;
+void EngineState::reset(bool isRestoring) {
+ if (!isRestoring) {
+ _memorySegmentSize = 0;
- _fileHandles.resize(5);
+ _fileHandles.resize(5);
- execution_stack_base = 0;
- _executionStackPosChanged = false;
-
- r_acc = NULL_REG;
- restAdjust = 0;
- r_prev = NULL_REG;
+ abortScriptProcessing = kAbortNone;
+ }
+ executionStackBase = 0;
+ _executionStackPosChanged = false;
stack_base = 0;
stack_top = 0;
- script_000 = 0;
-
- sys_strings_segment = 0;
- sys_strings = 0;
+ restAdjust = 0;
- _gameObj = NULL_REG;
+ r_acc = NULL_REG;
+ r_prev = NULL_REG;
- gc_countdown = 0;
+ lastWaitTime = 0;
- successor = 0;
+ gcCountDown = 0;
_throttleCounter = 0;
_throttleLastTime = 0;
_throttleTrigger = false;
- _memorySegmentSize = 0;
+ _lastSaveVirtualId = SAVEGAMEID_OFFICIALRANGE_START;
+ _lastSaveNewId = 0;
- _soundCmd = 0;
+ scriptStepCounter = 0;
+ scriptGCInterval = GC_INTERVAL;
}
-EngineState::~EngineState() {
- delete _msgState;
+void EngineState::speedThrottler(uint32 neededSleep) {
+ if (_throttleTrigger) {
+ uint32 curTime = g_system->getMillis();
+ uint32 duration = curTime - _throttleLastTime;
+
+ if (duration < neededSleep) {
+ g_sci->sleep(neededSleep - duration);
+ _throttleLastTime = g_system->getMillis();
+ } else {
+ _throttleLastTime = curTime;
+ }
+ _throttleTrigger = false;
+ }
}
void EngineState::wait(int16 ticks) {
- uint32 time;
-
- time = g_system->getMillis();
- r_acc = make_reg(0, ((long)time - (long)last_wait_time) * 60 / 1000);
- last_wait_time = time;
+ uint32 time = g_system->getMillis();
+ r_acc = make_reg(0, ((long)time - (long)lastWaitTime) * 60 / 1000);
+ lastWaitTime = time;
ticks *= g_debug_sleeptime_factor;
- _event->sleep(ticks * 1000 / 60);
+ g_sci->sleep(ticks * 1000 / 60);
+}
+
+void EngineState::initGlobals() {
+ Script *script_000 = _segMan->getScript(1);
+
+ if (!script_000->_localsBlock)
+ error("Script 0 has no locals block");
+
+ variablesSegment[VAR_GLOBAL] = script_000->_localsSegment;
+ variablesBase[VAR_GLOBAL] = variables[VAR_GLOBAL] = script_000->_localsBlock->_locals.begin();
+ variablesMax[VAR_GLOBAL] = script_000->_localsBlock->_locals.size();
}
uint16 EngineState::currentRoomNumber() const {
- return script_000->_localsBlock->_locals[13].toUint16();
+ return variables[VAR_GLOBAL][13].toUint16();
}
void EngineState::setRoomNumber(uint16 roomNumber) {
- script_000->_localsBlock->_locals[13] = make_reg(0, roomNumber);
+ variables[VAR_GLOBAL][13] = make_reg(0, roomNumber);
+}
+
+void EngineState::shrinkStackToBase() {
+ if (_executionStack.size() > 0) {
+ uint size = executionStackBase + 1;
+ assert(_executionStack.size() >= size);
+ Common::List<ExecStack>::iterator iter = _executionStack.begin();
+ for (uint i = 0; i < size; ++i)
+ ++iter;
+ _executionStack.erase(iter, _executionStack.end());
+ }
}
static kLanguage charToLanguage(const char c) {
@@ -190,7 +223,7 @@ Common::String SciEngine::getSciLanguageString(const char *str, kLanguage lang,
// Copy double-byte character
char c2 = *(++seeker);
if (!c2) {
- warning("SJIS character %02X is missing second byte", c);
+ error("SJIS character %02X is missing second byte", c);
break;
}
fullWidth += c;
@@ -217,8 +250,8 @@ kLanguage SciEngine::getSciLanguage() {
lang = K_LANG_ENGLISH;
- if (_kernel->_selectorCache.printLang != -1) {
- lang = (kLanguage)GET_SEL32V(_gamestate->_segMan, _gamestate->_gameObj, SELECTOR(printLang));
+ if (SELECTOR(printLang) != -1) {
+ lang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(printLang));
if ((getSciVersion() >= SCI_VERSION_1_1) || (lang == K_LANG_NONE)) {
// If language is set to none, we use the language from the game detector.
@@ -251,21 +284,27 @@ kLanguage SciEngine::getSciLanguage() {
default:
lang = K_LANG_ENGLISH;
}
-
- // Store language in printLang selector
- PUT_SEL32V(_gamestate->_segMan, _gamestate->_gameObj, SELECTOR(printLang), lang);
}
}
return lang;
}
+void SciEngine::setSciLanguage(kLanguage lang) {
+ if (SELECTOR(printLang) != -1)
+ writeSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(printLang), lang);
+}
+
+void SciEngine::setSciLanguage() {
+ setSciLanguage(getSciLanguage());
+}
+
Common::String SciEngine::strSplit(const char *str, const char *sep) {
kLanguage lang = getSciLanguage();
kLanguage subLang = K_LANG_NONE;
- if (_kernel->_selectorCache.subtitleLang != -1) {
- subLang = (kLanguage)GET_SEL32V(_gamestate->_segMan, _gamestate->_gameObj, SELECTOR(subtitleLang));
+ if (SELECTOR(subtitleLang) != -1) {
+ subLang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(subtitleLang));
}
kLanguage secondLang;
@@ -285,4 +324,17 @@ Common::String SciEngine::strSplit(const char *str, const char *sep) {
return retval;
}
+void SciEngine::checkVocabularySwitch() {
+ uint16 parserLanguage = 1;
+ if (SELECTOR(parseLang) != -1)
+ parserLanguage = readSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(parseLang));
+
+ if (parserLanguage != _vocabularyLanguage) {
+ delete _vocabulary;
+ _vocabulary = new Vocabulary(_resMan, parserLanguage > 1 ? true : false);
+ _vocabulary->reset();
+ _vocabularyLanguage = parserLanguage;
+ }
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index c4b995806f..4f1d686b17 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -41,17 +41,21 @@ namespace Common {
#include "sci/parser/vocabulary.h"
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-#include "sci/sound/iterator/core.h"
-#endif
#include "sci/sound/soundcmd.h"
namespace Sci {
-class SciEvent;
+class EventManager;
class MessageState;
class SoundCommandParser;
+enum AbortGameState {
+ kAbortNone = 0,
+ kAbortLoadGame = 1,
+ kAbortRestartGame = 2,
+ kAbortQuitGame = 3
+};
+
class DirSeeker {
protected:
reg_t _outbuffer;
@@ -72,12 +76,21 @@ enum {
MAX_SAVE_DIR_SIZE = MAXPATHLEN
};
-/** values for EngineState.restarting_flag */
enum {
- SCI_GAME_IS_NOT_RESTARTING = 0,
- SCI_GAME_WAS_RESTARTED = 1,
- SCI_GAME_IS_RESTARTING_NOW = 2,
- SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE = 4
+ MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */
+};
+
+// We assume that scripts give us savegameId 0->999 for creating a new save slot
+// and savegameId 1000->1999 for existing save slots ffs. kfile.cpp
+enum {
+ SAVEGAMEID_OFFICIALRANGE_START = 1000,
+ SAVEGAMEID_OFFICIALRANGE_END = 1999
+};
+
+enum {
+ GAMEISRESTARTING_NONE = 0,
+ GAMEISRESTARTING_RESTART = 1,
+ GAMEISRESTARTING_RESTORE = 2
};
class FileHandle {
@@ -96,32 +109,21 @@ public:
struct EngineState : public Common::Serializable {
public:
- EngineState(Vocabulary *voc, SegManager *segMan);
+ EngineState(SegManager *segMan);
virtual ~EngineState();
virtual void saveLoadWithSerializer(Common::Serializer &ser);
public:
SegManager *_segMan; /**< The segment manager */
- Vocabulary *_voc;
-
- Common::String _gameId; /**< Designation of the primary object (which inherits from Game) */
/* Non-VM information */
- SciEvent *_event; // Event handling
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- SfxState _sound; /**< sound subsystem */
- int sfx_init_flags; /**< flags the sfx subsystem was initialised with */
-#endif
- SoundCommandParser *_soundCmd;
-
- byte restarting_flags; /**< Flags used for restarting */
-
- uint32 game_start_time; /**< The time at which the interpreter was started */
- uint32 last_wait_time; /**< The last time the game invoked Wait() */
+ uint32 gameStartTime; /**< The time at which the interpreter was started */
+ uint32 lastWaitTime; /**< The last time the game invoked Wait() */
+ uint32 _screenUpdateTime; /**< The last time the game updated the screen */
+ void speedThrottler(uint32 neededSleep);
void wait(int16 ticks);
uint32 _throttleCounter; /**< total times kAnimate was invoked */
@@ -134,6 +136,9 @@ public:
DirSeeker _dirseeker;
+ uint _lastSaveVirtualId; // last virtual id fed to kSaveGame, if no kGetSaveFiles was called inbetween
+ uint _lastSaveNewId; // last newly created filename-id by kSaveGame
+
public:
/* VM Information */
@@ -142,28 +147,44 @@ public:
* When called from kernel functions, the vm is re-started recursively on
* the same stack. This variable contains the stack base for the current vm.
*/
- int execution_stack_base;
+ int executionStackBase;
bool _executionStackPosChanged; /**< Set to true if the execution stack position should be re-evaluated by the vm */
reg_t r_acc; /**< Accumulator */
- int16 restAdjust; /**< &rest register (only used for save games) */
+ int16 restAdjust; /**< current &rest register */
reg_t r_prev; /**< previous comparison result */
StackPtr stack_base; /**< Pointer to the least stack element */
StackPtr stack_top; /**< First invalid stack element */
- Script *script_000; /**< script 000, e.g. for globals */
+ // Script state
+ ExecStack *xs;
+ reg_t *variables[4]; ///< global, local, temp, param, as immediate pointers
+ reg_t *variablesBase[4]; ///< Used for referencing VM ops
+ SegmentId variablesSegment[4]; ///< Same as above, contains segment IDs
+ int variablesMax[4]; ///< Max. values for all variables
+
+ AbortGameState abortScriptProcessing;
+ int16 gameIsRestarting; // is set when restarting (=1) or restoring the game (=2)
+
+ int scriptStepCounter; // Counts the number of steps executed
+ int scriptGCInterval; // Number of steps in between gcs
uint16 currentRoomNumber() const;
void setRoomNumber(uint16 roomNumber);
- /* System strings */
- SegmentId sys_strings_segment;
- SystemStrings *sys_strings;
+ /**
+ * Sets global variables from script 0
+ */
+ void initGlobals();
- reg_t _gameObj; /**< Pointer to the game object */
+ /**
+ * Shrink execution stack to size.
+ * Contains an assert if it is not already smaller.
+ */
+ void shrinkStackToBase();
- int gc_countdown; /**< Number of kernel calls until next gc */
+ int gcCountDown; /**< Number of kernel calls until next gc */
public:
MessageState *_msgState;
@@ -176,7 +197,10 @@ public:
uint _memorySegmentSize;
byte _memorySegment[kMemorySegmentMax];
- EngineState *successor; /**< Successor of this state: Used for restoring */
+ /**
+ * Resets the engine state.
+ */
+ void reset(bool isRestoring);
};
} // End of namespace Sci
diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp
index 0f558f2dc8..aae6de01f1 100644
--- a/engines/sci/engine/static_selectors.cpp
+++ b/engines/sci/engine/static_selectors.cpp
@@ -38,75 +38,86 @@ struct SelectorRemap {
};
static const char * const sci0Selectors[] = {
- "y", "x", "view", "loop", "cel", // 0 - 4
- "underBits", "nsTop", "nsLeft", "nsBottom", "nsRight", // 5 - 9
- "lsTop", "lsLeft", "lsBottom", "lsRight", "signal", // 10 - 14
- "illegalBits", "brTop", "brLeft", "brBottom", "brRight", // 15 - 19
- "name", "key", "time", "text", "elements", // 20 - 25
- "color", "back", "mode", "style", "state", // 25 - 29
- "font", "type", "window", "cursor", "max", // 30 - 34
- "mark", "who", "message", "edit", "play", // 35 - 39
- "number", "handle", "client", "dx", "dy", // 40 - 44
- "b-moveCnt", "b-i1", "b-i2", "b-di", "b-xAxis", // 45 - 49
- "b-incr", "xStep", "yStep", "moveSpeed", "canBeHere", // 50 - 54
- "heading", "mover", "doit", "isBlocked", "looper", // 55 - 59
- "priority", "modifiers", "replay", "setPri", "at", // 60 - 64
- "next", "done", "width", "wordFail", "syntaxFail", // 65 - 69
- "semanticFail", "pragmaFail", "said", "claimed", "value", // 70 - 74
- "save", "restore", "title", "button", "icon", // 75 - 79
- "draw", "delete", "z" // 80 - 82
+ "y", "x", "view", "loop", "cel", // 0 - 4
+ "underBits", "nsTop", "nsLeft", "nsBottom", "nsRight", // 5 - 9
+ "lsTop", "lsLeft", "lsBottom", "lsRight", "signal", // 10 - 14
+ "illegalBits", "brTop", "brLeft", "brBottom", "brRight", // 15 - 19
+ "name", "key", "time", "text", "elements", // 20 - 25
+ "color", "back", "mode", "style", "state", // 25 - 29
+ "font", "type", "window", "cursor", "max", // 30 - 34
+ "mark", "who", "message", "edit", "play", // 35 - 39
+ "number", "handle", "client", "dx", "dy", // 40 - 44
+ "b-moveCnt", "b-i1", "b-i2", "b-di", "b-xAxis", // 45 - 49
+ "b-incr", "xStep", "yStep", "moveSpeed", "canBeHere", // 50 - 54
+ "heading", "mover", "doit", "isBlocked", "looper", // 55 - 59
+ "priority", "modifiers", "replay", "setPri", "at", // 60 - 64
+ "next", "done", "width", "wordFail", "syntaxFail", // 65 - 69
+ "semanticFail", "pragmaFail", "said", "claimed", "value", // 70 - 74
+ "save", "restore", "title", "button", "icon", // 75 - 79
+ "draw", "delete", "z" // 80 - 82
};
static const char * const sci1Selectors[] = {
- "parseLang", "printLang", "subtitleLang", "size", "points", // 83 - 87
- "palette", "dataInc", "handle", "min", "sec", // 88 - 92
- "frame", "vol", "pri", "perform", "moveDone" // 93 - 97
+ "parseLang", "printLang", "subtitleLang", "size", "points", // 83 - 87
+ "palette", "dataInc", "handle", "min", "sec", // 88 - 92
+ "frame", "vol", "pri", "perform", "moveDone" // 93 - 97
};
#ifdef ENABLE_SCI32
static const char * const sci2Selectors[] = {
- "plane", "x", "y", "z", "scaleX", // 0 - 4
- "scaleY", "maxScale", "priority", "fixPriority", "inLeft", // 5 - 9
- "inTop", "inRight", "inBottom", "useInsetRect", "view", // 10 - 14
- "loop", "cel", "bitmap", "nsLeft", "nsTop", // 15 - 19
- "nsRight", "nsBottom", "lsLeft", "lsTop", "lsRight", // 20 - 25
- "lsBottom", "signal", "illegalBits", "brLeft", "brTop", // 25 - 29
- "brRight", "brBottom", "name", "key", "time", // 30 - 34
- "text", "elements", "fore", "back", "mode", // 35 - 39
- "style", "state", "font", "type", "window", // 40 - 44
- "cursor", "max", "mark", "who", "message", // 45 - 49
- "edit", "play", "number", "nodePtr", "client", // 50 - 54
- "dx", "dy", "b-moveCnt", "b-i1", "b-i2", // 55 - 59
- "b-di", "b-xAxis", "b-incr", "xStep", "yStep", // 60 - 64
- "moveSpeed", "cantBeHere", "heading", "mover", "doit", // 65 - 69
- "isBlocked", "looper", "modifiers", "replay", "setPri", // 70 - 74
- "at", "next", "done", "width", "pragmaFail", // 75 - 79
- "claimed", "value", "save", "restore", "title", // 80 - 84
- "button", "icon", "draw", "delete", "printLang", // 85 - 89
- "size", "points", "palette", "dataInc", "handle", // 90 - 94
- "min", "sec", "frame", "vol", "perform", // 95 - 99
- "moveDone", "topString", "flags", "quitGame", "restart", // 100 - 104
- "hide", "scaleSignal", "vanishingX", "vanishingY", "picture", // 105 - 109
- "resX", "resY", "coordType", "data", "skip", // 110 - 104
- "center", "all", "show", "textLeft", "textTop", // 115 - 119
- "textRight", "textBottom", "borderColor", "titleFore", "titleBack", // 120 - 124
- "titleFont", "dimmed", "frameOut", "lastKey", "magnifier", // 125 - 129
- "magPower", "mirrored", "pitch", "roll", "yaw", // 130 - 134
- "left", "right", "top", "bottom", "numLines" // 135 - 139
+ "plane", "x", "y", "z", "scaleX", // 0 - 4
+ "scaleY", "maxScale", "priority", "fixPriority", "inLeft", // 5 - 9
+ "inTop", "inRight", "inBottom", "useInsetRect", "view", // 10 - 14
+ "loop", "cel", "bitmap", "nsLeft", "nsTop", // 15 - 19
+ "nsRight", "nsBottom", "lsLeft", "lsTop", "lsRight", // 20 - 25
+ "lsBottom", "signal", "illegalBits", "brLeft", "brTop", // 25 - 29
+ "brRight", "brBottom", "name", "key", "time", // 30 - 34
+ "text", "elements", "fore", "back", "mode", // 35 - 39
+ "style", "state", "font", "type", "window", // 40 - 44
+ "cursor", "max", "mark", "who", "message", // 45 - 49
+ "edit", "play", "number", "nodePtr", "client", // 50 - 54
+ "dx", "dy", "b-moveCnt", "b-i1", "b-i2", // 55 - 59
+ "b-di", "b-xAxis", "b-incr", "xStep", "yStep", // 60 - 64
+ "moveSpeed", "cantBeHere", "heading", "mover", "doit", // 65 - 69
+ "isBlocked", "looper", "modifiers", "replay", "setPri", // 70 - 74
+ "at", "next", "done", "width", "pragmaFail", // 75 - 79
+ "claimed", "value", "save", "restore", "title", // 80 - 84
+ "button", "icon", "draw", "delete", "printLang", // 85 - 89
+ "size", "points", "palette", "dataInc", "handle", // 90 - 94
+ "min", "sec", "frame", "vol", "perform", // 95 - 99
+ "moveDone", "topString", "flags", "quitGame", "restart", // 100 - 104
+ "hide", "scaleSignal", "vanishingX", "vanishingY", "picture", // 105 - 109
+ "resX", "resY", "coordType", "data", "skip", // 110 - 104
+ "center", "all", "show", "textLeft", "textTop", // 115 - 119
+ "textRight", "textBottom", "borderColor", "titleFore", "titleBack", // 120 - 124
+ "titleFont", "dimmed", "frameOut", "lastKey", "magnifier", // 125 - 129
+ "magPower", "mirrored", "pitch", "roll", "yaw", // 130 - 134
+ "left", "right", "top", "bottom", "numLines" // 135 - 139
};
#endif
static const SelectorRemap sciSelectorRemap[] = {
- { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "moveDone", 170 },
+ { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "moveDone", 170 },
{ SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "points", 316 },
{ SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "flags", 368 },
- { SCI_VERSION_1_EARLY, SCI_VERSION_1_1, "nodePtr", 44 },
- { SCI_VERSION_1_LATE, SCI_VERSION_1_1, "cantBeHere", 57 },
- { SCI_VERSION_1_EARLY, SCI_VERSION_1_1, "topString", 101 },
- { SCI_VERSION_1_EARLY, SCI_VERSION_1_1, "flags", 102 },
+ { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "nodePtr", 44 },
+ { SCI_VERSION_1_LATE, SCI_VERSION_1_LATE, "cantBeHere", 57 },
+ { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "topString", 101 },
+ { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "flags", 102 },
+ // SCI1.1
+ { SCI_VERSION_1_1, SCI_VERSION_1_1, "nodePtr", 41 },
+ { SCI_VERSION_1_1, SCI_VERSION_1_1, "cantBeHere", 54 },
+ { SCI_VERSION_1_1, SCI_VERSION_1_1, "topString", 98 },
+ { SCI_VERSION_1_1, SCI_VERSION_1_1, "flags", 99 },
+ // quitGame
+ // restart
+ // hide
{ SCI_VERSION_1_1, SCI_VERSION_1_1,"scaleSignal", 103 },
{ SCI_VERSION_1_1, SCI_VERSION_1_1, "scaleX", 104 },
{ SCI_VERSION_1_1, SCI_VERSION_1_1, "scaleY", 105 },
+ { SCI_VERSION_1_1, SCI_VERSION_1_1, "maxScale", 106 },
+ { SCI_VERSION_1_1, SCI_VERSION_1_1, "vanishingX", 107 },
+ { SCI_VERSION_1_1, SCI_VERSION_1_1, "vanishingY", 108 },
{ SCI_VERSION_NONE, SCI_VERSION_NONE, 0, 0 }
};
@@ -139,16 +150,41 @@ Common::StringArray Kernel::checkStaticSelectorNames() {
}
for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) {
- uint32 slot = selectorRemap->slot;
- if (selectorRemap->slot >= names.size())
- names.resize(selectorRemap->slot + 1);
if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) {
- // The SCI1 selectors we use exist in SCI1.1 too, offset by 3
- if (selectorRemap->minVersion >= SCI_VERSION_1_EARLY && getSciVersion() == SCI_VERSION_1_1)
- slot -= 3;
+ const uint32 slot = selectorRemap->slot;
+ if (slot >= names.size())
+ names.resize(slot + 1);
names[slot] = selectorRemap->name;
}
}
+
+ if (g_sci->getGameId() == GID_HOYLE4) {
+ // The demo of Hoyle 4 is one of the few demos with lip syncing and no selector vocabulary.
+ // This needs two selectors, "syncTime" and "syncCue", which keep changing positions in each
+ // game. Usually, games with speech and lip sync have a selector vocabulary, so we don't need
+ // to set these two selectors, but we need for Hoyle...
+ if (names.size() < 276)
+ names.resize(276);
+
+ names[274] = "syncTime";
+ names[275] = "syncCue";
+ } else if (g_sci->getGameId() == GID_ISLANDBRAIN) {
+ // The demo of Island of Dr. Brain needs the init selector set to match up with the full
+ // game's workaround - bug #3035033
+ if (names.size() < 111)
+ names.resize(111);
+
+ names[110] = "init";
+ } else if (g_sci->getGameId() == GID_LAURABOW2) {
+ // The floppy of version needs the open and changeState selectors set to match up with the
+ // CD version's workarounds - bugs #3035694 and #3036291
+ if (names.size() < 190)
+ names.resize(190);
+
+ names[144] = "changeState";
+ names[189] = "open";
+ }
+
#ifdef ENABLE_SCI32
} else {
// SCI2+
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index e2ee2e1971..7c989e43f4 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -30,29 +30,23 @@
#include "sci/sci.h"
#include "sci/console.h"
-#include "sci/debug.h" // for g_debugState
#include "sci/resource.h"
#include "sci/engine/features.h"
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
-#include "sci/engine/seg_manager.h"
#include "sci/engine/script.h"
+#include "sci/engine/seg_manager.h"
+#include "sci/engine/selector.h" // for SELECTOR
#include "sci/engine/gc.h"
+#include "sci/engine/workarounds.h"
namespace Sci {
const reg_t NULL_REG = {0, 0};
const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET};
-
+const reg_t TRUE_REG = {0, 1};
//#define VM_DEBUG_SEND
-ScriptState scriptState; // FIXME: Avoid non-const global vars
-int g_loadFromLauncher; // FIXME: Avoid non-const global vars
-
-int script_abort_flag = 0; // Set to 1 to abort execution. Set to 2 to force a replay afterwards // FIXME: Avoid non-const global vars
-int script_step_counter = 0; // Counts the number of steps executed // FIXME: Avoid non-const global vars
-int script_gc_interval = GC_INTERVAL; // Number of steps in between gcs // FIXME: Avoid non-const global vars
-
#define SCI_XS_CALLEE_LOCALS ((SegmentId)-1)
/**
@@ -66,6 +60,8 @@ int script_gc_interval = GC_INTERVAL; // Number of steps in between gcs // FIXME
* @param[in] argp Heap pointer to the first parameter
* @param[in] selector The selector by which it was called or
* NULL_SELECTOR if n.a. For debugging.
+ * @param[in] exportId The exportId by which it was called or
+ * -1 if n.a. For debugging.
* @param[in] sendp Pointer to the object which the message was
* sent to. Equal to objp for anything but super.
* @param[in] origin Number of the execution stack element this
@@ -76,10 +72,9 @@ int script_gc_interval = GC_INTERVAL; // Number of steps in between gcs // FIXME
* @return A pointer to the new exec stack TOS entry
*/
static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp,
- reg_t objp, int argc, StackPtr argp, Selector selector,
+ reg_t objp, int argc, StackPtr argp, Selector selector, int exportId, int localCallOffset,
reg_t sendp, int origin, SegmentId local_segment);
-
/**
* Adds one varselector access to the execution stack.
* This function is called from send_selector only.
@@ -97,30 +92,28 @@ static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack,
int origin);
-
-
// validation functionality
-#ifndef DISABLE_VALIDATIONS
-
static reg_t &validate_property(Object *obj, int index) {
// A static dummy reg_t, which we return if obj or index turn out to be
// invalid. Note that we cannot just return NULL_REG, because client code
// may modify the value of the returned reg_t.
static reg_t dummyReg = NULL_REG;
- if (!obj) {
- debugC(2, kDebugLevelVM, "[VM] Sending to disposed object!");
- return dummyReg;
- }
+ // If this occurs, it means there's probably something wrong with the garbage
+ // collector, so don't hide it with fake return values
+ if (!obj)
+ error("validate_property: Sending to disposed object");
if (index < 0 || (uint)index >= obj->getVarCount()) {
+ // This is same way sierra does it and there are some games, that contain such scripts like
+ // iceman script 998 (fred::canBeHere, executed right at the start)
debugC(2, kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested!",
index, obj->getVarCount());
return dummyReg;
}
- return obj->_variables[index];
+ return obj->getVariableRef(index);
}
static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) {
@@ -134,7 +127,9 @@ static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) {
static int validate_arithmetic(reg_t reg) {
if (reg.segment) {
- warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment);
+ // The results of this are likely unpredictable... It most likely means that a kernel function is returning something wrong.
+ // If such an error occurs, we usually need to find the last kernel function called and check its return value.
+ error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]. Address: %04x:%04x", reg.segment, PRINT_REG(reg));
return 0;
}
@@ -142,15 +137,10 @@ static int validate_arithmetic(reg_t reg) {
}
static int signed_validate_arithmetic(reg_t reg) {
- if (reg.segment) {
- warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment);
- return 0;
- }
-
- return (int16)reg.offset;
+ return (int16)validate_arithmetic(reg);
}
-static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int index, int line) {
+static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int index) {
const char *names[4] = {"global", "local", "temp", "param"};
if (index < 0 || index >= max) {
@@ -165,8 +155,8 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in
if (type == VAR_PARAM || type == VAR_TEMP) {
int total_offset = r - stack_base;
if (total_offset < 0 || total_offset >= VM_STACK_SIZE) {
- warning("%s", txt.c_str());
- warning("[VM] Access would be outside even of the stack (%d); access denied", total_offset);
+ // Fatal, as the game is trying to do an OOB access
+ error("%s. [VM] Access would be outside even of the stack (%d); access denied", txt.c_str(), total_offset);
return false;
} else {
debugC(2, kDebugLevelVM, "%s", txt.c_str());
@@ -180,15 +170,67 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in
return true;
}
-static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) {
- if (validate_variable(r, stack_base, type, max, index, line))
+static bool validate_unsignedInteger(reg_t reg, uint16 &integer) {
+ if (reg.segment)
+ return false;
+ integer = reg.offset;
+ return true;
+}
+
+static bool validate_signedInteger(reg_t reg, int16 &integer) {
+ if (reg.segment)
+ return false;
+ integer = (int16)reg.offset;
+ return true;
+}
+
+extern const char *opcodeNames[]; // from scriptdebug.cpp
+
+static reg_t arithmetic_lookForWorkaround(const byte opcode, const SciWorkaroundEntry *workaroundList, reg_t value1, reg_t value2) {
+ SciTrackOriginReply originReply;
+ SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, workaroundList, &originReply);
+ if (solution.type == WORKAROUND_NONE)
+ error("%s on non-integer (%04x:%04x, %04x:%04x) from method %s::%s (script %d, room %d, localCall %x)",
+ opcodeNames[opcode], PRINT_REG(value1), PRINT_REG(value2), originReply.objectName.c_str(),
+ originReply.methodName.c_str(), originReply.scriptNr, g_sci->getEngineState()->currentRoomNumber(),
+ originReply.localCallOffset);
+ assert(solution.type == WORKAROUND_FAKE);
+ return make_reg(0, solution.value);
+}
+
+static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t default_value) {
+ if (validate_variable(r, stack_base, type, max, index)) {
+ if (r[index].segment == 0xffff) {
+ switch (type) {
+ case VAR_TEMP: {
+ // Uninitialized read on a temp
+ // We need to find correct replacements for each situation manually
+ SciTrackOriginReply originReply;
+ SciWorkaroundSolution solution = trackOriginAndFindWorkaround(index, uninitializedReadWorkarounds, &originReply);
+ if (solution.type == WORKAROUND_NONE)
+ error("Uninitialized read for temp %d from method %s::%s (script %d, room %d, localCall %x)",
+ index, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr,
+ g_sci->getEngineState()->currentRoomNumber(), originReply.localCallOffset);
+ assert(solution.type == WORKAROUND_FAKE);
+ r[index] = make_reg(0, solution.value);
+ break;
+ }
+ case VAR_PARAM:
+ // Out-of-bounds read for a parameter that goes onto stack and hits an uninitialized temp
+ // We return 0 currently in that case
+ debugC(2, kDebugLevelVM, "[VM] Read for a parameter goes out-of-bounds, onto the stack and gets uninitialized temp");
+ return NULL_REG;
+ default:
+ break;
+ }
+ }
return r[index];
- else
+ } else
return default_value;
}
-static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t value, SegManager *segMan, Kernel *kernel) {
- if (validate_variable(r, stack_base, type, max, index, line)) {
+static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t value, SegManager *segMan, Kernel *kernel) {
+ if (validate_variable(r, stack_base, type, max, index)) {
// WORKAROUND: This code is needed to work around a probable script bug, or a
// limitation of the original SCI engine, which can be observed in LSL5.
@@ -207,59 +249,66 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
// stopGroop object, which points to ego, to the new ego object. If this is not
// done, ego's movement will not be updated properly, so the result is
// unpredictable (for example in LSL5, Patti spins around instead of walking).
- if (index == 0 && type == VAR_GLOBAL) { // global 0 is ego
+ if (index == 0 && type == VAR_GLOBAL && getSciVersion() > SCI_VERSION_0_EARLY) { // global 0 is ego
reg_t stopGroopPos = segMan->findObjectByName("stopGroop");
if (!stopGroopPos.isNull()) { // does the game have a stopGroop object?
// Find the "client" member variable of the stopGroop object, and update it
ObjVarRef varp;
- if (lookup_selector(segMan, stopGroopPos, kernel->_selectorCache.client, &varp, NULL) == kSelectorVariable) {
+ if (lookupSelector(segMan, stopGroopPos, SELECTOR(client), &varp, NULL) == kSelectorVariable) {
reg_t *clientVar = varp.getPointer(segMan);
*clientVar = value;
}
}
}
+ // If we are writing an uninitialized value into a temp, we remove the uninitialized segment
+ // this happens at least in sq1/room 44 (slot-machine), because a send is missing parameters, then
+ // those parameters are taken from uninitialized stack and afterwards they are copied back into temps
+ // if we don't remove the segment, we would get false-positive uninitialized reads later
+ if (type == VAR_TEMP && value.segment == 0xffff)
+ value.segment = 0;
+
r[index] = value;
}
}
-#else
-// Non-validating alternatives
-
-# define validate_stack_addr(s, sp) sp
-# define validate_arithmetic(r) ((r).offset)
-# define signed_validate_arithmetic(r) ((int16)(r).offset)
-# define validate_variable(r, sb, t, m, i, l)
-# define validate_read_var(r, sb, t, m, i, l, dv) ((r)[i])
-# define validate_write_var(r, sb, t, m, i, l, v, sm, k) ((r)[i] = (v))
-# define validate_property(o, p) ((o)->_variables[p])
-
-#endif
-
-#define READ_VAR(type, index, def) validate_read_var(scriptState.variables[type], s->stack_base, type, scriptState.variables_max[type], index, __LINE__, def)
-#define WRITE_VAR(type, index, value) validate_write_var(scriptState.variables[type], s->stack_base, type, scriptState.variables_max[type], index, __LINE__, value, s->_segMan, g_sci->getKernel())
+#define READ_VAR(type, index) validate_read_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, s->r_acc)
+#define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, value, s->_segMan, g_sci->getKernel())
#define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value));
-#define ACC_ARITHMETIC_L(op) make_reg(0, (op validate_arithmetic(s->r_acc)))
-#define ACC_AUX_LOAD() aux_acc = signed_validate_arithmetic(s->r_acc)
-#define ACC_AUX_STORE() s->r_acc = make_reg(0, aux_acc)
-
-#define OBJ_PROPERTY(o, p) (validate_property(o, p))
-
// Operating on the stack
// 16 bit:
#define PUSH(v) PUSH32(make_reg(0, v))
-#define POP() (validate_arithmetic(POP32()))
// 32 bit:
-#define PUSH32(a) (*(validate_stack_addr(s, (scriptState.xs->sp)++)) = (a))
-#define POP32() (*(validate_stack_addr(s, --(scriptState.xs->sp))))
+#define PUSH32(a) (*(validate_stack_addr(s, (s->xs->sp)++)) = (a))
+#define POP32() (*(validate_stack_addr(s, --(s->xs->sp))))
+
+bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) {
+ if (_debugState._activeBreakpointTypes & BREAK_EXPORT) {
+ uint32 bpaddress;
+
+ bpaddress = (script << 16 | pubfunct);
+
+ Common::List<Breakpoint>::const_iterator bp;
+ for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
+ if (bp->type == BREAK_EXPORT && bp->address == bpaddress) {
+ _console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct);
+ _debugState.debugging = true;
+ _debugState.breakpointWasHit = true;
+ return true;;
+ }
+ }
+ }
+
+ return false;
+}
ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp) {
int seg = s->_segMan->getScriptSegment(script);
Script *scr = s->_segMan->getScriptIfLoaded(seg);
if (!scr || scr->isMarkedAsDeleted()) { // Script not present yet?
- seg = script_instantiate(g_sci->getResMan(), s->_segMan, script);
+ seg = s->_segMan->instantiateScript(script);
scr = s->_segMan->getScript(seg);
}
@@ -277,24 +326,9 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
}
// Check if a breakpoint is set on this method
- if (g_debugState._activeBreakpointTypes & BREAK_EXPORT) {
- uint32 bpaddress;
-
- bpaddress = (script << 16 | pubfunct);
-
- Common::List<Breakpoint>::const_iterator bp;
- for (bp = g_debugState._breakpoints.begin(); bp != g_debugState._breakpoints.end(); ++bp) {
- if (bp->type == BREAK_EXPORT && bp->address == bpaddress) {
- Console *con = g_sci->getSciDebugger();
- con->DebugPrintf("Break on script %d, export %d\n", script, pubfunct);
- g_debugState.debugging = true;
- g_debugState.breakpointWasHit = true;
- break;
- }
- }
- }
+ g_sci->checkExportBreakpoint(script, pubfunct);
- return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, calling_obj, s->_executionStack.size()-1, seg);
+ return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, -1, calling_obj, s->_executionStack.size()-1, seg);
}
@@ -304,7 +338,7 @@ static void _exec_varselectors(EngineState *s) {
ExecStack &xs = s->_executionStack.back();
reg_t *var = xs.getVarPointer(s->_segMan);
if (!var) {
- warning("Invalid varselector exec stack entry");
+ error("Invalid varselector exec stack entry");
} else {
// varselector access?
if (xs.argc) { // write?
@@ -332,6 +366,30 @@ struct CallsStruct {
int type; /**< Same as ExecStack.type */
};
+bool SciEngine::checkSelectorBreakpoint(reg_t send_obj, int selector) {
+ if (_debugState._activeBreakpointTypes & BREAK_SELECTOR) {
+ char method_name[256];
+
+ sprintf(method_name, "%s::%s", _gamestate->_segMan->getObjectName(send_obj), getKernel()->getSelectorName(selector).c_str());
+
+ Common::List<Breakpoint>::const_iterator bp;
+ for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
+ int cmplen = bp->name.size();
+ if (bp->name.lastChar() != ':')
+ cmplen = 256;
+
+ if (bp->type == BREAK_SELECTOR && !strncmp(bp->name.c_str(), method_name, cmplen)) {
+ _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj));
+ _debugState.debugging = true;
+ _debugState.breakpointWasHit = true;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp) {
// send_obj and work_obj are equal for anything but 'super'
// Returns a pointer to the TOS exec_stack element
@@ -341,7 +399,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
int selector;
int argc;
int origin = s->_executionStack.size()-1; // Origin: Used for debugging
- int print_send_action = 0;
+ bool printSendActions = false;
// We return a pointer to the new active ExecStack
// The selector calls we catch are stored below:
@@ -356,34 +414,16 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
}
// Check if a breakpoint is set on this method
- if (g_debugState._activeBreakpointTypes & BREAK_SELECTOR) {
- char method_name[256];
-
- sprintf(method_name, "%s::%s", s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str());
-
- Common::List<Breakpoint>::const_iterator bp;
- for (bp = g_debugState._breakpoints.begin(); bp != g_debugState._breakpoints.end(); ++bp) {
- int cmplen = bp->name.size();
- if (bp->name.lastChar() != ':')
- cmplen = 256;
-
- if (bp->type == BREAK_SELECTOR && !strncmp(bp->name.c_str(), method_name, cmplen)) {
- Console *con = g_sci->getSciDebugger();
- con->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj));
- print_send_action = 1;
- g_debugState.debugging = true;
- g_debugState.breakpointWasHit = true;
- break;
- }
- }
- }
+ printSendActions = g_sci->checkSelectorBreakpoint(send_obj, selector);
#ifdef VM_DEBUG_SEND
- printf("Send to %04x:%04x, selector %04x (%s):", PRINT_REG(send_obj), selector, g_sci->getKernel()->getSelectorName(selector).c_str());
+ printf("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj),
+ s->_segMan->getObjectName(send_obj), selector,
+ g_sci->getKernel()->getSelectorName(selector).c_str());
#endif // VM_DEBUG_SEND
ObjVarRef varp;
- switch (lookup_selector(s->_segMan, send_obj, selector, &varp, &funcp)) {
+ switch (lookupSelector(s->_segMan, send_obj, selector, &varp, &funcp)) {
case kSelectorNone:
error("Send to invalid selector 0x%x of object at %04x:%04x", 0xffff & selector, PRINT_REG(send_obj));
break;
@@ -398,22 +438,35 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
#endif // VM_DEBUG_SEND
// argc == 0: read selector
- // argc == 1: write selector
- // argc > 1: write selector?
- if (print_send_action && argc == 0) { // read selector
- printf("[read selector]\n");
- print_send_action = 0;
+ // argc != 0: write selector
+ if (printSendActions && !argc) { // read selector
+ debug("[read selector]\n");
+ printSendActions = false;
}
- if (print_send_action && argc > 0) {
+ if (printSendActions && argc) {
reg_t oldReg = *varp.getPointer(s->_segMan);
reg_t newReg = argp[1];
- printf("[write to selector: change %04x:%04x to %04x:%04x]\n", PRINT_REG(oldReg), PRINT_REG(newReg));
- print_send_action = 0;
+ warning("[write to selector (%s:%s): change %04x:%04x to %04x:%04x]\n",
+ s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str(),
+ PRINT_REG(oldReg), PRINT_REG(newReg));
+ printSendActions = false;
}
- if (argc > 1)
- warning("send_selector(): more than 1 parameter (%d) while modifying a variable selector", argc);
+ if (argc > 1) {
+ // argc can indeed be bigger than 1 in some cases, and it's usually the
+ // result of a script bug. Usually these aren't fatal.
+
+ const char *objectName = s->_segMan->getObjectName(send_obj);
+
+ reg_t oldReg = *varp.getPointer(s->_segMan);
+ reg_t newReg = argp[1];
+ const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str();
+ debug(2, "send_selector(): argc = %d while modifying variable selector "
+ "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x",
+ argc, selector, selectorName, PRINT_REG(send_obj),
+ objectName, PRINT_REG(oldReg), PRINT_REG(newReg));
+ }
{
CallsStruct call;
@@ -438,9 +491,30 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
}
printf(") at %04x:%04x\n", PRINT_REG(funcp));
#endif // VM_DEBUG_SEND
- if (print_send_action) {
- printf("[invoke selector]\n");
- print_send_action = 0;
+ if (printSendActions) {
+ printf("[invoke selector]");
+#ifndef VM_DEBUG_SEND
+ int displaySize = 0;
+ for (int argNr = 1; argNr <= argc; argNr++) {
+ if (argNr == 1)
+ printf(" - ");
+ reg_t curParam = argp[argNr];
+ if (curParam.segment) {
+ printf("[%04x:%04x] ", PRINT_REG(curParam));
+ displaySize += 12;
+ } else {
+ printf("[%04x] ", curParam.offset);
+ displaySize += 7;
+ }
+ if (displaySize > 50) {
+ if (argNr < argc)
+ printf("...");
+ break;
+ }
+ }
+#endif
+ printf("\n");
+ printSendActions = false;
}
{
@@ -456,7 +530,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
}
break;
- } // switch (lookup_selector())
+ } // switch (lookupSelector())
framesize -= (2 + argc);
argp += argc + 1;
@@ -472,18 +546,16 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
else
add_exec_stack_entry(s->_executionStack, call.address.func, call.sp, work_obj,
call.argc, call.argp,
- call.selector, send_obj, origin, SCI_XS_CALLEE_LOCALS);
+ call.selector, -1, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS);
}
_exec_varselectors(s);
- if (s->_executionStack.empty())
- return NULL;
- return &(s->_executionStack.back());
+ return s->_executionStack.empty() ? NULL : &(s->_executionStack.back());
}
static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, reg_t objp, int argc, StackPtr argp, Selector selector, const ObjVarRef& address, int origin) {
- ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, objp, origin, SCI_XS_CALLEE_LOCALS);
+ ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, -1, -1, objp, origin, SCI_XS_CALLEE_LOCALS);
// Store selector address in sp
xstack->addr.varp = address;
@@ -493,7 +565,7 @@ static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack,
}
static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp, reg_t objp, int argc,
- StackPtr argp, Selector selector, reg_t sendp, int origin, SegmentId _localsSegment) {
+ StackPtr argp, Selector selector, int exportId, int localCallOffset, reg_t sendp, int origin, SegmentId _localsSegment) {
// Returns new TOS element for the execution stack
// _localsSegment may be -1 if derived from the called object
@@ -517,8 +589,10 @@ static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t
*argp = make_reg(0, argc); // SCI code relies on the zeroeth argument to equal argc
// Additional debug information
- xstack.selector = selector;
- xstack.origin = origin;
+ xstack.debugSelector = selector;
+ xstack.debugExportId = exportId;
+ xstack.debugLocalCallOffset = localCallOffset;
+ xstack.debugOrigin = origin;
xstack.type = EXEC_STACK_TYPE_CALL; // Normal call
@@ -526,10 +600,6 @@ static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t
return &(execStack.back());
}
-#ifdef DISABLE_VALIDATIONS
-# define kernel_matches_signature(a, b, c, d) 1
-#endif
-
static reg_t pointer_add(EngineState *s, reg_t base, int offset) {
SegmentObj *mobj = s->_segMan->getSegmentObj(base.segment);
@@ -557,77 +627,187 @@ static reg_t pointer_add(EngineState *s, reg_t base, int offset) {
}
}
-static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) {
-
- if (kernelFuncNum >= (int)g_sci->getKernel()->_kernelFuncs.size())
- error("Invalid kernel function 0x%x requested", kernelFuncNum);
-
- const KernelFuncWithSignature &kernelFunc = g_sci->getKernel()->_kernelFuncs[kernelFuncNum];
+static void addKernelCallToExecStack(EngineState *s, int kernelCallNr, int argc, reg_t *argv) {
+ // Add stack frame to indicate we're executing a callk.
+ // This is useful in debugger backtraces if this
+ // kernel function calls a script itself.
+ ExecStack *xstack;
+ xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG,
+ s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
+ xstack->debugSelector = kernelCallNr;
+ xstack->type = EXEC_STACK_TYPE_KERNEL;
+}
- if (kernelFunc.signature
- && !g_sci->getKernel()->signatureMatch(kernelFunc.signature, argc, scriptState.xs->sp + 1)) {
- error("[VM] Invalid arguments to kernel call %x", kernelFuncNum);
+static void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *kernelSubCall, EngineState *s, int argc, reg_t *argv, reg_t result) {
+ Kernel *kernel = g_sci->getKernel();
+ if (!kernelSubCall) {
+ printf("k%s: ", kernelCall->name);
+ } else {
+ int callNameLen = strlen(kernelCall->name);
+ if (strncmp(kernelCall->name, kernelSubCall->name, callNameLen) == 0) {
+ const char *subCallName = kernelSubCall->name + callNameLen;
+ printf("k%s(%s): ", kernelCall->name, subCallName);
+ } else {
+ printf("k%s(%s): ", kernelCall->name, kernelSubCall->name);
+ }
}
+ for (int parmNr = 0; parmNr < argc; parmNr++) {
+ if (parmNr)
+ printf(", ");
+ uint16 regType = kernel->findRegType(argv[parmNr]);
+ if (regType & SIG_TYPE_NULL)
+ printf("0");
+ else if (regType & SIG_TYPE_UNINITIALIZED)
+ printf("UNINIT");
+ else if (regType & SIG_IS_INVALID)
+ printf("INVALID");
+ else if (regType & SIG_TYPE_INTEGER)
+ printf("%d", argv[parmNr].offset);
+ else {
+ printf("%04x:%04x", PRINT_REG(argv[parmNr]));
+ switch (regType) {
+ case SIG_TYPE_OBJECT:
+ printf(" (%s)", s->_segMan->getObjectName(argv[parmNr]));
+ break;
+ case SIG_TYPE_REFERENCE:
+ if (kernelCall->function == kSaid) {
+ SegmentRef saidSpec = s->_segMan->dereference(argv[parmNr]);
+ if (saidSpec.isRaw) {
+ printf(" ('");
+ g_sci->getVocabulary()->debugDecipherSaidBlock(saidSpec.raw);
+ printf("')");
+ } else {
+ printf(" (non-raw said-spec)");
+ }
+ } else {
+ printf(" ('%s')", s->_segMan->getString(argv[parmNr]).c_str());
+ }
+ default:
+ break;
+ }
+ }
+ }
+ if (result.segment)
+ printf(" = %04x:%04x\n", PRINT_REG(result));
+ else
+ printf(" = %d\n", result.offset);
+}
- reg_t *argv = scriptState.xs->sp + 1;
-
- if (!kernelFunc.isDummy) {
- // Add stack frame to indicate we're executing a callk.
- // This is useful in debugger backtraces if this
- // kernel function calls a script itself.
- ExecStack *xstack;
- xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, NULL_REG,
- s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
- xstack->selector = kernelFuncNum;
- xstack->type = EXEC_STACK_TYPE_KERNEL;
-
- //warning("callk %s", kernelFunc.orig_name.c_str());
-
- // TODO: SCI2/SCI2.1+ equivalent, once saving/loading works in SCI2/SCI2.1+
- if (g_loadFromLauncher >= 0 && kernelFuncNum == 0x8) {
- // A game is being loaded from the launcher, and kDisplay is called, all initialization has taken
- // place (i.e. menus have been constructed etc). Therefore, inject a kRestoreGame call
- // here, instead of the requested function.
- int saveSlot = g_loadFromLauncher;
- g_loadFromLauncher = -1; // invalidate slot, so that we don't load again
-
- if (saveSlot < 0)
- error("Requested to load invalid save slot"); // should never happen, really
-
- reg_t restoreArgv[2] = { NULL_REG, make_reg(0, saveSlot) }; // special call (argv[0] is NULL)
- kRestoreGame(s, 2, restoreArgv);
- } else {
- // Call kernel function
- s->r_acc = kernelFunc.fun(s, argc, argv);
+static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
+ Kernel *kernel = g_sci->getKernel();
+
+ if (kernelCallNr >= (int)kernel->_kernelFuncs.size())
+ error("Invalid kernel function 0x%x requested", kernelCallNr);
+
+ const KernelFunction &kernelCall = kernel->_kernelFuncs[kernelCallNr];
+ reg_t *argv = s->xs->sp + 1;
+
+ if (kernelCall.signature
+ && !kernel->signatureMatch(kernelCall.signature, argc, argv)) {
+ // signature mismatch, check if a workaround is available
+ SciTrackOriginReply originReply;
+ SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, kernelCall.workarounds, &originReply);
+ switch (solution.type) {
+ case WORKAROUND_NONE:
+ kernel->signatureDebug(kernelCall.signature, argc, argv);
+ error("[VM] k%s[%x]: signature mismatch via method %s::%s (script %d, room %d, localCall 0x%x)",
+ kernelCall.name, kernelCallNr, originReply.objectName.c_str(), originReply.methodName.c_str(),
+ originReply.scriptNr, s->currentRoomNumber(), originReply.localCallOffset);
+ break;
+ case WORKAROUND_IGNORE: // don't do kernel call, leave acc alone
+ return;
+ case WORKAROUND_STILLCALL: // call kernel anyway
+ break;
+ case WORKAROUND_FAKE: // don't do kernel call, fake acc
+ s->r_acc = make_reg(0, solution.value);
+ return;
+ default:
+ error("unknown workaround type");
}
+ }
- // Remove callk stack frame again
- s->_executionStack.pop_back();
+
+ // Call kernel function
+ if (!kernelCall.subFunctionCount) {
+ addKernelCallToExecStack(s, kernelCallNr, argc, argv);
+ s->r_acc = kernelCall.function(s, argc, argv);
+
+ if (kernelCall.debugLogging)
+ logKernelCall(&kernelCall, NULL, s, argc, argv, s->r_acc);
+ if (kernelCall.debugBreakpoint) {
+ printf("Break on k%s\n", kernelCall.name);
+ g_sci->_debugState.debugging = true;
+ g_sci->_debugState.breakpointWasHit = true;
+ }
} else {
- Common::String warningMsg = "Dummy function " + kernelFunc.orig_name +
- Common::String::printf("[0x%x]", kernelFuncNum) +
- " invoked - ignoring. Params: " +
- Common::String::printf("%d", argc) + " (";
-
- for (int i = 0; i < argc; i++) {
- warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i]));
- warningMsg += (i == argc - 1 ? ")" : ", ");
+ // Sub-functions available, check signature and call that one directly
+ if (argc < 1)
+ error("[VM] k%s[%x]: no subfunction-id parameter given", kernelCall.name, kernelCallNr);
+ if (argv[0].segment)
+ error("[VM] k%s[%x]: given subfunction-id is actually a pointer", kernelCall.name, kernelCallNr);
+ const uint16 subId = argv[0].toUint16();
+ // Skip over subfunction-id
+ argc--;
+ argv++;
+ if (subId >= kernelCall.subFunctionCount)
+ error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId);
+ const KernelSubFunction &kernelSubCall = kernelCall.subFunctions[subId];
+ if (kernelSubCall.signature && !kernel->signatureMatch(kernelSubCall.signature, argc, argv)) {
+ // Signature mismatch
+ SciTrackOriginReply originReply;
+ SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, kernelSubCall.workarounds, &originReply);
+ switch (solution.type) {
+ case WORKAROUND_NONE: {
+ kernel->signatureDebug(kernelSubCall.signature, argc, argv);
+ int callNameLen = strlen(kernelCall.name);
+ if (strncmp(kernelCall.name, kernelSubCall.name, callNameLen) == 0) {
+ const char *subCallName = kernelSubCall.name + callNameLen;
+ error("[VM] k%s(%s): signature mismatch via method %s::%s (script %d, room %d, localCall %x)",
+ kernelCall.name, subCallName, originReply.objectName.c_str(), originReply.methodName.c_str(),
+ originReply.scriptNr, s->currentRoomNumber(), originReply.localCallOffset);
+ }
+ error("[VM] k%s: signature mismatch via method %s::%s (script %d, room %d, localCall %x)",
+ kernelSubCall.name, originReply.objectName.c_str(), originReply.methodName.c_str(),
+ originReply.scriptNr, s->currentRoomNumber(), originReply.localCallOffset);
+ break;
+ }
+ case WORKAROUND_IGNORE: // don't do kernel call, leave acc alone
+ return;
+ case WORKAROUND_STILLCALL: // call kernel anyway
+ break;
+ case WORKAROUND_FAKE: // don't do kernel call, fake acc
+ s->r_acc = make_reg(0, solution.value);
+ return;
+ default:
+ error("unknown workaround type");
+ }
+ }
+ if (!kernelSubCall.function)
+ error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId);
+ addKernelCallToExecStack(s, kernelCallNr, argc, argv);
+ s->r_acc = kernelSubCall.function(s, argc, argv);
+
+ if (kernelSubCall.debugLogging)
+ logKernelCall(&kernelCall, &kernelSubCall, s, argc, argv, s->r_acc);
+ if (kernelSubCall.debugBreakpoint) {
+ printf("Break on k%s\n", kernelSubCall.name);
+ g_sci->_debugState.debugging = true;
+ g_sci->_debugState.breakpointWasHit = true;
}
-
- warning("%s", warningMsg.c_str());
}
+
+ // Remove callk stack frame again, if there's still an execution stack
+ if (s->_executionStack.begin() != s->_executionStack.end())
+ s->_executionStack.pop_back();
}
-static void gc_countdown(EngineState *s) {
- if (s->gc_countdown-- <= 0) {
- s->gc_countdown = script_gc_interval;
+static void gcCountDown(EngineState *s) {
+ if (s->gcCountDown-- <= 0) {
+ s->gcCountDown = s->scriptGCInterval;
run_gc(s);
}
}
-static const byte _fake_return_buffer[2] = {op_ret << 1, op_ret << 1};
-
-
int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]) {
uint offset = 0;
extOpcode = src[offset++]; // Get "extended" opcode (lower bit has special meaning)
@@ -696,53 +876,31 @@ int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4])
return offset;
}
-void run_vm(EngineState *s, bool restoring) {
+void run_vm(EngineState *s) {
assert(s);
-#ifndef DISABLE_VALIDATIONS
- unsigned int code_buf_size = 0 ; // (Avoid spurious warning)
-#endif
int temp;
- int16 aux_acc; // Auxiliary 16 bit accumulator
reg_t r_temp; // Temporary register
StackPtr s_temp; // Temporary stack pointer
int16 opparams[4]; // opcode parameters
- scriptState.restAdjust = s->restAdjust;
- // &rest adjusts the parameter count by this value
+ s->restAdjust = 0; // &rest adjusts the parameter count by this value
// Current execution data:
- scriptState.xs = &(s->_executionStack.back());
+ s->xs = &(s->_executionStack.back());
ExecStack *xs_new = NULL;
- Object *obj = s->_segMan->getObject(scriptState.xs->objp);
- Script *local_script = s->_segMan->getScriptIfLoaded(scriptState.xs->local_segment);
- int old_execution_stack_base = s->execution_stack_base;
+ Object *obj = s->_segMan->getObject(s->xs->objp);
+ Script *scr = 0;
+ Script *local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment);
+ int old_executionStackBase = s->executionStackBase;
// Used to detect the stack bottom, for "physical" returns
- const byte *code_buf = NULL; // (Avoid spurious warning)
- if (!local_script) {
+ if (!local_script)
error("run_vm(): program counter gone astray (local_script pointer is null)");
- }
- if (!restoring)
- s->execution_stack_base = s->_executionStack.size()-1;
+ s->executionStackBase = s->_executionStack.size() - 1;
-#ifndef DISABLE_VALIDATIONS
- // Initialize maximum variable count
- if (s->script_000->_localsBlock)
- scriptState.variables_max[VAR_GLOBAL] = s->script_000->_localsBlock->_locals.size();
- else
- scriptState.variables_max[VAR_GLOBAL] = 0;
-#endif
-
- scriptState.variables_seg[VAR_GLOBAL] = s->script_000->_localsSegment;
- scriptState.variables_seg[VAR_TEMP] = scriptState.variables_seg[VAR_PARAM] = s->_segMan->findSegmentByType(SEG_TYPE_STACK);
- scriptState.variables_base[VAR_TEMP] = scriptState.variables_base[VAR_PARAM] = s->stack_base;
-
- // SCI code reads the zeroth argument to determine argc
- if (s->script_000->_localsBlock)
- scriptState.variables_base[VAR_GLOBAL] = scriptState.variables[VAR_GLOBAL] = s->script_000->_localsBlock->_locals.begin();
- else
- scriptState.variables_base[VAR_GLOBAL] = scriptState.variables[VAR_GLOBAL] = NULL;
+ s->variablesSegment[VAR_TEMP] = s->variablesSegment[VAR_PARAM] = s->_segMan->findSegmentByType(SEG_TYPE_STACK);
+ s->variablesBase[VAR_TEMP] = s->variablesBase[VAR_PARAM] = s->stack_base;
s->_executionStackPosChanged = true; // Force initialization
@@ -750,99 +908,89 @@ void run_vm(EngineState *s, bool restoring) {
int var_type; // See description below
int var_number;
- g_debugState.old_pc_offset = scriptState.xs->addr.pc.offset;
- g_debugState.old_sp = scriptState.xs->sp;
+ g_sci->_debugState.old_pc_offset = s->xs->addr.pc.offset;
+ g_sci->_debugState.old_sp = s->xs->sp;
+
+ if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit())
+ return; // Stop processing
if (s->_executionStackPosChanged) {
- Script *scr;
- scriptState.xs = &(s->_executionStack.back());
+ scr = s->_segMan->getScriptIfLoaded(s->xs->addr.pc.segment);
+ if (!scr)
+ error("No script in segment %d", s->xs->addr.pc.segment);
+ s->xs = &(s->_executionStack.back());
s->_executionStackPosChanged = false;
- scr = s->_segMan->getScriptIfLoaded(scriptState.xs->addr.pc.segment);
- if (!scr) {
- // No script? Implicit return via fake instruction buffer
- warning("Running on non-existant script in segment %x", scriptState.xs->addr.pc.segment);
- code_buf = _fake_return_buffer;
-#ifndef DISABLE_VALIDATIONS
- code_buf_size = 2;
-#endif
- scriptState.xs->addr.pc.offset = 1;
-
- scr = NULL;
- obj = NULL;
+ obj = s->_segMan->getObject(s->xs->objp);
+ local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment);
+ if (!local_script) {
+ error("Could not find local script from segment %x", s->xs->local_segment);
} else {
- obj = s->_segMan->getObject(scriptState.xs->objp);
- code_buf = scr->_buf;
-#ifndef DISABLE_VALIDATIONS
- code_buf_size = scr->_bufSize;
-#endif
- local_script = s->_segMan->getScriptIfLoaded(scriptState.xs->local_segment);
- if (!local_script) {
- warning("Could not find local script from segment %x", scriptState.xs->local_segment);
- local_script = NULL;
- scriptState.variables_base[VAR_LOCAL] = scriptState.variables[VAR_LOCAL] = NULL;
-#ifndef DISABLE_VALIDATIONS
- scriptState.variables_max[VAR_LOCAL] = 0;
-#endif
- } else {
-
- scriptState.variables_seg[VAR_LOCAL] = local_script->_localsSegment;
- if (local_script->_localsBlock)
- scriptState.variables_base[VAR_LOCAL] = scriptState.variables[VAR_LOCAL] = local_script->_localsBlock->_locals.begin();
- else
- scriptState.variables_base[VAR_LOCAL] = scriptState.variables[VAR_LOCAL] = NULL;
-#ifndef DISABLE_VALIDATIONS
- if (local_script->_localsBlock)
- scriptState.variables_max[VAR_LOCAL] = local_script->_localsBlock->_locals.size();
- else
- scriptState.variables_max[VAR_LOCAL] = 0;
- scriptState.variables_max[VAR_TEMP] = scriptState.xs->sp - scriptState.xs->fp;
- scriptState.variables_max[VAR_PARAM] = scriptState.xs->argc + 1;
-#endif
- }
- scriptState.variables[VAR_TEMP] = scriptState.xs->fp;
- scriptState.variables[VAR_PARAM] = scriptState.xs->variables_argp;
+ s->variablesSegment[VAR_LOCAL] = local_script->_localsSegment;
+ if (local_script->_localsBlock)
+ s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = local_script->_localsBlock->_locals.begin();
+ else
+ s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL;
+ if (local_script->_localsBlock)
+ s->variablesMax[VAR_LOCAL] = local_script->_localsBlock->_locals.size();
+ else
+ s->variablesMax[VAR_LOCAL] = 0;
+ s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp;
+ s->variablesMax[VAR_PARAM] = s->xs->argc + 1;
}
-
+ s->variables[VAR_TEMP] = s->xs->fp;
+ s->variables[VAR_PARAM] = s->xs->variables_argp;
}
- if (script_abort_flag || g_engine->shouldQuit())
- return; // Emergency
+ if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit())
+ return; // Stop processing
// Debug if this has been requested:
// TODO: re-implement sci_debug_flags
- if (g_debugState.debugging /* sci_debug_flags*/) {
- script_debug(s);
- g_debugState.breakpointWasHit = false;
+ if (g_sci->_debugState.debugging /* sci_debug_flags*/) {
+ g_sci->scriptDebug();
+ g_sci->_debugState.breakpointWasHit = false;
}
Console *con = g_sci->getSciDebugger();
- if (con->isAttached()) {
- con->onFrame();
- }
+ con->onFrame();
-#ifndef DISABLE_VALIDATIONS
- if (scriptState.xs->sp < scriptState.xs->fp)
- error("run_vm(): stack underflow");
+ if (s->xs->sp < s->xs->fp)
+ error("run_vm(): stack underflow, sp: %04x:%04x, fp: %04x:%04x",
+ PRINT_REG(*s->xs->sp), PRINT_REG(*s->xs->fp));
- scriptState.variables_max[VAR_TEMP] = scriptState.xs->sp - scriptState.xs->fp;
+ s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp;
- if (scriptState.xs->addr.pc.offset >= code_buf_size)
- error("run_vm(): program counter gone astray");
-#endif
+ if (s->xs->addr.pc.offset >= scr->getBufSize())
+ error("run_vm(): program counter gone astray, addr: %d, code buffer size: %d",
+ s->xs->addr.pc.offset, scr->getBufSize());
// Get opcode
byte extOpcode;
- scriptState.xs->addr.pc.offset += readPMachineInstruction(code_buf + scriptState.xs->addr.pc.offset, extOpcode, opparams);
+ s->xs->addr.pc.offset += readPMachineInstruction(scr->getBuf() + s->xs->addr.pc.offset, extOpcode, opparams);
const byte opcode = extOpcode >> 1;
switch (opcode) {
- case op_bnot: // 0x00 (00)
- s->r_acc = ACC_ARITHMETIC_L(0xffff ^ /*acc*/);
+ case op_bnot: { // 0x00 (00)
+ // Binary not
+ int16 value;
+ if (validate_signedInteger(s->r_acc, value))
+ s->r_acc = make_reg(0, 0xffff ^ value);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, NULL_REG);
break;
+ }
case op_add: // 0x01 (01)
r_temp = POP32();
+
+ // Happens in SQ1, room 28, when throwing the water at Orat
+ if (s->r_acc.segment == 0xFFFF) {
+ // WORKAROUND: init uninitialized variable to 0
+ warning("op_add: attempt to write to uninitialized variable");
+ s->r_acc = NULL_REG;
+ }
+
if (r_temp.segment || s->r_acc.segment) {
reg_t r_ptr = NULL_REG;
int offset;
@@ -896,45 +1044,115 @@ void run_vm(EngineState *s, bool restoring) {
}
break;
- case op_mul: // 0x03 (03)
- s->r_acc = ACC_ARITHMETIC_L(((int16)POP()) * (int16)/*acc*/);
+ case op_mul: { // 0x03 (03)
+ r_temp = POP32();
+ int16 value1, value2;
+ if (validate_signedInteger(s->r_acc, value1) && validate_signedInteger(r_temp, value2))
+ s->r_acc = make_reg(0, value1 * value2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeMulWorkarounds, s->r_acc, r_temp);
break;
+ }
- case op_div: // 0x04 (04)
- ACC_AUX_LOAD();
- aux_acc = aux_acc != 0 ? ((int16)POP()) / aux_acc : 0;
- ACC_AUX_STORE();
+ case op_div: { // 0x04 (04)
+ r_temp = POP32();
+ int16 divisor, dividend;
+ if (validate_signedInteger(s->r_acc, divisor) && validate_signedInteger(r_temp, dividend))
+ s->r_acc = make_reg(0, (divisor != 0 ? dividend / divisor : 0));
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeDivWorkarounds, s->r_acc, r_temp);
break;
+ }
+
+ case op_mod: { // 0x05 (05)
+ r_temp = POP32();
- case op_mod: // 0x05 (05)
- ACC_AUX_LOAD();
- aux_acc = aux_acc != 0 ? ((int16)POP()) % aux_acc : 0;
- ACC_AUX_STORE();
+ if (getSciVersion() <= SCI_VERSION_0_LATE) {
+ uint16 modulo, value;
+ if (validate_unsignedInteger(s->r_acc, modulo) && validate_unsignedInteger(r_temp, value))
+ s->r_acc = make_reg(0, (modulo != 0 ? value % modulo : 0));
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, r_temp);
+ } else {
+ // In Iceman (and perhaps from SCI0 0.000.685 onwards in general),
+ // handling for negative numbers was added. Since Iceman doesn't
+ // seem to have issues with the older code, we exclude it for now
+ // for simplicity's sake and use the new code for SCI01 and newer
+ // games. Fixes the battlecruiser mini game in SQ5 (room 850),
+ // bug #3035755
+ int16 modulo, value, result;
+ if (validate_signedInteger(s->r_acc, modulo) && validate_signedInteger(r_temp, value)) {
+ modulo = ABS(modulo);
+ result = (modulo != 0 ? value % modulo : 0);
+ if (result < 0)
+ result += modulo;
+ s->r_acc = make_reg(0, result);
+ } else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, r_temp);
+ }
break;
+ }
- case op_shr: // 0x06 (06)
- s->r_acc = ACC_ARITHMETIC_L(((uint16)POP()) >> /*acc*/);
+ case op_shr: { // 0x06 (06)
+ // Shift right logical
+ r_temp = POP32();
+ uint16 value, shiftCount;
+ if (validate_unsignedInteger(r_temp, value) && validate_unsignedInteger(s->r_acc, shiftCount))
+ s->r_acc = make_reg(0, value >> shiftCount);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
break;
+ }
- case op_shl: // 0x07 (07)
- s->r_acc = ACC_ARITHMETIC_L(((uint16)POP()) << /*acc*/);
+ case op_shl: { // 0x07 (07)
+ // Shift left logical
+ r_temp = POP32();
+ uint16 value, shiftCount;
+ if (validate_unsignedInteger(r_temp, value) && validate_unsignedInteger(s->r_acc, shiftCount))
+ s->r_acc = make_reg(0, value << shiftCount);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
break;
+ }
- case op_xor: // 0x08 (08)
- s->r_acc = ACC_ARITHMETIC_L(POP() ^ /*acc*/);
+ case op_xor: { // 0x08 (08)
+ r_temp = POP32();
+ uint16 value1, value2;
+ if (validate_unsignedInteger(r_temp, value1) && validate_unsignedInteger(s->r_acc, value2))
+ s->r_acc = make_reg(0, value1 ^ value2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
break;
+ }
- case op_and: // 0x09 (09)
- s->r_acc = ACC_ARITHMETIC_L(POP() & /*acc*/);
+ case op_and: { // 0x09 (09)
+ r_temp = POP32();
+ uint16 value1, value2;
+ if (validate_unsignedInteger(r_temp, value1) && validate_unsignedInteger(s->r_acc, value2))
+ s->r_acc = make_reg(0, value1 & value2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeAndWorkarounds, r_temp, s->r_acc);
break;
+ }
- case op_or: // 0x0a (10)
- s->r_acc = ACC_ARITHMETIC_L(POP() | /*acc*/);
+ case op_or: { // 0x0a (10)
+ r_temp = POP32();
+ uint16 value1, value2;
+ if (validate_unsignedInteger(r_temp, value1) && validate_unsignedInteger(s->r_acc, value2))
+ s->r_acc = make_reg(0, value1 | value2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeOrWorkarounds, r_temp, s->r_acc);
break;
+ }
- case op_neg: // 0x0b (11)
- s->r_acc = ACC_ARITHMETIC_L(-/*acc*/);
+ case op_neg: { // 0x0b (11)
+ int16 value;
+ if (validate_signedInteger(s->r_acc, value))
+ s->r_acc = make_reg(0, -value);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, NULL_REG);
break;
+ }
case op_not: // 0x0c (12)
s->r_acc = make_reg(0, !(s->r_acc.offset || s->r_acc.segment));
@@ -942,6 +1160,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_eq_: // 0x0d (13)
+ // ==
s->r_prev = s->r_acc;
r_temp = POP32();
s->r_acc = make_reg(0, r_temp == s->r_acc);
@@ -949,6 +1168,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_ne_: // 0x0e (14)
+ // !=
s->r_prev = s->r_acc;
r_temp = POP32();
s->r_acc = make_reg(0, r_temp != s->r_acc);
@@ -956,6 +1176,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_gt_: // 0x0f (15)
+ // >
s->r_prev = s->r_acc;
r_temp = POP32();
if (r_temp.segment && s->r_acc.segment) {
@@ -963,44 +1184,80 @@ void run_vm(EngineState *s, bool restoring) {
if (r_temp.segment != s->r_acc.segment)
warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc));
s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset > s->r_acc.offset);
- } else
- s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) > (int16)/*acc*/);
+ } else if (r_temp.segment && !s->r_acc.segment) {
+ if (s->r_acc.offset >= 1000)
+ error("[VM] op_gt: comparison between a pointer and number");
+ // Pseudo-WORKAROUND: Sierra allows any pointer <-> value comparison
+ // Happens in SQ1, room 28, when throwing the water at Orat
+ s->r_acc = make_reg(0, 1);
+ } else {
+ int16 compare1, compare2;
+ if (validate_signedInteger(r_temp, compare1) && validate_signedInteger(s->r_acc, compare2))
+ s->r_acc = make_reg(0, compare1 > compare2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
+ }
break;
case op_ge_: // 0x10 (16)
+ // >=
s->r_prev = s->r_acc;
r_temp = POP32();
if (r_temp.segment && s->r_acc.segment) {
if (r_temp.segment != s->r_acc.segment)
warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc));
s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset >= s->r_acc.offset);
- } else
- s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) >= (int16)/*acc*/);
+ } else {
+ int16 compare1, compare2;
+ if (validate_signedInteger(r_temp, compare1) && validate_signedInteger(s->r_acc, compare2))
+ s->r_acc = make_reg(0, compare1 >= compare2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeGeWorkarounds, r_temp, s->r_acc);
+ }
break;
case op_lt_: // 0x11 (17)
+ // <
s->r_prev = s->r_acc;
r_temp = POP32();
if (r_temp.segment && s->r_acc.segment) {
if (r_temp.segment != s->r_acc.segment)
warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc));
s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset < s->r_acc.offset);
- } else
- s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) < (int16)/*acc*/);
+ } else if (r_temp.segment && !s->r_acc.segment) {
+ if (s->r_acc.offset >= 1000)
+ error("[VM] op_lt: comparison between a pointer and number");
+ // Pseudo-WORKAROUND: Sierra allows any pointer <-> value comparison
+ // Happens in SQ1, room 58, when giving id-card to robot
+ s->r_acc = make_reg(0, 1);
+ } else {
+ int16 compare1, compare2;
+ if (validate_signedInteger(r_temp, compare1) && validate_signedInteger(s->r_acc, compare2))
+ s->r_acc = make_reg(0, compare1 < compare2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
+ }
break;
case op_le_: // 0x12 (18)
+ // <=
s->r_prev = s->r_acc;
r_temp = POP32();
if (r_temp.segment && s->r_acc.segment) {
if (r_temp.segment != s->r_acc.segment)
warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc));
s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset <= s->r_acc.offset);
- } else
- s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) <= (int16)/*acc*/);
+ } else {
+ int16 compare1, compare2;
+ if (validate_signedInteger(r_temp, compare1) && validate_signedInteger(s->r_acc, compare2))
+ s->r_acc = make_reg(0, compare1 <= compare2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeLeWorkarounds, r_temp, s->r_acc);
+ }
break;
case op_ugt_: // 0x13 (19)
+ // > (unsigned)
s->r_prev = s->r_acc;
r_temp = POP32();
@@ -1012,17 +1269,23 @@ void run_vm(EngineState *s, bool restoring) {
// (Print "foo") // Pointer to a string
// (Print 420 5) // Reference to the fifth message in text resource 420
- // It works because in those games, the maximum resource number is 999,
- // so any parameter value above that threshold must be a pointer.
+ // It works because in those games, the maximum resource number is 999,
+ // so any parameter value above that threshold must be a pointer.
if (r_temp.segment && (s->r_acc == make_reg(0, 1000)))
s->r_acc = make_reg(0, 1);
else if (r_temp.segment && s->r_acc.segment)
s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset > s->r_acc.offset);
- else
- s->r_acc = ACC_ARITHMETIC_L(validate_arithmetic(r_temp) > /*acc*/);
+ else {
+ uint16 compare1, compare2;
+ if (validate_unsignedInteger(r_temp, compare1) && validate_unsignedInteger(s->r_acc, compare2))
+ s->r_acc = make_reg(0, compare1 > compare2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
+ }
break;
case op_uge_: // 0x14 (20)
+ // >= (unsigned)
s->r_prev = s->r_acc;
r_temp = POP32();
@@ -1031,24 +1294,37 @@ void run_vm(EngineState *s, bool restoring) {
s->r_acc = make_reg(0, 1);
else if (r_temp.segment && s->r_acc.segment)
s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset >= s->r_acc.offset);
- else
- s->r_acc = ACC_ARITHMETIC_L(validate_arithmetic(r_temp) >= /*acc*/);
+ else {
+ uint16 compare1, compare2;
+ if (validate_unsignedInteger(r_temp, compare1) && validate_unsignedInteger(s->r_acc, compare2))
+ s->r_acc = make_reg(0, compare1 >= compare2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
+ }
break;
case op_ult_: // 0x15 (21)
+ // < (unsigned)
s->r_prev = s->r_acc;
r_temp = POP32();
// See above
- if (r_temp.segment && (s->r_acc == make_reg(0, 1000)))
+ // PQ2 japanese compares pointers to 2000 to find out if its a pointer or a resourceid
+ if (r_temp.segment && (s->r_acc == make_reg(0, 1000) || (s->r_acc == make_reg(0, 2000))))
s->r_acc = NULL_REG;
else if (r_temp.segment && s->r_acc.segment)
s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset < s->r_acc.offset);
- else
- s->r_acc = ACC_ARITHMETIC_L(validate_arithmetic(r_temp) < /*acc*/);
+ else {
+ uint16 compare1, compare2;
+ if (validate_unsignedInteger(r_temp, compare1) && validate_unsignedInteger(s->r_acc, compare2))
+ s->r_acc = make_reg(0, compare1 < compare2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
+ }
break;
case op_ule_: // 0x16 (22)
+ // <= (unsigned)
s->r_prev = s->r_acc;
r_temp = POP32();
@@ -1057,139 +1333,163 @@ void run_vm(EngineState *s, bool restoring) {
s->r_acc = NULL_REG;
else if (r_temp.segment && s->r_acc.segment)
s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset <= s->r_acc.offset);
- else
- s->r_acc = ACC_ARITHMETIC_L(validate_arithmetic(r_temp) <= /*acc*/);
+ else {
+ uint16 compare1, compare2;
+ if (validate_unsignedInteger(r_temp, compare1) && validate_unsignedInteger(s->r_acc, compare2))
+ s->r_acc = make_reg(0, compare1 <= compare2);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
+ }
break;
case op_bt: // 0x17 (23)
+ // Branch relative if true
if (s->r_acc.offset || s->r_acc.segment)
- scriptState.xs->addr.pc.offset += opparams[0];
+ s->xs->addr.pc.offset += opparams[0];
break;
case op_bnt: // 0x18 (24)
+ // Branch relative if not true
if (!(s->r_acc.offset || s->r_acc.segment))
- scriptState.xs->addr.pc.offset += opparams[0];
+ s->xs->addr.pc.offset += opparams[0];
break;
case op_jmp: // 0x19 (25)
- scriptState.xs->addr.pc.offset += opparams[0];
+ s->xs->addr.pc.offset += opparams[0];
break;
case op_ldi: // 0x1a (26)
+ // Load data immediate
s->r_acc = make_reg(0, opparams[0]);
break;
case op_push: // 0x1b (27)
+ // Push to stack
PUSH32(s->r_acc);
break;
case op_pushi: // 0x1c (28)
+ // Push immediate
PUSH(opparams[0]);
break;
case op_toss: // 0x1d (29)
- scriptState.xs->sp--;
+ // TOS (Top Of Stack) subtract
+ s->xs->sp--;
break;
case op_dup: // 0x1e (30)
- r_temp = scriptState.xs->sp[-1];
+ // Duplicate TOD (Top Of Stack) element
+ r_temp = s->xs->sp[-1];
PUSH32(r_temp);
break;
case op_link: // 0x1f (31)
+ // We shouldn't initialize temp variables at all
+ // We put special segment 0xFFFF in there, so that uninitialized reads can get detected
for (int i = 0; i < opparams[0]; i++)
- scriptState.xs->sp[i] = NULL_REG;
- scriptState.xs->sp += opparams[0];
+ s->xs->sp[i] = make_reg(0xffff, 0);
+
+ s->xs->sp += opparams[0];
break;
case op_call: { // 0x20 (32)
+ // Call a script subroutine
int argc = (opparams[1] >> 1) // Given as offset, but we need count
- + 1 + scriptState.restAdjust;
- StackPtr call_base = scriptState.xs->sp - argc;
- scriptState.xs->sp[1].offset += scriptState.restAdjust;
-
- xs_new = add_exec_stack_entry(s->_executionStack, make_reg(scriptState.xs->addr.pc.segment,
- scriptState.xs->addr.pc.offset + opparams[0]),
- scriptState.xs->sp, scriptState.xs->objp,
- (validate_arithmetic(*call_base)) + scriptState.restAdjust,
- call_base, NULL_SELECTOR, scriptState.xs->objp,
- s->_executionStack.size()-1, scriptState.xs->local_segment);
- scriptState.restAdjust = 0; // Used up the &rest adjustment
- scriptState.xs->sp = call_base;
+ + 1 + s->restAdjust;
+ StackPtr call_base = s->xs->sp - argc;
+ s->xs->sp[1].offset += s->restAdjust;
+
+ uint16 localCallOffset = s->xs->addr.pc.offset + opparams[0];
+
+ xs_new = add_exec_stack_entry(s->_executionStack, make_reg(s->xs->addr.pc.segment,
+ localCallOffset),
+ s->xs->sp, s->xs->objp,
+ (validate_arithmetic(*call_base)) + s->restAdjust,
+ call_base, NULL_SELECTOR, -1, localCallOffset, s->xs->objp,
+ s->_executionStack.size()-1, s->xs->local_segment);
+ s->restAdjust = 0; // Used up the &rest adjustment
+ s->xs->sp = call_base;
s->_executionStackPosChanged = true;
break;
}
case op_callk: { // 0x21 (33)
- gc_countdown(s);
+ // Call kernel function
+ gcCountDown(s);
- scriptState.xs->sp -= (opparams[1] >> 1) + 1;
+ s->xs->sp -= (opparams[1] >> 1) + 1;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
- if (!oldScriptHeader) {
- scriptState.xs->sp -= scriptState.restAdjust;
- s->restAdjust = 0; // We just used up the scriptState.restAdjust, remember?
- }
+ if (!oldScriptHeader)
+ s->xs->sp -= s->restAdjust;
- int argc = validate_arithmetic(scriptState.xs->sp[0]);
+ int argc = validate_arithmetic(s->xs->sp[0]);
if (!oldScriptHeader)
- argc += scriptState.restAdjust;
+ argc += s->restAdjust;
callKernelFunc(s, opparams[0], argc);
if (!oldScriptHeader)
- scriptState.restAdjust = s->restAdjust;
+ s->restAdjust = 0;
// Calculate xs again: The kernel function might
// have spawned a new VM
xs_new = &(s->_executionStack.back());
s->_executionStackPosChanged = true;
+
+ // If a game is being loaded, stop processing
+ if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit())
+ return; // Stop processing
+
break;
}
case op_callb: // 0x22 (34)
- temp = ((opparams[1] >> 1) + scriptState.restAdjust + 1);
- s_temp = scriptState.xs->sp;
- scriptState.xs->sp -= temp;
-
- scriptState.xs->sp[0].offset += scriptState.restAdjust;
- xs_new = execute_method(s, 0, opparams[0], s_temp, scriptState.xs->objp,
- scriptState.xs->sp[0].offset, scriptState.xs->sp);
- scriptState.restAdjust = 0; // Used up the &rest adjustment
+ // Call base script
+ temp = ((opparams[1] >> 1) + s->restAdjust + 1);
+ s_temp = s->xs->sp;
+ s->xs->sp -= temp;
+
+ s->xs->sp[0].offset += s->restAdjust;
+ xs_new = execute_method(s, 0, opparams[0], s_temp, s->xs->objp,
+ s->xs->sp[0].offset, s->xs->sp);
+ s->restAdjust = 0; // Used up the &rest adjustment
if (xs_new) // in case of error, keep old stack
s->_executionStackPosChanged = true;
break;
case op_calle: // 0x23 (35)
- temp = ((opparams[2] >> 1) + scriptState.restAdjust + 1);
- s_temp = scriptState.xs->sp;
- scriptState.xs->sp -= temp;
+ // Call external script
+ temp = ((opparams[2] >> 1) + s->restAdjust + 1);
+ s_temp = s->xs->sp;
+ s->xs->sp -= temp;
- scriptState.xs->sp[0].offset += scriptState.restAdjust;
- xs_new = execute_method(s, opparams[0], opparams[1], s_temp, scriptState.xs->objp,
- scriptState.xs->sp[0].offset, scriptState.xs->sp);
- scriptState.restAdjust = 0; // Used up the &rest adjustment
+ s->xs->sp[0].offset += s->restAdjust;
+ xs_new = execute_method(s, opparams[0], opparams[1], s_temp, s->xs->objp,
+ s->xs->sp[0].offset, s->xs->sp);
+ s->restAdjust = 0; // Used up the &rest adjustment
if (xs_new) // in case of error, keep old stack
s->_executionStackPosChanged = true;
break;
case op_ret: // 0x24 (36)
+ // Return from an execution loop started by call, calle, callb, send, self or super
do {
- StackPtr old_sp2 = scriptState.xs->sp;
- StackPtr old_fp = scriptState.xs->fp;
+ StackPtr old_sp2 = s->xs->sp;
+ StackPtr old_fp = s->xs->fp;
ExecStack *old_xs = &(s->_executionStack.back());
- if ((int)s->_executionStack.size()-1 == s->execution_stack_base) { // Have we reached the base?
- s->execution_stack_base = old_execution_stack_base; // Restore stack base
+ if ((int)s->_executionStack.size() - 1 == s->executionStackBase) { // Have we reached the base?
+ s->executionStackBase = old_executionStackBase; // Restore stack base
s->_executionStack.pop_back();
s->_executionStackPosChanged = true;
- s->restAdjust = scriptState.restAdjust; // Update &rest
return; // "Hard" return
}
@@ -1205,33 +1505,34 @@ void run_vm(EngineState *s, bool restoring) {
// Not reached the base, so let's do a soft return
s->_executionStack.pop_back();
s->_executionStackPosChanged = true;
- scriptState.xs = &(s->_executionStack.back());
+ s->xs = &(s->_executionStack.back());
- if (scriptState.xs->sp == CALL_SP_CARRY // Used in sends to 'carry' the stack pointer
- || scriptState.xs->type != EXEC_STACK_TYPE_CALL) {
- scriptState.xs->sp = old_sp2;
- scriptState.xs->fp = old_fp;
+ if (s->xs->sp == CALL_SP_CARRY // Used in sends to 'carry' the stack pointer
+ || s->xs->type != EXEC_STACK_TYPE_CALL) {
+ s->xs->sp = old_sp2;
+ s->xs->fp = old_fp;
}
- } while (scriptState.xs->type == EXEC_STACK_TYPE_VARSELECTOR);
+ } while (s->xs->type == EXEC_STACK_TYPE_VARSELECTOR);
// Iterate over all varselector accesses
s->_executionStackPosChanged = true;
- xs_new = scriptState.xs;
+ xs_new = s->xs;
break;
case op_send: // 0x25 (37)
- s_temp = scriptState.xs->sp;
- scriptState.xs->sp -= ((opparams[0] >> 1) + scriptState.restAdjust); // Adjust stack
+ // Send for one or more selectors
+ s_temp = s->xs->sp;
+ s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack
- scriptState.xs->sp[1].offset += scriptState.restAdjust;
+ s->xs->sp[1].offset += s->restAdjust;
xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp,
- (int)(opparams[0] >> 1) + (uint16)scriptState.restAdjust, scriptState.xs->sp);
+ (int)(opparams[0] >> 1) + (uint16)s->restAdjust, s->xs->sp);
- if (xs_new && xs_new != scriptState.xs)
+ if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- scriptState.restAdjust = 0;
+ s->restAdjust = 0;
break;
@@ -1241,8 +1542,9 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_class: // 0x28 (40)
+ // Get class address
s->r_acc = s->_segMan->getClassAddress((unsigned)opparams[0], SCRIPT_GET_LOCK,
- scriptState.xs->addr.pc);
+ s->xs->addr.pc);
break;
case 0x29: // (41)
@@ -1250,58 +1552,62 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_self: // 0x2a (42)
- s_temp = scriptState.xs->sp;
- scriptState.xs->sp -= ((opparams[0] >> 1) + scriptState.restAdjust); // Adjust stack
+ // Send to self
+ s_temp = s->xs->sp;
+ s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack
- scriptState.xs->sp[1].offset += scriptState.restAdjust;
- xs_new = send_selector(s, scriptState.xs->objp, scriptState.xs->objp,
- s_temp, (int)(opparams[0] >> 1) + (uint16)scriptState.restAdjust,
- scriptState.xs->sp);
+ s->xs->sp[1].offset += s->restAdjust;
+ xs_new = send_selector(s, s->xs->objp, s->xs->objp,
+ s_temp, (int)(opparams[0] >> 1) + (uint16)s->restAdjust,
+ s->xs->sp);
- if (xs_new && xs_new != scriptState.xs)
+ if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- scriptState.restAdjust = 0;
+ s->restAdjust = 0;
break;
case op_super: // 0x2b (43)
- r_temp = s->_segMan->getClassAddress(opparams[0], SCRIPT_GET_LOAD, scriptState.xs->addr.pc);
+ // Send to any class
+ r_temp = s->_segMan->getClassAddress(opparams[0], SCRIPT_GET_LOAD, s->xs->addr.pc);
if (!r_temp.segment)
error("[VM]: Invalid superclass in object");
else {
- s_temp = scriptState.xs->sp;
- scriptState.xs->sp -= ((opparams[1] >> 1) + scriptState.restAdjust); // Adjust stack
+ s_temp = s->xs->sp;
+ s->xs->sp -= ((opparams[1] >> 1) + s->restAdjust); // Adjust stack
- scriptState.xs->sp[1].offset += scriptState.restAdjust;
- xs_new = send_selector(s, r_temp, scriptState.xs->objp, s_temp,
- (int)(opparams[1] >> 1) + (uint16)scriptState.restAdjust,
- scriptState.xs->sp);
+ s->xs->sp[1].offset += s->restAdjust;
+ xs_new = send_selector(s, r_temp, s->xs->objp, s_temp,
+ (int)(opparams[1] >> 1) + (uint16)s->restAdjust,
+ s->xs->sp);
- if (xs_new && xs_new != scriptState.xs)
+ if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- scriptState.restAdjust = 0;
+ s->restAdjust = 0;
}
break;
case op_rest: // 0x2c (44)
+ // Pushes all or part of the parameter variable list on the stack
temp = (uint16) opparams[0]; // First argument
- scriptState.restAdjust = MAX<int16>(scriptState.xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't
+ s->restAdjust = MAX<int16>(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't
- for (; temp <= scriptState.xs->argc; temp++)
- PUSH32(scriptState.xs->variables_argp[temp]);
+ for (; temp <= s->xs->argc; temp++)
+ PUSH32(s->xs->variables_argp[temp]);
break;
case op_lea: // 0x2d (45)
+ // Load Effective Address
temp = (uint16) opparams[0] >> 1;
var_number = temp & 0x03; // Get variable type
// Get variable block offset
- r_temp.segment = scriptState.variables_seg[var_number];
- r_temp.offset = scriptState.variables[var_number] - scriptState.variables_base[var_number];
+ r_temp.segment = s->variablesSegment[var_number];
+ r_temp.offset = s->variables[var_number] - s->variablesBase[var_number];
if (temp & 0x08) // Add accumulator offset if requested
r_temp.offset += signed_validate_arithmetic(s->r_acc);
@@ -1314,7 +1620,8 @@ void run_vm(EngineState *s, bool restoring) {
case op_selfID: // 0x2e (46)
- s->r_acc = scriptState.xs->objp;
+ // Get 'self' identity
+ s->r_acc = s->xs->objp;
break;
case 0x2f: // (47)
@@ -1322,107 +1629,121 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_pprev: // 0x30 (48)
+ // Pushes the value of the prev register, set by the last comparison
+ // bytecode (eq?, lt?, etc.), on the stack
PUSH32(s->r_prev);
break;
case op_pToa: // 0x31 (49)
- s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1));
+ // Property To Accumulator
+ s->r_acc = validate_property(obj, (opparams[0] >> 1));
break;
case op_aTop: // 0x32 (50)
- OBJ_PROPERTY(obj, (opparams[0] >> 1)) = s->r_acc;
+ // Accumulator To Property
+ validate_property(obj, (opparams[0] >> 1)) = s->r_acc;
break;
case op_pTos: // 0x33 (51)
- PUSH32(OBJ_PROPERTY(obj, opparams[0] >> 1));
+ // Property To Stack
+ PUSH32(validate_property(obj, opparams[0] >> 1));
break;
case op_sTop: // 0x34 (52)
- OBJ_PROPERTY(obj, (opparams[0] >> 1)) = POP32();
+ // Stack To Property
+ validate_property(obj, (opparams[0] >> 1)) = POP32();
break;
- case op_ipToa: // 0x35 (53)
- s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1));
- s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(1 + /*acc*/);
+ case op_ipToa: { // 0x35 (53)
+ // Increment Property and copy To Accumulator
+ reg_t &opProperty = validate_property(obj, opparams[0] >> 1);
+ uint16 valueProperty;
+ if (validate_unsignedInteger(opProperty, valueProperty))
+ s->r_acc = make_reg(0, valueProperty + 1);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, opProperty, NULL_REG);
+ opProperty = s->r_acc;
break;
+ }
case op_dpToa: { // 0x36 (54)
- s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1));
-#if 0
- // Speed throttling is possible here as well
- // although this opens other issues like mud wrestling in lsl5 uses another local variable for delays
- Object *var_container = obj;
- if (!(obj->getInfoSelector().offset & SCRIPT_INFO_CLASS))
- var_container = s->_segMan->getObject(obj->getSuperClassSelector());
- uint16 varSelector = var_container->getVarSelector(opparams[0] >> 1);
-// printf("%X\n", varSelector);
-// printf("%s\n", g_sci->getKernel()->getSelectorName(varSelector).c_str());
- if ((varSelector == 0x84) || (varSelector == 0x92))) {
- // selectors cycles, cycleCnt from lsl5 hardcoded
- uint32 curTime = g_system->getMillis();
- if (s->_lastAnimateTime + 30 > curTime)
- break;
- s->_lastAnimateTime = curTime;
- }
-#endif
- s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(-1 + /*acc*/);
+ // Decrement Property and copy To Accumulator
+ reg_t &opProperty = validate_property(obj, opparams[0] >> 1);
+ uint16 valueProperty;
+ if (validate_unsignedInteger(opProperty, valueProperty))
+ s->r_acc = make_reg(0, valueProperty - 1);
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeDptoaWorkarounds, opProperty, NULL_REG);
+ opProperty = s->r_acc;
break;
}
- case op_ipTos: // 0x37 (55)
- validate_arithmetic(OBJ_PROPERTY(obj, (opparams[0] >> 1)));
- temp = ++OBJ_PROPERTY(obj, (opparams[0] >> 1)).offset;
- PUSH(temp);
+ case op_ipTos: { // 0x37 (55)
+ // Increment Property and push to Stack
+ reg_t &opProperty = validate_property(obj, opparams[0] >> 1);
+ uint16 valueProperty;
+ if (validate_unsignedInteger(opProperty, valueProperty))
+ valueProperty++;
+ else
+ valueProperty = arithmetic_lookForWorkaround(opcode, NULL, opProperty, NULL_REG).offset;
+ opProperty = make_reg(0, valueProperty);
+ PUSH(valueProperty);
break;
+ }
- case op_dpTos: // 0x38 (56)
- validate_arithmetic(OBJ_PROPERTY(obj, (opparams[0] >> 1)));
- temp = --OBJ_PROPERTY(obj, (opparams[0] >> 1)).offset;
- PUSH(temp);
+ case op_dpTos: { // 0x38 (56)
+ // Decrement Property and push to Stack
+ reg_t &opProperty = validate_property(obj, opparams[0] >> 1);
+ uint16 valueProperty;
+ if (validate_unsignedInteger(opProperty, valueProperty))
+ valueProperty--;
+ else
+ valueProperty = arithmetic_lookForWorkaround(opcode, NULL, opProperty, NULL_REG).offset;
+ opProperty = make_reg(0, valueProperty);
+ PUSH(valueProperty);
break;
+ }
case op_lofsa: // 0x39 (57)
- s->r_acc.segment = scriptState.xs->addr.pc.segment;
+ // Load Offset to Accumulator
+ s->r_acc.segment = s->xs->addr.pc.segment;
switch (g_sci->_features->detectLofsType()) {
case SCI_VERSION_1_1:
- s->r_acc.offset = opparams[0] + local_script->_scriptSize;
+ s->r_acc.offset = opparams[0] + local_script->getScriptSize();
break;
case SCI_VERSION_1_MIDDLE:
s->r_acc.offset = opparams[0];
break;
default:
- s->r_acc.offset = scriptState.xs->addr.pc.offset + opparams[0];
+ s->r_acc.offset = s->xs->addr.pc.offset + opparams[0];
}
-#ifndef DISABLE_VALIDATIONS
- if (s->r_acc.offset >= code_buf_size) {
+ if (s->r_acc.offset >= scr->getBufSize()) {
error("VM: lofsa operation overflowed: %04x:%04x beyond end"
- " of script (at %04x)\n", PRINT_REG(s->r_acc), code_buf_size);
+ " of script (at %04x)\n", PRINT_REG(s->r_acc), scr->getBufSize());
}
-#endif
break;
case op_lofss: // 0x3a (58)
- r_temp.segment = scriptState.xs->addr.pc.segment;
+ // Load Offset to Stack
+ r_temp.segment = s->xs->addr.pc.segment;
switch (g_sci->_features->detectLofsType()) {
case SCI_VERSION_1_1:
- r_temp.offset = opparams[0] + local_script->_scriptSize;
+ r_temp.offset = opparams[0] + local_script->getScriptSize();
break;
case SCI_VERSION_1_MIDDLE:
r_temp.offset = opparams[0];
break;
default:
- r_temp.offset = scriptState.xs->addr.pc.offset + opparams[0];
+ r_temp.offset = s->xs->addr.pc.offset + opparams[0];
}
-#ifndef DISABLE_VALIDATIONS
- if (r_temp.offset >= code_buf_size) {
+ if (r_temp.offset >= scr->getBufSize()) {
error("VM: lofss operation overflowed: %04x:%04x beyond end"
- " of script (at %04x)", PRINT_REG(r_temp), code_buf_size);
+ " of script (at %04x)", PRINT_REG(r_temp), scr->getBufSize());
}
-#endif
PUSH32(r_temp);
break;
@@ -1440,10 +1761,11 @@ void run_vm(EngineState *s, bool restoring) {
case op_pushSelf: // 0x3e (62)
if (!(extOpcode & 1)) {
- PUSH32(scriptState.xs->objp);
+ PUSH32(s->xs->objp);
} else {
// Debug opcode op_file, skip null-terminated string (file name)
- while (code_buf[scriptState.xs->addr.pc.offset++]) ;
+ const byte *code_buf = scr->getBuf();
+ while (code_buf[s->xs->addr.pc.offset++]) ;
}
break;
@@ -1455,42 +1777,53 @@ void run_vm(EngineState *s, bool restoring) {
case op_lal: // 0x41 (65)
case op_lat: // 0x42 (66)
case op_lap: // 0x43 (67)
+ // Load global, local, temp or param variable into the accumulator
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0];
- s->r_acc = READ_VAR(var_type, var_number, s->r_acc);
+ s->r_acc = READ_VAR(var_type, var_number);
break;
case op_lsg: // 0x44 (68)
case op_lsl: // 0x45 (69)
case op_lst: // 0x46 (70)
case op_lsp: // 0x47 (71)
+ // Load global, local, temp or param variable into the stack
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0];
- PUSH32(READ_VAR(var_type, var_number, s->r_acc));
+ PUSH32(READ_VAR(var_type, var_number));
break;
case op_lagi: // 0x48 (72)
case op_lali: // 0x49 (73)
case op_lati: // 0x4a (74)
case op_lapi: // 0x4b (75)
+ // Load global, local, temp or param variable into the accumulator,
+ // using the accumulator as an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- s->r_acc = READ_VAR(var_type, var_number, s->r_acc);
+ s->r_acc = READ_VAR(var_type, var_number);
break;
case op_lsgi: // 0x4c (76)
case op_lsli: // 0x4d (77)
case op_lsti: // 0x4e (78)
- case op_lspi: // 0x4f (79)
+ case op_lspi: { // 0x4f (79)
+ // Load global, local, temp or param variable into the stack,
+ // using the accumulator as an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- PUSH32(READ_VAR(var_type, var_number, s->r_acc));
+ int16 value;
+ if (!validate_signedInteger(s->r_acc, value))
+ value = arithmetic_lookForWorkaround(opcode, opcodeLsiWorkarounds, s->r_acc, NULL_REG).offset;
+ var_number = opparams[0] + value;
+ PUSH32(READ_VAR(var_type, var_number));
break;
+ }
case op_sag: // 0x50 (80)
case op_sal: // 0x51 (81)
case op_sat: // 0x52 (82)
case op_sap: // 0x53 (83)
+ // Save the accumulator into the global, local, temp or param variable
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0];
WRITE_VAR(var_type, var_number, s->r_acc);
@@ -1500,6 +1833,7 @@ void run_vm(EngineState *s, bool restoring) {
case op_ssl: // 0x55 (85)
case op_sst: // 0x56 (86)
case op_ssp: // 0x57 (87)
+ // Save the stack into the global, local, temp or param variable
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0];
WRITE_VAR(var_type, var_number, POP32());
@@ -1509,6 +1843,9 @@ void run_vm(EngineState *s, bool restoring) {
case op_sali: // 0x59 (89)
case op_sati: // 0x5a (90)
case op_sapi: // 0x5b (91)
+ // Save the accumulator into the global, local, temp or param variable,
+ // using the accumulator as an additional index
+
// Special semantics because it wouldn't really make a whole lot
// of sense otherwise, with acc being used for two things
// simultaneously...
@@ -1522,6 +1859,8 @@ void run_vm(EngineState *s, bool restoring) {
case op_ssli: // 0x5d (93)
case op_ssti: // 0x5e (94)
case op_sspi: // 0x5f (95)
+ // Save the stack into the global, local, temp or param variable,
+ // using the accumulator as an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
WRITE_VAR(var_type, var_number, POP32());
@@ -1531,9 +1870,11 @@ void run_vm(EngineState *s, bool restoring) {
case op_plusal: // 0x61 (97)
case op_plusat: // 0x62 (98)
case op_plusap: // 0x63 (99)
+ // Increment the global, local, temp or param variable and save it
+ // to the accumulator
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0];
- r_temp = READ_VAR(var_type, var_number, s->r_acc);
+ r_temp = READ_VAR(var_type, var_number);
if (r_temp.segment) {
// Pointer arithmetics!
s->r_acc = pointer_add(s, r_temp, 1);
@@ -1546,9 +1887,11 @@ void run_vm(EngineState *s, bool restoring) {
case op_plussl: // 0x65 (101)
case op_plusst: // 0x66 (102)
case op_plussp: // 0x67 (103)
+ // Increment the global, local, temp or param variable and save it
+ // to the stack
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0];
- r_temp = READ_VAR(var_type, var_number, s->r_acc);
+ r_temp = READ_VAR(var_type, var_number);
if (r_temp.segment) {
// Pointer arithmetics!
r_temp = pointer_add(s, r_temp, 1);
@@ -1562,9 +1905,11 @@ void run_vm(EngineState *s, bool restoring) {
case op_plusali: // 0x69 (105)
case op_plusati: // 0x6a (106)
case op_plusapi: // 0x6b (107)
+ // Increment the global, local, temp or param variable and save it
+ // to the accumulator, using the accumulator as an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- r_temp = READ_VAR(var_type, var_number, s->r_acc);
+ r_temp = READ_VAR(var_type, var_number);
if (r_temp.segment) {
// Pointer arithmetics!
s->r_acc = pointer_add(s, r_temp, 1);
@@ -1577,9 +1922,11 @@ void run_vm(EngineState *s, bool restoring) {
case op_plussli: // 0x6d (109)
case op_plussti: // 0x6e (110)
case op_plusspi: // 0x6f (111)
+ // Increment the global, local, temp or param variable and save it
+ // to the stack, using the accumulator as an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- r_temp = READ_VAR(var_type, var_number, s->r_acc);
+ r_temp = READ_VAR(var_type, var_number);
if (r_temp.segment) {
// Pointer arithmetics!
r_temp = pointer_add(s, r_temp, 1);
@@ -1593,9 +1940,11 @@ void run_vm(EngineState *s, bool restoring) {
case op_minusal: // 0x71 (113)
case op_minusat: // 0x72 (114)
case op_minusap: // 0x73 (115)
+ // Decrement the global, local, temp or param variable and save it
+ // to the accumulator
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0];
- r_temp = READ_VAR(var_type, var_number, s->r_acc);
+ r_temp = READ_VAR(var_type, var_number);
if (r_temp.segment) {
// Pointer arithmetics!
s->r_acc = pointer_add(s, r_temp, -1);
@@ -1608,9 +1957,11 @@ void run_vm(EngineState *s, bool restoring) {
case op_minussl: // 0x75 (117)
case op_minusst: // 0x76 (118)
case op_minussp: // 0x77 (119)
+ // Decrement the global, local, temp or param variable and save it
+ // to the stack
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0];
- r_temp = READ_VAR(var_type, var_number, s->r_acc);
+ r_temp = READ_VAR(var_type, var_number);
if (r_temp.segment) {
// Pointer arithmetics!
r_temp = pointer_add(s, r_temp, -1);
@@ -1624,9 +1975,11 @@ void run_vm(EngineState *s, bool restoring) {
case op_minusali: // 0x79 (121)
case op_minusati: // 0x7a (122)
case op_minusapi: // 0x7b (123)
+ // Decrement the global, local, temp or param variable and save it
+ // to the accumulator, using the accumulator as an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- r_temp = READ_VAR(var_type, var_number, s->r_acc);
+ r_temp = READ_VAR(var_type, var_number);
if (r_temp.segment) {
// Pointer arithmetics!
s->r_acc = pointer_add(s, r_temp, -1);
@@ -1639,9 +1992,11 @@ void run_vm(EngineState *s, bool restoring) {
case op_minussli: // 0x7d (125)
case op_minussti: // 0x7e (126)
case op_minusspi: // 0x7f (127)
+ // Decrement the global, local, temp or param variable and save it
+ // to the stack, using the accumulator as an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- r_temp = READ_VAR(var_type, var_number, s->r_acc);
+ r_temp = READ_VAR(var_type, var_number);
if (r_temp.segment) {
// Pointer arithmetics!
r_temp = pointer_add(s, r_temp, -1);
@@ -1657,121 +2012,23 @@ void run_vm(EngineState *s, bool restoring) {
} // switch (opcode)
if (s->_executionStackPosChanged) // Force initialization
- scriptState.xs = xs_new;
+ s->xs = xs_new;
-//#ifndef DISABLE_VALIDATIONS
- if (scriptState.xs != &(s->_executionStack.back())) {
- warning("xs is stale (%p vs %p); last command was %02x",
- (void *)scriptState.xs, (void *)&(s->_executionStack.back()),
+ if (s->xs != &(s->_executionStack.back())) {
+ error("xs is stale (%p vs %p); last command was %02x",
+ (void *)s->xs, (void *)&(s->_executionStack.back()),
opcode);
}
-//#endif
- ++script_step_counter;
+ ++s->scriptStepCounter;
}
}
-static void _init_stack_base_with_selector(EngineState *s, Selector selector) {
- s->stack_base[0] = make_reg(0, (uint16)selector);
- s->stack_base[1] = NULL_REG;
-}
-
-static EngineState *_game_run(EngineState *&s) {
- EngineState *successor = NULL;
- int game_is_finished = 0;
-
- if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup))
- g_sci->getSciDebugger()->attach();
-
- do {
- s->_executionStackPosChanged = false;
- run_vm(s, successor ? true : false);
- if (s->restarting_flags & SCI_GAME_IS_RESTARTING_NOW) { // Restart was requested?
- successor = NULL;
- s->_executionStack.clear();
- s->_executionStackPosChanged = false;
-
- game_exit(s);
- script_init_engine(s);
- game_init(s);
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- s->_sound.sfx_reset_player();
-#endif
- _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play);
-
- send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base);
-
- script_abort_flag = 0;
- s->restarting_flags = SCI_GAME_WAS_RESTARTED | SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE;
-
- } else {
- successor = s->successor;
- if (successor) {
- game_exit(s);
- delete s;
- s = successor;
-
- if (script_abort_flag == 2) {
- debugC(2, kDebugLevelVM, "Restarting with replay()");
- s->_executionStack.clear(); // Restart with replay
-
- _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.replay);
-
- send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base);
- }
-
- script_abort_flag = 0;
-
- } else
- game_is_finished = 1;
- }
- } while (!game_is_finished);
-
- return s;
-}
-
-int game_run(EngineState **_s) {
- EngineState *s = *_s;
-
- debugC(2, kDebugLevelVM, "Calling %s::play()", s->_gameId.c_str());
- _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play); // Call the play selector
-
- // Now: Register the first element on the execution stack-
- if (!send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base)) {
- Console *con = g_sci->getSciDebugger();
- con->printObject(s->_gameObj);
- warning("Failed to run the game! Aborting...");
- return 1;
- }
- // and ENGAGE!
- _game_run(*_s);
-
- debugC(2, kDebugLevelVM, "Game::play() finished.");
-
- return 0;
-}
-
-void quit_vm() {
- script_abort_flag = 1; // Terminate VM
- g_debugState.seeking = kDebugSeekNothing;
- g_debugState.runningStep = 0;
-}
-
-void shrink_execution_stack(EngineState *s, uint size) {
- assert(s->_executionStack.size() >= size);
- Common::List<ExecStack>::iterator iter;
- iter = s->_executionStack.begin();
- for (uint i = 0; i < size; ++i)
- ++iter;
- s->_executionStack.erase(iter, s->_executionStack.end());
-}
-
-reg_t* ObjVarRef::getPointer(SegManager *segMan) const {
+reg_t *ObjVarRef::getPointer(SegManager *segMan) const {
Object *o = segMan->getObject(obj);
- if (!o) return 0;
- return &(o->_variables[varindex]);
+ return o ? &o->getVariableRef(varindex) : 0;
}
-reg_t* ExecStack::getVarPointer(SegManager *segMan) const {
+reg_t *ExecStack::getVarPointer(SegManager *segMan) const {
assert(type == EXEC_STACK_TYPE_VARSELECTOR);
return addr.varp.getPointer(segMan);
}
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index 8e40fed818..ee22e03310 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -43,59 +43,16 @@ class ResourceManager;
/** Number of bytes to be allocated for the stack */
#define VM_STACK_SIZE 0x1000
-/** Maximum number of calls residing on the stack */
-#define SCRIPT_MAX_EXEC_STACK 256
-/** Maximum number of entries in the class table */
-#define SCRIPT_MAX_CLASSTABLE_SIZE 256
-/** Maximum number of cloned objects on the heap */
-#define SCRIPT_MAX_CLONES 256
-
-
-/** Object-relative offset of the selector area inside a script */
-#define SCRIPT_SELECTOR_OFFSET 8 -8
-
-/** Object-relative offset of the pointer to the underlying script's local variables */
-#define SCRIPT_LOCALVARPTR_OFFSET 2 -8
-
-/** Object-relative offset of the selector counter */
-#define SCRIPT_SELECTORCTR_OFFSET 6 -8
-
-/** Object-relative offset of the offset of the function area */
-#define SCRIPT_FUNCTAREAPTR_OFFSET 4 -8
-
-/** Offset that has to be added to the function area pointer */
-#define SCRIPT_FUNCTAREAPTR_MAGIC 8 -8
-
-/** Offset of the name pointer */
-#define SCRIPT_NAME_OFFSET (getSciVersion() < SCI_VERSION_1_1 ? 14 -8 : 16)
-
-/** Object-relative offset of the -info- selector */
-#define SCRIPT_INFO_OFFSET (getSciVersion() < SCI_VERSION_1_1 ? 12 -8 : 14)
-
-/** Flag fo the -info- selector */
-#define SCRIPT_INFO_CLONE 0x0001
-
-/** Flag for the -info- selector */
-#define SCRIPT_INFO_CLASS 0x8000
-
-
/** Magical object identifier */
#define SCRIPT_OBJECT_MAGIC_NUMBER 0x1234
+
/** Offset of this identifier */
#define SCRIPT_OBJECT_MAGIC_OFFSET (getSciVersion() < SCI_VERSION_1_1 ? -8 : 0)
-/** Script-relative offset of the species ID */
-#define SCRIPT_SPECIES_OFFSET 8 -8
-
-#define SCRIPT_SUPERCLASS_OFFSET (getSciVersion() < SCI_VERSION_1_1 ? 10 -8 : 12)
-
-/** Magic adjustment value for lofsa and lofss */
-#define SCRIPT_LOFS_MAGIC 3
-
/** Stack pointer value: Use predecessor's value */
#define CALL_SP_CARRY NULL
-/** Types of selectors as returned by lookup_selector() below. */
+/** Types of selectors as returned by lookupSelector() below. */
enum SelectorType {
kSelectorNone = 0,
kSelectorVariable,
@@ -107,113 +64,7 @@ struct Class {
reg_t reg; ///< offset; script-relative offset, segment: 0 if not instantiated
};
-#define RAW_IS_OBJECT(datablock) (READ_SCI11ENDIAN_UINT16(((byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER)
-
-/** Contains selector IDs for a few selected selectors */
-struct SelectorCache {
- SelectorCache() {
- memset(this, 0, sizeof(*this));
- }
-
- // Statically defined selectors, (almost the) same in all SCI versions
- Selector y;
- Selector x;
- Selector view, loop, cel; ///< Description of a specific image
- Selector underBits; ///< Used by the graphics subroutines to store backupped BG pic data
- Selector nsTop, nsLeft, nsBottom, nsRight; ///< View boundaries ('now seen')
- Selector lsTop, lsLeft, lsBottom, lsRight; ///< Used by Animate() subfunctions and scroll list controls
- Selector signal; ///< Used by Animate() to control a view's behaviour
- Selector illegalBits; ///< Used by CanBeHere
- Selector brTop, brLeft, brBottom, brRight; ///< Bounding Rectangle
- // name, key, time
- Selector text; ///< Used by controls
- Selector elements; ///< Used by SetSynonyms()
- // color, back
- Selector mode; ///< Used by text controls (-> DrawControl())
- // style
- Selector state, font, type;///< Used by controls
- // window
- Selector cursor, max; ///< Used by EditControl
- // mark, who
- Selector message; ///< Used by GetEvent
- // edit
- Selector play; ///< Play function (first function to be called)
- Selector number;
- Selector handle; ///< Replaced by nodePtr in SCI1+
- Selector nodePtr; ///< Replaces handle in SCI1+
- Selector client; ///< The object that wants to be moved
- Selector dx, dy; ///< Deltas
- Selector b_movCnt, b_i1, b_i2, b_di, b_xAxis, b_incr; ///< Various Bresenham vars
- Selector xStep, yStep; ///< BR adjustments
- Selector moveSpeed; ///< Used for DoBresen
- Selector canBeHere; ///< Funcselector: Checks for movement validity in SCI0
- Selector heading, mover; ///< Used in DoAvoider
- Selector doit; ///< Called (!) by the Animate() system call
- Selector isBlocked, looper; ///< Used in DoAvoider
- Selector priority;
- Selector modifiers; ///< Used by GetEvent
- Selector replay; ///< Replay function
- // setPri, at, next, done, width
- Selector wordFail, syntaxFail; ///< Used by Parse()
- // semanticFail, pragmaFail
- // said
- Selector claimed; ///< Used generally by the event mechanism
- // value, save, restore, title, button, icon, draw
- Selector delete_; ///< Called by Animate() to dispose a view object
- Selector z;
-
- // SCI1+ static selectors
- Selector parseLang;
- Selector printLang; ///< Used for i18n
- Selector subtitleLang;
- Selector size;
- Selector points; ///< Used by AvoidPath()
- Selector palette;
- Selector dataInc;
- // handle (in SCI1)
- Selector min; ///< SMPTE time format
- Selector sec;
- Selector frame;
- Selector vol;
- Selector pri;
- // perform
- Selector moveDone; ///< used for DoBresen
-
- // SCI1 selectors which have been moved a bit in SCI1.1, but otherwise static
- Selector cantBeHere; ///< Checks for movement avoidance in SCI1+. Replaces canBeHere
- Selector topString; ///< SCI1 scroll lists use this instead of lsTop
- Selector flags;
-
- // SCI1+ audio sync related selectors, not static. They're used for lip syncing in
- // CD talkie games
- Selector syncCue; ///< Used by DoSync()
- Selector syncTime;
-
- // SCI1.1 specific selectors
- Selector scaleSignal; // < Used by Animate() for cel scaling (SCI1.1+)
- Selector scaleX, scaleY; ///< SCI1.1 view scaling
-
- // Used for auto detection purposes
- Selector overlay; ///< Used to determine if a game is using old gfx functions or not
- Selector setCursor; ///< For cursor semantics autodetection
-
-#ifdef ENABLE_SCI32
- Selector data; // Used by Array()/String()
- Selector picture; // Used to hold the picture ID for SCI32 pictures
-
- Selector plane;
- Selector top;
- Selector left;
- Selector bottom;
- Selector right;
- Selector resX;
- Selector resY;
-
- Selector fore;
- Selector back;
- Selector dimmed;
-#endif
-};
+#define RAW_IS_OBJECT(datablock) (READ_SCI11ENDIAN_UINT16(((const byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER)
// A reference to an object's variable.
// The object is stored as a reg_t, the variable as an index into _variables
@@ -246,8 +97,10 @@ struct ExecStack {
StackPtr variables_argp; // Argument pointer
SegmentId local_segment; // local variables etc
- Selector selector; // The selector which was used to call or -1 if not applicable
- int origin; // The stack frame position the call was made from, or -1 if it was the initial call
+ Selector debugSelector; // The selector which was used to call or -1 if not applicable
+ int debugExportId; // The exportId which was called or -1 if not applicable
+ int debugLocalCallOffset; // Local call offset or -1 if not applicable
+ int debugOrigin; // The stack frame position the call was made from, or -1 if it was the initial call
ExecStackType type;
reg_t* getVarPointer(SegManager *segMan) const;
@@ -260,41 +113,165 @@ enum {
VAR_PARAM = 3
};
-/**
- * Structure for storing the current internal state of the VM.
- */
-struct ScriptState {
- ExecStack *xs;
- int16 restAdjust;
- reg_t *variables[4]; ///< global, local, temp, param, as immediate pointers
- reg_t *variables_base[4]; ///< Used for referencing VM ops
- SegmentId variables_seg[4]; ///< Same as above, contains segment IDs
- int variables_max[4]; ///< Max. values for all variables
-};
-
-/**
- * The current internal state of the VM.
- */
-extern ScriptState scriptState;
-
-/**
- * Set this to 1 to abort script execution immediately. Aborting will
- * leave the debug exec stack intact.
- * Set it to 2 to force a replay afterwards.
- */
-extern int script_abort_flag;
-
/** Number of kernel calls in between gcs; should be < 50000 */
enum {
GC_INTERVAL = 32768
};
-/** Initially GC_DELAY, can be set at runtime */
-extern int script_gc_interval;
+// Opcode formats
+enum opcode_format {
+ Script_Invalid = -1,
+ Script_None = 0,
+ Script_Byte,
+ Script_SByte,
+ Script_Word,
+ Script_SWord,
+ Script_Variable,
+ Script_SVariable,
+ Script_SRelative,
+ Script_Property,
+ Script_Global,
+ Script_Local,
+ Script_Temp,
+ Script_Param,
+ Script_Offset,
+ Script_End
+};
+
+enum sci_opcodes {
+ op_bnot = 0x00, // 000
+ op_add = 0x01, // 001
+ op_sub = 0x02, // 002
+ op_mul = 0x03, // 003
+ op_div = 0x04, // 004
+ op_mod = 0x05, // 005
+ op_shr = 0x06, // 006
+ op_shl = 0x07, // 007
+ op_xor = 0x08, // 008
+ op_and = 0x09, // 009
+ op_or = 0x0a, // 010
+ op_neg = 0x0b, // 011
+ op_not = 0x0c, // 012
+ op_eq_ = 0x0d, // 013
+ op_ne_ = 0x0e, // 014
+ op_gt_ = 0x0f, // 015
+ op_ge_ = 0x10, // 016
+ op_lt_ = 0x11, // 017
+ op_le_ = 0x12, // 018
+ op_ugt_ = 0x13, // 019
+ op_uge_ = 0x14, // 020
+ op_ult_ = 0x15, // 021
+ op_ule_ = 0x16, // 022
+ op_bt = 0x17, // 023
+ op_bnt = 0x18, // 024
+ op_jmp = 0x19, // 025
+ op_ldi = 0x1a, // 026
+ op_push = 0x1b, // 027
+ op_pushi = 0x1c, // 028
+ op_toss = 0x1d, // 029
+ op_dup = 0x1e, // 030
+ op_link = 0x1f, // 031
+ op_call = 0x20, // 032
+ op_callk = 0x21, // 033
+ op_callb = 0x22, // 034
+ op_calle = 0x23, // 035
+ op_ret = 0x24, // 036
+ op_send = 0x25, // 037
+ // dummy 0x26, // 038
+ // dummy 0x27, // 039
+ op_class = 0x28, // 040
+ // dummy 0x29, // 041
+ op_self = 0x2a, // 042
+ op_super = 0x2b, // 043
+ op_rest = 0x2c, // 044
+ op_lea = 0x2d, // 045
+ op_selfID = 0x2e, // 046
+ // dummy 0x2f // 047
+ op_pprev = 0x30, // 048
+ op_pToa = 0x31, // 049
+ op_aTop = 0x32, // 050
+ op_pTos = 0x33, // 051
+ op_sTop = 0x34, // 052
+ op_ipToa = 0x35, // 053
+ op_dpToa = 0x36, // 054
+ op_ipTos = 0x37, // 055
+ op_dpTos = 0x38, // 056
+ op_lofsa = 0x39, // 057
+ op_lofss = 0x3a, // 058
+ op_push0 = 0x3b, // 059
+ op_push1 = 0x3c, // 060
+ op_push2 = 0x3d, // 061
+ op_pushSelf = 0x3e, // 062
+ op_line = 0x3f, // 063
+ op_lag = 0x40, // 064
+ op_lal = 0x41, // 065
+ op_lat = 0x42, // 066
+ op_lap = 0x43, // 067
+ op_lsg = 0x44, // 068
+ op_lsl = 0x45, // 069
+ op_lst = 0x46, // 070
+ op_lsp = 0x47, // 071
+ op_lagi = 0x48, // 072
+ op_lali = 0x49, // 073
+ op_lati = 0x4a, // 074
+ op_lapi = 0x4b, // 075
+ op_lsgi = 0x4c, // 076
+ op_lsli = 0x4d, // 077
+ op_lsti = 0x4e, // 078
+ op_lspi = 0x4f, // 079
+ op_sag = 0x50, // 080
+ op_sal = 0x51, // 081
+ op_sat = 0x52, // 082
+ op_sap = 0x53, // 083
+ op_ssg = 0x54, // 084
+ op_ssl = 0x55, // 085
+ op_sst = 0x56, // 086
+ op_ssp = 0x57, // 087
+ op_sagi = 0x58, // 088
+ op_sali = 0x59, // 089
+ op_sati = 0x5a, // 090
+ op_sapi = 0x5b, // 091
+ op_ssgi = 0x5c, // 092
+ op_ssli = 0x5d, // 093
+ op_ssti = 0x5e, // 094
+ op_sspi = 0x5f, // 095
+ op_plusag = 0x60, // 096
+ op_plusal = 0x61, // 097
+ op_plusat = 0x62, // 098
+ op_plusap = 0x63, // 099
+ op_plussg = 0x64, // 100
+ op_plussl = 0x65, // 101
+ op_plusst = 0x66, // 102
+ op_plussp = 0x67, // 103
+ op_plusagi = 0x68, // 104
+ op_plusali = 0x69, // 105
+ op_plusati = 0x6a, // 106
+ op_plusapi = 0x6b, // 107
+ op_plussgi = 0x6c, // 108
+ op_plussli = 0x6d, // 109
+ op_plussti = 0x6e, // 110
+ op_plusspi = 0x6f, // 111
+ op_minusag = 0x70, // 112
+ op_minusal = 0x71, // 113
+ op_minusat = 0x72, // 114
+ op_minusap = 0x73, // 115
+ op_minussg = 0x74, // 116
+ op_minussl = 0x75, // 117
+ op_minusst = 0x76, // 118
+ op_minussp = 0x77, // 119
+ op_minusagi = 0x78, // 120
+ op_minusali = 0x79, // 121
+ op_minusati = 0x7a, // 122
+ op_minusapi = 0x7b, // 123
+ op_minussgi = 0x7c, // 124
+ op_minussli = 0x7d, // 125
+ op_minussti = 0x7e, // 126
+ op_minusspi = 0x7f // 127
+};
-/** Number of steps executed */
-extern int script_step_counter;
+extern opcode_format g_opcode_formats[128][4];
+void script_adjust_opcode_formats();
/**
* Executes function pubfunct of the specified script.
@@ -338,9 +315,8 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj,
* It executes the code on s->heap[pc] until it hits a 'ret' operation
* while (stack_base == stack_pos). Requires s to be set up correctly.
* @param[in] s The state to use
- * @param[in] restoring true if s has just been restored, false otherwise
*/
-void run_vm(EngineState *s, bool restoring);
+void run_vm(EngineState *s);
/**
* Debugger functionality
@@ -349,14 +325,6 @@ void run_vm(EngineState *s, bool restoring);
void script_debug(EngineState *s);
/**
- * Initializes a EngineState block
- * @param[in] s The state to initialize
- * @return 0 on success, 1 if vocab.996 (the class table) is missing
- * or corrupted
- */
-int script_init_engine(EngineState *);
-
-/**
* Looks up a selector and returns its type and value
* varindex is written to iff it is non-NULL and the selector indicates a property of the object.
* @param[in] segMan The Segment Manager
@@ -376,105 +344,10 @@ int script_init_engine(EngineState *);
* kSelectorMethod if the selector represents a
* method
*/
-SelectorType lookup_selector(SegManager *segMan, reg_t obj, Selector selectorid,
+SelectorType lookupSelector(SegManager *segMan, reg_t obj, Selector selectorid,
ObjVarRef *varp, reg_t *fptr);
/**
- * Makes sure that a script and its superclasses get loaded to the heap.
- * If the script already has been loaded, only the number of lockers is
- * increased. All scripts containing superclasses of this script are loaded
- * recursively as well, unless 'recursive' is set to zero. The
- * complementary function is "script_uninstantiate()" below.
- * @param[in] resMan The resource manager
- * @param[in] segMan The segment manager
- * @param[in] script_nr The script number to load
- * @return The script's segment ID or 0 if out of heap
- */
-int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr);
-
-/**
- * Decreases the numer of lockers of a script and unloads it if that number
- * reaches zero.
- * This function will recursively unload scripts containing its
- * superclasses, if those aren't locked by other scripts as well.
- * @param[in] segMan The segment manager
- * @param[in] version The SCI version to use
- * @param[in] script_nr The script number that is requestet to be unloaded
- */
-void script_uninstantiate(SegManager *segMan, int script_nr);
-
-/**
- * Converts the builtin Sierra game IDs to the ones we use in ScummVM
- * @param[in] gameId The internal game ID
- * @param[in] gameFlags The game's flags, which are adjusted accordingly for demos
- * @return The equivalent ScummVM game id
- */
-Common::String convertSierraGameId(const char *gameId, uint32 *gameFlags, ResourceManager *resMan);
-
-/**
- * Initializes an SCI game
- * This function must be run before script_run() is executed. Graphics data
- * is initialized iff s->gfx_state != NULL.
- * @param[in] s The state to operate on
- * @return 0 on success, 1 if an error occured.
- */
-int game_init(EngineState *s);
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-/**
- * Initializes the sound part of an SCI game
- * This function may only be called if game_init() did not initialize
- * the sound data.
- * @param[in] s The state to initialize the sound in
- * @param[in] sound_flags Flags to pass to the sound subsystem
- * @param[in] soundVersion sound-version that got detected during game init
- * @return 0 on success, 1 if an error occured
- */
-int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion);
-#endif
-
-/**
- * Runs an SCI game
- * This is the main function for SCI games. It takes a valid state, loads
- * script 0 to it, finds the game object, allocates a stack, and runs the
- * init method of the game object. In layman's terms, this runs an SCI game.
- * Note that, EngineState *s may be changed during the game, e.g. if a game
- * state is restored.
- * @param[in] s Pointer to the pointer of the state to operate on
- * @return 0 on success, 1 if an error occured.
- */
-int game_run(EngineState **s);
-
-/**
- * Restores an SCI game state and runs the game
- * This restores a savegame; otherwise, it behaves just like game_run().
- * @param[in] s Pointer to the pointer of the state to
- * operate on
- * @param[in] savegame_name Name of the savegame to restore
- * @return 0 on success, 1 if an error occured.
- */
-int game_restore(EngineState **s, char *savegame_name);
-
-/**
- * Uninitializes an initialized SCI game
- * This function should be run after each script_run() call.
- * @param[in] s The state to operate on
- * @return 0 on success, 1 if an error occured.
- */
-int game_exit(EngineState *s);
-
-/**
- * Instructs the virtual machine to abort
- */
-void quit_vm();
-
-/**
- * Shrink execution stack to size.
- * Contains an assert it is not already smaller.
- */
-void shrink_execution_stack(EngineState *s, uint size);
-
-/**
* Read a PMachine instruction from a memory buffer and return its length.
*
* @param[in] src address from which to start parsing
diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h
index 29dc798c35..edf35a122a 100644
--- a/engines/sci/engine/vm_types.h
+++ b/engines/sci/engine/vm_types.h
@@ -81,6 +81,7 @@ enum {
extern const reg_t NULL_REG;
extern const reg_t SIGNAL_REG;
+extern const reg_t TRUE_REG;
// Selector ID
typedef int Selector;
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
new file mode 100644
index 0000000000..4dc4ae93d8
--- /dev/null
+++ b/engines/sci/engine/workarounds.cpp
@@ -0,0 +1,457 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/engine/kernel.h"
+#include "sci/engine/state.h"
+#include "sci/engine/vm.h"
+#include "sci/engine/workarounds.h"
+
+#define SCI_WORKAROUNDENTRY_TERMINATOR { (SciGameId)0, -1, -1, 0, NULL, NULL, -1, 0, { WORKAROUND_NONE, 0 } }
+
+namespace Sci {
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry opcodeDivWorkarounds[] = {
+ { GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // when entering inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call, index, workaround
+const SciWorkaroundEntry opcodeDptoaWorkarounds[] = {
+ { GID_LSL6, 360, 938, 0, "ROsc", "cycleDone", -1, 0, { WORKAROUND_FAKE, 1 } }, // when looking through tile in the shower room initial cycles get set to an object instead of 2, we fix this by setting 1 after decrease
+ { GID_LSL6HIRES, 360,64938, 0, "ROsc", "cycleDone", -1, 0, { WORKAROUND_FAKE, 1 } }, // when looking through tile in the shower room initial cycles get set to an object instead of 2, we fix this by setting 1 after decrease
+ { GID_SQ5, 200, 939, 0, "Osc", "cycleDone", -1, 0, { WORKAROUND_FAKE, 1 } }, // when going back to bridge the crew is goofing off, we get an object as cycle count
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry opcodeGeWorkarounds[] = {
+ { GID_PQ3, 31, 31, 0, "rm031", "init", -1, 0, { WORKAROUND_FAKE, 1 } }, // pq3 english: when exiting the car, while morales is making phonecalls - bug #3037565
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry opcodeLeWorkarounds[] = {
+ { GID_PEPPER, 370, 23, 0, "eastExitFeature", "onMe", -1, 0, { WORKAROUND_FAKE, 1 } }, // Pugh's office, when trying to use either the left or right exits, gets called on an integer and a pointer - bug #3040142
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry opcodeLsiWorkarounds[] = {
+ { GID_QFG2, 200, 200, 0, "astro", "messages", -1, 0, { WORKAROUND_FAKE, 0 } }, // when getting asked for your name by the astrologer bug #3039879
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry opcodeMulWorkarounds[] = {
+ { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, 0, { WORKAROUND_FAKE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #3038913
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry opcodeAndWorkarounds[] = {
+ { GID_MOTHERGOOSE, -1, 999, 0, "Event", "new", -1, 0, { WORKAROUND_FAKE, 0 } }, // constantly during the game
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry opcodeOrWorkarounds[] = {
+ { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xcc6, 0, { WORKAROUND_FAKE, 0 } }, // when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #3034464
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
+ { GID_CASTLEBRAIN, 280, 280, 0, "programmer", "dispatchEvent", -1, 0, { WORKAROUND_FAKE, 0xf } }, // pressing 'q' on the computer screen in the robot room, and closing the help dialog that pops up (bug #3039656). Moves the cursor to the view with the ID returned (in this case, the robot hand)
+ { GID_CNICK_KQ, 200, 0, 1, "Character", "<noname446>", -1, 504, { WORKAROUND_FAKE, 0 } }, // checkers, like in hoyle 3
+ { GID_CNICK_KQ, 200, 0, 1, "Character", "<noname446>", -1, 505, { WORKAROUND_FAKE, 0 } }, // checkers, like in hoyle 3
+ { GID_CNICK_KQ, -1, 700, 0, "gcWindow", "<noname183>", -1, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu, like in hoyle 3
+ { GID_CNICK_LONGBOW, 0, 0, 0, "RH Budget", "<noname110>", -1, 1, { WORKAROUND_FAKE, 0 } }, // when starting the game
+ { GID_ECOQUEST, -1, -1, 0, NULL, "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // almost clicking anywhere triggers this in almost all rooms
+ { GID_FANMADE, 516, 979, 0, "", "export 0", -1, 20, { WORKAROUND_FAKE, 0 } }, // Happens in Grotesteing after the logos
+ { GID_FANMADE, 528, 990, 0, "GDialog", "doit", -1, 4, { WORKAROUND_FAKE, 0 } }, // Happens in Cascade Quest when closing the glossary - bug #3038757
+ { GID_FREDDYPHARKAS, -1, 24, 0, "gcWin", "open", -1, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu
+ { GID_FREDDYPHARKAS, -1, 31, 0, "quitWin", "open", -1, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu
+ { GID_GK1, -1, 64950, -1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // sometimes when walk-clicking
+ { GID_GK2, -1, 11, 0, "", "export 10", -1, 3, { WORKAROUND_FAKE, 0 } }, // called when the game starts
+ { GID_GK2, -1, 11, 0, "", "export 10", -1, 4, { WORKAROUND_FAKE, 0 } }, // called during the game
+ { GID_HOYLE1, 4, 104, 0, "GinRummyCardList", "calcRuns", -1, 4, { WORKAROUND_FAKE, 0 } }, // Gin Rummy / right when the game starts
+ { GID_HOYLE1, 5, 204, 0, "tableau", "checkRuns", -1, 2, { WORKAROUND_FAKE, 0 } }, // Cribbage / during the game
+ { GID_HOYLE3, -1, 0, 1, "Character", "say", -1, 504, { WORKAROUND_FAKE, 0 } }, // when starting checkers or dominoes, first time a character says something
+ { GID_HOYLE3, -1, 0, 1, "Character", "say", -1, 505, { WORKAROUND_FAKE, 0 } }, // when starting checkers or dominoes, first time a character says something
+ { GID_HOYLE3, -1, 700, 0, "gcWindow", "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu
+ { GID_HOYLE3, 100, 100, 0, "dominoHand2", "cue", -1, 1, { WORKAROUND_FAKE, 0 } }, // while playing domino - bug #3036918
+ { GID_HOYLE4, -1, 0, 0, "gcWindow", "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when selecting "Control" from the menu (temp vars 0-3) - bug #3039294
+ { GID_HOYLE4, 910, 910, 0, "IconBarList", "setup", -1, 3, { WORKAROUND_FAKE, 0 } }, // when selecting "Tutorial" from the main menu - bug #3039294
+ { GID_ISLANDBRAIN, 140, 140, 0, "piece", "init", -1, 3, { WORKAROUND_FAKE, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0
+ { GID_ISLANDBRAIN, 200, 268, 0, "anElement", "select", -1, 0, { WORKAROUND_FAKE, 0 } }, // elements puzzle, gets used before super TextIcon
+ { GID_JONES, 1, 232, 0, "weekendText", "draw", 0x3d3, 0, { WORKAROUND_FAKE, 0 } }, // jones/cd only - gets called during the game
+ { GID_JONES, 1, 255, 0, "", "export 0", -1, 13, { WORKAROUND_FAKE, 0 } }, // jones/cd only - called when a game ends
+ { GID_JONES, 1, 255, 0, "", "export 0", -1, 14, { WORKAROUND_FAKE, 0 } }, // jones/cd only - called when a game ends
+ { GID_JONES, 764, 255, 0, "", "export 0", -1, 13, { WORKAROUND_FAKE, 0 } }, // jones/ega&vga only - called when the game starts
+ { GID_JONES, 764, 255, 0, "", "export 0", -1, 14, { WORKAROUND_FAKE, 0 } }, // jones/ega&vga only - called when the game starts
+ { GID_KQ5, -1, 0, 0, "", "export 29", -1, 3, { WORKAROUND_FAKE, 0 } }, // called when playing harp for the harpies or when aborting dialog in toy shop, is used for kDoAudio - bug #3034700
+ { GID_KQ5, 25, 25, 0, "rm025", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // inside witch forest, when going to the room where the walking rock is
+ { GID_KQ6, -1, 30, 0, "rats", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // rats in the catacombs (temps 1 - 5) - bugs #3034597, #3035495, #3035824
+ { GID_KQ6, 210, 210, 0, "rm210", "scriptCheck", -1, 0, { WORKAROUND_FAKE, 1 } }, // using inventory in that room - bug #3034565
+ { GID_KQ6, 500, 500, 0, "rm500", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // going to island of the beast
+ { GID_KQ6, 520, 520, 0, "rm520", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // going to boiling water trap on beast isle
+ { GID_KQ6, -1, 903, 0, "controlWin", "open", -1, 4, { WORKAROUND_FAKE, 0 } }, // when opening the controls window (save, load etc)
+ { GID_KQ7, 30, 64996, 0, "User", "handleEvent", -1, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key
+ { GID_LAURABOW, 37, 0, 0, "CB1", "doit", -1, 1, { WORKAROUND_FAKE, 0 } }, // when going up the stairs (bug #3037694)
+ { GID_LAURABOW, -1, 967, 0, "myIcon", "cycle", -1, 1, { WORKAROUND_FAKE, 0 } }, // having any portrait conversation coming up (initial bug #3034985)
+ { GID_LAURABOW2, -1, 24, 0, "gcWin", "open", -1, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu
+ { GID_LAURABOW2, -1, 21, 0, "dropCluesCode", "doit", -1, 1, { WORKAROUND_FAKE, 0x7fff } }, // when asking some questions (e.g. the reporter about the burglary, or the policeman about Ziggy). Must be big, as the game scripts perform lt on it and start deleting journal entries - bugs #3035068, #3036274
+ { GID_LAURABOW2, -1, 90, 0, "aTut", "init", -1, 6, { WORKAROUND_FAKE, 0 } }, // Random actors in museum (bug #3041257)
+ { GID_LAURABOW2, -1, 90, 0, "aZiggy", "init", -1, 6, { WORKAROUND_FAKE, 0 } }, // Random actors in museum (bug #3041257)
+ { GID_LAURABOW2, 240, 240, 0, "sSteveAnimates", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // Steve Dorian's idle animation at the docks - bug #3036291
+ { GID_LONGBOW, -1, 213, 0, "clear", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // When giving an answer using the druid hand sign code in any room
+ { GID_LONGBOW, -1, 213, 0, "letter", "handleEvent", 0xa8, 1, { WORKAROUND_FAKE, 0 } }, // When using the druid hand sign code in any room - bug #3036601
+ { GID_LSL1, 250, 250, 0, "increase", "handleEvent", -1, 2, { WORKAROUND_FAKE, 0 } }, // casino, playing game, increasing bet
+ { GID_LSL1, 720, 720, 0, "rm720", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // age check room
+ { GID_LSL2, 38, 38, 0, "cloudScript", "changeState", -1, 1, { WORKAROUND_FAKE, 0 } }, // entering the room in the middle deck of the ship - bug #3036483
+ { GID_LSL3, 340, 340, 0, "ComicScript", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // right after entering the 3 ethnic groups inside comedy club (temps 200, 201, 202, 203)
+ { GID_LSL3, -1, 997, 0, "TheMenuBar", "handleEvent", -1, 1, { WORKAROUND_FAKE, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's')
+ { GID_LSL6, 820, 82, 0, "", "export 0", -1, -1, { WORKAROUND_FAKE, 0 } }, // when touching the electric fence - bug #3038326
+ { GID_LSL6, -1, 85, 0, "washcloth", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // washcloth in inventory
+ { GID_LSL6, -1, 928, -1, "Narrator", "startText", -1, 0, { WORKAROUND_FAKE, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class
+ { GID_LSL6HIRES, 0, 85, 0, "LL6Inv", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // on startup
+ { GID_LSL6HIRES, -1, 64950, 1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // at least when entering swimming pool area
+ { GID_LSL6HIRES, -1, 64964, 0, "DPath", "init", -1, 1, { WORKAROUND_FAKE, 0 } }, // during the game
+ { GID_MOTHERGOOSE, 18, 992, 0, "AIPath", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // DEMO: Called when walking north from mother goose's house two screens
+ { GID_MOTHERGOOSEHIRES,-1,64950, 1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // right when clicking on a child at the start and probably also later
+ { GID_MOTHERGOOSEHIRES,-1,64950, 1, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // see above
+ { GID_PEPPER, -1, 894, 0, "Package", "doVerb", -1, 3, { WORKAROUND_FAKE, 0 } }, // using the hand on the book in the inventory - bug #3040012
+ { GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbd0, 0, { WORKAROUND_FAKE, 0 } }, // hq1: going to the brigands hideout
+ { GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbe4, 0, { WORKAROUND_FAKE, 0 } }, // qfg1: going to the brigands hideout
+ { GID_QFG2, -1, 71, 0, "theInvSheet", "doit", -1, 1, { WORKAROUND_FAKE, 0 } }, // accessing the inventory
+ { GID_QFG2, -1, 701, -1, "Alley", "at", -1, 0, { WORKAROUND_FAKE, 0 } }, // when walking inside the alleys in the town - bug #3035835 & #3038367
+ { GID_QFG2, -1, 990, 0, "Restore", "doit", -1, 364, { WORKAROUND_FAKE, 0 } }, // when pressing enter in restore dialog w/o any saved games present
+ { GID_QFG2, 260, 260, 0, "abdulS", "changeState",0x2d22, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Abdul is about to enter the house (where you have to hide in the wardrobe), bug #3039891, temps 1 and 2
+ { GID_QFG2, 260, 260, 0, "jabbarS", "changeState",0x2d22, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Jabbar is about to enter the house (where you have to hide in the wardrobe), bug #3040469, temps 1 and 2
+ { GID_QFG3, 140, 140, 0, "rm140", "init", 0x1008, 0, { WORKAROUND_FAKE, 0 } }, // when importing a character and selecting the previous profession - bug #3040460
+ { GID_QFG3, 330, 330, -1, "Teller", "doChild", -1, -1, { WORKAROUND_FAKE, 0 } }, // when talking to King Rajah about "Rajah" (bug #3036390, temp 1) or "Tarna" (temp 0), or when clicking on yourself and saying "Greet" (bug #3039774, temp 1)
+ { GID_QFG3, 700, 700, -1, "monsterIsDead", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // in the jungle, after winning any fight, bug #3040624
+ { GID_QFG3, 470, 470, -1, "rm470", "notify", -1, 0, { WORKAROUND_FAKE, 0 } }, // closing the character screen in the Simbani village in the room with the bridge, bug #3040565
+ { GID_QFG4, -1, 15, -1, "charInitScreen", "dispatchEvent", -1, 5, { WORKAROUND_FAKE, 0 } }, // floppy version, when viewing the character screen
+ { GID_QFG4, -1, 64917, -1, "controlPlane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, when entering the game menu
+ { GID_QFG4, -1, 64917, -1, "Plane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, happen sometimes in fights
+ { GID_SQ1, 103, 103, 0, "hand", "internalEvent", -1, -1, { WORKAROUND_FAKE, 0 } }, // Spanish (and maybe early versions?) only: when moving cursor over input pad, temps 1 and 2
+ { GID_SQ1, -1, 703, 0, "", "export 1", -1, 0, { WORKAROUND_FAKE, 0 } }, // sub that's called from several objects while on sarien battle cruiser
+ { GID_SQ1, -1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { WORKAROUND_FAKE, 0 } }, // export 1, but called locally (when shooting at aliens)
+ { GID_SQ4, -1, 398, 0, "showBox", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // sq4cd: called when rummaging in Software Excess bargain bin
+ { GID_SQ4, -1, 928, 0, "Narrator", "startText", -1, 1000, { WORKAROUND_FAKE, 1 } }, // sq4cd: method returns this to the caller
+ { GID_SQ5, 201, 201, 0, "buttonPanel", "doVerb", -1, 0, { WORKAROUND_FAKE, 1 } }, // when looking at the orange or red button - bug #3038563
+ { GID_SQ6, 100, 0, 0, "SQ6", "init", -1, 2, { WORKAROUND_FAKE, 0 } }, // called when the game starts
+ { GID_SQ6, 100, 64950, 0, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu
+ { GID_SQ6, -1, 64964, 0, "DPath", "init", -1, 1, { WORKAROUND_FAKE, 0 } }, // during the game
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kAbs_workarounds[] = {
+ { GID_HOYLE1, 1, 1, 0, "room1", "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // crazy eights - called with objects instead of integers
+ { GID_HOYLE1, 2, 2, 0, "room2", "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // old maid - called with objects instead of integers
+ { GID_HOYLE1, 3, 3, 0, "room3", "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // hearts - called with objects instead of integers
+ { GID_QFG1VGA, -1, -1, 0, NULL, "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // when the game is patched with the NRS patch
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kCelHigh_workarounds[] = {
+ { GID_KQ5, -1, 255, 0, "deathIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when getting beaten up in the inn and probably more, called with 2nd parameter as object - bug #3037003
+ { GID_PQ2, -1, 255, 0, "DIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when showing picture within windows, called with 2nd/3rd parameters as objects
+ { GID_SQ1, 1, 255, 0, "DIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // DEMO: Called with 2nd/3rd parameters as objects when clicking on the menu - bug #3035720
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kCelWide_workarounds[] = {
+ { GID_KQ5, -1, 255, 0, "deathIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when getting beaten up in the inn and probably more, called with 2nd parameter as object - bug #3037003
+ { GID_PQ2, -1, 255, 0, "DIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when showing picture within windows, called with 2nd/3rd parameters as objects
+ { GID_SQ1, 1, 255, 0, "DIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // DEMO: Called with 2nd/3rd parameters as objects when clicking on the menu - bug #3035720
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kDeviceInfo_workarounds[] = {
+ { GID_FANMADE, -1, 994, 1, "Game", "save", 0xd1c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Cascade Quest)
+ { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe55, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Demo Quest)
+ { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe57, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (I Want My C64 Back)
+ { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe5c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Most of them)
+ { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xd1c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Cascade Quest)
+ { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe55, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Demo Quest)
+ { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe57, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (I Want My C64 Back)
+ { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe5c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Most of them)
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kDisplay_workarounds[] = {
+ { GID_ISLANDBRAIN, 300, 300, 0, "geneDude", "show", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the gene explanation chart - a parameter is an object
+ { GID_PQ2, 23, 23, 0, "rm23Script", "elements", 0x4ae, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id
+ { GID_QFG1, 11, 11, 0, "battle", "<noname90>", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When entering battle, 0x75 as id
+ { GID_SQ4, 391, 391, 0, "doCatalog", "mode", 0x84, 0, { WORKAROUND_IGNORE, 0 } }, // clicking on catalog in roboter sale - a parameter is an object
+ { GID_SQ4, 391, 391, 0, "choosePlug", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // ordering connector in roboter sale - a parameter is an object
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kDisposeScript_workarounds[] = {
+ { GID_LAURABOW, 777, 777, 0, "myStab", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the will is signed, parameter 0 is an object - bug #3034907
+ { GID_QFG1, -1, 64, 0, "rm64", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving graveyard, parameter 0 is an object
+ { GID_SQ4, 150, 151, 0, "fightScript", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during fight with vohaul, parameter 0 is an object
+ { GID_SQ4, 150, 152, 0, "driveCloseUp", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download", parameter 0 is an object
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kDoSoundFade_workarounds[] = {
+ { GID_CAMELOT, -1, 989, 0, "rmMusic", "fade", -1, 0, { WORKAROUND_IGNORE, 0 } }, // gets called frequently with a NULL reference (i.e. 0:0) - bug #3035149
+ { GID_KQ1, -1, 989, 0, "gameSound", "fade", -1, 0, { WORKAROUND_IGNORE, 0 } }, // gets called in several scenes (e.g. graham cracker) with 0:0
+ { GID_KQ4, -1, 989, 0, "mySound", "", -1, 0, { WORKAROUND_IGNORE, 0 } }, // gets called in the demo when trying to open the non-existent menu with 0:0 - bug #3036942
+ { GID_KQ5, 213, 989, 0, "globalSound3", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when bandits leave the secret temple, parameter 4 is an object - bug #3037594
+ { GID_KQ6, 105, 989, 0, "globalSound", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // floppy: during intro, parameter 4 is an object
+ { GID_KQ6, 460, 989, 0, "globalSound2", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // after pulling the black widow's web on the isle of wonder, parameter 4 is an object - bug #3034567
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kGetAngle_workarounds[] = {
+ { GID_FANMADE, 516, 992, 0, "Motion", "init", -1, 0, { WORKAROUND_IGNORE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with third/fourth parameters as objects
+ { GID_KQ6, -1, 752, 0, "throwDazzle", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // room 740/790 after the Genie is exposed in the Palace (short and long ending), it starts shooting lightning bolts around. An extra 5th parameter is passed - bug #3034610 & #3041734
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kFindKey_workarounds[] = {
+ { GID_ECOQUEST2, 100, 999, 0, "myList", "contains", -1, 0, { WORKAROUND_FAKE, 0 } }, // When Noah Greene gives Adam the Ecorder, and just before the game gives a demonstration, a null reference to a list is passed - bug #3035186
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kGraphDrawLine_workarounds[] = {
+ { GID_ISLANDBRAIN, 300, 300, 0, "dudeViewer", "show", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when looking at the gene explanation chart, gets called with 1 extra parameter
+ { GID_SQ1, 43, 43, 0, "someoneDied", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when ordering beer, gets called with 1 extra parameter
+ { GID_SQ1, 71, 71, 0, "destroyXenon", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // during the Xenon destruction cutscene (which results in death), gets called with 1 extra parameter - bug #3040894
+ { GID_SQ1, 53, 53, 0, "blastEgo", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when Roger is found and zapped by the cleaning robot, gets called with 1 extra parameter - bug #3040905
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kGraphSaveBox_workarounds[] = {
+ { GID_CASTLEBRAIN, 420, 427, 0, "alienIcon", "select", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when selecting a card during the alien card game, gets called with 1 extra parameter
+ { GID_ISLANDBRAIN, 290, 291, 0, "upElevator", "changeState",0x201f, 0, { WORKAROUND_STILLCALL, 0 } }, // when testing in the elevator puzzle, gets called with 1 argument less - 15 is on stack - bug #3034485
+ { GID_ISLANDBRAIN, 290, 291, 0, "downElevator", "changeState",0x201f, 0, { WORKAROUND_STILLCALL, 0 } }, // see above
+ { GID_ISLANDBRAIN, 290, 291, 0, "correctElevator", "changeState",0x201f, 0, { WORKAROUND_STILLCALL, 0 } }, // see above (when testing the correct solution)
+ { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = {
+ { GID_LSL6, -1, 85, 0, "rScroller", "hide", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when restoring (sometimes), same as the one below
+ { GID_LSL6, -1, 85, 0, "lScroller", "hide", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when restoring (sometimes), same as the one below
+ { GID_LSL6, -1, 86, 0, "LL6Inv", "show", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when restoring, is called with hunk segment, but hunk is not allocated at that time
+ // ^^ TODO: check, if this is really a script error or an issue with our restore code
+ { GID_LSL6, -1, 86, 0, "LL6Inv", "hide", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens during the game, gets called with 1 extra parameter
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kGraphFillBoxForeground_workarounds[] = {
+ { GID_LSL6, -1, 0, 0, "LSL6", "hideControls", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when giving the bungee key to merrily (room 240) and at least in room 650 too - gets called with additional 5th parameter
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = {
+ { GID_SQ4, -1, 818, 0, "iconTextSwitch", "show", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kGraphRedrawBox_workarounds[] = {
+ { GID_SQ4, 405, 405, 0, "swimAfterEgo", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified
+ { GID_SQ4, 406, 406, 0, "swimAndShoot", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified
+ { GID_SQ4, 410, 410, 0, "swimAfterEgo", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified
+ { GID_SQ4, 411, 411, 0, "swimAndShoot", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified
+ { GID_SQ4, -1, 704, 0, "shootEgo", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // When shot by Droid in Super Computer Maze (Rooms 500, 505, 510...) - accidental additional parameter specified
+ { GID_KQ5, -1, 981, 0, "myWindow", "dispose", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing any dialog box, accidental additional parameter specified - bug #3036331
+ { GID_KQ5, -1, 995, 0, "invW", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing the inventory window, accidental additional parameter specified
+ { GID_KQ5, -1, 995, 0, "", "export 0", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when opening the gem pouch, accidental additional parameter specified - bug #3039395
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kGraphUpdateBox_workarounds[] = {
+ { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077
+ { GID_PQ3, 202, 202, 0, "MapEdit", "addPt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kIsObject_workarounds[] = {
+ { GID_GK1, 50, 999, 0, "List", "eachElementDo", -1, 0, { WORKAROUND_FAKE, 0 } }, // GK1 demo, when asking Grace for messages it gets called with an invalid parameter (type "error") - bug #3034519
+ { GID_ISLANDBRAIN, -1, 999, 0, "List", "eachElementDo", -1, 0, { WORKAROUND_FAKE, 0 } }, // when going to the game options, choosing "Info" and selecting anything from the list, gets called with an invalid parameter (type "error") - bug #3035262
+ { GID_QFG3, -1, 999, 0, "List", "eachElementDo", -1, 0, { WORKAROUND_FAKE, 0 } }, // when asking for something, gets called with type error parameter
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kMemory_workarounds[] = {
+ { GID_LAURABOW2, -1, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // during the intro, when exiting the train, talking to Mr. Augustini, etc. - bug #3034490
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kNewWindow_workarounds[] = {
+ { GID_ECOQUEST, -1, 981, 0, "SysWindow", "<noname178>", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // EcoQuest 1 demo uses an in-between interpreter from SCI1 to SCI1.1. It's SCI1.1, but uses the SCI1 semantics for this call - bug #3035057
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[] = {
+ { GID_QFG4, 100, 100, 0, "doMovie", "<noname144>", -1, 0, { WORKAROUND_IGNORE, 0 } }, // after the Sierra logo, no flags are passed, thus the call is meaningless - bug #3034506
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kSetCursor_workarounds[] = {
+ { GID_KQ5, -1, 768, 0, "KQCursor", "init", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // CD: gets called with 4 additional "900d" parameters
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kSetPort_workarounds[] = {
+ { GID_LSL6, 740, 740, 0, "rm740", "drawPic", -1, 0, { WORKAROUND_IGNORE, 0 } }, // ending scene, is called with additional 3 (!) parameters
+ { GID_QFG3, 830, 830, 0, "portalOpens", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when the portal appears during the end, bug #3040844
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kStrAt_workarounds[] = {
+ { GID_CASTLEBRAIN, 220, 220, 0, "robotJokes", "animateOnce", -1, 0, { WORKAROUND_FAKE, 0 } }, // when trying to view the terminal at the end of the maze without having collected any robot jokes - bug #3039036
+ { GID_ISLANDBRAIN, 300, 310, 0, "childBreed", "changeState",0x1c7c, 0, { WORKAROUND_FAKE, 0 } }, // when clicking Breed to get the second-generation cyborg hybrid (Standard difficulty), the two parameters are swapped - bug #3037835
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kUnLoad_workarounds[] = {
+ { GID_CAMELOT, 921, 921, 1, "Script", "changeState", 0x36, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: While showing Camelot (and other places), the reference is invalid - bug #3035000
+ { GID_CAMELOT, 921, 921, 1, "Script", "init", 0x36, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When being attacked by the boar (and other places), the reference is invalid - bug #3035000
+ { GID_CASTLEBRAIN, 320, 377, 0, "SWord", "upDate", -1, 0, { WORKAROUND_IGNORE, 0 } }, // after solving the cross-word-puzzle, trying to unload invalid reference
+ { GID_CASTLEBRAIN, 320, 377, 0, "theWord", "show", -1, 0, { WORKAROUND_IGNORE, 0 } }, // 2nd word puzzle, when exiting before solving, trying to unload invalid reference - bug #3034473
+ { GID_ECOQUEST, 380, 61, 0, "gotIt", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // after talking to the dolphin the first time
+ { GID_LAURABOW2, 1, 1, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #3034902
+ { GID_LAURABOW2, 2, 2, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #3034902
+ { GID_LAURABOW2, 4, 4, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: inside the museum, a 3rd parameter is passed by accident - bug #3034902
+ { GID_LAURABOW2, 6, 6, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the murder, a 3rd parameter is passed by accident - bug #3034902
+ { GID_LAURABOW2, 7, 7, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the logo is shown, a 3rd parameter is passed by accident - bug #3034902
+ { GID_LSL6, 130, 130, 0, "recruitLarryScr", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident
+ { GID_LSL6, 740, 740, 0, "showCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during ending, 4 additional parameters are passed by accident
+ { GID_LSL6HIRES, 130, 130, 0, "recruitLarryScr", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident
+ { GID_PQ3, 877, 998, 0, "View", "delete", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when getting run over on the freeway, the reference is invalid
+ { GID_SQ1, 43, 303, 0, "slotGuy", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciTrackOriginReply *trackOrigin) {
+ EngineState *state = g_sci->getEngineState();
+ ExecStack *lastCall = state->xs;
+ Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment);
+ int curScriptNr = local_script->getScriptNumber();
+
+ if (lastCall->debugLocalCallOffset != -1) {
+ // if lastcall was actually a local call search back for a real call
+ Common::List<ExecStack>::iterator callIterator = state->_executionStack.end();
+ while (callIterator != state->_executionStack.begin()) {
+ callIterator--;
+ ExecStack loopCall = *callIterator;
+ if ((loopCall.debugSelector != -1) || (loopCall.debugExportId != -1)) {
+ lastCall->debugSelector = loopCall.debugSelector;
+ lastCall->debugExportId = loopCall.debugExportId;
+ break;
+ }
+ }
+ }
+
+ Common::String curObjectName = state->_segMan->getObjectName(lastCall->sendp);
+ Common::String curMethodName;
+ const SciGameId gameId = g_sci->getGameId();
+ const int curRoomNumber = state->currentRoomNumber();
+
+ if (lastCall->type == EXEC_STACK_TYPE_CALL) {
+ if (lastCall->debugSelector != -1) {
+ curMethodName = g_sci->getKernel()->getSelectorName(lastCall->debugSelector);
+ } else if (lastCall->debugExportId != -1) {
+ curObjectName = "";
+ curMethodName = curMethodName.printf("export %d", lastCall->debugExportId);
+ }
+ }
+
+ if (workaroundList) {
+ // Search if there is a workaround for this one
+ const SciWorkaroundEntry *workaround;
+ int16 inheritanceLevel = 0;
+ Common::String searchObjectName = curObjectName;
+ reg_t searchObject = lastCall->sendp;
+ do {
+ workaround = workaroundList;
+ while (workaround->methodName) {
+ if (workaround->gameId == gameId
+ && ((workaround->scriptNr == -1) || (workaround->scriptNr == curScriptNr))
+ && ((workaround->roomNr == -1) || (workaround->roomNr == curRoomNumber))
+ && ((workaround->inheritanceLevel == -1) || (workaround->inheritanceLevel == inheritanceLevel))
+ && ((workaround->objectName == NULL) || (workaround->objectName == searchObjectName))
+ && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->debugLocalCallOffset
+ && ((workaround->index == -1) || (workaround->index == index))) {
+ // Workaround found
+ return workaround->newValue;
+ }
+ workaround++;
+ }
+
+ // Go back to the parent
+ inheritanceLevel++;
+ searchObject = state->_segMan->getObject(searchObject)->getSuperClassSelector();
+ if (!searchObject.isNull())
+ searchObjectName = state->_segMan->getObjectName(searchObject);
+ } while (!searchObject.isNull()); // no parent left?
+ }
+
+ // give caller origin data
+ trackOrigin->objectName = curObjectName;
+ trackOrigin->methodName = curMethodName;
+ trackOrigin->scriptNr = curScriptNr;
+ trackOrigin->localCallOffset = lastCall->debugLocalCallOffset;
+
+ SciWorkaroundSolution noneFound;
+ noneFound.type = WORKAROUND_NONE;
+ noneFound.value = 0;
+ return noneFound;
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h
new file mode 100644
index 0000000000..220ffd7fda
--- /dev/null
+++ b/engines/sci/engine/workarounds.h
@@ -0,0 +1,109 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 SCI_ENGINE_WORKAROUNDS_H
+#define SCI_ENGINE_WORKAROUNDS_H
+
+#include "sci/engine/vm_types.h"
+#include "sci/sci.h"
+
+namespace Sci {
+
+enum SciWorkaroundType {
+ WORKAROUND_NONE, // only used by terminator or when no workaround was found
+ WORKAROUND_IGNORE, // ignore kernel call
+ WORKAROUND_STILLCALL, // still do kernel call
+ WORKAROUND_FAKE // fake kernel call / replace temp value / fake opcode
+};
+
+struct SciTrackOriginReply {
+ int scriptNr;
+ Common::String objectName;
+ Common::String methodName;
+ int localCallOffset;
+};
+
+struct SciWorkaroundSolution {
+ SciWorkaroundType type;
+ uint16 value;
+};
+
+/**
+ * A structure describing a 'workaround' for a SCI script bug.
+ *
+ * Arrays of SciWorkaroundEntry instances are terminated by
+ * a fake entry in which "objectName" is NULL.
+ */
+struct SciWorkaroundEntry {
+ SciGameId gameId;
+ int roomNr;
+ int scriptNr;
+ int16 inheritanceLevel;
+ const char *objectName;
+ const char *methodName;
+ int localCallOffset;
+ int index;
+ SciWorkaroundSolution newValue;
+};
+
+extern const SciWorkaroundEntry opcodeDivWorkarounds[];
+extern const SciWorkaroundEntry opcodeDptoaWorkarounds[];
+extern const SciWorkaroundEntry opcodeGeWorkarounds[];
+extern const SciWorkaroundEntry opcodeLeWorkarounds[];
+extern const SciWorkaroundEntry opcodeLsiWorkarounds[];
+extern const SciWorkaroundEntry opcodeMulWorkarounds[];
+extern const SciWorkaroundEntry opcodeAndWorkarounds[];
+extern const SciWorkaroundEntry opcodeOrWorkarounds[];
+extern const SciWorkaroundEntry uninitializedReadWorkarounds[];
+extern const SciWorkaroundEntry kAbs_workarounds[];
+extern const SciWorkaroundEntry kCelHigh_workarounds[];
+extern const SciWorkaroundEntry kCelWide_workarounds[];
+extern const SciWorkaroundEntry kDeviceInfo_workarounds[];
+extern const SciWorkaroundEntry kDisplay_workarounds[];
+extern const SciWorkaroundEntry kDisposeScript_workarounds[];
+extern const SciWorkaroundEntry kDoSoundFade_workarounds[];
+extern const SciWorkaroundEntry kFindKey_workarounds[];
+extern const SciWorkaroundEntry kGetAngle_workarounds[];
+extern const SciWorkaroundEntry kGraphDrawLine_workarounds[];
+extern const SciWorkaroundEntry kGraphSaveBox_workarounds[];
+extern const SciWorkaroundEntry kGraphRestoreBox_workarounds[];
+extern const SciWorkaroundEntry kGraphUpdateBox_workarounds[];
+extern const SciWorkaroundEntry kGraphFillBoxForeground_workarounds[];
+extern const SciWorkaroundEntry kGraphFillBoxAny_workarounds[];
+extern const SciWorkaroundEntry kGraphRedrawBox_workarounds[];
+extern const SciWorkaroundEntry kIsObject_workarounds[];
+extern const SciWorkaroundEntry kMemory_workarounds[];
+extern const SciWorkaroundEntry kNewWindow_workarounds[];
+extern const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[];
+extern const SciWorkaroundEntry kSetCursor_workarounds[];
+extern const SciWorkaroundEntry kSetPort_workarounds[];
+extern const SciWorkaroundEntry kStrAt_workarounds[];
+extern const SciWorkaroundEntry kUnLoad_workarounds[];
+
+extern SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciTrackOriginReply *trackOrigin);
+
+} // End of namespace Sci
+
+#endif // SCI_ENGINE_WORKAROUNDS_H
diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp
index 53f4675f56..5923e501cf 100644
--- a/engines/sci/event.cpp
+++ b/engines/sci/event.cpp
@@ -25,6 +25,7 @@
#include "common/system.h"
#include "common/events.h"
+#include "common/file.h"
#include "sci/sci.h"
#include "sci/event.h"
@@ -34,33 +35,51 @@
namespace Sci {
-#define SCANCODE_ROWS_NR 3
+EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended), _modifierStates(0) {
-SciEvent::SciEvent(ResourceManager *resMan) {
- // Check, if font of current game includes extended chars
- _fontIsExtended = resMan->detectFontExtended();
+ if (getSciVersion() >= SCI_VERSION_1_MIDDLE) {
+ _usesNewKeyboardDirectionType = true;
+ } else if (getSciVersion() <= SCI_VERSION_01) {
+ _usesNewKeyboardDirectionType = false;
+ } else {
+ // they changed this somewhere inbetween SCI1EGA/EARLY
+ _usesNewKeyboardDirectionType = false;
+
+ // We are looking if script 933 exists, that one has the PseudoMouse class in it that handles it
+ // The good thing is that PseudoMouse seems to only exists in games that use the new method
+ if (g_sci->getResMan()->testResource(ResourceId(kResourceTypeScript, 933)))
+ _usesNewKeyboardDirectionType = true;
+ // Checking the keyboard driver size in here would also be a valid method, but the driver is only available
+ // in PC versions of the game
+ }
+}
+
+EventManager::~EventManager() {
}
-SciEvent::~SciEvent() {
+bool EventManager::getUsesNewKeyboardDirectionType() {
+ return _usesNewKeyboardDirectionType;
}
-struct scancode_row {
+struct ScancodeRow {
int offset;
const char *keys;
-} scancode_rows[SCANCODE_ROWS_NR] = {
+};
+
+static const ScancodeRow s_scancodeRows[] = {
{0x10, "QWERTYUIOP[]"},
{0x1e, "ASDFGHJKL;'\\"},
{0x2c, "ZXCVBNM,./"}
};
-int SciEvent::altify (int ch) {
+static int altify(int ch) {
// Calculates a PC keyboard scancode from a character */
int row;
int c = toupper((char)ch);
- for (row = 0; row < SCANCODE_ROWS_NR; row++) {
- const char *keys = scancode_rows[row].keys;
- int offset = scancode_rows[row].offset;
+ for (row = 0; row < ARRAYSIZE(s_scancodeRows); row++) {
+ const char *keys = s_scancodeRows[row].keys;
+ int offset = s_scancodeRows[row].offset;
while (*keys) {
if (*keys == c)
@@ -74,7 +93,8 @@ int SciEvent::altify (int ch) {
return ch;
}
-int SciEvent::numlockify (int c) {
+/*
+static int numlockify(int c) {
switch (c) {
case SCI_KEY_DELETE:
return '.';
@@ -102,6 +122,7 @@ int SciEvent::numlockify (int c) {
return c; // Unchanged
}
}
+*/
static const byte codepagemap_88591toDOS[0x80] = {
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0x8x
@@ -114,9 +135,8 @@ static const byte codepagemap_88591toDOS[0x80] = {
'?', 0xa4, 0x95, 0xa2, 0x93, '?', 0x94, '?', '?', 0x97, 0xa3, 0x96, 0x81, '?', '?', 0x98 // 0xFx
};
-sciEvent SciEvent::getFromScummVM() {
- static int _modifierStates = 0; // FIXME: Avoid non-const global vars
- sciEvent input = { SCI_EVENT_NONE, 0, 0, 0 };
+SciEvent EventManager::getScummVMEvent() {
+ SciEvent input = { SCI_EVENT_NONE, 0, 0, 0 };
Common::EventManager *em = g_system->getEventManager();
Common::Event ev;
@@ -293,6 +313,10 @@ sciEvent SciEvent::getFromScummVM() {
input.type = SCI_EVENT_MOUSE_PRESS;
input.data = 2;
break;
+ case Common::EVENT_MBUTTONDOWN:
+ input.type = SCI_EVENT_MOUSE_PRESS;
+ input.data = 3;
+ break;
case Common::EVENT_LBUTTONUP:
input.type = SCI_EVENT_MOUSE_RELEASE;
input.data = 1;
@@ -301,6 +325,10 @@ sciEvent SciEvent::getFromScummVM() {
input.type = SCI_EVENT_MOUSE_RELEASE;
input.data = 2;
break;
+ case Common::EVENT_MBUTTONUP:
+ input.type = SCI_EVENT_MOUSE_RELEASE;
+ input.data = 3;
+ break;
// Misc events
case Common::EVENT_QUIT:
@@ -315,24 +343,30 @@ sciEvent SciEvent::getFromScummVM() {
return input;
}
-sciEvent SciEvent::get(unsigned int mask) {
- //sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 };
- sciEvent event = { 0, 0, 0, 0 };
+void EventManager::updateScreen() {
+ // Update the screen here, since it's called very often.
+ // Throttle the screen update rate to 60fps.
+ if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) {
+ g_system->updateScreen();
+ g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis();
+ }
+}
- // TODO: we need to call Cursor::refreshPosition() before each screen update to limit the mouse cursor position
+SciEvent EventManager::getSciEvent(unsigned int mask) {
+ //sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 };
+ SciEvent event = { 0, 0, 0, 0 };
- // Update the screen here, since it's called very often
- g_system->updateScreen();
+ EventManager::updateScreen();
// Get all queued events from graphics driver
do {
- event = getFromScummVM();
+ event = getScummVMEvent();
if (event.type != SCI_EVENT_NONE)
_events.push_back(event);
} while (event.type != SCI_EVENT_NONE);
// Search for matching event in queue
- Common::List<sciEvent>::iterator iter = _events.begin();
+ Common::List<SciEvent>::iterator iter = _events.begin();
while (iter != _events.end() && !((*iter).type & mask))
++iter;
@@ -382,14 +416,13 @@ sciEvent SciEvent::get(unsigned int mask) {
return event;
}
-void SciEvent::sleep(uint32 msecs) {
+void SciEngine::sleep(uint32 msecs) {
uint32 time;
const uint32 wakeup_time = g_system->getMillis() + msecs;
while (true) {
// let backend process events and update the screen
- get(SCI_EVENT_PEEK);
- // TODO: we need to call Cursor::refreshPosition() before each screen update to limit the mouse cursor position
+ _eventMan->getSciEvent(SCI_EVENT_PEEK);
time = g_system->getMillis();
if (time + 10 < wakeup_time) {
g_system->delayMillis(10);
diff --git a/engines/sci/event.h b/engines/sci/event.h
index 9301b1ca09..fade7dd337 100644
--- a/engines/sci/event.h
+++ b/engines/sci/event.h
@@ -23,31 +23,29 @@
*
*/
-#ifndef SCI_ENGINE_EVENT_H
-#define SCI_ENGINE_EVENT_H
+#ifndef SCI_EVENT_H
+#define SCI_EVENT_H
#include "common/list.h"
namespace Sci {
-#define SCI_INPUT_DEFAULT_CLOCKTIME 100000
-#define SCI_INPUT_DEFAULT_REDRAWTIME 30000
-
-
-struct sciEvent {
+struct SciEvent {
short type;
short data;
short modifiers;
- short character; /* for keyboard events: 'data' after applying
- ** the effects of 'modifiers', e.g. if
- ** type == SCI_EVT_KEYBOARD
- ** data == 'a'
- ** buckybits == SCI_EVM_LSHIFT
- ** then
- ** character == 'A'
- ** For 'Alt', characters are interpreted by their
- ** PC keyboard scancodes.
- */
+ /**
+ * For keyboard events: 'data' after applying
+ * the effects of 'modifiers', e.g. if
+ * type == SCI_EVT_KEYBOARD
+ * data == 'a'
+ * buckybits == SCI_EVM_LSHIFT
+ * then
+ * character == 'A'
+ * For 'Alt', characters are interpreted by their
+ * PC keyboard scancodes.
+ */
+ short character;
};
/*Values for type*/
@@ -55,7 +53,7 @@ struct sciEvent {
#define SCI_EVENT_MOUSE_PRESS (1<<0)
#define SCI_EVENT_MOUSE_RELEASE (1<<1)
#define SCI_EVENT_KEYBOARD (1<<2)
-#define SCI_EVENT_JOYSTICK (1<<6)
+#define SCI_EVENT_DIRECTION (1<<6)
#define SCI_EVENT_SAID (1<<7)
/*Fake values for other events*/
#define SCI_EVENT_ERROR (1<<10)
@@ -111,25 +109,23 @@ struct sciEvent {
#define SCI_KEYMOD_NO_FOOLOCK (~(SCI_KEYMOD_SCRLOCK | SCI_KEYMOD_NUMLOCK | SCI_KEYMOD_CAPSLOCK | SCI_KEYMOD_INSERT))
#define SCI_KEYMOD_ALL 0xFF
-class SciEvent {
+class EventManager {
public:
- SciEvent(ResourceManager *resMgr);
- ~SciEvent();
-
- sciEvent get(unsigned int mask);
+ EventManager(bool fontIsExtended);
+ ~EventManager();
- void sleep(uint32 msecs);
+ void updateScreen();
+ SciEvent getSciEvent(unsigned int mask);
+ bool getUsesNewKeyboardDirectionType();
private:
- int altify (int ch);
- int shiftify (int c);
- int numlockify (int c);
- sciEvent getFromScummVM();
+ SciEvent getScummVMEvent();
- ResourceManager *_resMan;
+ const bool _fontIsExtended;
+ int _modifierStates;
+ Common::List<SciEvent> _events;
- bool _fontIsExtended;
- Common::List<sciEvent> _events;
+ bool _usesNewKeyboardDirectionType;
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp
index 71c7b7dd7f..ab4362cda9 100644
--- a/engines/sci/graphics/animate.cpp
+++ b/engines/sci/graphics/animate.cpp
@@ -28,6 +28,8 @@
#include "graphics/primitives.h"
#include "sci/sci.h"
+#include "sci/event.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
#include "sci/engine/vm.h"
@@ -35,6 +37,7 @@
#include "sci/graphics/cursor.h"
#include "sci/graphics/ports.h"
#include "sci/graphics/paint16.h"
+#include "sci/graphics/palette.h"
#include "sci/graphics/view.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/transitions.h"
@@ -48,28 +51,25 @@ GfxAnimate::GfxAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, Gfx
}
GfxAnimate::~GfxAnimate() {
- free(_listData);
- free(_lastCastData);
}
void GfxAnimate::init() {
- _listData = NULL;
- _listCount = 0;
- _lastCastData = NULL;
- _lastCastCount = 0;
+ _lastCastData.clear();
_ignoreFastCast = false;
// fastCast object is not found in any SCI games prior SCI1
if (getSciVersion() <= SCI_VERSION_01)
_ignoreFastCast = true;
// Also if fastCast object exists at gamestartup, we can assume that the interpreter doesnt do kAnimate aborts
- // (found in larry 1)
- if (!_s->_segMan->findObjectByName("fastCast").isNull())
- _ignoreFastCast = true;
+ // (found in Larry 1)
+ if (getSciVersion() > SCI_VERSION_0_EARLY) {
+ if (!_s->_segMan->findObjectByName("fastCast").isNull())
+ _ignoreFastCast = true;
+ }
}
void GfxAnimate::disposeLastCast() {
- _lastCastCount = 0;
+ _lastCastData.clear();
}
bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) {
@@ -84,20 +84,27 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) {
if (!_ignoreFastCast) {
// Check if the game has a fastCast object set
// if we don't abort kAnimate processing, at least in kq5 there will be animation cels drawn into speech boxes.
- reg_t global84 = _s->script_000->_localsBlock->_locals[84];
-
- if (!global84.isNull()) {
- if (!strcmp(_s->_segMan->getObjectName(global84), "fastCast"))
+ if (!_s->variables[VAR_GLOBAL][84].isNull()) {
+ if (!strcmp(_s->_segMan->getObjectName(_s->variables[VAR_GLOBAL][84]), "fastCast"))
return false;
}
}
- signal = GET_SEL32V(_s->_segMan, curObject, SELECTOR(signal));
+ signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal));
if (!(signal & kSignalFrozen)) {
// Call .doit method of that object
- invoke_selector(_s, curObject, g_sci->getKernel()->_selectorCache.doit, kContinueOnInvalidSelector, argc, argv, 0);
- // Lookup node again, since the nodetable it was in may have been reallocated
- curNode = _s->_segMan->lookupNode(curAddress);
+ invokeSelector(_s, curObject, SELECTOR(doit), argc, argv, 0);
+
+ // If a game is being loaded, stop processing
+ if (_s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit())
+ return true; // Stop processing
+
+ // Lookup node again, since the nodetable it was in may have been reallocated.
+ // The node might have been deallocated at this point (e.g. LSL2, room 42),
+ // in which case the node reference will be null and the loop will stop below.
+ // If the node is deleted from kDeleteKey, it won't have a successor node, thus
+ // list processing will stop here (which is what SSCI does).
+ curNode = _s->_segMan->lookupNode(curAddress, false);
}
if (curNode) {
@@ -108,141 +115,163 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) {
return true;
}
-bool sortHelper(const AnimateEntry* entry1, const AnimateEntry* entry2) {
- return (entry1->y == entry2->y) ? (entry1->z < entry2->z) : (entry1->y < entry2->y);
+bool sortHelper(const AnimateEntry &entry1, const AnimateEntry &entry2) {
+ if (entry1.y == entry2.y) {
+ // if both y and z are the same, use the order we were given originally
+ // this is needed for special cases like iceman room 35
+ if (entry1.z == entry2.z)
+ return entry1.givenOrderNo < entry2.givenOrderNo;
+ else
+ return entry1.z < entry2.z;
+ }
+ return entry1.y < entry2.y;
}
void GfxAnimate::makeSortedList(List *list) {
reg_t curAddress = list->first;
Node *curNode = _s->_segMan->lookupNode(curAddress);
- reg_t curObject;
- AnimateEntry *listEntry;
- int16 listNr, listCount = 0;
-
- // Count the list entries
- while (curNode) {
- listCount++;
- curAddress = curNode->succ;
- curNode = _s->_segMan->lookupNode(curAddress);
- }
+ int16 listNr;
+ // Clear lists
_list.clear();
-
- // No entries -> exit immediately
- if (listCount == 0)
- return;
-
- // Adjust list size, if needed
- if ((_listData == NULL) || (_listCount < listCount)) {
- free(_listData);
- _listData = (AnimateEntry *)malloc(listCount * sizeof(AnimateEntry));
- if (!_listData)
- error("Could not allocate memory for _listData");
- _listCount = listCount;
-
- free(_lastCastData);
- _lastCastData = (AnimateEntry *)malloc(listCount * sizeof(AnimateEntry));
- if (!_lastCastData)
- error("Could not allocate memory for _lastCastData");
- _lastCastCount = 0;
- }
+ _lastCastData.clear();
// Fill the list
- curAddress = list->first;
- curNode = _s->_segMan->lookupNode(curAddress);
- listEntry = _listData;
- for (listNr = 0; listNr < listCount; listNr++) {
- curObject = curNode->value;
- listEntry->object = curObject;
+ for (listNr = 0; curNode != 0; listNr++) {
+ AnimateEntry listEntry;
+ const reg_t curObject = curNode->value;
+ listEntry.object = curObject;
// Get data from current object
- listEntry->viewId = GET_SEL32V(_s->_segMan, curObject, SELECTOR(view));
- listEntry->loopNo = GET_SEL32V(_s->_segMan, curObject, SELECTOR(loop));
- listEntry->celNo = GET_SEL32V(_s->_segMan, curObject, SELECTOR(cel));
- listEntry->paletteNo = GET_SEL32V(_s->_segMan, curObject, SELECTOR(palette));
- listEntry->x = GET_SEL32V(_s->_segMan, curObject, SELECTOR(x));
- listEntry->y = GET_SEL32V(_s->_segMan, curObject, SELECTOR(y));
- listEntry->z = GET_SEL32V(_s->_segMan, curObject, SELECTOR(z));
- listEntry->priority = GET_SEL32V(_s->_segMan, curObject, SELECTOR(priority));
- listEntry->signal = GET_SEL32V(_s->_segMan, curObject, SELECTOR(signal));
+ listEntry.givenOrderNo = listNr;
+ listEntry.viewId = readSelectorValue(_s->_segMan, curObject, SELECTOR(view));
+ listEntry.loopNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(loop));
+ listEntry.celNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(cel));
+ listEntry.paletteNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(palette));
+ listEntry.x = readSelectorValue(_s->_segMan, curObject, SELECTOR(x));
+ listEntry.y = readSelectorValue(_s->_segMan, curObject, SELECTOR(y));
+ listEntry.z = readSelectorValue(_s->_segMan, curObject, SELECTOR(z));
+ listEntry.priority = readSelectorValue(_s->_segMan, curObject, SELECTOR(priority));
+ listEntry.signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal));
if (getSciVersion() >= SCI_VERSION_1_1) {
// Cel scaling
- listEntry->scaleSignal = GET_SEL32V(_s->_segMan, curObject, SELECTOR(scaleSignal));
- if (listEntry->scaleSignal & kScaleSignalDoScaling) {
- listEntry->scaleX = GET_SEL32V(_s->_segMan, curObject, SELECTOR(scaleX));
- listEntry->scaleY = GET_SEL32V(_s->_segMan, curObject, SELECTOR(scaleY));
+ listEntry.scaleSignal = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleSignal));
+ if (listEntry.scaleSignal & kScaleSignalDoScaling) {
+ listEntry.scaleX = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX));
+ listEntry.scaleY = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY));
} else {
- listEntry->scaleX = 128;
- listEntry->scaleY = 128;
+ listEntry.scaleX = 128;
+ listEntry.scaleY = 128;
}
- // TODO
- // On scaleSignal bit 1 sierra sci does some stuff with global var 2, current Port
- // and some other stuff and sets scaleX/Y accordingly. It seems this functionality is needed in at
- // least sq5 right when starting the game before wilco exists the room. Currently we dont get scaling
- // but sierra sci does scaling there. I dont fully understand the code yet, that's why i didnt implement
- // anything.
} else {
- listEntry->scaleSignal = 0;
- listEntry->scaleX = 128;
- listEntry->scaleY = 128;
+ listEntry.scaleSignal = 0;
+ listEntry.scaleX = 128;
+ listEntry.scaleY = 128;
}
- // listEntry->celRect is filled in AnimateFill()
- listEntry->showBitsFlag = false;
+ // listEntry.celRect is filled in AnimateFill()
+ listEntry.showBitsFlag = false;
_list.push_back(listEntry);
- listEntry++;
curAddress = curNode->succ;
curNode = _s->_segMan->lookupNode(curAddress);
}
+ // Possible TODO: As noted in the comment in sortHelper we actually
+ // require a stable sorting algorithm here. Since Common::sort is not stable
+ // at the time of writing this comment, we work around that in our ordering
+ // comparator. If that changes in the future or we want to use some
+ // stable sorting algorithm here, we should change that.
+ // In that case we should test such changes intensively. A good place to test stable sort
+ // is iceman, cupboard within the submarine. If sort isn't stable, the cupboard will be
+ // half-open, half-closed. Of course that's just one of many special cases.
+
// Now sort the list according y and z (descending)
Common::sort(_list.begin(), _list.end(), sortHelper);
}
void GfxAnimate::fill(byte &old_picNotValid) {
reg_t curObject;
- AnimateEntry *listEntry;
uint16 signal;
GfxView *view = NULL;
- AnimateList::iterator listIterator;
- AnimateList::iterator listEnd = _list.end();
+ AnimateList::iterator it;
+ const AnimateList::iterator end = _list.end();
- listIterator = _list.begin();
- while (listIterator != listEnd) {
- listEntry = *listIterator;
- curObject = listEntry->object;
+ for (it = _list.begin(); it != end; ++it) {
+ curObject = it->object;
+ signal = it->signal;
// Get the corresponding view
- view = _cache->getView(listEntry->viewId);
+ view = _cache->getView(it->viewId);
// adjust loop and cel, if any of those is invalid
- if (listEntry->loopNo >= view->getLoopCount()) {
- listEntry->loopNo = 0;
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(loop), listEntry->loopNo);
+ if (it->loopNo >= view->getLoopCount()) {
+ it->loopNo = 0;
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(loop), it->loopNo);
+ }
+ if (it->celNo >= view->getCelCount(it->loopNo)) {
+ it->celNo = 0;
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(cel), it->celNo);
+ }
+
+ // Process global scaling, if needed
+ if (it->scaleSignal & kScaleSignalDoScaling) {
+ if (it->scaleSignal & kScaleSignalGlobalScaling) {
+ // Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY
+ int16 maxScale = readSelectorValue(_s->_segMan, curObject, SELECTOR(maxScale));
+ int16 celHeight = view->getHeight(it->loopNo, it->celNo);
+ int16 maxCelHeight = (maxScale * celHeight) >> 7;
+ reg_t globalVar2 = _s->variables[VAR_GLOBAL][2]; // current room object
+ int16 vanishingY = readSelectorValue(_s->_segMan, globalVar2, SELECTOR(vanishingY));
+
+ int16 fixedPortY = _ports->getPort()->rect.bottom - vanishingY;
+ int16 fixedEntryY = it->y - vanishingY;
+ if (!fixedEntryY)
+ fixedEntryY = 1;
+
+ if ((celHeight == 0) || (fixedPortY == 0))
+ error("global scaling panic");
+
+ it->scaleY = ( maxCelHeight * fixedEntryY ) / fixedPortY;
+ it->scaleY = (it->scaleY * 128) / celHeight;
+
+ it->scaleX = it->scaleY;
+
+ // and set objects scale selectors
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX), it->scaleX);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY), it->scaleY);
+ }
}
- if (listEntry->celNo >= view->getCelCount(listEntry->loopNo)) {
- listEntry->celNo = 0;
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(cel), listEntry->celNo);
+
+ if (!view->isScaleable()) {
+ // Laura Bow 2 (especially floppy) depends on this, some views are not supposed to be scaleable
+ // this "feature" was removed in later versions of SCI1.1
+ it->scaleSignal = 0;
+ it->scaleY = it->scaleX = 128;
}
+ bool setNsRect = true;
+
// Create rect according to coordinates and given cel
- if (listEntry->scaleSignal & kScaleSignalDoScaling) {
- view->getCelScaledRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, listEntry->scaleX, listEntry->scaleY, &listEntry->celRect);
+ if (it->scaleSignal & kScaleSignalDoScaling) {
+ view->getCelScaledRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->scaleX, it->scaleY, it->celRect);
+ // when being scaled, only set nsRect, if object will get drawn
+ if ((signal & kSignalHidden) && !(signal & kSignalAlwaysUpdate))
+ setNsRect = false;
} else {
- view->getCelRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, &listEntry->celRect);
+ view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
+ }
+ if (setNsRect) {
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft), it->celRect.left);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop), it->celRect.top);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsRight), it->celRect.right);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsBottom), it->celRect.bottom);
}
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(nsLeft), listEntry->celRect.left);
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(nsTop), listEntry->celRect.top);
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(nsRight), listEntry->celRect.right);
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(nsBottom), listEntry->celRect.bottom);
-
- signal = listEntry->signal;
// Calculate current priority according to y-coordinate
if (!(signal & kSignalFixedPriority)) {
- listEntry->priority = _ports->kernelCoordinateToPriority(listEntry->y);
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(priority), listEntry->priority);
+ it->priority = _ports->kernelCoordinateToPriority(it->y);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(priority), it->priority);
}
if (signal & kSignalNoUpdate) {
@@ -251,205 +280,182 @@ void GfxAnimate::fill(byte &old_picNotValid) {
|| (!(signal & kSignalHidden) && signal & kSignalRemoveView)
|| (signal & kSignalAlwaysUpdate))
old_picNotValid++;
- signal &= 0xFFFF ^ kSignalStopUpdate;
+ signal &= ~kSignalStopUpdate;
} else {
if (signal & kSignalStopUpdate || signal & kSignalAlwaysUpdate)
old_picNotValid++;
- signal &= 0xFFFF ^ kSignalForceUpdate;
+ signal &= ~kSignalForceUpdate;
}
- listEntry->signal = signal;
-
- listIterator++;
+ it->signal = signal;
}
}
void GfxAnimate::update() {
reg_t curObject;
- AnimateEntry *listEntry;
uint16 signal;
reg_t bitsHandle;
Common::Rect rect;
- AnimateList::iterator listIterator;
- AnimateList::iterator listBegin = _list.begin();
- AnimateList::iterator listEnd = _list.end();
+ AnimateList::iterator it;
+ const AnimateList::iterator end = _list.end();
// Remove all no-update cels, if requested
- listIterator = _list.reverse_begin();
- while (listIterator != listEnd) {
- listEntry = *listIterator;
- curObject = listEntry->object;
- signal = listEntry->signal;
+ for (it = _list.reverse_begin(); it != end; --it) {
+ curObject = it->object;
+ signal = it->signal;
if (signal & kSignalNoUpdate) {
if (!(signal & kSignalRemoveView)) {
- bitsHandle = GET_SEL32(_s->_segMan, curObject, SELECTOR(underBits));
+ bitsHandle = readSelector(_s->_segMan, curObject, SELECTOR(underBits));
if (_screen->_picNotValid != 1) {
_paint16->bitsRestore(bitsHandle);
- listEntry->showBitsFlag = true;
+ it->showBitsFlag = true;
} else {
_paint16->bitsFree(bitsHandle);
}
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(underBits), 0);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(underBits), 0);
}
- signal &= 0xFFFF ^ kSignalForceUpdate;
- signal &= signal & kSignalViewUpdated ? 0xFFFF ^ (kSignalViewUpdated | kSignalNoUpdate) : 0xFFFF;
+ signal &= ~kSignalForceUpdate;
+ if (signal & kSignalViewUpdated)
+ signal &= ~(kSignalViewUpdated | kSignalNoUpdate);
} else if (signal & kSignalStopUpdate) {
- signal = (signal & (0xFFFF ^ kSignalStopUpdate)) | kSignalNoUpdate;
+ signal &= ~kSignalStopUpdate;
+ signal |= kSignalNoUpdate;
}
- listEntry->signal = signal;
- listIterator--;
+ it->signal = signal;
}
// Draw always-update cels
- listIterator = listBegin;
- while (listIterator != listEnd) {
- listEntry = *listIterator;
- curObject = listEntry->object;
- signal = listEntry->signal;
+ for (it = _list.begin(); it != end; ++it) {
+ curObject = it->object;
+ signal = it->signal;
if (signal & kSignalAlwaysUpdate) {
// draw corresponding cel
- _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY);
- listEntry->showBitsFlag = true;
+ _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
+ it->showBitsFlag = true;
- signal &= 0xFFFF ^ (kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate);
+ signal &= ~(kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate);
if ((signal & kSignalIgnoreActor) == 0) {
- rect = listEntry->celRect;
- rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1);
+ rect = it->celRect;
+ rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, rect.top, rect.bottom - 1);
_paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
}
- listEntry->signal = signal;
+ it->signal = signal;
}
- listIterator++;
}
// Saving background for all NoUpdate-cels
- listIterator = listBegin;
- while (listIterator != listEnd) {
- listEntry = *listIterator;
- curObject = listEntry->object;
- signal = listEntry->signal;
+ for (it = _list.begin(); it != end; ++it) {
+ curObject = it->object;
+ signal = it->signal;
if (signal & kSignalNoUpdate) {
if (signal & kSignalHidden) {
signal |= kSignalRemoveView;
} else {
- signal &= 0xFFFF ^ kSignalRemoveView;
+ signal &= ~kSignalRemoveView;
if (signal & kSignalIgnoreActor)
- bitsHandle = _paint16->bitsSave(listEntry->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY);
+ bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY);
else
- bitsHandle = _paint16->bitsSave(listEntry->celRect, GFX_SCREEN_MASK_ALL);
- PUT_SEL32(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle);
+ bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_ALL);
+ writeSelector(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle);
}
- listEntry->signal = signal;
+ it->signal = signal;
}
- listIterator++;
}
// Draw NoUpdate cels
- listIterator = listBegin;
- while (listIterator != listEnd) {
- listEntry = *listIterator;
- curObject = listEntry->object;
- signal = listEntry->signal;
+ for (it = _list.begin(); it != end; ++it) {
+ curObject = it->object;
+ signal = it->signal;
if (signal & kSignalNoUpdate && !(signal & kSignalHidden)) {
// draw corresponding cel
- _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY);
- listEntry->showBitsFlag = true;
+ _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
+ it->showBitsFlag = true;
- if ((signal & kSignalIgnoreActor) == 0) {
- rect = listEntry->celRect;
- rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1);
+ if (!(signal & kSignalIgnoreActor)) {
+ rect = it->celRect;
+ rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, rect.top, rect.bottom - 1);
_paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
}
}
- listIterator++;
}
}
void GfxAnimate::drawCels() {
reg_t curObject;
- AnimateEntry *listEntry;
- AnimateEntry *lastCastEntry = _lastCastData;
uint16 signal;
reg_t bitsHandle;
- AnimateList::iterator listIterator;
- AnimateList::iterator listEnd = _list.end();
- _lastCastCount = 0;
+ AnimateList::iterator it;
+ const AnimateList::iterator end = _list.end();
+ _lastCastData.clear();
- listIterator = _list.begin();
- while (listIterator != listEnd) {
- listEntry = *listIterator;
- curObject = listEntry->object;
- signal = listEntry->signal;
+ for (it = _list.begin(); it != end; ++it) {
+ curObject = it->object;
+ signal = it->signal;
if (!(signal & (kSignalNoUpdate | kSignalHidden | kSignalAlwaysUpdate))) {
// Save background
- bitsHandle = _paint16->bitsSave(listEntry->celRect, GFX_SCREEN_MASK_ALL);
- PUT_SEL32(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle);
+ bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_ALL);
+ writeSelector(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle);
// draw corresponding cel
- _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY);
- listEntry->showBitsFlag = true;
+ _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
+ it->showBitsFlag = true;
if (signal & kSignalRemoveView) {
- signal &= 0xFFFF ^ kSignalRemoveView;
+ signal &= ~kSignalRemoveView;
}
- listEntry->signal = signal;
+ it->signal = signal;
// Remember that entry in lastCast
- memcpy(lastCastEntry, listEntry, sizeof(AnimateEntry));
- lastCastEntry++; _lastCastCount++;
+ _lastCastData.push_back(*it);
}
- listIterator++;
}
}
void GfxAnimate::updateScreen(byte oldPicNotValid) {
reg_t curObject;
- AnimateEntry *listEntry;
uint16 signal;
- AnimateList::iterator listIterator;
- AnimateList::iterator listEnd = _list.end();
+ AnimateList::iterator it;
+ const AnimateList::iterator end = _list.end();
Common::Rect lsRect;
Common::Rect workerRect;
- listIterator = _list.begin();
- while (listIterator != listEnd) {
- listEntry = *listIterator;
- curObject = listEntry->object;
- signal = listEntry->signal;
+ for (it = _list.begin(); it != end; ++it) {
+ curObject = it->object;
+ signal = it->signal;
- if (listEntry->showBitsFlag || !(signal & (kSignalRemoveView | kSignalNoUpdate) ||
+ if (it->showBitsFlag || !(signal & (kSignalRemoveView | kSignalNoUpdate) ||
(!(signal & kSignalRemoveView) && (signal & kSignalNoUpdate) && oldPicNotValid))) {
- lsRect.left = GET_SEL32V(_s->_segMan, curObject, SELECTOR(lsLeft));
- lsRect.top = GET_SEL32V(_s->_segMan, curObject, SELECTOR(lsTop));
- lsRect.right = GET_SEL32V(_s->_segMan, curObject, SELECTOR(lsRight));
- lsRect.bottom = GET_SEL32V(_s->_segMan, curObject, SELECTOR(lsBottom));
+ lsRect.left = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft));
+ lsRect.top = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop));
+ lsRect.right = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight));
+ lsRect.bottom = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom));
workerRect = lsRect;
- workerRect.clip(listEntry->celRect);
+ workerRect.clip(it->celRect);
if (!workerRect.isEmpty()) {
workerRect = lsRect;
- workerRect.extend(listEntry->celRect);
+ workerRect.extend(it->celRect);
} else {
_paint16->bitsShow(lsRect);
- workerRect = listEntry->celRect;
+ workerRect = it->celRect;
}
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(lsLeft), workerRect.left);
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(lsTop), workerRect.top);
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(lsRight), workerRect.right);
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(lsBottom), workerRect.bottom);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft), it->celRect.left);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop), it->celRect.top);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight), it->celRect.right);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom), it->celRect.bottom);
+ // may get used for debugging
+ //_paint16->frameRect(workerRect);
_paint16->bitsShow(workerRect);
if (signal & kSignalHidden) {
- listEntry->signal |= kSignalRemoveView;
+ it->signal |= kSignalRemoveView;
}
}
-
- listIterator++;
}
// use this for debug purposes
// _screen->copyToScreen();
@@ -457,64 +463,53 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) {
void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) {
reg_t curObject;
- AnimateEntry *listEntry;
uint16 signal;
- AnimateList::iterator listIterator;
- AnimateList::iterator listEnd = _list.end();
+ AnimateList::iterator it;
+ const AnimateList::iterator end = _list.end();
- // This has to be done in a separate loop. At least in sq1 some .dispose modifies FIXEDLOOP flag in signal for
- // another object. In that case we would overwrite the new signal with our version of the old signal
- listIterator = _list.begin();
- while (listIterator != listEnd) {
- listEntry = *listIterator;
- curObject = listEntry->object;
- signal = listEntry->signal;
+ // This has to be done in a separate loop. At least in sq1 some .dispose
+ // modifies FIXEDLOOP flag in signal for another object. In that case we
+ // would overwrite the new signal with our version of the old signal.
+ for (it = _list.begin(); it != end; ++it) {
+ curObject = it->object;
+ signal = it->signal;
// Finally update signal
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(signal), signal);
- listIterator++;
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(signal), signal);
}
- listIterator = _list.reverse_begin();
- while (listIterator != listEnd) {
- listEntry = *listIterator;
- curObject = listEntry->object;
- // We read out signal here again, this is not by accident but to ensure that we got an up-to-date signal
- signal = GET_SEL32V(_s->_segMan, curObject, SELECTOR(signal));
+ for (it = _list.reverse_begin(); it != end; --it) {
+ curObject = it->object;
+ // We read out signal here again, this is not by accident but to ensure
+ // that we got an up-to-date signal
+ signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal));
if ((signal & (kSignalNoUpdate | kSignalRemoveView)) == 0) {
- _paint16->bitsRestore(GET_SEL32(_s->_segMan, curObject, SELECTOR(underBits)));
- PUT_SEL32V(_s->_segMan, curObject, SELECTOR(underBits), 0);
+ _paint16->bitsRestore(readSelector(_s->_segMan, curObject, SELECTOR(underBits)));
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(underBits), 0);
}
if (signal & kSignalDisposeMe) {
// Call .delete_ method of that object
- invoke_selector(_s, curObject, g_sci->getKernel()->_selectorCache.delete_, kContinueOnInvalidSelector, argc, argv, 0);
+ invokeSelector(_s, curObject, SELECTOR(delete_), argc, argv, 0);
}
- listIterator--;
}
}
void GfxAnimate::reAnimate(Common::Rect rect) {
- AnimateEntry *lastCastEntry;
- uint16 lastCastCount;
-
- if (_lastCastCount > 0) {
- lastCastEntry = _lastCastData;
- lastCastCount = _lastCastCount;
- while (lastCastCount > 0) {
- lastCastEntry->castHandle = _paint16->bitsSave(lastCastEntry->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY);
- _paint16->drawCel(lastCastEntry->viewId, lastCastEntry->loopNo, lastCastEntry->celNo, lastCastEntry->celRect, lastCastEntry->priority, lastCastEntry->paletteNo, lastCastEntry->scaleX, lastCastEntry->scaleY);
- lastCastEntry++; lastCastCount--;
+ if (!_lastCastData.empty()) {
+ AnimateArray::iterator it;
+ AnimateArray::iterator end = _lastCastData.end();
+ for (it = _lastCastData.begin(); it != end; ++it) {
+ it->castHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY);
+ _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
}
_paint16->bitsShow(rect);
// restoring
- lastCastCount = _lastCastCount;
- while (lastCastCount > 0) {
- lastCastEntry--;
- _paint16->bitsRestore(lastCastEntry->castHandle);
- lastCastCount--;
+ while (it != _lastCastData.begin()) { // FIXME: HACK, this iterator use is not very safe
+ it--;
+ _paint16->bitsRestore(it->castHandle);
}
} else {
_paint16->bitsShow(rect);
@@ -523,43 +518,46 @@ void GfxAnimate::reAnimate(Common::Rect rect) {
void GfxAnimate::addToPicDrawCels() {
reg_t curObject;
- AnimateEntry *listEntry;
GfxView *view = NULL;
- AnimateList::iterator listIterator;
- AnimateList::iterator listEnd = _list.end();
+ AnimateList::iterator it;
+ const AnimateList::iterator end = _list.end();
- listIterator = _list.begin();
- while (listIterator != listEnd) {
- listEntry = *listIterator;
- curObject = listEntry->object;
+ for (it = _list.begin(); it != end; ++it) {
+ curObject = it->object;
- if (listEntry->priority == -1)
- listEntry->priority = _ports->kernelCoordinateToPriority(listEntry->y);
+ if (it->priority == -1)
+ it->priority = _ports->kernelCoordinateToPriority(it->y);
// Get the corresponding view
- view = _cache->getView(listEntry->viewId);
+ view = _cache->getView(it->viewId);
// Create rect according to coordinates and given cel
- view->getCelRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, &listEntry->celRect);
+ view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
// draw corresponding cel
- _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo);
- if ((listEntry->signal & kSignalIgnoreActor) == 0) {
- listEntry->celRect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, listEntry->celRect.top, listEntry->celRect.bottom - 1);
- _paint16->fillRect(listEntry->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
+ _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo);
+ if ((it->signal & kSignalIgnoreActor) == 0) {
+ it->celRect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, it->celRect.top, it->celRect.bottom - 1);
+ _paint16->fillRect(it->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
}
-
- listIterator++;
}
}
-void GfxAnimate::addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control) {
+void GfxAnimate::addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 x, int16 y, int16 priority, int16 control) {
GfxView *view = _cache->getView(viewId);
Common::Rect celRect;
+ if (priority == -1)
+ priority = _ports->kernelCoordinateToPriority(y);
+
// Create rect according to coordinates and given cel
- view->getCelRect(loopNo, celNo, leftPos, topPos, priority, &celRect);
+ view->getCelRect(loopNo, celNo, x, y, 0, celRect);
_paint16->drawCel(view, loopNo, celNo, celRect, priority, 0);
+
+ if (control != -1) {
+ celRect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(priority) - 1, celRect.top, celRect.bottom - 1);
+ _paint16->fillRect(celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, control);
+ }
}
@@ -575,14 +573,14 @@ void GfxAnimate::animateShowPic() {
_transitions->doit(picRect);
if (previousCursorState)
_cursor->kernelShow();
-
- // We set SCI1.1 priority band information here
- _ports->priorityBandsRecall();
}
void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t *argv) {
byte old_picNotValid = _screen->_picNotValid;
+ if (getSciVersion() >= SCI_VERSION_1_1)
+ _palette->palVaryUpdate();
+
if (listReference.isNull()) {
disposeLastCast();
if (_screen->_picNotValid)
@@ -597,6 +595,9 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t
if (cycle) {
if (!invoke(list, argc, argv))
return;
+
+ // Look up the list again, as it may have been modified
+ list = _s->_segMan->lookupList(listReference);
}
Port *oldPort = _ports->setPort((Port *)_ports->_picWind);
@@ -606,9 +607,9 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t
fill(old_picNotValid);
if (old_picNotValid) {
- // beginUpdate()/endUpdate() were introduced SCI1
- // calling those for SCI0 will work most of the time but breaks minor stuff like percentage bar of qfg1ega
- // at the character skill screen
+ // beginUpdate()/endUpdate() were introduced SCI1.
+ // Calling those for SCI0 will work most of the time but breaks minor
+ // stuff like percentage bar of qfg1ega at the character skill screen.
if (getSciVersion() >= SCI_VERSION_1_EGA)
_ports->beginUpdate(_ports->_picWind);
update();
@@ -624,10 +625,49 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t
updateScreen(old_picNotValid);
restoreAndDelete(argc, argv);
- if (getLastCastCount() > 1)
- _s->_throttleTrigger = true;
+ // We update the screen here as well, some scenes like EQ1 credits run w/o calling kGetEvent thus we wouldn't update
+ // screen at all
+ g_sci->getEventManager()->updateScreen();
_ports->setPort(oldPort);
+
+
+ // Now trigger speed throttler
+ switch (_lastCastData.size()) {
+ case 0:
+ // No entries drawn -> no speed throttler triggering
+ break;
+ case 1: {
+
+ // One entry drawn -> check if that entry was a speed benchmark view, if not enable speed throttler
+ AnimateEntry *onlyCast = &_lastCastData[0];
+ if ((onlyCast->viewId == 0) && (onlyCast->loopNo == 13) && (onlyCast->celNo == 0)) {
+ // this one is used by jones talkie
+ if ((onlyCast->celRect.height() == 8) && (onlyCast->celRect.width() == 8))
+ return;
+ }
+ // first loop and first cel used?
+ if ((onlyCast->loopNo == 0) && (onlyCast->celNo == 0)) {
+ // and that cel has a known speed benchmark resolution
+ int16 onlyHeight = onlyCast->celRect.height();
+ int16 onlyWidth = onlyCast->celRect.width();
+ if (((onlyWidth == 12) && (onlyHeight == 35)) || // regular benchmark view ("fred", "Speedy", "ego")
+ ((onlyWidth == 29) && (onlyHeight == 45)) || // King's Quest 5 french "fred"
+ ((onlyWidth == 1) && (onlyHeight == 1))) { // Laura Bow 2 Talkie
+ // check further that there is only one cel in that view
+ GfxView *onlyView = _cache->getView(onlyCast->viewId);
+ if ((onlyView->getLoopCount() == 1) && (onlyView->getCelCount(0)))
+ return;
+ }
+ }
+ _s->_throttleTrigger = true;
+ break;
+ }
+ default:
+ // More than 1 entry drawn -> time for speed throttling
+ _s->_throttleTrigger = true;
+ break;
+ }
}
void GfxAnimate::addToPicSetPicNotValid() {
@@ -652,9 +692,9 @@ void GfxAnimate::kernelAddToPicList(reg_t listReference, int argc, reg_t *argv)
addToPicSetPicNotValid();
}
-void GfxAnimate::kernelAddToPicView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control) {
+void GfxAnimate::kernelAddToPicView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 x, int16 y, int16 priority, int16 control) {
_ports->setPort((Port *)_ports->_picWind);
- addToPicDrawView(viewId, loopNo, celNo, leftPos, topPos, priority, control);
+ addToPicDrawView(viewId, loopNo, celNo, x, y, priority, control);
addToPicSetPicNotValid();
}
diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h
index 2cc59b1767..7e82187eed 100644
--- a/engines/sci/graphics/animate.h
+++ b/engines/sci/graphics/animate.h
@@ -40,7 +40,7 @@ enum ViewSignals {
kSignalAlwaysUpdate = 0x0020,
kSignalForceUpdate = 0x0040,
kSignalRemoveView = 0x0080,
- kSignalFrozen = 0x0100,
+ kSignalFrozen = 0x0100, // I got frozen today!!
kSignalExtraActor = 0x0200, // unused by us, defines all actors that may be included into the background if speed is too slow
kSignalHitObstacle = 0x0400, // used in the actor movement code by kDoBresen()
kSignalDoesntTurn = 0x0800, // used by _k_dirloop() to determine if an actor can turn or not
@@ -51,12 +51,13 @@ enum ViewSignals {
};
enum ViewScaleSignals {
- kScaleSignalDoScaling = 0x0001, // enables scaling when drawing that cel (involves scaleX and scaleY)
- kScaleSignalUnknown1 = 0x0002, // seems to do something with globalvar 2, sets scaleX/scaleY
- kScaleSignalUnknown2 = 0x0004 // really unknown
+ kScaleSignalDoScaling = 0x0001, // enables scaling when drawing that cel (involves scaleX and scaleY)
+ kScaleSignalGlobalScaling = 0x0002, // means that global scaling shall get applied on that cel (sets scaleX/scaleY)
+ kScaleSignalUnknown2 = 0x0004 // really unknown
};
struct AnimateEntry {
+ int16 givenOrderNo;
reg_t object;
GuiResourceId viewId;
int16 loopNo;
@@ -72,7 +73,8 @@ struct AnimateEntry {
bool showBitsFlag;
reg_t castHandle;
};
-typedef Common::List<AnimateEntry *> AnimateList;
+typedef Common::List<AnimateEntry> AnimateList;
+typedef Common::Array<AnimateEntry> AnimateArray;
class GfxCache;
class GfxCursor;
@@ -89,9 +91,6 @@ public:
GfxAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxPalette *palette, GfxCursor *cursor, GfxTransitions *transitions);
virtual ~GfxAnimate();
- // FIXME: Don't store EngineState
- void resetEngineState(EngineState *newState) { _s = newState; }
-
void disposeLastCast();
bool invoke(List *list, int argc, reg_t *argv);
void makeSortedList(List *list);
@@ -104,8 +103,6 @@ public:
void addToPicDrawCels();
void addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control);
- uint16 getLastCastCount() { return _lastCastCount; }
-
virtual void kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t *argv);
virtual void kernelAddToPicList(reg_t listReference, int argc, reg_t *argv);
virtual void kernelAddToPicView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control);
@@ -125,12 +122,8 @@ private:
GfxCursor *_cursor;
GfxTransitions *_transitions;
- uint16 _listCount;
- AnimateEntry *_listData;
AnimateList _list;
-
- uint16 _lastCastCount;
- AnimateEntry *_lastCastData;
+ AnimateArray _lastCastData;
bool _ignoreFastCast;
};
diff --git a/engines/sci/graphics/cache.cpp b/engines/sci/graphics/cache.cpp
index 81bdab80ea..25475c727f 100644
--- a/engines/sci/graphics/cache.cpp
+++ b/engines/sci/graphics/cache.cpp
@@ -90,11 +90,11 @@ GfxView *GfxCache::getView(GuiResourceId viewId) {
}
int16 GfxCache::kernelViewGetCelWidth(GuiResourceId viewId, int16 loopNo, int16 celNo) {
- return getView(viewId)->getCelInfo(loopNo, celNo)->width;
+ return getView(viewId)->getCelInfo(loopNo, celNo)->scriptWidth;
}
int16 GfxCache::kernelViewGetCelHeight(GuiResourceId viewId, int16 loopNo, int16 celNo) {
- return getView(viewId)->getCelInfo(loopNo, celNo)->height;
+ return getView(viewId)->getCelInfo(loopNo, celNo)->scriptHeight;
}
int16 GfxCache::kernelViewGetLoopCount(GuiResourceId viewId) {
@@ -102,7 +102,7 @@ int16 GfxCache::kernelViewGetLoopCount(GuiResourceId viewId) {
}
int16 GfxCache::kernelViewGetCelCount(GuiResourceId viewId, int16 loopNo) {
- return getView(viewId)->getLoopInfo(loopNo)->celCount;
+ return getView(viewId)->getCelCount(loopNo);
}
} // End of namespace Sci
diff --git a/engines/sci/graphics/cache.h b/engines/sci/graphics/cache.h
index 16ab1916d4..2e9a345230 100644
--- a/engines/sci/graphics/cache.h
+++ b/engines/sci/graphics/cache.h
@@ -26,8 +26,6 @@
#ifndef SCI_GRAPHICS_CACHE_H
#define SCI_GRAPHICS_CACHE_H
-#include "sci/graphics/gui.h"
-
#include "common/hashmap.h"
namespace Sci {
diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp
index 36dd2d4aed..1c961b2ad6 100644
--- a/engines/sci/graphics/compare.cpp
+++ b/engines/sci/graphics/compare.cpp
@@ -28,6 +28,7 @@
#include "graphics/primitives.h"
#include "sci/sci.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
#include "sci/graphics/compare.h"
@@ -69,7 +70,7 @@ uint16 GfxCompare::isOnControl(uint16 screenMask, const Common::Rect &rect) {
return result;
}
-bool GfxCompare::canBeHereCheckRectList(reg_t checkObject, const Common::Rect &checkRect, List *list) {
+reg_t GfxCompare::canBeHereCheckRectList(reg_t checkObject, const Common::Rect &checkRect, List *list) {
reg_t curAddress = list->first;
Node *curNode = _segMan->lookupNode(curAddress);
reg_t curObject;
@@ -79,12 +80,12 @@ bool GfxCompare::canBeHereCheckRectList(reg_t checkObject, const Common::Rect &c
while (curNode) {
curObject = curNode->value;
if (curObject != checkObject) {
- signal = GET_SEL32V(_segMan, curObject, SELECTOR(signal));
+ signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));
if ((signal & (kSignalIgnoreActor | kSignalRemoveView | kSignalNoUpdate)) == 0) {
- curRect.left = GET_SEL32V(_segMan, curObject, SELECTOR(brLeft));
- curRect.top = GET_SEL32V(_segMan, curObject, SELECTOR(brTop));
- curRect.right = GET_SEL32V(_segMan, curObject, SELECTOR(brRight));
- curRect.bottom = GET_SEL32V(_segMan, curObject, SELECTOR(brBottom));
+ curRect.left = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
+ curRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
+ curRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight));
+ curRect.bottom = readSelectorValue(_segMan, curObject, SELECTOR(brBottom));
// Check if curRect is within checkRect
// TODO: This check is slightly odd, because it means that a rect is not contained
// in itself. It may very well be that the original SCI engine did it just
@@ -95,14 +96,14 @@ bool GfxCompare::canBeHereCheckRectList(reg_t checkObject, const Common::Rect &c
curRect.left < checkRect.right &&
curRect.bottom > checkRect.top &&
curRect.top < checkRect.bottom) {
- return false;
+ return curObject;
}
}
}
curAddress = curNode->succ;
curNode = _segMan->lookupNode(curAddress);
}
- return true;
+ return NULL_REG;
}
uint16 GfxCompare::kernelOnControl(byte screenMask, const Common::Rect &rect) {
@@ -115,98 +116,150 @@ uint16 GfxCompare::kernelOnControl(byte screenMask, const Common::Rect &rect) {
void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
GfxView *view = NULL;
Common::Rect celRect(0, 0);
- GuiResourceId viewId = (GuiResourceId)GET_SEL32V(_segMan, objectReference, SELECTOR(view));
+ GuiResourceId viewId = (GuiResourceId)readSelectorValue(_segMan, objectReference, SELECTOR(view));
// HACK: Ignore invalid views for now (perhaps unimplemented text views?)
if (viewId == 0xFFFF) // invalid view
return;
- int16 loopNo = GET_SEL32V(_segMan, objectReference, SELECTOR(loop));
- int16 celNo = GET_SEL32V(_segMan, objectReference, SELECTOR(cel));
- int16 x = (int16)GET_SEL32V(_segMan, objectReference, SELECTOR(x));
- int16 y = (int16)GET_SEL32V(_segMan, objectReference, SELECTOR(y));
+ int16 loopNo = readSelectorValue(_segMan, objectReference, SELECTOR(loop));
+ int16 celNo = readSelectorValue(_segMan, objectReference, SELECTOR(cel));
+ int16 x = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(x));
+ int16 y = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(y));
int16 z = 0;
- if (_kernel->_selectorCache.z > -1)
- z = (int16)GET_SEL32V(_segMan, objectReference, SELECTOR(z));
+ if (SELECTOR(z) > -1)
+ z = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(z));
- // now get cel rectangle
view = _cache->getView(viewId);
- view->getCelRect(loopNo, celNo, x, y, z, &celRect);
- if (lookup_selector(_segMan, objectReference, _kernel->_selectorCache.nsTop, NULL, NULL) == kSelectorVariable) {
- PUT_SEL32V(_segMan, objectReference, SELECTOR(nsLeft), celRect.left);
- PUT_SEL32V(_segMan, objectReference, SELECTOR(nsRight), celRect.right);
- PUT_SEL32V(_segMan, objectReference, SELECTOR(nsTop), celRect.top);
- PUT_SEL32V(_segMan, objectReference, SELECTOR(nsBottom), celRect.bottom);
+#ifdef ENABLE_SCI32
+ switch (getSciVersion()) {
+ case SCI_VERSION_2:
+ if (view->isSci2Hires())
+ _screen->adjustToUpscaledCoordinates(y, x);
+ break;
+ case SCI_VERSION_2_1:
+ _coordAdjuster->fromScriptToDisplay(y, x);
+ break;
+ default:
+ break;
+ }
+#endif
+
+ view->getCelRect(loopNo, celNo, x, y, z, celRect);
+
+#ifdef ENABLE_SCI32
+ switch (getSciVersion()) {
+ case SCI_VERSION_2:
+ if (view->isSci2Hires()) {
+ _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
+ _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
+ }
+ break;
+ case SCI_VERSION_2_1: {
+ _coordAdjuster->fromDisplayToScript(celRect.top, celRect.left);
+ _coordAdjuster->fromDisplayToScript(celRect.bottom, celRect.right);
+ break;
+ }
+ default:
+ break;
+ }
+#endif
+
+ if (lookupSelector(_segMan, objectReference, SELECTOR(nsTop), NULL, NULL) == kSelectorVariable) {
+ writeSelectorValue(_segMan, objectReference, SELECTOR(nsLeft), celRect.left);
+ writeSelectorValue(_segMan, objectReference, SELECTOR(nsRight), celRect.right);
+ writeSelectorValue(_segMan, objectReference, SELECTOR(nsTop), celRect.top);
+ writeSelectorValue(_segMan, objectReference, SELECTOR(nsBottom), celRect.bottom);
}
}
-bool GfxCompare::kernelCanBeHere(reg_t curObject, reg_t listReference) {
+reg_t GfxCompare::kernelCanBeHere(reg_t curObject, reg_t listReference) {
Common::Rect checkRect;
Common::Rect adjustedRect;
uint16 signal, controlMask;
- bool result;
+ uint16 result;
- checkRect.left = GET_SEL32V(_segMan, curObject, SELECTOR(brLeft));
- checkRect.top = GET_SEL32V(_segMan, curObject, SELECTOR(brTop));
- checkRect.right = GET_SEL32V(_segMan, curObject, SELECTOR(brRight));
- checkRect.bottom = GET_SEL32V(_segMan, curObject, SELECTOR(brBottom));
+ checkRect.left = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
+ checkRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
+ checkRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight));
+ checkRect.bottom = readSelectorValue(_segMan, curObject, SELECTOR(brBottom));
if (!checkRect.isValidRect()) { // can occur in Iceman - HACK? TODO: is this really occuring in sierra sci? check this
warning("kCan(t)BeHere - invalid rect %d, %d -> %d, %d", checkRect.left, checkRect.top, checkRect.right, checkRect.bottom);
- return false;
+ return NULL_REG;
}
adjustedRect = _coordAdjuster->onControl(checkRect);
- signal = GET_SEL32V(_segMan, curObject, SELECTOR(signal));
- controlMask = GET_SEL32V(_segMan, curObject, SELECTOR(illegalBits));
- result = (isOnControl(GFX_SCREEN_MASK_CONTROL, adjustedRect) & controlMask) ? false : true;
- if ((result) && (signal & (kSignalIgnoreActor | kSignalRemoveView)) == 0) {
+ signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));
+ controlMask = readSelectorValue(_segMan, curObject, SELECTOR(illegalBits));
+ result = isOnControl(GFX_SCREEN_MASK_CONTROL, adjustedRect) & controlMask;
+ if ((!result) && (signal & (kSignalIgnoreActor | kSignalRemoveView)) == 0) {
List *list = _segMan->lookupList(listReference);
if (!list)
error("kCanBeHere called with non-list as parameter");
- result = canBeHereCheckRectList(curObject, checkRect, list);
+ return canBeHereCheckRectList(curObject, checkRect, list);
}
- return result;
+ return make_reg(0, result);
}
bool GfxCompare::kernelIsItSkip(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Point position) {
GfxView *tmpView = _cache->getView(viewId);
- CelInfo *celInfo = tmpView->getCelInfo(loopNo, celNo);
+ const CelInfo *celInfo = tmpView->getCelInfo(loopNo, celNo);
position.x = CLIP<int>(position.x, 0, celInfo->width - 1);
position.y = CLIP<int>(position.y, 0, celInfo->height - 1);
- byte *celData = tmpView->getBitmap(loopNo, celNo);
+ const byte *celData = tmpView->getBitmap(loopNo, celNo);
bool result = (celData[position.y * celInfo->width + position.x] == celInfo->clearKey);
return result;
}
void GfxCompare::kernelBaseSetter(reg_t object) {
- if (lookup_selector(_segMan, object, _kernel->_selectorCache.brLeft, NULL, NULL) == kSelectorVariable) {
- int16 x = GET_SEL32V(_segMan, object, SELECTOR(x));
- int16 y = GET_SEL32V(_segMan, object, SELECTOR(y));
- int16 z = (_kernel->_selectorCache.z > -1) ? GET_SEL32V(_segMan, object, SELECTOR(z)) : 0;
- int16 yStep = GET_SEL32V(_segMan, object, SELECTOR(yStep));
- GuiResourceId viewId = GET_SEL32V(_segMan, object, SELECTOR(view));
- int16 loopNo = GET_SEL32V(_segMan, object, SELECTOR(loop));
- int16 celNo = GET_SEL32V(_segMan, object, SELECTOR(cel));
+ if (lookupSelector(_segMan, object, SELECTOR(brLeft), NULL, NULL) == kSelectorVariable) {
+ int16 x = readSelectorValue(_segMan, object, SELECTOR(x));
+ int16 y = readSelectorValue(_segMan, object, SELECTOR(y));
+ int16 z = (SELECTOR(z) > -1) ? readSelectorValue(_segMan, object, SELECTOR(z)) : 0;
+ int16 yStep = readSelectorValue(_segMan, object, SELECTOR(yStep));
+ GuiResourceId viewId = readSelectorValue(_segMan, object, SELECTOR(view));
+ int16 loopNo = readSelectorValue(_segMan, object, SELECTOR(loop));
+ int16 celNo = readSelectorValue(_segMan, object, SELECTOR(cel));
// HACK: Ignore invalid views for now (perhaps unimplemented text views?)
if (viewId == 0xFFFF) // invalid view
return;
- GfxView *tmpView = _cache->getView(viewId);
+ uint16 scaleSignal = 0;
+ if (getSciVersion() >= SCI_VERSION_1_1) {
+ scaleSignal = readSelectorValue(_segMan, object, SELECTOR(scaleSignal));
+ }
+
Common::Rect celRect;
- tmpView->getCelRect(loopNo, celNo, x, y, z, &celRect);
+ GfxView *tmpView = _cache->getView(viewId);
+ if (tmpView->isSci2Hires())
+ _screen->adjustToUpscaledCoordinates(y, x);
+
+ if (scaleSignal & kScaleSignalDoScaling) {
+ int16 scaleX = readSelectorValue(_segMan, object, SELECTOR(scaleX));
+ int16 scaleY = readSelectorValue(_segMan, object, SELECTOR(scaleY));
+ tmpView->getCelScaledRect(loopNo, celNo, x, y, z, scaleX, scaleY, celRect);
+ } else {
+ tmpView->getCelRect(loopNo, celNo, x, y, z, celRect);
+ }
+
+ if (tmpView->isSci2Hires()) {
+ _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
+ _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
+ }
+
celRect.bottom = y + 1;
celRect.top = celRect.bottom - yStep;
- PUT_SEL32V(_segMan, object, SELECTOR(brLeft), celRect.left);
- PUT_SEL32V(_segMan, object, SELECTOR(brRight), celRect.right);
- PUT_SEL32V(_segMan, object, SELECTOR(brTop), celRect.top);
- PUT_SEL32V(_segMan, object, SELECTOR(brBottom), celRect.bottom);
+ writeSelectorValue(_segMan, object, SELECTOR(brLeft), celRect.left);
+ writeSelectorValue(_segMan, object, SELECTOR(brRight), celRect.right);
+ writeSelectorValue(_segMan, object, SELECTOR(brTop), celRect.top);
+ writeSelectorValue(_segMan, object, SELECTOR(brBottom), celRect.bottom);
}
}
diff --git a/engines/sci/graphics/compare.h b/engines/sci/graphics/compare.h
index 348d5ef723..1079f5f98c 100644
--- a/engines/sci/graphics/compare.h
+++ b/engines/sci/graphics/compare.h
@@ -26,8 +26,6 @@
#ifndef SCI_GRAPHICS_GFX_H
#define SCI_GRAPHICS_GFX_H
-#include "sci/graphics/gui.h"
-
#include "common/hashmap.h"
namespace Sci {
@@ -44,7 +42,7 @@ public:
uint16 kernelOnControl(byte screenMask, const Common::Rect &rect);
void kernelSetNowSeen(reg_t objectReference);
- bool kernelCanBeHere(reg_t curObject, reg_t listReference);
+ reg_t kernelCanBeHere(reg_t curObject, reg_t listReference);
bool kernelIsItSkip(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Point position);
void kernelBaseSetter(reg_t object);
@@ -62,7 +60,7 @@ private:
* *different* from checkObject, has a brRect which is contained inside
* checkRect.
*/
- bool canBeHereCheckRectList(reg_t checkObject, const Common::Rect &checkRect, List *list);
+ reg_t canBeHereCheckRectList(reg_t checkObject, const Common::Rect &checkRect, List *list);
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/controls.cpp b/engines/sci/graphics/controls.cpp
index f744d6e7f1..5891413be8 100644
--- a/engines/sci/graphics/controls.cpp
+++ b/engines/sci/graphics/controls.cpp
@@ -30,6 +30,7 @@
#include "sci/sci.h"
#include "sci/event.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
#include "sci/graphics/ports.h"
@@ -74,7 +75,9 @@ void GfxControls::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars,
// draw UP/DOWN arrows
// we draw UP arrow one pixel lower than sierra did, because it looks nicer. Also the DOWN arrow has one pixel
// line inbetween as well
- workerRect.top++;
+ // They "fixed" this in SQ4 by having the arrow character start one pixel line later, we don't adjust there
+ if (g_sci->getGameId() != GID_SQ4)
+ workerRect.top++;
_text16->Box(controlListUpArrow, 0, workerRect, SCI_TEXT16_ALIGNMENT_CENTER, 0);
workerRect.top = workerRect.bottom - 10;
_text16->Box(controlListDownArrow, 0, workerRect, SCI_TEXT16_ALIGNMENT_CENTER, 0);
@@ -88,7 +91,7 @@ void GfxControls::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars,
_text16->SetFont(fontId);
fontSize = _ports->_curPort->fontHeight;
_ports->penColor(_ports->_curPort->penClr); _ports->backColor(_ports->_curPort->backClr);
- workerRect.bottom = workerRect.top + 9;
+ workerRect.bottom = workerRect.top + fontSize;
lastYpos = rect.bottom - fontSize;
// Write actual text
@@ -143,9 +146,9 @@ void GfxControls::texteditSetBlinkTime() {
}
void GfxControls::kernelTexteditChange(reg_t controlObject, reg_t eventObject) {
- uint16 cursorPos = GET_SEL32V(_segMan, controlObject, SELECTOR(cursor));
- uint16 maxChars = GET_SEL32V(_segMan, controlObject, SELECTOR(max));
- reg_t textReference = GET_SEL32(_segMan, controlObject, SELECTOR(text));
+ uint16 cursorPos = readSelectorValue(_segMan, controlObject, SELECTOR(cursor));
+ uint16 maxChars = readSelectorValue(_segMan, controlObject, SELECTOR(max));
+ reg_t textReference = readSelector(_segMan, controlObject, SELECTOR(text));
Common::String text;
uint16 textSize, eventType, eventKey = 0;
bool textChanged = false;
@@ -158,14 +161,14 @@ void GfxControls::kernelTexteditChange(reg_t controlObject, reg_t eventObject) {
if (!eventObject.isNull()) {
textSize = text.size();
- eventType = GET_SEL32V(_segMan, eventObject, SELECTOR(type));
+ eventType = readSelectorValue(_segMan, eventObject, SELECTOR(type));
switch (eventType) {
case SCI_EVENT_MOUSE_PRESS:
// TODO: Implement mouse support for cursor change
break;
case SCI_EVENT_KEYBOARD:
- eventKey = GET_SEL32V(_segMan, eventObject, SELECTOR(message));
+ eventKey = readSelectorValue(_segMan, eventObject, SELECTOR(message));
switch (eventKey) {
case SCI_KEY_BACKSPACE:
if (cursorPos > 0) {
@@ -207,9 +210,9 @@ void GfxControls::kernelTexteditChange(reg_t controlObject, reg_t eventObject) {
if (textChanged) {
GuiResourceId oldFontId = _text16->GetFontId();
- GuiResourceId fontId = GET_SEL32V(_segMan, controlObject, SELECTOR(font));
- rect = Common::Rect(GET_SEL32V(_segMan, controlObject, SELECTOR(nsLeft)), GET_SEL32V(_segMan, controlObject, SELECTOR(nsTop)),
- GET_SEL32V(_segMan, controlObject, SELECTOR(nsRight)), GET_SEL32V(_segMan, controlObject, SELECTOR(nsBottom)));
+ GuiResourceId fontId = readSelectorValue(_segMan, controlObject, SELECTOR(font));
+ rect = Common::Rect(readSelectorValue(_segMan, controlObject, SELECTOR(nsLeft)), readSelectorValue(_segMan, controlObject, SELECTOR(nsTop)),
+ readSelectorValue(_segMan, controlObject, SELECTOR(nsRight)), readSelectorValue(_segMan, controlObject, SELECTOR(nsBottom)));
_text16->SetFont(fontId);
if (textAddChar) {
// We check, if we are really able to add the new char
@@ -241,7 +244,7 @@ void GfxControls::kernelTexteditChange(reg_t controlObject, reg_t eventObject) {
}
}
- PUT_SEL32V(_segMan, controlObject, SELECTOR(cursor), cursorPos);
+ writeSelectorValue(_segMan, controlObject, SELECTOR(cursor), cursorPos);
}
int GfxControls::getPicNotValid() {
diff --git a/engines/sci/graphics/coordadjuster.cpp b/engines/sci/graphics/coordadjuster.cpp
index 40ef655be7..bbeade87b5 100644
--- a/engines/sci/graphics/coordadjuster.cpp
+++ b/engines/sci/graphics/coordadjuster.cpp
@@ -26,10 +26,12 @@
#include "common/util.h"
#include "sci/sci.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/ports.h"
+#include "sci/graphics/screen.h"
namespace Sci {
@@ -87,32 +89,41 @@ Common::Rect GfxCoordAdjuster16::pictureGetDisplayArea() {
#ifdef ENABLE_SCI32
GfxCoordAdjuster32::GfxCoordAdjuster32(SegManager *segMan)
: _segMan(segMan) {
+ scriptsRunningWidth = 0;
+ scriptsRunningHeight = 0;
}
GfxCoordAdjuster32::~GfxCoordAdjuster32() {
}
void GfxCoordAdjuster32::kernelGlobalToLocal(int16 &x, int16 &y, reg_t planeObject) {
- //int16 resY = GET_SEL32V(_s->_segMan, planeObj, SELECTOR(resY));
- //int16 resX = GET_SEL32V(_s->_segMan, planeObj, SELECTOR(resX));
- //*x = ( *x * _screen->getWidth()) / resX;
- //*y = ( *y * _screen->getHeight()) / resY;
- x -= GET_SEL32V(_segMan, planeObject, SELECTOR(left));
- y -= GET_SEL32V(_segMan, planeObject, SELECTOR(top));
+ uint16 planeTop = readSelectorValue(_segMan, planeObject, SELECTOR(top));
+ uint16 planeLeft = readSelectorValue(_segMan, planeObject, SELECTOR(left));
+
+ y -= planeTop;
+ x -= planeLeft;
}
void GfxCoordAdjuster32::kernelLocalToGlobal(int16 &x, int16 &y, reg_t planeObject) {
- //int16 resY = GET_SEL32V(_s->_segMan, planeObj, SELECTOR(resY));
- //int16 resX = GET_SEL32V(_s->_segMan, planeObj, SELECTOR(resX));
- x += GET_SEL32V(_segMan, planeObject, SELECTOR(left));
- y += GET_SEL32V(_segMan, planeObject, SELECTOR(top));
- //*x = ( *x * resX) / _screen->getWidth();
- //*y = ( *y * resY) / _screen->getHeight();
+ uint16 planeTop = readSelectorValue(_segMan, planeObject, SELECTOR(top));
+ uint16 planeLeft = readSelectorValue(_segMan, planeObject, SELECTOR(left));
+
+ x += planeLeft;
+ y += planeTop;
}
-Common::Rect GfxCoordAdjuster32::onControl(Common::Rect rect) {
- Common::Rect adjustedRect = rect;
- adjustedRect.translate(0, 10);
- return adjustedRect;
+void GfxCoordAdjuster32::setScriptsResolution(uint16 width, uint16 height) {
+ scriptsRunningWidth = width;
+ scriptsRunningHeight = height;
+}
+
+void GfxCoordAdjuster32::fromDisplayToScript(int16 &y, int16 &x) {
+ y = ((y * scriptsRunningHeight) / g_sci->_gfxScreen->getHeight());
+ x = ((x * scriptsRunningWidth) / g_sci->_gfxScreen->getWidth());
+}
+
+void GfxCoordAdjuster32::fromScriptToDisplay(int16 &y, int16 &x) {
+ y = ((y * g_sci->_gfxScreen->getHeight()) / scriptsRunningHeight);
+ x = ((x * g_sci->_gfxScreen->getWidth()) / scriptsRunningWidth);
}
void GfxCoordAdjuster32::pictureSetDisplayArea(Common::Rect displayArea) {
diff --git a/engines/sci/graphics/coordadjuster.h b/engines/sci/graphics/coordadjuster.h
index 9b2bef48f1..59afd1dcb7 100644
--- a/engines/sci/graphics/coordadjuster.h
+++ b/engines/sci/graphics/coordadjuster.h
@@ -50,6 +50,10 @@ public:
virtual void setCursorPos(Common::Point &pos) { }
virtual void moveCursor(Common::Point &pos) { }
+ virtual void setScriptsResolution(uint16 width, uint16 height) { }
+ virtual void fromScriptToDisplay(int16 &y, int16 &x) { }
+ virtual void fromDisplayToScript(int16 &y, int16 &x) { }
+
virtual Common::Rect pictureGetDisplayArea() { return Common::Rect(0, 0); }
private:
};
@@ -83,7 +87,9 @@ public:
void kernelGlobalToLocal(int16 &x, int16 &y, reg_t planeObject = NULL_REG);
void kernelLocalToGlobal(int16 &x, int16 &y, reg_t planeObject = NULL_REG);
- Common::Rect onControl(Common::Rect rect);
+ void setScriptsResolution(uint16 width, uint16 height);
+ void fromScriptToDisplay(int16 &y, int16 &x);
+ void fromDisplayToScript(int16 &y, int16 &x);
void pictureSetDisplayArea(Common::Rect displayArea);
Common::Rect pictureGetDisplayArea();
@@ -92,6 +98,9 @@ private:
SegManager *_segMan;
Common::Rect _pictureDisplayArea;
+
+ uint16 scriptsRunningWidth;
+ uint16 scriptsRunningHeight;
};
#endif
diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp
index 2f8393f9ac..f6e2077cb3 100644
--- a/engines/sci/graphics/cursor.cpp
+++ b/engines/sci/graphics/cursor.cpp
@@ -43,18 +43,18 @@ GfxCursor::GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *sc
: _resMan(resMan), _palette(palette), _screen(screen) {
_upscaledHires = _screen->getUpscaledHires();
+ _isVisible = true;
+
// center mouse cursor
setPosition(Common::Point(_screen->getWidth() / 2, _screen->getHeight() / 2));
- kernelSetMoveZone(Common::Rect(0, 0, _screen->getDisplayWidth(), _screen->getDisplayHeight()));
-
- _isVisible = true;
+ _moveZoneActive = false;
}
GfxCursor::~GfxCursor() {
purgeCache();
}
-void GfxCursor::init(GfxCoordAdjuster *coordAdjuster, SciEvent *event) {
+void GfxCursor::init(GfxCoordAdjuster *coordAdjuster, EventManager *event) {
_coordAdjuster = coordAdjuster;
_event = event;
}
@@ -120,7 +120,7 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) {
colorMapping[0] = 0; // Black is hardcoded
colorMapping[1] = _screen->getColorWhite(); // White is also hardcoded
colorMapping[2] = SCI_CURSOR_SCI0_TRANSPARENCYCOLOR;
- colorMapping[3] = _palette->matchColor(&_palette->_sysPalette, 170, 170, 170); // Grey
+ colorMapping[3] = _palette->matchColor(170, 170, 170); // Grey
// Seek to actual data
resourceData += 4;
@@ -164,42 +164,39 @@ void GfxCursor::kernelSetView(GuiResourceId viewNum, int loopNum, int celNum, Co
GfxView *cursorView = _cachedCursors[viewNum];
- CelInfo *celInfo = cursorView->getCelInfo(loopNum, celNum);
+ const CelInfo *celInfo = cursorView->getCelInfo(loopNum, celNum);
int16 width = celInfo->width;
int16 height = celInfo->height;
byte clearKey = celInfo->clearKey;
Common::Point *cursorHotspot = hotspot;
- byte *cursorBitmap;
if (!cursorHotspot)
// Compute hotspot from xoffset/yoffset
cursorHotspot = new Common::Point((celInfo->width >> 1) - celInfo->displaceX, celInfo->height - celInfo->displaceY - 1);
- // Eco Quest 1 uses a 1x1 transparent cursor to hide the cursor from the user. Some scalers don't seem to support this
+ // Eco Quest 1 uses a 1x1 transparent cursor to hide the cursor from the
+ // user. Some scalers don't seem to support this
if (width < 2 || height < 2) {
kernelHide();
delete cursorHotspot;
return;
}
- celInfo->rawBitmap = cursorView->getBitmap(loopNum, celNum);
+ const byte *rawBitmap = cursorView->getBitmap(loopNum, celNum);
if (_upscaledHires) {
// Scale cursor by 2x - note: sierra didn't do this, but it looks much better
width *= 2;
height *= 2;
cursorHotspot->x *= 2;
cursorHotspot->y *= 2;
- cursorBitmap = new byte[width * height];
- _screen->scale2x(celInfo->rawBitmap, cursorBitmap, celInfo->width, celInfo->height);
+ byte *cursorBitmap = new byte[width * height];
+ _screen->scale2x(rawBitmap, cursorBitmap, celInfo->width, celInfo->height);
+ CursorMan.replaceCursor(cursorBitmap, width, height, cursorHotspot->x, cursorHotspot->y, clearKey);
+ delete[] cursorBitmap;
} else {
- cursorBitmap = celInfo->rawBitmap;
+ CursorMan.replaceCursor(rawBitmap, width, height, cursorHotspot->x, cursorHotspot->y, clearKey);
}
- CursorMan.replaceCursor(cursorBitmap, width, height, cursorHotspot->x, cursorHotspot->y, clearKey);
-
- if (_upscaledHires)
- delete[] cursorBitmap;
-
kernelShow();
delete cursorHotspot;
@@ -209,7 +206,7 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu
// See http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-402.html
// for more information.
- // View 998 seems to be a fake resource used to call for for the Mac CURS resources
+ // View 998 seems to be a fake resource used to call for the Mac CURS resources.
// For other resources, they're still in the views, so use them.
if (viewNum != 998) {
kernelSetView(viewNum, loopNum, celNum, hotspot);
@@ -219,6 +216,7 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu
// TODO: What about the 2000 resources? Inventory items? How to handle?
// TODO: What games does this work for? At least it does for KQ6.
// TODO: Stop asking rhetorical questions.
+ // TODO: It was fred all along!
Resource *resource = _resMan->findResource(ResourceId(kResourceTypeCursor, 1000 + celNum), false);
@@ -258,6 +256,15 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu
}
void GfxCursor::setPosition(Common::Point pos) {
+ // Don't set position, when cursor is not visible.
+ // This fixes eco quest 1 (floppy) right at the start, which is setting
+ // mouse cursor to (0,0) all the time during the intro. It's escapeable
+ // (now) by moving to the left or top, but it's getting on your nerves. This
+ // could theoretically break some things, although sierra normally sets
+ // position only when showing the cursor.
+ if (!_isVisible)
+ return;
+
if (!_upscaledHires) {
g_system->warpMouse(pos.x, pos.y);
} else {
@@ -269,52 +276,46 @@ void GfxCursor::setPosition(Common::Point pos) {
Common::Point GfxCursor::getPosition() {
Common::Point mousePos = g_system->getEventManager()->getMousePos();
- switch (_upscaledHires) {
- case GFX_SCREEN_UPSCALED_640x400:
- mousePos.x /= 2;
- mousePos.y /= 2;
- break;
- case GFX_SCREEN_UPSCALED_640x440:
- mousePos.x /= 2;
- mousePos.y = (mousePos.y * 5) / 11;
- break;
- case GFX_SCREEN_UPSCALED_640x480:
- mousePos.x /= 2;
- mousePos.y = (mousePos.y * 5) / 12;
- default:
- break;
- }
+ if (_upscaledHires)
+ _screen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x);
return mousePos;
}
void GfxCursor::refreshPosition() {
- bool clipped = false;
- Common::Point mousePoint = getPosition();
-
- if (mousePoint.x < _moveZone.left) {
- mousePoint.x = _moveZone.left;
- clipped = true;
- } else if (mousePoint.x >= _moveZone.right) {
- mousePoint.x = _moveZone.right - 1;
- clipped = true;
- }
+ if (_moveZoneActive) {
+ bool clipped = false;
+ Common::Point mousePoint = getPosition();
+
+ if (mousePoint.x < _moveZone.left) {
+ mousePoint.x = _moveZone.left;
+ clipped = true;
+ } else if (mousePoint.x >= _moveZone.right) {
+ mousePoint.x = _moveZone.right - 1;
+ clipped = true;
+ }
+
+ if (mousePoint.y < _moveZone.top) {
+ mousePoint.y = _moveZone.top;
+ clipped = true;
+ } else if (mousePoint.y >= _moveZone.bottom) {
+ mousePoint.y = _moveZone.bottom - 1;
+ clipped = true;
+ }
- if (mousePoint.y < _moveZone.top) {
- mousePoint.y = _moveZone.top;
- clipped = true;
- } else if (mousePoint.y >= _moveZone.bottom) {
- mousePoint.y = _moveZone.bottom - 1;
- clipped = true;
+ // FIXME: Do this only when mouse is grabbed?
+ if (clipped)
+ setPosition(mousePoint);
}
+}
- // FIXME: Do this only when mouse is grabbed?
- if (clipped)
- setPosition(mousePoint);
+void GfxCursor::kernelResetMoveZone() {
+ _moveZoneActive = false;
}
void GfxCursor::kernelSetMoveZone(Common::Rect zone) {
- _moveZone = zone;
+ _moveZone = zone;
+ _moveZoneActive = true;
}
void GfxCursor::kernelSetPos(Common::Point pos) {
@@ -333,7 +334,7 @@ void GfxCursor::kernelMoveCursor(Common::Point pos) {
// Trigger event reading to make sure the mouse coordinates will
// actually have changed the next time we read them.
- _event->get(SCI_EVENT_PEEK);
+ _event->getSciEvent(SCI_EVENT_PEEK);
}
} // End of namespace Sci
diff --git a/engines/sci/graphics/cursor.h b/engines/sci/graphics/cursor.h
index 6d92b3cf5f..787841f5be 100644
--- a/engines/sci/graphics/cursor.h
+++ b/engines/sci/graphics/cursor.h
@@ -45,7 +45,7 @@ public:
GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *screen);
~GfxCursor();
- void init(GfxCoordAdjuster *coordAdjuster, SciEvent *event);
+ void init(GfxCoordAdjuster *coordAdjuster, EventManager *event);
void kernelShow();
void kernelHide();
@@ -58,6 +58,11 @@ public:
void refreshPosition();
/**
+ * Removes limit for mouse movement
+ */
+ void kernelResetMoveZone();
+
+ /**
* Limits the mouse movement to a given rectangle.
*
* @param[in] rect The rectangle
@@ -74,10 +79,11 @@ private:
GfxScreen *_screen;
GfxPalette *_palette;
GfxCoordAdjuster *_coordAdjuster;
- SciEvent *_event;
+ EventManager *_event;
int _upscaledHires;
+ bool _moveZoneActive;
Common::Rect _moveZone; // Rectangle in which the pointer can move
CursorCache _cachedCursors;
diff --git a/engines/sci/graphics/font.cpp b/engines/sci/graphics/font.cpp
index 91cf01c912..852771d081 100644
--- a/engines/sci/graphics/font.cpp
+++ b/engines/sci/graphics/font.cpp
@@ -82,17 +82,18 @@ void GfxFontFromResource::draw(uint16 chr, int16 top, int16 left, byte color, bo
int charWidth = MIN<int>(getCharWidth(chr), _screen->getWidth() - left);
int charHeight = MIN<int>(getCharHeight(chr), _screen->getHeight() - top);
byte b = 0, mask = 0xFF;
- int y = top;
+ int y = 0;
+ int16 greyedTop = top;
byte *pIn = getCharData(chr);
for (int i = 0; i < charHeight; i++, y++) {
if (greyedOutput)
- mask = top++ % 2 ? 0xAA : 0x55;
+ mask = greyedTop++ % 2 ? 0xAA : 0x55;
for (int done = 0; done < charWidth; done++) {
if ((done & 7) == 0) // fetching next data byte
b = *(pIn++) & mask;
if (b & 0x80) // if MSB is set - paint it
- _screen->putPixel(left + done, y, 1, color, 0, 0);
+ _screen->putFontPixel(top, left + done, y, color);
b = b << 1;
}
}
diff --git a/engines/sci/graphics/font.h b/engines/sci/graphics/font.h
index 90f18e426d..b9bee0fa9e 100644
--- a/engines/sci/graphics/font.h
+++ b/engines/sci/graphics/font.h
@@ -32,14 +32,14 @@ namespace Sci {
class GfxFont {
public:
- GfxFont() {};
- virtual ~GfxFont() {};
-
- virtual GuiResourceId getResourceId() { return 0; };
- virtual byte getHeight() { return 0; };
- virtual bool isDoubleByte(uint16 chr) { return false; };
- virtual byte getCharWidth(uint16 chr) { return 0; };
- virtual void draw(uint16 chr, int16 top, int16 left, byte color, bool greyedOutput) {};
+ GfxFont() {}
+ virtual ~GfxFont() {}
+
+ virtual GuiResourceId getResourceId() { return 0; }
+ virtual byte getHeight() { return 0; }
+ virtual bool isDoubleByte(uint16 chr) { return false; }
+ virtual byte getCharWidth(uint16 chr) { return 0; }
+ virtual void draw(uint16 chr, int16 top, int16 left, byte color, bool greyedOutput) {}
};
diff --git a/engines/sci/graphics/fontsjis.h b/engines/sci/graphics/fontsjis.h
index 24c8423ddb..684e6cac5e 100644
--- a/engines/sci/graphics/fontsjis.h
+++ b/engines/sci/graphics/fontsjis.h
@@ -26,10 +26,12 @@
#ifndef SCI_GRAPHICS_FONTSJIS_H
#define SCI_GRAPHICS_FONTSJIS_H
-#include "graphics/sjis.h"
-
#include "sci/graphics/helpers.h"
+namespace Graphics {
+ class FontSJIS;
+}
+
namespace Sci {
/**
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 78253bd913..a433b26ef2 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -28,6 +28,7 @@
#include "graphics/primitives.h"
#include "sci/sci.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
#include "sci/engine/vm.h"
@@ -37,6 +38,7 @@
#include "sci/graphics/view.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/paint32.h"
+#include "sci/graphics/palette.h"
#include "sci/graphics/picture.h"
#include "sci/graphics/frameout.h"
@@ -46,43 +48,103 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd
: _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette), _paint32(paint32) {
_coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster;
- _highPlanePri = 0;
+ scriptsRunningWidth = 320;
+ scriptsRunningHeight = 200;
}
GfxFrameout::~GfxFrameout() {
}
void GfxFrameout::kernelAddPlane(reg_t object) {
- _planes.push_back(object);
- int16 planePri = GET_SEL32V(_segMan, object, SELECTOR(priority)) & 0xFFFF;
- if (planePri > _highPlanePri)
- _highPlanePri = planePri;
+ PlaneEntry newPlane;
+
+ if (_planes.empty()) {
+ // There has to be another way for sierra sci to do this or maybe script resolution is compiled into
+ // interpreter (TODO)
+ scriptsRunningHeight = readSelectorValue(_segMan, object, SELECTOR(resY));
+ scriptsRunningWidth = readSelectorValue(_segMan, object, SELECTOR(resX));
+ _coordAdjuster->setScriptsResolution(scriptsRunningWidth, scriptsRunningHeight);
+ }
+
+ newPlane.object = object;
+ newPlane.pictureId = 0xFFFF;
+ newPlane.priority = readSelectorValue(_segMan, object, SELECTOR(priority));
+ newPlane.lastPriority = 0xFFFF; // hidden
+ _planes.push_back(newPlane);
+
+ kernelUpdatePlane(object);
}
void GfxFrameout::kernelUpdatePlane(reg_t object) {
+ for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
+ if (it->object == object) {
+ // Read some information
+ it->priority = readSelectorValue(_segMan, object, SELECTOR(priority));
+ GuiResourceId lastPictureId = it->pictureId;
+ it->pictureId = readSelectorValue(_segMan, object, SELECTOR(picture));
+ if (lastPictureId != it->pictureId) {
+ // picture got changed, load new picture
+ deletePlanePictures(object);
+ if ((it->pictureId != 0xFFFF) && (it->pictureId != 0xFFFE)) {
+ // SQ6 gives us a bad picture number for the control menu
+ if (_resMan->testResource(ResourceId(kResourceTypePic, it->pictureId)))
+ addPlanePicture(object, it->pictureId, 0);
+ }
+ }
+ sortPlanes();
+ return;
+ }
+ }
+ error("kUpdatePlane called on plane that wasn't added before");
}
void GfxFrameout::kernelDeletePlane(reg_t object) {
- for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) {
- if (_planes[planeNr] == object) {
- _planes.remove_at(planeNr);
- break;
+ deletePlanePictures(object);
+ for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
+ if (it->object == object) {
+ _planes.erase(it);
+ Common::Rect planeRect;
+ planeRect.top = readSelectorValue(_segMan, object, SELECTOR(top));
+ planeRect.left = readSelectorValue(_segMan, object, SELECTOR(left));
+ planeRect.bottom = readSelectorValue(_segMan, object, SELECTOR(bottom)) + 1;
+ planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right)) + 1;
+
+ Common::Rect screenRect(_screen->getWidth(), _screen->getHeight());
+ planeRect.top = (planeRect.top * screenRect.height()) / scriptsRunningHeight;
+ planeRect.left = (planeRect.left * screenRect.width()) / scriptsRunningWidth;
+ planeRect.bottom = (planeRect.bottom * screenRect.height()) / scriptsRunningHeight;
+ planeRect.right = (planeRect.right * screenRect.width()) / scriptsRunningWidth;
+ planeRect.clip(screenRect); // we need to do this, at least in gk1 on cemetary we get bottom right -> 201, 321
+ // Blackout removed plane rect
+ _paint32->fillRect(planeRect, 0);
+ return;
}
}
+}
- // Recalculate highPlanePri
- _highPlanePri = 0;
+void GfxFrameout::addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX) {
+ PlanePictureEntry newPicture;
+ newPicture.object = object;
+ newPicture.pictureId = pictureId;
+ newPicture.picture = new GfxPicture(_resMan, _coordAdjuster, 0, _screen, _palette, pictureId, false);
+ newPicture.startX = startX;
+ newPicture.pictureCels = 0;
+ _planePictures.push_back(newPicture);
+}
- for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) {
- int16 planePri = GET_SEL32V(_segMan, _planes[planeNr], SELECTOR(priority)) & 0xFFFF;
- if (planePri > _highPlanePri)
- _highPlanePri = planePri;
+void GfxFrameout::deletePlanePictures(reg_t object) {
+ for (PlanePictureList::iterator it = _planePictures.begin(); it != _planePictures.end(); it++) {
+ if (it->object == object) {
+ delete it->picture;
+ _planePictures.erase(it);
+ deletePlanePictures(object);
+ return;
+ }
}
}
void GfxFrameout::kernelAddScreenItem(reg_t object) {
_screenItems.push_back(object);
- warning("addScreenItem %X:%X (%s)", object.segment, object.offset, _segMan->getObjectName(object));
}
void GfxFrameout::kernelDeleteScreenItem(reg_t object) {
@@ -95,186 +157,378 @@ void GfxFrameout::kernelDeleteScreenItem(reg_t object) {
}
int16 GfxFrameout::kernelGetHighPlanePri() {
- return _highPlanePri;
+ sortPlanes();
+ return readSelectorValue(g_sci->getEngineState()->_segMan, _planes.back().object, SELECTOR(priority));
+}
+
+// No idea yet how to implement this
+void GfxFrameout::kernelAddPicAt(reg_t planeObj, int16 forWidth, GuiResourceId pictureId) {
+ addPlanePicture(planeObj, pictureId, forWidth);
}
bool sortHelper(const FrameoutEntry* entry1, const FrameoutEntry* entry2) {
- return (entry1->priority == entry2->priority) ? (entry1->y < entry2->y) : (entry1->priority < entry2->priority);
+ if (entry1->priority == entry2->priority) {
+ if (entry1->y == entry2->y)
+ return (entry1->givenOrderNr < entry2->givenOrderNr);
+ return (entry1->y < entry2->y);
+ }
+ return (entry1->priority < entry2->priority);
+}
+
+bool planeSortHelper(const PlaneEntry &entry1, const PlaneEntry &entry2) {
+// SegManager *segMan = g_sci->getEngineState()->_segMan;
+
+// uint16 plane1Priority = readSelectorValue(segMan, entry1, SELECTOR(priority));
+// uint16 plane2Priority = readSelectorValue(segMan, entry2, SELECTOR(priority));
+
+ if (entry1.priority == 0xffff)
+ return true;
+
+ if (entry2.priority == 0xffff)
+ return false;
+
+ return entry1.priority < entry2.priority;
+}
+
+void GfxFrameout::sortPlanes() {
+ // First, remove any invalid planes
+ for (PlaneList::iterator it = _planes.begin(); it != _planes.end();) {
+ if (!_segMan->isObject(it->object))
+ it = _planes.erase(it);
+ else
+ it++;
+ }
+
+ // Sort the rest of them
+ Common::sort(_planes.begin(), _planes.end(), planeSortHelper);
}
void GfxFrameout::kernelFrameout() {
- int16 itemCount = 0;
- reg_t planeObject;
- GuiResourceId planePictureNr;
- GfxPicture *planePicture = 0;
- int16 planePictureCels = 0;
- int16 planePictureCel;
- int16 planePriority;
- Common::Rect planeRect;
- int16 planeResY, planeResX;
- byte planeBack;
-
- reg_t itemObject;
- reg_t itemPlane;
-
- FrameoutEntry *itemData;
- FrameoutList itemList;
- FrameoutEntry *itemEntry;
+ _palette->palVaryUpdate();
// Allocate enough space for all screen items
- itemData = (FrameoutEntry *)malloc(_screenItems.size() * sizeof(FrameoutEntry));
+ FrameoutEntry *itemData = new FrameoutEntry[_screenItems.size()];
- for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) {
- planeObject = _planes[planeNr];
- planePriority = GET_SEL32V(_segMan, planeObject, SELECTOR(priority));
+ for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
+ reg_t planeObject = it->object;
+ uint16 planeLastPriority = it->lastPriority;
- if (planePriority == -1) // Plane currently not meant to be shown
- continue;
+ Common::Rect planeRect;
+ planeRect.top = readSelectorValue(_segMan, planeObject, SELECTOR(top));
+ planeRect.left = readSelectorValue(_segMan, planeObject, SELECTOR(left));
+ planeRect.bottom = readSelectorValue(_segMan, planeObject, SELECTOR(bottom)) + 1;
+ planeRect.right = readSelectorValue(_segMan, planeObject, SELECTOR(right)) + 1;
- planeRect.top = GET_SEL32V(_segMan, planeObject, SELECTOR(top));
- planeRect.left = GET_SEL32V(_segMan, planeObject, SELECTOR(left));
- planeRect.bottom = GET_SEL32V(_segMan, planeObject, SELECTOR(bottom));
- planeRect.right = GET_SEL32V(_segMan, planeObject, SELECTOR(right));
- planeResY = GET_SEL32V(_segMan, planeObject, SELECTOR(resY));
- planeResX = GET_SEL32V(_segMan, planeObject, SELECTOR(resX));
+ // Update priority here, sq6 sets it w/o UpdatePlane
+ uint16 planePriority = it->priority = readSelectorValue(_segMan, planeObject, SELECTOR(priority));
- planeRect.top = (planeRect.top * _screen->getHeight()) / planeResY;
- planeRect.left = (planeRect.left * _screen->getWidth()) / planeResX;
- planeRect.bottom = (planeRect.bottom * _screen->getHeight()) / planeResY;
- planeRect.right = (planeRect.right * _screen->getWidth()) / planeResX;
+ Common::Rect screenRect(_screen->getWidth(), _screen->getHeight());
+ planeRect.top = (planeRect.top * screenRect.height()) / scriptsRunningHeight;
+ planeRect.left = (planeRect.left * screenRect.width()) / scriptsRunningWidth;
+ planeRect.bottom = (planeRect.bottom * screenRect.height()) / scriptsRunningHeight;
+ planeRect.right = (planeRect.right * screenRect.width()) / scriptsRunningWidth;
- planeBack = GET_SEL32V(_segMan, planeObject, SELECTOR(back));
- if (planeBack) {
- _paint32->fillRect(planeRect, planeBack);
+ int16 planeOffsetX = 0;
+
+ // We get negative left in kq7 in scrolling rooms
+ if (planeRect.left < 0) {
+ planeOffsetX = -planeRect.left;
+ planeRect.left = 0;
+ }
+ if (planeRect.top < 0)
+ planeRect.top = 0;
+ // We get bad plane-bottom in sq6
+ if (planeRect.right > _screen->getWidth())
+ planeRect.right = _screen->getWidth();
+ if (planeRect.bottom > _screen->getHeight())
+ planeRect.bottom = _screen->getHeight();
+
+ it->lastPriority = planePriority;
+ if (planePriority == 0xffff) { // Plane currently not meant to be shown
+ // If plane was shown before, delete plane rect
+ if (planePriority != planeLastPriority)
+ _paint32->fillRect(planeRect, 0);
+ continue;
}
- planePictureNr = GET_SEL32V(_segMan, planeObject, SELECTOR(picture));
- if ((planePictureNr != 0xFFFF) && (planePictureNr != 0xFFFE)) {
- planePicture = new GfxPicture(_resMan, _coordAdjuster, 0, _screen, _palette, planePictureNr, false);
- planePictureCels = planePicture->getSci32celCount();
+ Common::Rect planeClipRect(planeRect.width(), planeRect.height());
- _coordAdjuster->pictureSetDisplayArea(planeRect);
+ Common::Rect upscaledPlaneRect = planeRect;
+ Common::Rect upscaledPlaneClipRect = planeClipRect;
+ if (_screen->getUpscaledHires()) {
+ _screen->adjustToUpscaledCoordinates(upscaledPlaneRect.top, upscaledPlaneRect.left);
+ _screen->adjustToUpscaledCoordinates(upscaledPlaneRect.bottom, upscaledPlaneRect.right);
+ _screen->adjustToUpscaledCoordinates(upscaledPlaneClipRect.top, upscaledPlaneClipRect.left);
+ _screen->adjustToUpscaledCoordinates(upscaledPlaneClipRect.bottom, upscaledPlaneClipRect.right);
}
+ byte planeBack = readSelectorValue(_segMan, planeObject, SELECTOR(back));
+ if (planeBack)
+ _paint32->fillRect(planeRect, planeBack);
+
+ GuiResourceId planeMainPictureId = it->pictureId;
+
+ bool planePictureMirrored = false;
+ if (readSelectorValue(_segMan, planeObject, SELECTOR(mirrored)))
+ planePictureMirrored = true;
+
+ _coordAdjuster->pictureSetDisplayArea(planeRect);
+ _palette->drewPicture(planeMainPictureId);
+
// Fill our itemlist for this plane
- itemCount = 0;
- itemEntry = itemData;
+ int16 itemCount = 0;
+ FrameoutEntry *itemEntry = itemData;
+ FrameoutList itemList;
+
for (uint32 itemNr = 0; itemNr < _screenItems.size(); itemNr++) {
- itemObject = _screenItems[itemNr];
- itemPlane = GET_SEL32(_segMan, itemObject, SELECTOR(plane));
- if (planeObject == itemPlane) {
- // Found an item on current plane
- itemEntry->viewId = GET_SEL32V(_segMan, itemObject, SELECTOR(view));
- itemEntry->loopNo = GET_SEL32V(_segMan, itemObject, SELECTOR(loop));
- itemEntry->celNo = GET_SEL32V(_segMan, itemObject, SELECTOR(cel));
- itemEntry->x = GET_SEL32V(_segMan, itemObject, SELECTOR(x));
- itemEntry->y = GET_SEL32V(_segMan, itemObject, SELECTOR(y));
- itemEntry->z = GET_SEL32V(_segMan, itemObject, SELECTOR(z));
- itemEntry->priority = GET_SEL32V(_segMan, itemObject, SELECTOR(priority));
- itemEntry->signal = GET_SEL32V(_segMan, itemObject, SELECTOR(signal));
- itemEntry->scaleX = GET_SEL32V(_segMan, itemObject, SELECTOR(scaleX));
- itemEntry->scaleY = GET_SEL32V(_segMan, itemObject, SELECTOR(scaleY));
- itemEntry->object = itemObject;
+ reg_t itemObject = _screenItems[itemNr];
- itemEntry->y = ((itemEntry->y * _screen->getHeight()) / planeResY);
- itemEntry->x = ((itemEntry->x * _screen->getWidth()) / planeResX);
- itemEntry->y += planeRect.top;
- itemEntry->x += planeRect.left;
+ // Remove any invalid items
+ if (!_segMan->isObject(itemObject)) {
+ _screenItems.remove_at(itemNr);
+ itemNr--;
+ continue;
+ }
- if (itemEntry->priority == 0)
+ reg_t itemPlane = readSelector(_segMan, itemObject, SELECTOR(plane));
+ if (planeObject == itemPlane) {
+ // Found an item on current plane
+ itemEntry->viewId = readSelectorValue(_segMan, itemObject, SELECTOR(view));
+ itemEntry->loopNo = readSelectorValue(_segMan, itemObject, SELECTOR(loop));
+ itemEntry->celNo = readSelectorValue(_segMan, itemObject, SELECTOR(cel));
+ itemEntry->x = readSelectorValue(_segMan, itemObject, SELECTOR(x));
+ itemEntry->y = readSelectorValue(_segMan, itemObject, SELECTOR(y));
+ itemEntry->z = readSelectorValue(_segMan, itemObject, SELECTOR(z));
+ itemEntry->priority = readSelectorValue(_segMan, itemObject, SELECTOR(priority));
+ if (readSelectorValue(_segMan, itemObject, SELECTOR(fixPriority)) == 0)
itemEntry->priority = itemEntry->y;
+ itemEntry->signal = readSelectorValue(_segMan, itemObject, SELECTOR(signal));
+ itemEntry->scaleX = readSelectorValue(_segMan, itemObject, SELECTOR(scaleX));
+ itemEntry->scaleY = readSelectorValue(_segMan, itemObject, SELECTOR(scaleY));
+ itemEntry->object = itemObject;
+ itemEntry->givenOrderNr = itemNr;
+
itemList.push_back(itemEntry);
itemEntry++;
itemCount++;
}
}
+ for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
+ if (pictureIt->object == planeObject) {
+ GfxPicture *planePicture = pictureIt->picture;
+ // Allocate memory for picture cels
+ pictureIt->pictureCels = new FrameoutEntry[planePicture->getSci32celCount()];
+
+ // Add following cels to the itemlist
+ FrameoutEntry *picEntry = pictureIt->pictureCels;
+ int planePictureCels = planePicture->getSci32celCount();
+ for (int pictureCelNr = 0; pictureCelNr < planePictureCels; pictureCelNr++) {
+ picEntry->celNo = pictureCelNr;
+ picEntry->object = NULL_REG;
+ picEntry->picture = planePicture;
+ picEntry->y = planePicture->getSci32celY(pictureCelNr);
+ picEntry->x = planePicture->getSci32celX(pictureCelNr);
+ picEntry->picStartX = pictureIt->startX;
+
+ picEntry->priority = planePicture->getSci32celPriority(pictureCelNr);
+
+ itemList.push_back(picEntry);
+ picEntry++;
+ }
+ }
+ }
+
// Now sort our itemlist
Common::sort(itemList.begin(), itemList.end(), sortHelper);
// Now display itemlist
- planePictureCel = 0;
-
itemEntry = itemData;
- FrameoutList::iterator listIterator = itemList.begin();
- FrameoutList::iterator listEnd = itemList.end();
- while (listIterator != listEnd) {
+
+// warning("Plane %s", _segMan->getObjectName(planeObject));
+
+ for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) {
itemEntry = *listIterator;
- if (planePicture) {
- while ((planePictureCel <= itemEntry->priority) && (planePictureCel < planePictureCels)) {
- planePicture->drawSci32Vga(planePictureCel);
- planePictureCel++;
+
+ if (itemEntry->object.isNull()) {
+ // Picture cel data
+ itemEntry->y = ((itemEntry->y * _screen->getHeight()) / scriptsRunningHeight);
+ itemEntry->x = ((itemEntry->x * _screen->getWidth()) / scriptsRunningWidth);
+ itemEntry->picStartX = ((itemEntry->picStartX * _screen->getWidth()) / scriptsRunningWidth);
+
+ // Out of view
+ int16 pictureCelStartX = itemEntry->picStartX + itemEntry->x;
+ int16 pictureCelEndX = pictureCelStartX + itemEntry->picture->getSci32celWidth(itemEntry->celNo);
+ int16 planeStartX = planeOffsetX;
+ int16 planeEndX = planeStartX + planeRect.width();
+ if (pictureCelEndX < planeStartX)
+ continue;
+ if (pictureCelStartX > planeEndX)
+ continue;
+
+ int16 pictureOffsetX = planeOffsetX;
+ int16 pictureX = itemEntry->x;
+ if ((planeOffsetX) || (itemEntry->picStartX)) {
+ if (planeOffsetX <= itemEntry->picStartX) {
+ pictureX += itemEntry->picStartX - planeOffsetX;
+ pictureOffsetX = 0;
+ } else {
+ pictureOffsetX = planeOffsetX - itemEntry->picStartX;
+ }
}
- }
- if (itemEntry->viewId != 0xFFFF) {
+
+ itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, planePictureMirrored);
+// warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority);
+
+ } else if (itemEntry->viewId != 0xFFFF) {
GfxView *view = _cache->getView(itemEntry->viewId);
- if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) {
- view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, &itemEntry->celRect);
- } else
- view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, &itemEntry->celRect);
+// warning("view %s %04x:%04x", _segMan->getObjectName(itemEntry->object), PRINT_REG(itemEntry->object));
- if (itemEntry->celRect.top < 0 || itemEntry->celRect.top >= _screen->getHeight()) {
- listIterator++;
- continue;
+ switch (getSciVersion()) {
+ case SCI_VERSION_2:
+ if (view->isSci2Hires()) {
+ int16 dummyX = 0;
+ _screen->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
+ _screen->adjustToUpscaledCoordinates(itemEntry->z, dummyX);
+ }
+ break;
+ case SCI_VERSION_2_1:
+ itemEntry->y = (itemEntry->y * _screen->getHeight()) / scriptsRunningHeight;
+ itemEntry->x = (itemEntry->x * _screen->getWidth()) / scriptsRunningWidth;
+ itemEntry->z = (itemEntry->z * _screen->getHeight()) / scriptsRunningHeight;
+ break;
+ default:
+ break;
+ }
+ // Adjust according to current scroll position
+ itemEntry->x -= planeOffsetX;
+
+ uint16 useInsetRect = readSelectorValue(_segMan, itemEntry->object, SELECTOR(useInsetRect));
+ if (useInsetRect) {
+ itemEntry->celRect.top = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inTop));
+ itemEntry->celRect.left = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inLeft));
+ itemEntry->celRect.bottom = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inBottom)) + 1;
+ itemEntry->celRect.right = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inRight)) + 1;
+ if (view->isSci2Hires()) {
+ _screen->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left);
+ _screen->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right);
+ }
+ itemEntry->celRect.translate(itemEntry->x, itemEntry->y);
+ // TODO: maybe we should clip the cels rect with this, i'm not sure
+ // the only currently known usage is game menu of gk1
+ } else {
+ if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
+ view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect);
+ else
+ view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, itemEntry->celRect);
+
+ Common::Rect nsRect = itemEntry->celRect;
+ // Translate back to actual coordinate within scrollable plane
+ nsRect.translate(planeOffsetX, 0);
+ switch (getSciVersion()) {
+ case SCI_VERSION_2:
+ if (view->isSci2Hires()) {
+ _screen->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
+ _screen->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right);
+ }
+ break;
+ case SCI_VERSION_2_1:
+ nsRect.top = (nsRect.top * scriptsRunningHeight) / _screen->getHeight();
+ nsRect.left = (nsRect.left * scriptsRunningWidth) / _screen->getWidth();
+ nsRect.bottom = (nsRect.bottom * scriptsRunningHeight) / _screen->getHeight();
+ nsRect.right = (nsRect.right * scriptsRunningWidth) / _screen->getWidth();
+ break;
+ default:
+ break;
+ }
+ writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsLeft), nsRect.left);
+ writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsTop), nsRect.top);
+ writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsRight), nsRect.right);
+ writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsBottom), nsRect.bottom);
}
- if (itemEntry->celRect.left < 0 || itemEntry->celRect.left >= _screen->getWidth()) {
- listIterator++;
- continue;
+ int16 screenHeight = _screen->getHeight();
+ int16 screenWidth = _screen->getWidth();
+ if (view->isSci2Hires()) {
+ screenHeight = _screen->getDisplayHeight();
+ screenWidth = _screen->getDisplayWidth();
}
- Common::Rect clipRect;
+ if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top >= screenHeight)
+ continue;
+
+ if (itemEntry->celRect.right < 0 || itemEntry->celRect.left >= screenWidth)
+ continue;
+
+ Common::Rect clipRect, translatedClipRect;
clipRect = itemEntry->celRect;
- clipRect.clip(planeRect);
+ if (view->isSci2Hires()) {
+ clipRect.clip(upscaledPlaneClipRect);
+ translatedClipRect = clipRect;
+ translatedClipRect.translate(upscaledPlaneRect.left, upscaledPlaneRect.top);
+ } else {
+ clipRect.clip(planeClipRect);
+ translatedClipRect = clipRect;
+ translatedClipRect.translate(planeRect.left, planeRect.top);
+ }
- if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
- view->draw(itemEntry->celRect, clipRect, clipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, false);
- else
- view->drawScaled(itemEntry->celRect, clipRect, clipRect, itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY);
+ if (!clipRect.isEmpty()) {
+ if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
+ view->draw(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires());
+ else
+ view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY);
+ }
} else {
// Most likely a text entry
// This draws text the "SCI0-SCI11" way. In SCI2, text is prerendered in kCreateTextBitmap
// TODO: rewrite this the "SCI2" way (i.e. implement the text buffer to draw inside kCreateTextBitmap)
- // This doesn't work for SCI2.1 games...
- if (getSciVersion() == SCI_VERSION_2) {
- Kernel *kernel = g_sci->getKernel();
- if (lookup_selector(_segMan, itemEntry->object, kernel->_selectorCache.text, NULL, NULL) == kSelectorVariable) {
- Common::String text = _segMan->getString(GET_SEL32(_segMan, itemEntry->object, SELECTOR(text)));
- int16 fontRes = GET_SEL32V(_segMan, itemEntry->object, SELECTOR(font));
- GfxFont *font = new GfxFontFromResource(_resMan, _screen, fontRes);
- bool dimmed = GET_SEL32V(_segMan, itemEntry->object, SELECTOR(dimmed));
- uint16 foreColor = GET_SEL32V(_segMan, itemEntry->object, SELECTOR(fore));
- uint16 curX = itemEntry->x;
- uint16 curY = itemEntry->y;
- for (uint32 i = 0; i < text.size(); i++) {
- // TODO: proper text splitting... this is a hack
- if ((text[i] == ' ' && i > 0 && text[i - i] == ' ') || text[i] == '\n' ||
- (curX + font->getCharWidth(text[i]) > _screen->getWidth())) {
- curY += font->getHeight();
- curX = itemEntry->x;
- }
- font->draw(text[i], curY, curX, foreColor, dimmed);
- curX += font->getCharWidth(text[i]);
+ if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) {
+ reg_t stringObject = readSelector(_segMan, itemEntry->object, SELECTOR(text));
+
+ // The object in the text selector of the item can be either a raw string
+ // or a Str object. In the latter case, we need to access the object's data
+ // selector to get the raw string.
+ if (_segMan->isHeapObject(stringObject))
+ stringObject = readSelector(_segMan, stringObject, SELECTOR(data));
+
+ Common::String text = _segMan->getString(stringObject);
+ GfxFont *font = _cache->getFont(readSelectorValue(_segMan, itemEntry->object, SELECTOR(font)));
+ bool dimmed = readSelectorValue(_segMan, itemEntry->object, SELECTOR(dimmed));
+ uint16 foreColor = readSelectorValue(_segMan, itemEntry->object, SELECTOR(fore));
+
+ itemEntry->y = ((itemEntry->y * _screen->getHeight()) / scriptsRunningHeight);
+ itemEntry->x = ((itemEntry->x * _screen->getWidth()) / scriptsRunningWidth);
+
+ uint16 curX = itemEntry->x + planeRect.left;
+ uint16 curY = itemEntry->y + planeRect.top;
+ for (uint32 i = 0; i < text.size(); i++) {
+ unsigned char curChar = text[i];
+ // TODO: proper text splitting... this is a hack
+ if ((curChar == ' ' && i > 0 && text[i - i] == ' ') || curChar == '\n' ||
+ (curX + font->getCharWidth(curChar) > _screen->getWidth())) {
+ curY += font->getHeight();
+ curX = itemEntry->x;
}
- delete font;
+ font->draw(curChar, curY, curX, foreColor, dimmed);
+ curX += font->getCharWidth(curChar);
}
}
}
- listIterator++;
}
- if (planePicture) {
- while (planePictureCel < planePictureCels) {
- planePicture->drawSci32Vga(planePictureCel);
- planePictureCel++;
+
+ for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
+ if (pictureIt->object == planeObject) {
+ delete[] pictureIt->pictureCels;
}
- delete planePicture;
- planePicture = 0;
}
}
- free(itemData);
+
+ delete[] itemData;
_screen->copyToScreen();
+
+ g_sci->getEngineState()->_throttleTrigger = true;
}
} // End of namespace Sci
diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h
index 36c02af278..f8f7e54a27 100644
--- a/engines/sci/graphics/frameout.h
+++ b/engines/sci/graphics/frameout.h
@@ -28,7 +28,17 @@
namespace Sci {
+struct PlaneEntry {
+ reg_t object;
+ uint16 priority;
+ uint16 lastPriority;
+ GuiResourceId pictureId;
+};
+
+typedef Common::List<PlaneEntry> PlaneList;
+
struct FrameoutEntry {
+ uint16 givenOrderNr;
reg_t object;
GuiResourceId viewId;
int16 loopNo;
@@ -40,11 +50,27 @@ struct FrameoutEntry {
int16 scaleX;
int16 scaleY;
Common::Rect celRect;
+ GfxPicture *picture;
+ int16 picStartX;
};
+
typedef Common::List<FrameoutEntry *> FrameoutList;
+struct PlanePictureEntry {
+ reg_t object;
+ int16 startX;
+ GuiResourceId pictureId;
+ GfxPicture *picture;
+ FrameoutEntry *pictureCels; // temporary
+};
+
+typedef Common::List<PlanePictureEntry> PlanePictureList;
+
class GfxCache;
+class GfxCoordAdjuster32;
class GfxPaint32;
+class GfxPalette;
+class GfxScreen;
/**
* Frameout class, kFrameout and relevant functions for SCI32 games
*/
@@ -59,8 +85,12 @@ public:
void kernelAddScreenItem(reg_t object);
void kernelDeleteScreenItem(reg_t object);
int16 kernelGetHighPlanePri();
+ void kernelAddPicAt(reg_t planeObj, int16 forWidth, GuiResourceId pictureId);
void kernelFrameout();
+ void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX);
+ void deletePlanePictures(reg_t object);
+
private:
SegManager *_segMan;
ResourceManager *_resMan;
@@ -71,8 +101,13 @@ private:
GfxPaint32 *_paint32;
Common::Array<reg_t> _screenItems;
- Common::Array<reg_t> _planes;
- int16 _highPlanePri;
+ PlaneList _planes;
+ PlanePictureList _planePictures;
+
+ void sortPlanes();
+
+ uint16 scriptsRunningWidth;
+ uint16 scriptsRunningHeight;
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/gui.cpp b/engines/sci/graphics/gui.cpp
deleted file mode 100644
index 46f7fcd689..0000000000
--- a/engines/sci/graphics/gui.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/timer.h"
-#include "common/util.h"
-
-#include "sci/sci.h"
-#include "sci/debug.h" // for g_debug_sleeptime_factor
-#include "sci/event.h"
-#include "sci/engine/state.h"
-#include "sci/engine/selector.h"
-#include "sci/graphics/gui.h"
-#include "sci/graphics/screen.h"
-#include "sci/graphics/palette.h"
-#include "sci/graphics/cursor.h"
-#include "sci/graphics/ports.h"
-#include "sci/graphics/paint16.h"
-#include "sci/graphics/cache.h"
-#include "sci/graphics/compare.h"
-#include "sci/graphics/coordadjuster.h"
-#include "sci/graphics/animate.h"
-#include "sci/graphics/controls.h"
-#include "sci/graphics/menu.h"
-#include "sci/graphics/portrait.h"
-#include "sci/graphics/text16.h"
-#include "sci/graphics/transitions.h"
-#include "sci/graphics/view.h"
-#include "sci/sound/audio.h"
-
-namespace Sci {
-
-SciGui::SciGui(EngineState *state, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor, GfxPorts *ports, AudioPlayer *audio)
- : _s(state), _screen(screen), _palette(palette), _cache(cache), _cursor(cursor), _ports(ports), _audio(audio) {
-
- // FIXME/TODO: If SciGui inits all the stuff below, then it should *own* it,
- // not SciEngine. Conversely, if we want SciEngine to own this stuff,
- // then it should init it!
- _coordAdjuster = new GfxCoordAdjuster16(_ports);
- g_sci->_gfxCoordAdjuster = _coordAdjuster;
- _cursor->init(_coordAdjuster, _s->_event);
- _compare = new GfxCompare(_s->_segMan, g_sci->getKernel(), _cache, _screen, _coordAdjuster);
- g_sci->_gfxCompare = _compare;
- _transitions = new GfxTransitions(this, _screen, _palette, g_sci->getResMan()->isVGA());
- _paint16 = new GfxPaint16(g_sci->getResMan(), _s->_segMan, g_sci->getKernel(), this, _cache, _ports, _coordAdjuster, _screen, _palette, _transitions);
- g_sci->_gfxPaint = _paint16;
- g_sci->_gfxPaint16 = _paint16;
- _animate = new GfxAnimate(_s, _cache, _ports, _paint16, _screen, _palette, _cursor, _transitions);
- g_sci->_gfxAnimate = _animate;
- _text16 = new GfxText16(g_sci->getResMan(), _cache, _ports, _paint16, _screen);
- _controls = new GfxControls(_s->_segMan, _ports, _paint16, _text16, _screen);
- g_sci->_gfxControls = _controls;
- _menu = new GfxMenu(_s->_event, _s->_segMan, this, _ports, _paint16, _text16, _screen, _cursor);
- g_sci->_gfxMenu = _menu;
-}
-
-SciGui::~SciGui() {
- delete _menu;
- delete _controls;
- delete _text16;
- delete _animate;
- delete _paint16;
- delete _transitions;
- delete _compare;
- delete _coordAdjuster;
-}
-
-void SciGui::resetEngineState(EngineState *s) {
- _s = s;
- _animate->resetEngineState(s);
-}
-
-void SciGui::init(bool usesOldGfxFunctions) {
- _ports->init(usesOldGfxFunctions, this, _paint16, _text16, _s->_gameId);
- _paint16->init(_animate, _text16);
-}
-
-void SciGui::wait(int16 ticks) {
- _s->wait(ticks);
-}
-
-void SciGui::textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) {
- Common::Rect rect(0, 0, *textWidth, *textHeight);
- _text16->Size(rect, text, font, maxWidth);
- *textWidth = rect.width();
- *textHeight = rect.height();
-}
-
-// Used SCI1+ for text codes
-void SciGui::textFonts(int argc, reg_t *argv) {
- _text16->CodeSetFonts(argc, argv);
-}
-
-// Used SCI1+ for text codes
-void SciGui::textColors(int argc, reg_t *argv) {
- _text16->CodeSetColors(argc, argv);
-}
-
-reg_t SciGui::portraitLoad(Common::String resourceName) {
- //Portrait *myPortrait = new Portrait(g_sci->getResMan(), _screen, _palette, resourceName);
- return NULL_REG;
-}
-
-void SciGui::portraitShow(Common::String resourceName, Common::Point position, uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq) {
- Portrait *myPortrait = new Portrait(g_sci->getResMan(), _s->_event, this, _screen, _palette, _audio, resourceName);
- // TODO: cache portraits
- // adjust given coordinates to curPort (but dont adjust coordinates on upscaledHires_Save_Box and give us hires coordinates
- // on kDrawCel, yeah this whole stuff makes sense)
- position.x += _ports->getPort()->left; position.y += _ports->getPort()->top;
- _screen->adjustToUpscaledCoordinates(position.y, position.x);
- myPortrait->doit(position, resourceId, noun, verb, cond, seq);
- delete myPortrait;
-}
-
-void SciGui::portraitUnload(uint16 portraitId) {
-}
-
-bool SciGui::debugEGAdrawingVisualize(bool state) {
- _paint16->setEGAdrawingVisualize(state);
- return false;
-}
-
-} // End of namespace Sci
diff --git a/engines/sci/graphics/gui.h b/engines/sci/graphics/gui.h
deleted file mode 100644
index 732e195026..0000000000
--- a/engines/sci/graphics/gui.h
+++ /dev/null
@@ -1,93 +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$
- *
- */
-
-#ifndef SCI_GRAPHICS_GUI_H
-#define SCI_GRAPHICS_GUI_H
-
-#include "sci/graphics/helpers.h"
-
-namespace Sci {
-
-class GfxScreen;
-class GfxPalette;
-class GfxCursor;
-class GfxCache;
-class GfxCompare;
-class GfxCoordAdjuster16;
-class GfxPorts;
-class GfxPaint16;
-class GfxAnimate;
-class GfxControls;
-class GfxMenu;
-class GfxText16;
-class GfxTransitions;
-
-class SciGui {
-public:
- SciGui(EngineState *s, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor, GfxPorts *ports, AudioPlayer *audio);
- virtual ~SciGui();
-
- virtual void init(bool usesOldGfxFunctions);
-
- virtual void wait(int16 ticks);
-
- virtual void textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
- virtual void textFonts(int argc, reg_t *argv);
- virtual void textColors(int argc, reg_t *argv);
-
- virtual reg_t portraitLoad(Common::String resourceName);
- virtual void portraitShow(Common::String resourceName, Common::Point position, uint16 resourceNum, uint16 noun, uint16 verb, uint16 cond, uint16 seq);
- virtual void portraitUnload(uint16 portraitId);
-
- virtual bool debugEGAdrawingVisualize(bool state);
-
- // FIXME: Don't store EngineState
- virtual void resetEngineState(EngineState *s);
-
-protected:
- GfxCursor *_cursor;
- EngineState *_s;
- GfxScreen *_screen;
- GfxPalette *_palette;
- GfxCache *_cache;
- GfxCoordAdjuster16 *_coordAdjuster;
- GfxCompare *_compare;
- GfxPorts *_ports;
- GfxPaint16 *_paint16;
-
-private:
- AudioPlayer *_audio;
- GfxAnimate *_animate;
- GfxControls *_controls;
- GfxMenu *_menu;
- GfxText16 *_text16;
- GfxTransitions *_transitions;
-
- bool _usesOldGfxFunctions;
-};
-
-} // End of namespace Sci
-
-#endif
diff --git a/engines/sci/graphics/gui32.cpp b/engines/sci/graphics/gui32.cpp
deleted file mode 100644
index 4b72050d0b..0000000000
--- a/engines/sci/graphics/gui32.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/timer.h"
-#include "common/util.h"
-
-#include "sci/sci.h"
-#include "sci/event.h"
-#include "sci/engine/state.h"
-#include "sci/engine/selector.h"
-#include "sci/graphics/gui32.h"
-#include "sci/graphics/screen.h"
-#include "sci/graphics/palette.h"
-#include "sci/graphics/cursor.h"
-#include "sci/graphics/cache.h"
-#include "sci/graphics/compare.h"
-#include "sci/graphics/coordadjuster.h"
-#include "sci/graphics/frameout.h"
-#include "sci/graphics/paint32.h"
-#include "sci/graphics/picture.h"
-#include "sci/graphics/robot.h"
-#include "sci/graphics/view.h"
-
-namespace Sci {
-
-SciGui32::SciGui32(SegManager *segMan, SciEvent *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor)
- : _screen(screen), _palette(palette), _cache(cache), _cursor(cursor) {
-
- _coordAdjuster = new GfxCoordAdjuster32(segMan);
- g_sci->_gfxCoordAdjuster = _coordAdjuster;
- _cursor->init(_coordAdjuster, event);
- _compare = new GfxCompare(segMan, g_sci->getKernel(), _cache, _screen, _coordAdjuster);
- g_sci->_gfxCompare = _compare;
- _paint32 = new GfxPaint32(g_sci->getResMan(), segMan, g_sci->getKernel(), _coordAdjuster, _cache, _screen, _palette);
- g_sci->_gfxPaint = _paint32;
- _frameout = new GfxFrameout(segMan, g_sci->getResMan(), _coordAdjuster, _cache, _screen, _palette, _paint32);
- g_sci->_gfxFrameout = _frameout;
-}
-
-SciGui32::~SciGui32() {
- delete _frameout;
- delete _paint32;
- delete _compare;
- delete _coordAdjuster;
-}
-
-void SciGui32::init() {
-}
-
-void SciGui32::textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) {
- *textWidth = 0;
- *textHeight = 0;
-}
-
-void SciGui32::drawRobot(GuiResourceId robotId) {
- Robot *test = new Robot(g_sci->getResMan(), _screen, robotId);
- test->draw();
- delete test;
-}
-
-} // End of namespace Sci
diff --git a/engines/sci/graphics/helpers.h b/engines/sci/graphics/helpers.h
index f0ffecfb59..4b4cd673b4 100644
--- a/engines/sci/graphics/helpers.h
+++ b/engines/sci/graphics/helpers.h
@@ -28,6 +28,7 @@
#include "common/endian.h" // for READ_LE_UINT16
#include "common/rect.h"
+#include "common/serializer.h"
#include "sci/engine/vm_types.h"
namespace Sci {
@@ -54,11 +55,12 @@ struct Port {
bool greyedOutput;
int16 penClr, backClr;
int16 penMode;
+ uint16 counterTillFree;
Port(uint16 theId) : id(theId), top(0), left(0),
curTop(0), curLeft(0),
fontHeight(0), fontId(0), greyedOutput(false),
- penClr(0), backClr(0xFF), penMode(0) {
+ penClr(0), backClr(0xFF), penMode(0), counterTillFree(0) {
}
};
diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp
new file mode 100644
index 0000000000..6f2c9596db
--- /dev/null
+++ b/engines/sci/graphics/maciconbar.cpp
@@ -0,0 +1,92 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/sci.h"
+#include "sci/engine/kernel.h"
+#include "sci/engine/selector.h"
+#include "sci/engine/state.h"
+#include "sci/graphics/maciconbar.h"
+#include "sci/graphics/palette.h"
+
+#include "common/stream.h"
+#include "common/system.h"
+#include "graphics/pict.h"
+#include "graphics/surface.h"
+
+namespace Sci {
+
+void GfxMacIconBar::addIcon(reg_t obj) {
+ _iconBarObjects.push_back(obj);
+}
+
+void GfxMacIconBar::drawIcons() {
+ // Draw the icons to the bottom of the screen
+
+ byte *pal = new byte[256 * 4];
+ Graphics::PictDecoder *pict = new Graphics::PictDecoder(Graphics::PixelFormat::createFormatCLUT8());
+ uint32 lastX = 0;
+
+ for (uint32 i = 0; i < _iconBarObjects.size(); i++) {
+ uint32 iconIndex = readSelectorValue(g_sci->getEngineState()->_segMan, _iconBarObjects[i], SELECTOR(iconIndex));
+ Resource *res = g_sci->getResMan()->findResource(ResourceId(kResourceTypeMacIconBarPictN, iconIndex + 1), false);
+ if (!res)
+ continue;
+
+ Common::MemoryReadStream *stream = new Common::MemoryReadStream(res->data, res->size);
+ Graphics::Surface *surf = pict->decodeImage(stream, pal);
+ remapColors(surf, pal);
+
+ g_system->copyRectToScreen((byte *)surf->pixels, surf->pitch, lastX, 200, MIN<uint32>(surf->w, 320 - lastX), surf->h);
+
+ lastX += surf->w;
+ surf->free();
+ delete surf;
+ delete stream;
+ }
+
+ delete pict;
+ delete[] pal;
+}
+
+void GfxMacIconBar::remapColors(Graphics::Surface *surf, byte *palette) {
+ byte *pixels = (byte *)surf->pixels;
+
+ // Remap to the screen palette
+ for (uint16 i = 0; i < surf->w * surf->h; i++) {
+ byte color = *pixels;
+
+ byte r = palette[color * 4];
+ byte g = palette[color * 4 + 1];
+ byte b = palette[color * 4 + 2];
+
+ // For black, make sure the index is 0
+ if (r == 0 && g == 0 && b == 0)
+ *pixels++ = 0;
+ else
+ *pixels++ = g_sci->_gfxPalette->kernelFindColor(r, g, b);
+ }
+}
+
+} // End of namespace Sci
diff --git a/backends/platform/PalmOS/Src/init_palmos.h b/engines/sci/graphics/maciconbar.h
index d4691dd15b..71e65fcb40 100644
--- a/backends/platform/PalmOS/Src/init_palmos.h
+++ b/engines/sci/graphics/maciconbar.h
@@ -23,20 +23,33 @@
*
*/
-#ifndef INIT_PALMOS_H
-#define INIT_PALMOS_H
+#ifndef SCI_GRAPHICS_MACICONBAR_H
+#define SCI_GRAPHICS_MACICONBAR_H
-#define PALM_PORTRAIT 1
-#define PALM_LANDSCAPE 2
+#include "common/array.h"
-void PalmInit(UInt8 init);
-void PalmRelease(UInt8 init);
+#include "sci/engine/vm.h"
-Err PalmHRInit(UInt32 depth);
-void PalmHRRelease();
+namespace Graphics {
+ struct Surface;
+}
+namespace Sci {
-UInt8 PalmScreenSize(Coord *stdw, Coord *stdh, Coord *fullw, Coord *fullh);
-void PalmGetMemory(UInt32* storageMemoryP, UInt32* dynamicMemoryP, UInt32 *storageFreeP, UInt32 *dynamicFreeP);
+class GfxMacIconBar {
+public:
+ GfxMacIconBar() {}
+ ~GfxMacIconBar() {}
+
+ void addIcon(reg_t obj);
+ void drawIcons();
+
+private:
+ Common::Array<reg_t> _iconBarObjects;
+
+ void remapColors(Graphics::Surface *surf, byte *palette);
+};
+
+} // End of namespace Sci
#endif
diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp
index 5e3b419fe3..630626c128 100644
--- a/engines/sci/graphics/menu.cpp
+++ b/engines/sci/graphics/menu.cpp
@@ -29,9 +29,9 @@
#include "sci/sci.h"
#include "sci/event.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
-#include "sci/graphics/gui.h"
#include "sci/graphics/ports.h"
#include "sci/graphics/paint16.h"
#include "sci/graphics/animate.h"
@@ -43,8 +43,8 @@
namespace Sci {
-GfxMenu::GfxMenu(SciEvent *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor)
- : _event(event), _segMan(segMan), _gui(gui), _ports(ports), _paint16(paint16), _text16(text16), _screen(screen), _cursor(cursor) {
+GfxMenu::GfxMenu(EventManager *event, SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor)
+ : _event(event), _segMan(segMan), _ports(ports), _paint16(paint16), _text16(text16), _screen(screen), _cursor(cursor) {
_menuSaveHandle = NULL_REG;
_barSaveHandle = NULL_REG;
@@ -63,8 +63,9 @@ void GfxMenu::reset() {
_itemList.clear();
_listCount = 0;
- // We actually set active item in here and remember last selection of the user
- // sierra sci always defaulted to first item every time menu was called via ESC, we dont follow that logic
+ // We actually set active item in here and remember last selection of the
+ // user. Sierra SCI always defaulted to first item every time menu was
+ // called via ESC, we don't follow that logic.
_curMenuId = 1;
_curItemId = 1;
}
@@ -92,15 +93,16 @@ void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t
beginPos = curPos;
- // Now go through the content till we find end-marker and collect data about it
- // ':' is an end-marker for each item
+ // Now go through the content till we find end-marker and collect data about it.
+ // ':' is an end-marker for each item.
tagPos = 0; rightAlignedPos = 0;
controlPos = 0; altPos = 0; functionPos = 0;
while ((curPos < contentSize) && (content[curPos] != ':')) {
switch (content[curPos]) {
case '=': // Set tag
- // Special case for normal animation speed - they use right aligned "=" for that one, so we ignore it
- // as being recognized as tag marker
+ // Special case for normal animation speed - they use right
+ // aligned "=" for that one, so we ignore it as being recognized
+ // as tag marker.
if (rightAlignedPos == curPos - 1)
break;
if (tagPos)
@@ -199,8 +201,9 @@ void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t
if (separatorCount == tempPos - beginPos) {
itemEntry->separatorLine = true;
} else {
- // we don't strSplit here, because multilingual SCI01 support language switching on the fly, so we have to do
- // this everytime the menu is called
+ // We don't strSplit here, because multilingual SCI01 support
+ // language switching on the fly, so we have to do this everytime
+ // the menu is called.
itemEntry->text = Common::String(content.c_str() + beginPos, tempPos - beginPos);
// LSL6 uses "Ctrl-" prefix string instead of ^ like all the other games do
@@ -222,10 +225,12 @@ void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t
if (tagPos && tagPos >= rightAlignedPos)
tempPos = tagPos;
itemEntry->textRightAligned = Common::String(content.c_str() + rightAlignedPos, tempPos - rightAlignedPos);
- // Remove ending space, if there is one. Strangely sometimes there are lone spaces at the end in some games
+ // Remove ending space, if there is one. Strangely sometimes there
+ // are lone spaces at the end in some games
if (itemEntry->textRightAligned.hasSuffix(" "))
itemEntry->textRightAligned.deleteLastChar();
- // - and + are used sometimes for volume control/animation speed, = sometimes for animation speed
+ // - and + are used sometimes for volume control/animation speed,
+ // = sometimes for animation speed
if (itemEntry->textRightAligned == "-") {
itemEntry->keyPress = '-';
} else if (itemEntry->textRightAligned == "+") {
@@ -266,8 +271,15 @@ GuiMenuItemEntry *GfxMenu::findItem(uint16 menuId, uint16 itemId) {
void GfxMenu::kernelSetAttribute(uint16 menuId, uint16 itemId, uint16 attributeId, reg_t value) {
GuiMenuItemEntry *itemEntry = findItem(menuId, itemId);
- if (!itemEntry)
- error("Tried to setAttribute() on non-existant menu-item %d:%d", menuId, itemId);
+
+ if (!itemEntry) {
+ // PQ2 demo calls this, for example, but has no menus (bug report #3034507). Some SCI
+ // fan games (Al Pond 2, Aquarius) call this too on non-existent menu items. The
+ // original interpreter ignored these as well.
+ debugC(2, kDebugLevelGraphics, "Tried to setAttribute() on non-existent menu-item %d:%d", menuId, itemId);
+ return;
+ }
+
switch (attributeId) {
case SCI_MENU_ATTRIBUTE_ENABLED:
itemEntry->enabled = value.isNull() ? false : true;
@@ -377,8 +389,8 @@ void GfxMenu::calculateMenuAndItemWidth() {
}
}
-reg_t GfxMenu::kernelSelect(reg_t eventObject) {
- int16 eventType = GET_SEL32V(_segMan, eventObject, SELECTOR(type));
+reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) {
+ int16 eventType = readSelectorValue(_segMan, eventObject, SELECTOR(type));
int16 keyPress, keyModifier;
Common::Point mousePosition;
GuiMenuItemList::iterator itemIterator = _itemList.begin();
@@ -386,13 +398,13 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) {
GuiMenuItemEntry *itemEntry = NULL;
bool forceClaimed = false;
EngineState *s;
- byte saidSpec[64];
switch (eventType) {
case SCI_EVENT_KEYBOARD:
- keyPress = GET_SEL32V(_segMan, eventObject, SELECTOR(message));
- keyModifier = GET_SEL32V(_segMan, eventObject, SELECTOR(modifiers));
- // If tab got pressed, handle it here as if it was Ctrl-I - at least sci0 also did it that way
+ keyPress = readSelectorValue(_segMan, eventObject, SELECTOR(message));
+ keyModifier = readSelectorValue(_segMan, eventObject, SELECTOR(modifiers));
+ // If tab got pressed, handle it here as if it was Ctrl-I - at least
+ // sci0 also did it that way
if (keyPress == SCI_KEY_TAB) {
keyModifier = SCI_KEYMOD_CTRL;
keyPress = 'i';
@@ -401,9 +413,9 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) {
case 0:
break;
case SCI_KEY_ESC:
- interactiveShowMouse();
+ interactiveStart(pauseSound);
itemEntry = interactiveWithKeyboard();
- interactiveRestoreMouse();
+ interactiveEnd(pauseSound);
forceClaimed = true;
break;
default:
@@ -425,8 +437,13 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) {
itemEntry = *itemIterator;
if (!itemEntry->saidVmPtr.isNull()) {
- // TODO: get a pointer to saidVmPtr or make said() work on VmPtrs
- _segMan->memcpy(saidSpec, itemEntry->saidVmPtr, 64);
+ byte *saidSpec = _segMan->derefBulkPtr(itemEntry->saidVmPtr, 0);
+
+ if (!saidSpec) {
+ warning("Could not dereference saidSpec");
+ continue;
+ }
+
if (said(s, saidSpec, 0) != SAID_NO_MATCH)
break;
}
@@ -439,9 +456,9 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) {
case SCI_EVENT_MOUSE_PRESS:
mousePosition = _cursor->getPosition();
if (mousePosition.y < 10) {
- interactiveShowMouse();
+ interactiveStart(pauseSound);
itemEntry = interactiveWithMouse();
- interactiveRestoreMouse();
+ interactiveEnd(pauseSound);
forceClaimed = true;
}
break;
@@ -461,11 +478,13 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) {
_paint16->bitsShow(_ports->_menuRect);
_barSaveHandle = NULL_REG;
}
- if (_oldPort)
+ if (_oldPort) {
_ports->setPort(_oldPort);
+ _oldPort = NULL;
+ }
if ((itemEntry) || (forceClaimed))
- PUT_SEL32(_segMan, eventObject, SELECTOR(claimed), make_reg(0, 1));
+ writeSelector(_segMan, eventObject, SELECTOR(claimed), make_reg(0, 1));
if (itemEntry)
return make_reg(0, (itemEntry->menuId << 8) | (itemEntry->id));
return NULL_REG;
@@ -562,7 +581,8 @@ void GfxMenu::drawMenu(uint16 oldMenuId, uint16 newMenuId) {
if (!maxTextRightAlignedWidth)
_menuRect.right -= 5;
- // if part of menu window is outside the screen, move it into the screen (this happens in multilingual sq3 and lsl3)
+ // If part of menu window is outside the screen, move it into the screen
+ // (this happens in multilingual sq3 and lsl3).
if (_menuRect.right > _screen->getWidth()) {
_menuRect.translate(-(_menuRect.right - _screen->getWidth()), 0);
}
@@ -625,12 +645,16 @@ void GfxMenu::invertMenuSelection(uint16 itemId) {
_paint16->bitsShow(itemRect);
}
-void GfxMenu::interactiveShowMouse() {
+void GfxMenu::interactiveStart(bool pauseSound) {
_mouseOldState = _cursor->isVisible();
_cursor->kernelShow();
+ if (pauseSound)
+ g_sci->_soundCmd->pauseAll(true);
}
-void GfxMenu::interactiveRestoreMouse() {
+void GfxMenu::interactiveEnd(bool pauseSound) {
+ if (pauseSound)
+ g_sci->_soundCmd->pauseAll(false);
if (!_mouseOldState)
_cursor->kernelHide();
}
@@ -682,18 +706,19 @@ uint16 GfxMenu::mouseFindMenuItemSelection(Common::Point mousePosition, uint16 m
}
GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() {
- sciEvent curEvent;
+ SciEvent curEvent;
uint16 newMenuId = _curMenuId;
uint16 newItemId = _curItemId;
GuiMenuItemEntry *curItemEntry = findItem(_curMenuId, _curItemId);
GuiMenuItemEntry *newItemEntry = curItemEntry;
Common::Point mousePosition;
- // We don't 100% follow sierra here: we select last item instead of selecting first item of first menu everytime
- // Also sierra sci didnt allow mouse interaction, when menu was activated via keyboard
+ // We don't 100% follow Sierra here: we select last item instead of
+ // selecting first item of first menu every time. Also sierra sci didn't
+ // allow mouse interaction, when menu was activated via keyboard.
- calculateMenuAndItemWidth();
_oldPort = _ports->setPort(_ports->_menuPort);
+ calculateMenuAndItemWidth();
_barSaveHandle = _paint16->bitsSave(_ports->_menuRect, GFX_SCREEN_MASK_VISUAL);
_ports->penColor(0);
@@ -706,12 +731,13 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() {
_paint16->bitsShow(_menuRect);
while (true) {
- curEvent = _event->get(SCI_EVENT_ANY);
+ curEvent = _event->getSciEvent(SCI_EVENT_ANY);
switch (curEvent.type) {
case SCI_EVENT_KEYBOARD:
- // We don't 100% follow sierra here: - sierra didn't wrap around when changing item id
- // - sierra allowed item id to be 0, which didnt make any sense
+ // We don't 100% follow sierra here:
+ // - sierra didn't wrap around when changing item id
+ // - sierra allowed item id to be 0, which didn't make any sense
do {
switch (curEvent.data) {
case SCI_KEY_ESC:
@@ -796,25 +822,26 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() {
}
break;
case SCI_EVENT_NONE:
- _event->sleep(2500 / 1000);
+ g_sci->sleep(2500 / 1000);
break;
}
}
}
-// Mouse button is currently pressed - we are now interpreting mouse coordinates till mouse button is released
-// The menu item that is selected at that time is chosen. If no menu item is selected we cancel
-// No keyboard interaction is allowed, cause that wouldnt make any sense at all
+// Mouse button is currently pressed - we are now interpreting mouse coordinates
+// till mouse button is released. The menu item that is selected at that time is
+// chosen. If no menu item is selected we cancel. No keyboard interaction is
+// allowed, cause that wouldnt make any sense at all.
GuiMenuItemEntry *GfxMenu::interactiveWithMouse() {
- sciEvent curEvent;
+ SciEvent curEvent;
uint16 newMenuId = 0, newItemId = 0;
uint16 curMenuId = 0, curItemId = 0;
Common::Point mousePosition = _cursor->getPosition();
bool firstMenuChange = true;
GuiMenuItemEntry *curItemEntry = NULL;
- calculateMenuAndItemWidth();
_oldPort = _ports->setPort(_ports->_menuPort);
+ calculateMenuAndItemWidth();
_barSaveHandle = _paint16->bitsSave(_ports->_menuRect, GFX_SCREEN_MASK_VISUAL);
_ports->penColor(0);
@@ -824,7 +851,7 @@ GuiMenuItemEntry *GfxMenu::interactiveWithMouse() {
_paint16->bitsShow(_ports->_menuRect);
while (true) {
- curEvent = _event->get(SCI_EVENT_ANY);
+ curEvent = _event->getSciEvent(SCI_EVENT_ANY);
switch (curEvent.type) {
case SCI_EVENT_MOUSE_RELEASE:
@@ -835,7 +862,7 @@ GuiMenuItemEntry *GfxMenu::interactiveWithMouse() {
return curItemEntry;
case SCI_EVENT_NONE:
- _event->sleep(2500 / 1000);
+ g_sci->sleep(2500 / 1000);
break;
}
diff --git a/engines/sci/graphics/menu.h b/engines/sci/graphics/menu.h
index 8f23b46ff8..9a14d4c64a 100644
--- a/engines/sci/graphics/menu.h
+++ b/engines/sci/graphics/menu.h
@@ -83,7 +83,7 @@ typedef Common::List<GuiMenuItemEntry *> GuiMenuItemList;
*/
class GfxMenu {
public:
- GfxMenu(SciEvent *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor);
+ GfxMenu(EventManager *event, SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor);
~GfxMenu();
void reset();
@@ -92,7 +92,7 @@ public:
reg_t kernelGetAttribute(uint16 menuId, uint16 itemId, uint16 attributeId);
void drawBar();
- reg_t kernelSelect(reg_t eventObject);
+ reg_t kernelSelect(reg_t eventObject, bool pauseSound);
void kernelDrawStatus(const char *text, int16 colorPen, int16 colorBack);
void kernelDrawMenuBar(bool clear);
@@ -103,17 +103,16 @@ private:
void calculateMenuAndItemWidth();
void drawMenu(uint16 oldMenuId, uint16 newMenuId);
void invertMenuSelection(uint16 itemId);
- void interactiveShowMouse();
- void interactiveRestoreMouse();
+ void interactiveStart(bool pauseSound);
+ void interactiveEnd(bool pauseSound);
GuiMenuItemEntry *interactiveWithKeyboard();
GuiMenuItemEntry *interactiveWithMouse();
uint16 mouseFindMenuSelection(Common::Point mousePosition);
uint16 mouseFindMenuItemSelection(Common::Point mousePosition, uint16 menuId);
GuiMenuItemEntry *interactiveGetItem(uint16 menuId, uint16 itemId, bool menuChanged);
- SciEvent *_event;
+ EventManager *_event;
SegManager *_segMan;
- SciGui *_gui;
GfxPorts *_ports;
GfxPaint16 *_paint16;
GfxText16 *_text16;
diff --git a/engines/sci/graphics/paint.cpp b/engines/sci/graphics/paint.cpp
index 13dcebc27a..50b0534ba7 100644
--- a/engines/sci/graphics/paint.cpp
+++ b/engines/sci/graphics/paint.cpp
@@ -49,8 +49,4 @@ void GfxPaint::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, ui
void GfxPaint::kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control) {
}
-void GfxPaint::kernelShakeScreen(uint16 shakeCount, uint16 directions) {
- warning("Unimplemented kShakeScreen");
-}
-
} // End of namespace Sci
diff --git a/engines/sci/graphics/paint.h b/engines/sci/graphics/paint.h
index f1342d55e5..994bc4e5e9 100644
--- a/engines/sci/graphics/paint.h
+++ b/engines/sci/graphics/paint.h
@@ -26,8 +26,6 @@
#ifndef SCI_GRAPHICS_PAINT_H
#define SCI_GRAPHICS_PAINT_H
-#include "sci/graphics/gui.h"
-
#include "common/hashmap.h"
namespace Sci {
@@ -40,10 +38,6 @@ public:
virtual void kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo);
virtual void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle);
virtual void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control);
-
- virtual void kernelShakeScreen(uint16 shakeCount, uint16 directions);
-
-private:
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp
index d0975f3d3d..4551e9dafc 100644
--- a/engines/sci/graphics/paint16.cpp
+++ b/engines/sci/graphics/paint16.cpp
@@ -32,6 +32,7 @@
#include "sci/engine/features.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
+#include "sci/engine/workarounds.h"
#include "sci/graphics/cache.h"
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/ports.h"
@@ -42,13 +43,14 @@
#include "sci/graphics/view.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/portrait.h"
#include "sci/graphics/text16.h"
#include "sci/graphics/transitions.h"
namespace Sci {
-GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, SciGui *gui, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions)
- : _resMan(resMan), _segMan(segMan), _kernel(kernel), _gui(gui), _cache(cache), _ports(ports), _coordAdjuster(coordAdjuster), _screen(screen), _palette(palette), _transitions(transitions) {
+GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio)
+ : _resMan(resMan), _segMan(segMan), _kernel(kernel), _cache(cache), _ports(ports), _coordAdjuster(coordAdjuster), _screen(screen), _palette(palette), _transitions(transitions), _audio(audio) {
}
GfxPaint16::~GfxPaint16() {
@@ -61,7 +63,7 @@ void GfxPaint16::init(GfxAnimate *animate, GfxText16 *text16) {
_EGAdrawingVisualize = false;
}
-void GfxPaint16::setEGAdrawingVisualize(bool state) {
+void GfxPaint16::debugSetEGAdrawingVisualize(bool state) {
_EGAdrawingVisualize = state;
}
@@ -74,6 +76,11 @@ void GfxPaint16::drawPicture(GuiResourceId pictureId, int16 animationNr, bool mi
picture->draw(animationNr, mirroredFlag, addToFlag, paletteId);
delete picture;
+
+ // We make a call to SciPalette here, for increasing sys timestamp and also loading targetpalette, if palvary active
+ // (SCI1.1 only)
+ if (getSciVersion() == SCI_VERSION_1_1)
+ _palette->drewPicture(pictureId);
}
// This one is the only one that updates screen!
@@ -101,12 +108,12 @@ void GfxPaint16::drawCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo,
}
// This version of drawCel is not supposed to call BitsShow()!
-void GfxPaint16::drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) {
+void GfxPaint16::drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) {
drawCel(_cache->getView(viewId), loopNo, celNo, celRect, priority, paletteNo, scaleX, scaleY);
}
// This version of drawCel is not supposed to call BitsShow()!
-void GfxPaint16::drawCel(GfxView *view, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) {
+void GfxPaint16::drawCel(GfxView *view, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) {
Common::Rect clipRect = celRect;
clipRect.clip(_ports->_curPort->rect);
if (clipRect.isEmpty()) // nothing to draw
@@ -121,8 +128,8 @@ void GfxPaint16::drawCel(GfxView *view, int16 loopNo, int16 celNo, Common::Rect
}
}
-// This is used as replacement for drawCelAndShow() when hires-cels are drawn to screen
-// Hires-cels are available only SCI 1.1+
+// This is used as replacement for drawCelAndShow() when hires-cels are drawn to
+// screen. Hires-cels are available only SCI 1.1+.
void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, reg_t upscaledHiresHandle, uint16 scaleX, uint16 scaleY) {
GfxView *view = _cache->getView(viewId);
Common::Rect celRect, curPortRect, clipRect, clipRectTranslated;
@@ -131,9 +138,10 @@ void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 c
if (view) {
if ((leftPos == 0) && (topPos == 0)) {
- // HACK: in kq6, we get leftPos&topPos == 0 SOMETIMES, that's why we need to get coordinates from upscaledHiresHandle
- // I'm not sure if this is what we are supposed to do or if there is some other bug that actually makes
- // coordinates to be 0 in the first place
+ // HACK: in kq6, we get leftPos&topPos == 0 SOMETIMES, that's why we
+ // need to get coordinates from upscaledHiresHandle. I'm not sure if
+ // this is what we are supposed to do or if there is some other bug
+ // that actually makes coordinates to be 0 in the first place.
byte *memoryPtr = NULL;
memoryPtr = _segMan->getHunkPointer(upscaledHiresHandle);
if (memoryPtr) {
@@ -310,11 +318,12 @@ reg_t GfxPaint16::bitsSave(const Common::Rect &rect, byte screenMask) {
return NULL_REG;
if (screenMask == GFX_SCREEN_MASK_DISPLAY) {
+ // The coordinates we are given are actually up-to-including right/bottom - we extend accordingly
+ workerRect.bottom++;
+ workerRect.right++;
// Adjust rect to upscaled hires, but dont adjust according to port
_screen->adjustToUpscaledCoordinates(workerRect.top, workerRect.left);
_screen->adjustToUpscaledCoordinates(workerRect.bottom, workerRect.right);
- workerRect.bottom++;
- workerRect.right++;
} else {
_ports->offsetRect(workerRect);
}
@@ -324,7 +333,8 @@ reg_t GfxPaint16::bitsSave(const Common::Rect &rect, byte screenMask) {
memoryId = _segMan->allocateHunkEntry("SaveBits()", size);
memoryPtr = _segMan->getHunkPointer(memoryId);
- _screen->bitsSave(workerRect, screenMask, memoryPtr);
+ if (memoryPtr)
+ _screen->bitsSave(workerRect, screenMask, memoryPtr);
return memoryId;
}
@@ -354,7 +364,8 @@ void GfxPaint16::bitsRestore(reg_t memoryHandle) {
}
void GfxPaint16::bitsFree(reg_t memoryHandle) {
- _segMan->freeHunkEntry(memoryHandle);
+ if (!memoryHandle.isNull()) // happens in KQ5CD
+ _segMan->freeHunkEntry(memoryHandle);
}
void GfxPaint16::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo) {
@@ -372,28 +383,29 @@ void GfxPaint16::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, b
_ports->setPort(oldPort);
}
-void GfxPaint16::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle) {
- // some calls are hiresMode even under kq6 DOS, that's why we check for upscaled hires here
+void GfxPaint16::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY, bool hiresMode, reg_t upscaledHiresHandle) {
+ // some calls are hiresMode even under kq6 DOS, that's why we check for
+ // upscaled hires here
if ((!hiresMode) || (!_screen->getUpscaledHires())) {
- drawCelAndShow(viewId, loopNo, celNo, leftPos, topPos, priority, paletteNo);
+ drawCelAndShow(viewId, loopNo, celNo, leftPos, topPos, priority, paletteNo, scaleX, scaleY);
} else {
drawHiresCelAndShow(viewId, loopNo, celNo, leftPos, topPos, priority, paletteNo, upscaledHiresHandle);
}
}
-void GfxPaint16::kernelGraphFillBoxForeground(Common::Rect rect) {
+void GfxPaint16::kernelGraphFillBoxForeground(const Common::Rect &rect) {
paintRect(rect);
}
-void GfxPaint16::kernelGraphFillBoxBackground(Common::Rect rect) {
+void GfxPaint16::kernelGraphFillBoxBackground(const Common::Rect &rect) {
eraseRect(rect);
}
-void GfxPaint16::kernelGraphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control) {
+void GfxPaint16::kernelGraphFillBox(const Common::Rect &rect, uint16 colorMask, int16 color, int16 priority, int16 control) {
fillRect(rect, colorMask, color, priority, control);
}
-void GfxPaint16::kernelGraphFrameBox(Common::Rect rect, int16 color) {
+void GfxPaint16::kernelGraphFrameBox(const Common::Rect &rect, int16 color) {
int16 oldColor = _ports->getPort()->penClr;
_ports->penColor(color);
frameRect(rect);
@@ -405,11 +417,11 @@ void GfxPaint16::kernelGraphDrawLine(Common::Point startPoint, Common::Point end
_screen->drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, color, priority, control);
}
-reg_t GfxPaint16::kernelGraphSaveBox(Common::Rect rect, uint16 screenMask) {
+reg_t GfxPaint16::kernelGraphSaveBox(const Common::Rect &rect, uint16 screenMask) {
return bitsSave(rect, screenMask);
}
-reg_t GfxPaint16::kernelGraphSaveUpscaledHiresBox(Common::Rect rect) {
+reg_t GfxPaint16::kernelGraphSaveUpscaledHiresBox(const Common::Rect &rect) {
return bitsSave(rect, GFX_SCREEN_MASK_DISPLAY);
}
@@ -417,8 +429,9 @@ void GfxPaint16::kernelGraphRestoreBox(reg_t handle) {
bitsRestore(handle);
}
-void GfxPaint16::kernelGraphUpdateBox(Common::Rect rect, bool hiresMode) {
- // some calls are hiresMode even under kq6 DOS, that's why we check for upscaled hires here
+void GfxPaint16::kernelGraphUpdateBox(const Common::Rect &rect, bool hiresMode) {
+ // some calls are hiresMode even under kq6 DOS, that's why we check for
+ // upscaled hires here
if ((!hiresMode) || (!_screen->getUpscaledHires()))
bitsShow(rect);
else
@@ -446,17 +459,20 @@ void GfxPaint16::kernelGraphRedrawBox(Common::Rect rect) {
#define SCI_DISPLAY_WIDTH 106
#define SCI_DISPLAY_SAVEUNDER 107
#define SCI_DISPLAY_RESTOREUNDER 108
+#define SCI_DISPLAY_DUMMY1 114 // used in longbow demo/qfg1 ega demo, not supported in sierra sci - no parameters
+#define SCI_DISPLAY_DUMMY2 115 // used in longbow demo, not supported in sierra sci - has 1 parameter
#define SCI_DISPLAY_DONTSHOWBITS 121
reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
- int displayArg;
+ reg_t displayArg;
TextAlignment alignment = SCI_TEXT16_ALIGNMENT_LEFT;
int16 colorPen = -1, colorBack = -1, width = -1, bRedraw = 1;
bool doSaveUnder = false;
Common::Rect rect;
reg_t result = NULL_REG;
- // Make a "backup" of the port settings (required for some SCI0LATE and SCI01+ only)
+ // Make a "backup" of the port settings (required for some SCI0LATE and
+ // SCI01+ only)
Port oldPort = *_ports->getPort();
// setting defaults
@@ -465,9 +481,11 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
_ports->textGreyedOutput(false);
// processing codes in argv
while (argc > 0) {
- displayArg = argv[0].toUint16();
+ displayArg = argv[0];
+ if (displayArg.segment)
+ displayArg.offset = 0xFFFF;
argc--; argv++;
- switch (displayArg) {
+ switch (displayArg.offset) {
case SCI_DISPLAY_MOVEPEN:
_ports->moveTo(argv[0].toUint16(), argv[1].toUint16());
argc -= 2; argv += 2;
@@ -511,8 +529,27 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
case SCI_DISPLAY_DONTSHOWBITS:
bRedraw = 0;
break;
+
+ // 2 Dummy functions, longbow-demo is using those several times but sierra sci doesn't support them at all
+ // The Quest for Glory 1 EGA demo also calls kDisplay(114)
+ case SCI_DISPLAY_DUMMY1:
+ case SCI_DISPLAY_DUMMY2:
+ if (!g_sci->isDemo() || (g_sci->getGameId() != GID_LONGBOW && g_sci->getGameId() != GID_QFG1))
+ error("Unknown kDisplay argument %d", displayArg.offset);
+ if (displayArg.offset == SCI_DISPLAY_DUMMY2) {
+ if (argc) {
+ argc--; argv++;
+ } else {
+ error("No parameter left for kDisplay(115)");
+ }
+ }
+ break;
default:
- warning("Unknown kDisplay argument %X", displayArg);
+ SciTrackOriginReply originReply;
+ SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, kDisplay_workarounds, &originReply);
+ if (solution.type == WORKAROUND_NONE)
+ error("Unknown kDisplay argument (%04x:%04x) from method %s::%s (script %d, localCall %x)", PRINT_REG(displayArg), originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset);
+ assert(solution.type == WORKAROUND_IGNORE);
break;
}
}
@@ -539,14 +576,20 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
uint16 tTop = currport->curTop;
uint16 tLeft = currport->curLeft;
if (!g_sci->_features->usesOldGfxFunctions()) {
- // Restore port settings for some SCI0LATE and SCI01+ only
- // the change actually happened inbetween .530 (hoyle1) and .566 (heros quest). We don't have any detection for
- // that currently, so we are using oldGfxFunctions (.502). The only games that could get regressions because of
- // this are hoyle1, kq4 and funseeker. If there are regressions, we should use interpreter version (which would
- // require exe version detection)
- // If we restore the port for whole SCI0LATE, at least sq3old will get an issue - font 0 will get used when
- // scanning for planets instead of font 600 - a setfont parameter is missing in one of the kDisplay calls in
- // script 19. I assume this is a script bug, because it was added in sq3new.
+ // Restore port settings for some SCI0LATE and SCI01+ only.
+ //
+ // The change actually happened inbetween .530 (hoyle1) and .566 (heros
+ // quest). We don't have any detection for that currently, so we are
+ // using oldGfxFunctions (.502). The only games that could get
+ // regressions because of this are hoyle1, kq4 and funseeker. If there
+ // are regressions, we should use interpreter version (which would
+ // require exe version detection).
+ //
+ // If we restore the port for whole SCI0LATE, at least sq3old will get
+ // an issue - font 0 will get used when scanning for planets instead of
+ // font 600 - a setfont parameter is missing in one of the kDisplay
+ // calls in script 19. I assume this is a script bug, because it was
+ // added in sq3new.
*currport = oldPort;
}
currport->curTop = tTop;
@@ -554,19 +597,23 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
return result;
}
-// TODO: If this matches the sci32 implementation, we may put it into GfxScreen
-void GfxPaint16::kernelShakeScreen(uint16 shakeCount, uint16 directions) {
- while (shakeCount--) {
- if (directions & SCI_SHAKE_DIRECTION_VERTICAL)
- _screen->setVerticalShakePos(10);
- // TODO: horizontal shakes
- g_system->updateScreen();
- _gui->wait(3);
- if (directions & SCI_SHAKE_DIRECTION_VERTICAL)
- _screen->setVerticalShakePos(0);
- g_system->updateScreen();
- _gui->wait(3);
- }
+reg_t GfxPaint16::kernelPortraitLoad(const Common::String &resourceName) {
+ //Portrait *myPortrait = new Portrait(g_sci->getResMan(), _screen, _palette, resourceName);
+ return NULL_REG;
+}
+
+void GfxPaint16::kernelPortraitShow(const Common::String &resourceName, Common::Point position, uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq) {
+ Portrait *myPortrait = new Portrait(g_sci->getResMan(), g_sci->getEventManager(), _screen, _palette, _audio, resourceName);
+ // TODO: cache portraits
+ // adjust given coordinates to curPort (but dont adjust coordinates on upscaledHires_Save_Box and give us hires coordinates
+ // on kDrawCel, yeah this whole stuff makes sense)
+ position.x += _ports->getPort()->left; position.y += _ports->getPort()->top;
+ _screen->adjustToUpscaledCoordinates(position.y, position.x);
+ myPortrait->doit(position, resourceId, noun, verb, cond, seq);
+ delete myPortrait;
+}
+
+void GfxPaint16::kernelPortraitUnload(uint16 portraitId) {
}
} // End of namespace Sci
diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h
index b18c879387..e944c71bdd 100644
--- a/engines/sci/graphics/paint16.h
+++ b/engines/sci/graphics/paint16.h
@@ -26,7 +26,6 @@
#ifndef SCI_GRAPHICS_PAINT16_H
#define SCI_GRAPHICS_PAINT16_H
-#include "sci/graphics/gui.h"
#include "sci/graphics/paint.h"
#include "common/hashmap.h"
@@ -45,17 +44,17 @@ class GfxView;
*/
class GfxPaint16 : public GfxPaint {
public:
- GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, SciGui *gui, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions);
+ GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio);
~GfxPaint16();
void init(GfxAnimate *animate, GfxText16 *text16);
- void setEGAdrawingVisualize(bool state);
+ void debugSetEGAdrawingVisualize(bool state);
void drawPicture(GuiResourceId pictureId, int16 animationNr, bool mirroredFlag, bool addToFlag, GuiResourceId paletteId);
void drawCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128);
- void drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128);
- void drawCel(GfxView *view, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128);
+ void drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128);
+ void drawCel(GfxView *view, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128);
void drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, reg_t upscaledHiresHandle, uint16 scaleX = 128, uint16 scaleY = 128);
void clearScreen(byte color = 255);
@@ -74,28 +73,30 @@ public:
void bitsFree(reg_t memoryHandle);
void kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo);
- void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle);
+ void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY, bool hiresMode, reg_t upscaledHiresHandle);
- void kernelGraphFillBoxForeground(Common::Rect rect);
- void kernelGraphFillBoxBackground(Common::Rect rect);
- void kernelGraphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control);
- void kernelGraphFrameBox(Common::Rect rect, int16 color);
+ void kernelGraphFillBoxForeground(const Common::Rect &rect);
+ void kernelGraphFillBoxBackground(const Common::Rect &rect);
+ void kernelGraphFillBox(const Common::Rect &rect, uint16 colorMask, int16 color, int16 priority, int16 control);
+ void kernelGraphFrameBox(const Common::Rect &rect, int16 color);
void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control);
- reg_t kernelGraphSaveBox(Common::Rect rect, uint16 flags);
- reg_t kernelGraphSaveUpscaledHiresBox(Common::Rect rect);
+ reg_t kernelGraphSaveBox(const Common::Rect &rect, uint16 flags);
+ reg_t kernelGraphSaveUpscaledHiresBox(const Common::Rect &rect);
void kernelGraphRestoreBox(reg_t handle);
- void kernelGraphUpdateBox(Common::Rect rect, bool hiresMode);
+ void kernelGraphUpdateBox(const Common::Rect &rect, bool hiresMode);
void kernelGraphRedrawBox(Common::Rect rect);
reg_t kernelDisplay(const char *text, int argc, reg_t *argv);
- void kernelShakeScreen(uint16 shakeCount, uint16 directions);
+ reg_t kernelPortraitLoad(const Common::String &resourceName);
+ void kernelPortraitShow(const Common::String &resourceName, Common::Point position, uint16 resourceNum, uint16 noun, uint16 verb, uint16 cond, uint16 seq);
+ void kernelPortraitUnload(uint16 portraitId);
private:
ResourceManager *_resMan;
SegManager *_segMan;
Kernel *_kernel;
- SciGui *_gui;
+ AudioPlayer *_audio;
GfxAnimate *_animate;
GfxCache *_cache;
GfxPorts *_ports;
diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp
index 711efc9816..9b24da413b 100644
--- a/engines/sci/graphics/paint32.cpp
+++ b/engines/sci/graphics/paint32.cpp
@@ -38,6 +38,7 @@
#include "sci/graphics/view.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/robot.h"
namespace Sci {
@@ -79,4 +80,10 @@ void GfxPaint32::kernelGraphDrawLine(Common::Point startPoint, Common::Point end
_screen->drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, color, priority, control);
}
+void GfxPaint32::debugDrawRobot(GuiResourceId robotId) {
+ GfxRobot *test = new GfxRobot(g_sci->getResMan(), _screen, robotId);
+ test->draw();
+ delete test;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/paint32.h b/engines/sci/graphics/paint32.h
index f4d6340361..a048d7f307 100644
--- a/engines/sci/graphics/paint32.h
+++ b/engines/sci/graphics/paint32.h
@@ -26,7 +26,6 @@
#ifndef SCI_GRAPHICS_PAINT32_H
#define SCI_GRAPHICS_PAINT32_H
-#include "sci/graphics/gui.h"
#include "sci/graphics/paint.h"
#include "common/hashmap.h"
@@ -49,6 +48,8 @@ public:
void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle);
void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control);
+ void debugDrawRobot(GuiResourceId robotId);
+
private:
ResourceManager *_resMan;
SegManager *_segMan;
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index 6fe472f5fa..5c17f76558 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -30,12 +30,15 @@
#include "sci/sci.h"
#include "sci/engine/state.h"
-#include "sci/graphics/screen.h"
+#include "sci/graphics/cache.h"
+#include "sci/graphics/maciconbar.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/screen.h"
+#include "sci/graphics/view.h"
namespace Sci {
-GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool autoSetPalette)
+GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool useMerging)
: _resMan(resMan), _screen(screen) {
int16 color;
@@ -56,23 +59,41 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool autoSetP
_sysPalette.colors[255].b = 255;
_sysPaletteChanged = false;
- if (autoSetPalette) {
- if (_resMan->getViewType() == kViewEga)
- setEGA();
- else if (_resMan->isAmiga32color())
- setAmiga();
- else
- kernelSetFromResource(999, true);
- }
+
+ // Quest for Glory 3 demo, Eco Quest 1 demo, Laura Bow 2 demo, Police Quest
+ // 1 vga and all Nick's Picks all use the older palette format and thus are
+ // not using the SCI1.1 palette merging (copying over all the colors) but
+ // the real merging done in earlier games. If we use the copying over, we
+ // will get issues because some views have marked all colors as being used
+ // and those will overwrite the current palette in that case
+ _useMerging = useMerging;
+
+ palVaryInit();
}
GfxPalette::~GfxPalette() {
+ if (_palVaryResourceId != -1)
+ palVaryRemoveTimer();
+}
+
+bool GfxPalette::isMerging() {
+ return _useMerging;
+}
+
+// meant to get called only once during init of engine
+void GfxPalette::setDefault() {
+ if (_resMan->getViewType() == kViewEga)
+ setEGA();
+ else if (_resMan->isAmiga32color())
+ setAmiga();
+ else
+ kernelSetFromResource(999, true);
}
#define SCI_PAL_FORMAT_CONSTANT 1
#define SCI_PAL_FORMAT_VARIABLE 0
-void GfxPalette::createFromData(byte *data, Palette *paletteOut) {
+void GfxPalette::createFromData(byte *data, int bytesLeft, Palette *paletteOut) {
int palFormat = 0;
int palOffset = 0;
int palColorStart = 0;
@@ -80,10 +101,18 @@ void GfxPalette::createFromData(byte *data, Palette *paletteOut) {
int colorNo = 0;
memset(paletteOut, 0, sizeof(Palette));
- // Setup default mapping
+ // Setup 1:1 mapping
for (colorNo = 0; colorNo < 256; colorNo++) {
paletteOut->mapping[colorNo] = colorNo;
}
+ if (bytesLeft < 37) {
+ // This happens when loading palette of picture 0 in sq5 - the resource is broken and doesn't contain a full
+ // palette
+ debugC(2, "GfxPalette::createFromData() - not enough bytes in resource (%d), expected palette header", bytesLeft);
+ return;
+ }
+ // palette formats in here are not really version exclusive, we can not use sci-version to differentiate between them
+ // they were just called that way, because they started appearing in sci1.1 for example
if ((data[0] == 0 && data[1] == 1) || (data[0] == 0 && data[1] == 0 && READ_LE_UINT16(data + 29) == 0)) {
// SCI0/SCI1 palette
palFormat = SCI_PAL_FORMAT_VARIABLE; // CONSTANT;
@@ -98,6 +127,11 @@ void GfxPalette::createFromData(byte *data, Palette *paletteOut) {
}
switch (palFormat) {
case SCI_PAL_FORMAT_CONSTANT:
+ // Check, if enough bytes left
+ if (bytesLeft < palOffset + (3 * palColorCount)) {
+ warning("GfxPalette::createFromData() - not enough bytes in resource, expected palette colors");
+ return;
+ }
for (colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) {
paletteOut->colors[colorNo].used = 1;
paletteOut->colors[colorNo].r = data[palOffset++];
@@ -106,6 +140,10 @@ void GfxPalette::createFromData(byte *data, Palette *paletteOut) {
}
break;
case SCI_PAL_FORMAT_VARIABLE:
+ if (bytesLeft < palOffset + (4 * palColorCount)) {
+ warning("GfxPalette::createFromData() - not enough bytes in resource, expected palette colors");
+ return;
+ }
for (colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) {
paletteOut->colors[colorNo].used = data[palOffset++];
paletteOut->colors[colorNo].r = data[palOffset++];
@@ -179,112 +217,144 @@ void GfxPalette::setEGA() {
// Now setting colors 16-254 to the correct mix colors that occur when not doing a dithering run on
// finished pictures
for (curColor = 0x10; curColor <= 0xFE; curColor++) {
- _sysPalette.colors[curColor].used = curColor;
+ _sysPalette.colors[curColor].used = 1;
color1 = curColor & 0x0F; color2 = curColor >> 4;
_sysPalette.colors[curColor].r = (_sysPalette.colors[color1].r >> 1) + (_sysPalette.colors[color2].r >> 1);
_sysPalette.colors[curColor].g = (_sysPalette.colors[color1].g >> 1) + (_sysPalette.colors[color2].g >> 1);
_sysPalette.colors[curColor].b = (_sysPalette.colors[color1].b >> 1) + (_sysPalette.colors[color2].b >> 1);
}
+ _sysPalette.timestamp = 1;
setOnScreen();
}
-void GfxPalette::set(Palette *sciPal, bool force, bool forceRealMerge) {
+void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) {
uint32 systime = _sysPalette.timestamp;
- if (force || sciPal->timestamp != systime) {
- _sysPaletteChanged |= merge(sciPal, &_sysPalette, force, forceRealMerge);
- sciPal->timestamp = _sysPalette.timestamp;
- if (_sysPaletteChanged && _screen->_picNotValid == 0) { // && systime != _sysPalette.timestamp) {
- // Removed timestamp checking, because this shouldnt be needed anymore. I'm leaving it commented just in
- // case this causes regressions
+ if (force || newPalette->timestamp != systime) {
+ // SCI1.1+ doesnt do real merging anymore, but simply copying over the used colors from other palettes
+ // There are some games with inbetween SCI1.1 interpreters, use real merging for them (e.g. laura bow 2 demo)
+ if ((forceRealMerge) || (_useMerging))
+ _sysPaletteChanged |= merge(newPalette, force, forceRealMerge);
+ else
+ _sysPaletteChanged |= insert(newPalette, &_sysPalette);
+
+ // Adjust timestamp on newPalette, so it wont get merged/inserted w/o need
+ newPalette->timestamp = _sysPalette.timestamp;
+
+ bool updatePalette = _sysPaletteChanged && _screen->_picNotValid == 0;
+
+ if (_palVaryResourceId != -1) {
+ // Pal-vary currently active, we don't set at any time, but also insert into origin palette
+ insert(newPalette, &_palVaryOriginPalette);
+ palVaryProcess(0, updatePalette);
+ return;
+ }
+
+ if (updatePalette) {
setOnScreen();
_sysPaletteChanged = false;
}
}
}
-bool GfxPalette::merge(Palette *pFrom, Palette *pTo, bool force, bool forceRealMerge) {
+bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) {
+ bool paletteChanged = false;
+
+ for (int i = 1; i < 255; i++) {
+ if (newPalette->colors[i].used) {
+ if ((newPalette->colors[i].r != destPalette->colors[i].r) || (newPalette->colors[i].g != destPalette->colors[i].g) || (newPalette->colors[i].b != destPalette->colors[i].b)) {
+ destPalette->colors[i].r = newPalette->colors[i].r;
+ destPalette->colors[i].g = newPalette->colors[i].g;
+ destPalette->colors[i].b = newPalette->colors[i].b;
+ paletteChanged = true;
+ }
+ destPalette->colors[i].used = newPalette->colors[i].used;
+ newPalette->mapping[i] = i;
+ }
+ }
+ // We don't update the timestamp for SCI1.1, it's only updated on kDrawPic calls
+ return paletteChanged;
+}
+
+bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
uint16 res;
int i,j;
bool paletteChanged = false;
- if ((!forceRealMerge) && (getSciVersion() >= SCI_VERSION_1_1)) {
- // SCI1.1+ doesnt do real merging anymore, but simply copying over the used colors from other palettes
- for (i = 1; i < 255; i++) {
- if (pFrom->colors[i].used) {
- if ((pFrom->colors[i].r != pTo->colors[i].r) || (pFrom->colors[i].g != pTo->colors[i].g) || (pFrom->colors[i].b != pTo->colors[i].b)) {
- pTo->colors[i].r = pFrom->colors[i].r;
- pTo->colors[i].g = pFrom->colors[i].g;
- pTo->colors[i].b = pFrom->colors[i].b;
- paletteChanged = true;
- }
- pTo->colors[i].used = pFrom->colors[i].used;
- pFrom->mapping[i] = i;
+ // colors 0 (black) and 255 (white) are not affected by merging
+ for (i = 1 ; i < 255; i++) {
+ if (!newPalette->colors[i].used)// color is not used - so skip it
+ continue;
+ // forced palette merging or dest color is not used yet
+ if (force || (!_sysPalette.colors[i].used)) {
+ _sysPalette.colors[i].used = newPalette->colors[i].used;
+ if ((newPalette->colors[i].r != _sysPalette.colors[i].r) || (newPalette->colors[i].g != _sysPalette.colors[i].g) || (newPalette->colors[i].b != _sysPalette.colors[i].b)) {
+ _sysPalette.colors[i].r = newPalette->colors[i].r;
+ _sysPalette.colors[i].g = newPalette->colors[i].g;
+ _sysPalette.colors[i].b = newPalette->colors[i].b;
+ paletteChanged = true;
}
+ newPalette->mapping[i] = i;
+ continue;
}
- } else {
- // colors 0 (black) and 255 (white) are not affected by merging
- for (i = 1 ; i < 255; i++) {
- if (!pFrom->colors[i].used)// color is not used - so skip it
- continue;
- // forced palette merging or dest color is not used yet
- if (force || (!pTo->colors[i].used)) {
- pTo->colors[i].used = pFrom->colors[i].used;
- if ((pFrom->colors[i].r != pTo->colors[i].r) || (pFrom->colors[i].g != pTo->colors[i].g) || (pFrom->colors[i].b != pTo->colors[i].b)) {
- pTo->colors[i].r = pFrom->colors[i].r;
- pTo->colors[i].g = pFrom->colors[i].g;
- pTo->colors[i].b = pFrom->colors[i].b;
- paletteChanged = true;
- }
- pFrom->mapping[i] = i;
- continue;
- }
- // is the same color already at the same position? -> match it directly w/o lookup
- // this fixes games like lsl1demo/sq5 where the same rgb color exists multiple times and where we would
- // otherwise match the wrong one (which would result into the pixels affected (or not) by palette changes)
- if ((pTo->colors[i].r == pFrom->colors[i].r) && (pTo->colors[i].g == pFrom->colors[i].g) && (pTo->colors[i].b == pFrom->colors[i].b)) {
- pFrom->mapping[i] = i;
- continue;
- }
- // check if exact color could be matched
- res = matchColor(pTo, pFrom->colors[i].r, pFrom->colors[i].g, pFrom->colors[i].b);
- if (res & 0x8000) { // exact match was found
- pFrom->mapping[i] = res & 0xFF;
- continue;
- }
- // no exact match - see if there is an unused color
- for (j = 1; j < 256; j++)
- if (!pTo->colors[j].used) {
- pTo->colors[j].used = pFrom->colors[i].used;
- pTo->colors[j].r = pFrom->colors[i].r;
- pTo->colors[j].g = pFrom->colors[i].g;
- pTo->colors[j].b = pFrom->colors[i].b;
- pFrom->mapping[i] = j;
- paletteChanged = true;
- break;
- }
- // if still no luck - set an approximate color
- if (j == 256) {
- pFrom->mapping[i] = res & 0xFF;
- pTo->colors[res & 0xFF].used |= 0x10;
+ // is the same color already at the same position? -> match it directly w/o lookup
+ // this fixes games like lsl1demo/sq5 where the same rgb color exists multiple times and where we would
+ // otherwise match the wrong one (which would result into the pixels affected (or not) by palette changes)
+ if ((_sysPalette.colors[i].r == newPalette->colors[i].r) && (_sysPalette.colors[i].g == newPalette->colors[i].g) && (_sysPalette.colors[i].b == newPalette->colors[i].b)) {
+ newPalette->mapping[i] = i;
+ continue;
+ }
+ // check if exact color could be matched
+ res = matchColor(newPalette->colors[i].r, newPalette->colors[i].g, newPalette->colors[i].b);
+ if (res & 0x8000) { // exact match was found
+ newPalette->mapping[i] = res & 0xFF;
+ continue;
+ }
+ // no exact match - see if there is an unused color
+ for (j = 1; j < 256; j++)
+ if (!_sysPalette.colors[j].used) {
+ _sysPalette.colors[j].used = newPalette->colors[i].used;
+ _sysPalette.colors[j].r = newPalette->colors[i].r;
+ _sysPalette.colors[j].g = newPalette->colors[i].g;
+ _sysPalette.colors[j].b = newPalette->colors[i].b;
+ newPalette->mapping[i] = j;
+ paletteChanged = true;
+ break;
}
+ // if still no luck - set an approximate color
+ if (j == 256) {
+ newPalette->mapping[i] = res & 0xFF;
+ _sysPalette.colors[res & 0xFF].used |= 0x10;
}
}
- pTo->timestamp = g_system->getMillis() * 60 / 1000;
+
+ if (!forceRealMerge)
+ _sysPalette.timestamp = g_system->getMillis() * 60 / 1000;
return paletteChanged;
}
-uint16 GfxPalette::matchColor(Palette *pPal, byte r, byte g, byte b) {
+// This is called for SCI1.1, when kDrawPic got done. We update sysPalette timestamp this way for SCI1.1 and also load
+// target-palette, if palvary is active
+void GfxPalette::drewPicture(GuiResourceId pictureId) {
+ if (!_useMerging) // Don't do this on inbetween SCI1.1 games
+ _sysPalette.timestamp++;
+
+ if (_palVaryResourceId != -1) {
+ palVaryLoadTargetPalette(pictureId);
+ }
+}
+
+uint16 GfxPalette::matchColor(byte r, byte g, byte b) {
byte found = 0xFF;
int diff = 0x2FFFF, cdiff;
int16 dr,dg,db;
for (int i = 1; i < 255; i++) {
- if ((!pPal->colors[i].used))
+ if ((!_sysPalette.colors[i].used))
continue;
- dr = pPal->colors[i].r - r;
- dg = pPal->colors[i].g - g;
- db = pPal->colors[i].b - b;
+ dr = _sysPalette.colors[i].r - r;
+ dg = _sysPalette.colors[i].g - g;
+ db = _sysPalette.colors[i].b - b;
// minimum squares match
cdiff = (dr*dr) + (dg*dg) + (db*db);
// minimum sum match (Sierra's)
@@ -305,20 +375,22 @@ void GfxPalette::getSys(Palette *pal) {
}
void GfxPalette::setOnScreen() {
-// if (pal != &_sysPalette)
-// memcpy(&_sysPalette,pal,sizeof(Palette));
// We dont change palette at all times for amiga
if (_resMan->isAmiga32color())
return;
_screen->setPalette(&_sysPalette);
+
+ // Redraw the Mac SCI1.1 Icon bar every palette change
+ if (g_sci->_gfxMacIconBar)
+ g_sci->_gfxMacIconBar->drawIcons();
}
bool GfxPalette::kernelSetFromResource(GuiResourceId resourceId, bool force) {
- Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), 0);
+ Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false);
Palette palette;
if (palResource) {
- createFromData(palResource->data, &palette);
+ createFromData(palResource->data, palResource->size, &palette);
set(&palette, force);
return true;
}
@@ -341,12 +413,18 @@ void GfxPalette::kernelUnsetFlag(uint16 fromColor, uint16 toColor, uint16 flag)
void GfxPalette::kernelSetIntensity(uint16 fromColor, uint16 toColor, uint16 intensity, bool setPalette) {
memset(&_sysPalette.intensity[0] + fromColor, intensity, toColor - fromColor);
- if (setPalette)
+ if (setPalette) {
setOnScreen();
+ EngineState *state = g_sci->getEngineState();
+ // Call speed throttler from here as well just in case we need it
+ // At least in kq6 intro the scripts call us in a tight loop for fadein/fadeout
+ state->speedThrottler(30);
+ state->_throttleTrigger = true;
+ }
}
int16 GfxPalette::kernelFindColor(uint16 r, uint16 g, uint16 b) {
- return matchColor(&_sysPalette, r, g, b) & 0xFF;
+ return matchColor(r, g, b) & 0xFF;
}
// Returns true, if palette got changed
@@ -373,6 +451,8 @@ bool GfxPalette::kernelAnimate(byte fromColor, byte toColor, int speed) {
scheduleCount++;
}
+ g_sci->getEngineState()->_throttleTrigger = true;
+
for (scheduleNr = 0; scheduleNr < scheduleCount; scheduleNr++) {
if (_schedules[scheduleNr].from == fromColor) {
if (_schedules[scheduleNr].schedule <= now) {
@@ -408,8 +488,58 @@ void GfxPalette::kernelAnimateSet() {
setOnScreen();
}
+reg_t GfxPalette::kernelSave() {
+ SegManager *segMan = g_sci->getEngineState()->_segMan;
+ reg_t memoryId = segMan->allocateHunkEntry("kPalette(save)", 1024);
+ byte *memoryPtr = segMan->getHunkPointer(memoryId);
+ if (memoryPtr) {
+ for (int colorNr = 0; colorNr < 256; colorNr++) {
+ *memoryPtr++ = _sysPalette.colors[colorNr].used;
+ *memoryPtr++ = _sysPalette.colors[colorNr].r;
+ *memoryPtr++ = _sysPalette.colors[colorNr].g;
+ *memoryPtr++ = _sysPalette.colors[colorNr].b;
+ }
+ }
+ return memoryId;
+}
+
+void GfxPalette::kernelRestore(reg_t memoryHandle) {
+ SegManager *segMan = g_sci->getEngineState()->_segMan;
+ if (!memoryHandle.isNull()) {
+ byte *memoryPtr = segMan->getHunkPointer(memoryHandle);
+ if (!memoryPtr)
+ error("Bad handle used for kPalette(restore)");
+
+ Palette restoredPalette;
+
+ restoredPalette.timestamp = 0;
+ for (int colorNr = 0; colorNr < 256; colorNr++) {
+ restoredPalette.colors[colorNr].used = *memoryPtr++;
+ restoredPalette.colors[colorNr].r = *memoryPtr++;
+ restoredPalette.colors[colorNr].g = *memoryPtr++;
+ restoredPalette.colors[colorNr].b = *memoryPtr++;
+ }
+
+ set(&restoredPalette, true);
+ }
+}
+
void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) {
- warning("kAssertPalette %d", resourceId);
+ // Sometimes invalid viewIds are asked for, ignore those (e.g. qfg1vga)
+ //if (!_resMan->testResource(ResourceId(kResourceTypeView, resourceId)))
+ // return;
+ // maybe we took the wrong parameter before, if this causes invalid view again, enable to commented out code again
+
+ GfxView *view = g_sci->_gfxCache->getView(resourceId);
+ Palette *viewPalette = view->getPalette();
+ if (viewPalette) {
+ // merge/insert this palette
+ set(viewPalette, true);
+ }
+}
+
+void GfxPalette::kernelSyncScreenPalette() {
+ _screen->getPalette(&_sysPalette);
}
// palVary
@@ -438,40 +568,191 @@ void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) {
// Saving/restoring
// need to save start and target-palette, when palVaryOn = true
-void GfxPalette::startPalVary(uint16 paletteId, uint16 ticks) {
- kernelSetFromResource(paletteId, true);
- return;
+void GfxPalette::palVaryInit() {
+ _palVaryResourceId = -1;
+ _palVaryPaused = 0;
+ _palVarySignal = 0;
+ _palVaryStep = 0;
+ _palVaryStepStop = 0;
+ _palVaryDirection = 0;
+ _palVaryTicks = 0;
+}
- if (_palVaryId >= 0) // another palvary is taking place, return
- return;
+bool GfxPalette::palVaryLoadTargetPalette(GuiResourceId resourceId) {
+ _palVaryResourceId = resourceId;
+ Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false);
+ if (palResource) {
+ // Load and initialize destination palette
+ createFromData(palResource->data, palResource->size, &_palVaryTargetPalette);
+ return true;
+ }
+ return false;
+}
+
+void GfxPalette::palVaryInstallTimer() {
+ int16 ticks = _palVaryTicks > 0 ? _palVaryTicks : 1;
+ // Call signal increase every [ticks]
+ g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this);
+}
+
+void GfxPalette::palVaryRemoveTimer() {
+ g_sci->getTimerManager()->removeTimerProc(&palVaryCallback);
+}
+
+bool GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, uint16 direction) {
+ if (_palVaryResourceId != -1) // another palvary is taking place, return
+ return false;
+
+ if (palVaryLoadTargetPalette(resourceId)) {
+ // Save current palette
+ memcpy(&_palVaryOriginPalette, &_sysPalette, sizeof(Palette));
+
+ _palVarySignal = 0;
+ _palVaryTicks = ticks;
+ _palVaryStep = 1;
+ _palVaryStepStop = stepStop;
+ _palVaryDirection = direction;
+ // if no ticks are given, jump directly to destination
+ if (!_palVaryTicks)
+ _palVaryDirection = stepStop;
+ palVaryInstallTimer();
+ return true;
+ }
+ return false;
+}
+
+int16 GfxPalette::kernelPalVaryReverse(int16 ticks, uint16 stepStop, int16 direction) {
+ if (_palVaryResourceId == -1)
+ return 0;
+
+ if (_palVaryStep > 64)
+ _palVaryStep = 64;
+ if (ticks != -1)
+ _palVaryTicks = ticks;
+ _palVaryStepStop = stepStop;
+ _palVaryDirection = direction != -1 ? -direction : -_palVaryDirection;
+
+ if (!_palVaryTicks)
+ _palVaryDirection = _palVaryStepStop - _palVaryStep;
+ palVaryInstallTimer();
+ return kernelPalVaryGetCurrentStep();
+}
+
+int16 GfxPalette::kernelPalVaryGetCurrentStep() {
+ if (_palVaryDirection >= 0)
+ return _palVaryStep;
+ return -_palVaryStep;
+}
+
+int16 GfxPalette::kernelPalVaryChangeTarget(GuiResourceId resourceId) {
+ if (_palVaryResourceId != -1) {
+ Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false);
+ if (palResource) {
+ Palette insertPalette;
+ createFromData(palResource->data, palResource->size, &insertPalette);
+ // insert new palette into target
+ insert(&insertPalette, &_palVaryTargetPalette);
+ // update palette and set on screen
+ palVaryProcess(0, true);
+ }
+ }
+ return kernelPalVaryGetCurrentStep();
+}
- _palVaryId = paletteId;
- _palVaryStart = g_system->getMillis();
- _palVaryEnd = _palVaryStart + ticks * 1000 / 60;
- g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000 / 60, this);
+void GfxPalette::kernelPalVaryChangeTicks(uint16 ticks) {
+ _palVaryTicks = ticks;
+ if (_palVaryStep - _palVaryStepStop) {
+ palVaryRemoveTimer();
+ palVaryInstallTimer();
+ }
}
-void GfxPalette::togglePalVary(bool pause) {
+void GfxPalette::kernelPalVaryPause(bool pause) {
+ if (_palVaryResourceId == -1)
+ return;
// this call is actually counting states, so calling this 3 times with true will require calling it later
// 3 times with false to actually remove pause
-
- // TODO
+ if (pause) {
+ _palVaryPaused++;
+ } else {
+ if (_palVaryPaused)
+ _palVaryPaused--;
+ }
}
-void GfxPalette::stopPalVary() {
- g_sci->getTimerManager()->removeTimerProc(&palVaryCallback);
- _palVaryId = -1; // invalidate the target palette
+void GfxPalette::kernelPalVaryDeinit() {
+ palVaryRemoveTimer();
- // HACK: just set the target palette
- kernelSetFromResource(_palVaryId, true);
+ _palVaryResourceId = -1; // invalidate the target palette
}
void GfxPalette::palVaryCallback(void *refCon) {
- ((GfxPalette *)refCon)->doPalVary();
+ ((GfxPalette *)refCon)->palVaryIncreaseSignal();
+}
+
+void GfxPalette::palVaryIncreaseSignal() {
+ if (!_palVaryPaused)
+ _palVarySignal++;
}
-void GfxPalette::doPalVary() {
- // TODO: do palette transition here...
+// Actually do the pal vary processing
+void GfxPalette::palVaryUpdate() {
+ if (_palVarySignal) {
+ palVaryProcess(_palVarySignal, true);
+ _palVarySignal = 0;
+ }
+}
+
+void GfxPalette::palVaryPrepareForTransition() {
+ if (_palVaryResourceId != -1) {
+ // Before doing transitions, we have to prepare palette
+ palVaryProcess(0, false);
+ }
+}
+
+// Processes pal vary updates
+void GfxPalette::palVaryProcess(int signal, bool setPalette) {
+ int16 stepChange = signal * _palVaryDirection;
+
+ _palVaryStep += stepChange;
+ if (stepChange > 0) {
+ if (_palVaryStep > _palVaryStepStop)
+ _palVaryStep = _palVaryStepStop;
+ } else {
+ if (_palVaryStep < _palVaryStepStop) {
+ if (signal)
+ _palVaryStep = _palVaryStepStop;
+ }
+ }
+
+ // We don't need updates anymore, if we reached end-position
+ if (_palVaryStep == _palVaryStepStop)
+ palVaryRemoveTimer();
+ if (_palVaryStep == 0)
+ _palVaryResourceId = -1;
+
+ // Calculate inbetween palette
+ Sci::Color inbetween;
+ int16 color;
+ for (int colorNr = 1; colorNr < 255; colorNr++) {
+ inbetween.used = _sysPalette.colors[colorNr].used;
+ color = _palVaryTargetPalette.colors[colorNr].r - _palVaryOriginPalette.colors[colorNr].r;
+ inbetween.r = ((color * _palVaryStep) / 64) + _palVaryOriginPalette.colors[colorNr].r;
+ color = _palVaryTargetPalette.colors[colorNr].g - _palVaryOriginPalette.colors[colorNr].g;
+ inbetween.g = ((color * _palVaryStep) / 64) + _palVaryOriginPalette.colors[colorNr].g;
+ color = _palVaryTargetPalette.colors[colorNr].b - _palVaryOriginPalette.colors[colorNr].b;
+ inbetween.b = ((color * _palVaryStep) / 64) + _palVaryOriginPalette.colors[colorNr].b;
+
+ if (memcmp(&inbetween, &_sysPalette.colors[colorNr], sizeof(Sci::Color))) {
+ _sysPalette.colors[colorNr] = inbetween;
+ _sysPaletteChanged = true;
+ }
+ }
+
+ if ((_sysPaletteChanged) && (setPalette) && (_screen->_picNotValid == 0)) {
+ setOnScreen();
+ _sysPaletteChanged = false;
+ }
}
} // End of namespace Sci
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 46fec48739..e10c10718d 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -34,22 +34,28 @@ class Screen;
/**
* Palette class, handles palette operations like changing intensity, setting up the palette, merging different palettes
*/
-class GfxPalette {
+class GfxPalette : public Common::Serializable {
public:
- GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool autoSetPalette = true);
+ GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool useMerging);
~GfxPalette();
- void createFromData(byte *data, Palette *paletteOut);
+ bool isMerging();
+
+ void setDefault();
+ void createFromData(byte *data, int bytesLeft, Palette *paletteOut);
bool setAmiga();
void modifyAmigaPalette(byte *data);
void setEGA();
void set(Palette *sciPal, bool force, bool forceRealMerge = false);
- bool merge(Palette *pFrom, Palette *pTo, bool force, bool forceRealMerge);
- uint16 matchColor(Palette *pPal, byte r, byte g, byte b);
+ bool insert(Palette *newPalette, Palette *destPalette);
+ bool merge(Palette *pFrom, bool force, bool forceRealMerge);
+ uint16 matchColor(byte r, byte g, byte b);
void getSys(Palette *pal);
void setOnScreen();
+ void drewPicture(GuiResourceId pictureId);
+
bool kernelSetFromResource(GuiResourceId resourceId, bool force);
void kernelSetFlag(uint16 fromColor, uint16 toColor, uint16 flag);
void kernelUnsetFlag(uint16 fromColor, uint16 toColor, uint16 flag);
@@ -57,27 +63,53 @@ public:
int16 kernelFindColor(uint16 r, uint16 g, uint16 b);
bool kernelAnimate(byte fromColor, byte toColor, int speed);
void kernelAnimateSet();
+ reg_t kernelSave();
+ void kernelRestore(reg_t memoryHandle);
void kernelAssertPalette(GuiResourceId resourceId);
- void startPalVary(uint16 paletteId, uint16 ticks);
- void togglePalVary(bool pause);
- void stopPalVary();
+ void kernelSyncScreenPalette();
+
+ bool kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, uint16 direction);
+ int16 kernelPalVaryReverse(int16 ticks, uint16 stepStop, int16 direction);
+ int16 kernelPalVaryGetCurrentStep();
+ int16 kernelPalVaryChangeTarget(GuiResourceId resourceId);
+ void kernelPalVaryChangeTicks(uint16 ticks);
+ void kernelPalVaryPause(bool pause);
+ void kernelPalVaryDeinit();
+ void palVaryUpdate();
+ void palVaryPrepareForTransition();
+ void palVaryProcess(int signal, bool setPalette);
Palette _sysPalette;
+ virtual void saveLoadWithSerializer(Common::Serializer &s);
+ void palVarySaveLoadPalette(Common::Serializer &s, Palette *palette);
+
private:
+ void palVaryInit();
+ void palVaryInstallTimer();
+ void palVaryRemoveTimer();
+ bool palVaryLoadTargetPalette(GuiResourceId resourceId);
static void palVaryCallback(void *refCon);
- void doPalVary();
+ void palVaryIncreaseSignal();
GfxScreen *_screen;
ResourceManager *_resMan;
- int16 _palVaryId;
- uint32 _palVaryStart;
- uint32 _palVaryEnd;
bool _sysPaletteChanged;
+ bool _useMerging;
Common::Array<PalSchedule> _schedules;
+
+ GuiResourceId _palVaryResourceId;
+ Palette _palVaryOriginPalette;
+ Palette _palVaryTargetPalette;
+ int16 _palVaryStep;
+ int16 _palVaryStepStop;
+ int16 _palVaryDirection;
+ uint16 _palVaryTicks;
+ int _palVaryPaused;
+ int _palVarySignal;
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp
index 74f651a88a..e568316919 100644
--- a/engines/sci/graphics/picture.cpp
+++ b/engines/sci/graphics/picture.cpp
@@ -43,10 +43,11 @@ GfxPicture::GfxPicture(ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster,
}
GfxPicture::~GfxPicture() {
+ _resMan->unlockResource(_resource);
}
void GfxPicture::initData(GuiResourceId resourceId) {
- _resource = _resMan->findResource(ResourceId(kResourceTypePic, resourceId), false);
+ _resource = _resMan->findResource(ResourceId(kResourceTypePic, resourceId), true);
if (!_resource) {
error("picture resource %d not found", resourceId);
}
@@ -56,7 +57,9 @@ GuiResourceId GfxPicture::getResourceId() {
return _resourceId;
}
-// TODO: subclass this
+// differentiation between various picture formats can NOT get done using sci-version checks.
+// Games like PQ1 use the "old" vector data picture format, but are actually SCI1.1
+// We should leave this that way to decide the format on-the-fly instead of hardcoding it in any way
void GfxPicture::draw(int16 animationNr, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo) {
uint16 headerSize;
@@ -69,15 +72,18 @@ void GfxPicture::draw(int16 animationNr, bool mirroredFlag, bool addToFlag, int1
headerSize = READ_LE_UINT16(_resource->data);
switch (headerSize) {
case 0x26: // SCI 1.1 VGA picture
+ _resourceType = SCI_PICTURE_TYPE_SCI11;
drawSci11Vga();
break;
#ifdef ENABLE_SCI32
case 0x0e: // SCI32 VGA picture
- drawSci32Vga();
+ _resourceType = SCI_PICTURE_TYPE_SCI32;
+ //drawSci32Vga();
break;
#endif
default:
// VGA, EGA or Amiga vector data
+ _resourceType = SCI_PICTURE_TYPE_REGULAR;
drawVectorData(_resource->data, _resource->size);
}
}
@@ -94,29 +100,46 @@ void GfxPicture::reset() {
void GfxPicture::drawSci11Vga() {
byte *inbuffer = _resource->data;
int size = _resource->size;
- int has_cel = READ_LE_UINT16(inbuffer + 4);
- int vector_dataPos = READ_LE_UINT16(inbuffer + 16);
+ int priorityBandsCount = inbuffer[3];
+ int has_cel = inbuffer[4];
+ int vector_dataPos = READ_LE_UINT32(inbuffer + 16);
int vector_size = size - vector_dataPos;
- int palette_data_ptr = READ_LE_UINT16(inbuffer + 28);
- int cel_headerPos = READ_LE_UINT16(inbuffer + 32);
- int cel_RlePos = READ_LE_UINT16(inbuffer + cel_headerPos + 24);
- int cel_LiteralPos = READ_LE_UINT16(inbuffer + cel_headerPos + 28);
+ int palette_data_ptr = READ_LE_UINT32(inbuffer + 28);
+ int cel_headerPos = READ_LE_UINT32(inbuffer + 32);
+ int cel_RlePos = READ_LE_UINT32(inbuffer + cel_headerPos + 24);
+ int cel_LiteralPos = READ_LE_UINT32(inbuffer + cel_headerPos + 28);
Palette palette;
+ // Header
+ // [headerSize:WORD] [unknown:BYTE] [priorityBandCount:BYTE] [hasCel:BYTE] [unknown:BYTE]
+ // [unknown:WORD] [unknown:WORD] [unknown:WORD] [unknown:WORD] [unknown:WORD]
+ // Offset 16
+ // [vectorDataOffset:DWORD] [unknown:DWORD] [unknown:DWORD] [paletteDataOffset:DWORD]
+ // Offset 32
+ // [celHeaderOffset:DWORD] [unknown:DWORD]
+ // [priorityBandData:WORD] * priorityBandCount
+ // [priority:BYTE] [unknown:BYTE]
+
// Create palette and set it
- _palette->createFromData(inbuffer + palette_data_ptr, &palette);
+ _palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette);
_palette->set(&palette, true);
- // display Cel-data
- if (has_cel) {
- drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, 0, 0, false);
+ // priority bands are supposed to be 14 for sci1.1 pictures
+ assert(priorityBandsCount == 14);
+
+ if (_addToFlag) {
+ _priority = inbuffer[40 + priorityBandsCount * 2] & 0xF;
}
+ // display Cel-data
+ if (has_cel)
+ drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, 0, 0, 0);
+
// process vector data
drawVectorData(inbuffer + vector_dataPos, vector_size);
- // Remember priority band information for later
- _ports->priorityBandsRemember(inbuffer + 40);
+ // Set priority band information
+ _ports->priorityBandsInitSci11(inbuffer + 40);
}
#ifdef ENABLE_SCI32
@@ -125,44 +148,80 @@ int16 GfxPicture::getSci32celCount() {
return inbuffer[2];
}
-void GfxPicture::drawSci32Vga(int16 celNo) {
+int16 GfxPicture::getSci32celY(int16 celNo) {
+ byte *inbuffer = _resource->data;
+ int header_size = READ_LE_UINT16(inbuffer);
+ int cel_headerPos = header_size + 42 * celNo;
+ return READ_LE_UINT16(inbuffer + cel_headerPos + 40);
+}
+
+int16 GfxPicture::getSci32celX(int16 celNo) {
+ byte *inbuffer = _resource->data;
+ int header_size = READ_LE_UINT16(inbuffer);
+ int cel_headerPos = header_size + 42 * celNo;
+ return READ_LE_UINT16(inbuffer + cel_headerPos + 38);
+}
+
+int16 GfxPicture::getSci32celWidth(int16 celNo) {
+ byte *inbuffer = _resource->data;
+ int header_size = READ_LE_UINT16(inbuffer);
+ int cel_headerPos = header_size + 42 * celNo;
+ return READ_LE_UINT16(inbuffer + cel_headerPos + 0);
+}
+
+int16 GfxPicture::getSci32celPriority(int16 celNo) {
+ byte *inbuffer = _resource->data;
+ int header_size = READ_LE_UINT16(inbuffer);
+ int cel_headerPos = header_size + 42 * celNo;
+ return READ_LE_UINT16(inbuffer + cel_headerPos + 36);
+}
+
+void GfxPicture::drawSci32Vga(int16 celNo, int16 drawX, int16 drawY, int16 pictureX, bool mirrored) {
byte *inbuffer = _resource->data;
int size = _resource->size;
int header_size = READ_LE_UINT16(inbuffer);
int palette_data_ptr = READ_LE_UINT16(inbuffer + 6);
- int celCount = inbuffer[2];
+// int celCount = inbuffer[2];
int cel_headerPos = header_size;
int cel_RlePos, cel_LiteralPos;
- int cel_relXpos, cel_relYpos;
Palette palette;
// HACK
- _mirroredFlag = false;
+ _mirroredFlag = mirrored;
_addToFlag = false;
+ _resourceType = SCI_PICTURE_TYPE_SCI32;
- if ((celNo == -1) || (celNo == 0)) {
+ if (celNo == 0) {
// Create palette and set it
- _palette->createFromData(inbuffer + palette_data_ptr, &palette);
+ _palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette);
_palette->set(&palette, true);
}
- if (celNo != -1) {
- cel_headerPos += 42 * celNo;
- celCount = 1;
- }
- while (celCount > 0) {
- cel_RlePos = READ_LE_UINT32(inbuffer + cel_headerPos + 24);
- cel_LiteralPos = READ_LE_UINT32(inbuffer + cel_headerPos + 28);
- cel_relXpos = READ_LE_UINT16(inbuffer + cel_headerPos + 38);
- cel_relYpos = READ_LE_UINT16(inbuffer + cel_headerPos + 40);
- drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, cel_relXpos, cel_relYpos, true);
- cel_headerPos += 42;
- celCount--;
+ // Header
+ // [headerSize:WORD] [celCount:BYTE] [Unknown:BYTE] [Unknown:WORD] [paletteOffset:DWORD] [Unknown:DWORD]
+ // cel-header follow afterwards, each is 42 bytes
+ // Cel-Header
+ // [width:WORD] [height:WORD] [displaceX:WORD] [displaceY:WORD] [clearColor:BYTE] [compressed:BYTE]
+ // offset 10-23 is unknown
+ // [rleOffset:DWORD] [literalOffset:DWORD] [Unknown:WORD] [Unknown:WORD] [priority:WORD] [relativeXpos:WORD] [relativeYpos:WORD]
+
+ cel_headerPos += 42 * celNo;
+
+ if (mirrored) {
+ // switch around relativeXpos
+ Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea();
+ drawX = displayArea.width() - drawX - READ_LE_UINT16(inbuffer + cel_headerPos + 0);
}
+
+ cel_RlePos = READ_LE_UINT32(inbuffer + cel_headerPos + 24);
+ cel_LiteralPos = READ_LE_UINT32(inbuffer + cel_headerPos + 28);
+
+ drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, drawX, drawY, pictureX);
+ cel_headerPos += 42;
}
#endif
-void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 callerX, int16 callerY, bool hasSci32Header) {
+void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX) {
byte *celBitmap = NULL;
byte *ptr = NULL;
byte *headerPtr = inbuffer + headerPos;
@@ -179,11 +238,16 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
int pixelNr, pixelCount;
#ifdef ENABLE_SCI32
- if (!hasSci32Header) {
+ if (_resourceType != SCI_PICTURE_TYPE_SCI32) {
#endif
displaceX = (signed char)headerPtr[4];
displaceY = (unsigned char)headerPtr[5];
- clearColor = headerPtr[6];
+ if (_resourceType == SCI_PICTURE_TYPE_SCI11) {
+ // SCI1.1 uses hardcoded clearcolor for pictures, even if cel header specifies otherwise
+ clearColor = _screen->getColorWhite();
+ } else {
+ clearColor = headerPtr[6];
+ }
#ifdef ENABLE_SCI32
} else {
displaceX = READ_LE_UINT16(headerPtr + 4); // probably signed?!?
@@ -285,52 +349,71 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea();
- y = callerY + displayArea.top;
- lastY = MIN<int16>(height + y, displayArea.bottom);
- leftX = callerX + displayArea.left;
- rightX = MIN<int16>(width + leftX, displayArea.right);
-
- // Change clearcolor to white, if we dont add to an existing picture. That way we will paint everything on screen
- // but white and that wont matter because the screen is supposed to be already white. It seems that most (if not all)
- // SCI1.1 games use color 0 as transparency and SCI1 games use color 255 as transparency. Sierra SCI seems to paint
- // the whole data to screen and wont skip over transparent pixels. So this will actually make it work like Sierra
- if (!_addToFlag)
- clearColor = _screen->getColorWhite();
-
- ptr = celBitmap;
- if (!_mirroredFlag) {
- // Draw bitmap to screen
- x = leftX;
- while (y < lastY) {
- curByte = *ptr++;
- if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y)))
- _screen->putPixel(x, y, GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY, curByte, priority, 0);
-
- x++;
-
- if (x >= rightX) {
- if (width > rightX - leftX) // Skip extra pixels at the end of the row
- ptr += width - (rightX - leftX);
- x = leftX;
- y++;
- }
+ uint16 skipCelBitmapPixels = 0;
+ int16 displayWidth = width;
+ if (pictureX) {
+ // scroll position for picture active, we need to adjust drawX accordingly
+ drawX -= pictureX;
+ if (drawX < 0) {
+ skipCelBitmapPixels = -drawX;
+ displayWidth -= skipCelBitmapPixels;
+ drawX = 0;
}
- } else {
- // Draw bitmap to screen (mirrored)
- x = rightX - 1;
- while (y < lastY) {
- curByte = *ptr++;
- if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y)))
- _screen->putPixel(x, y, GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY, curByte, priority, 0);
-
- if (x == leftX) {
- if (width > rightX - leftX) // Skip extra pixels at the end of the row
- ptr += width - (rightX - leftX);
- x = rightX;
- y++;
+ }
+
+ if (displayWidth > 0) {
+ y = displayArea.top + drawY;
+ lastY = MIN<int16>(height + y, displayArea.bottom);
+ leftX = displayArea.left + drawX;
+ rightX = MIN<int16>(displayWidth + leftX, displayArea.right);
+
+ uint16 sourcePixelSkipPerRow = 0;
+ if (width > rightX - leftX)
+ sourcePixelSkipPerRow = width - (rightX - leftX);
+
+ // Change clearcolor to white, if we dont add to an existing picture. That way we will paint everything on screen
+ // but white and that wont matter because the screen is supposed to be already white. It seems that most (if not all)
+ // SCI1.1 games use color 0 as transparency and SCI1 games use color 255 as transparency. Sierra SCI seems to paint
+ // the whole data to screen and wont skip over transparent pixels. So this will actually make it work like Sierra
+ if (!_addToFlag)
+ clearColor = _screen->getColorWhite();
+
+ byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY;
+
+ ptr = celBitmap;
+ ptr += skipCelBitmapPixels;
+ if (!_mirroredFlag) {
+ // Draw bitmap to screen
+ x = leftX;
+ while (y < lastY) {
+ curByte = *ptr++;
+ if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y)))
+ _screen->putPixel(x, y, drawMask, curByte, priority, 0);
+
+ x++;
+
+ if (x >= rightX) {
+ ptr += sourcePixelSkipPerRow;
+ x = leftX;
+ y++;
+ }
}
+ } else {
+ // Draw bitmap to screen (mirrored)
+ x = rightX - 1;
+ while (y < lastY) {
+ curByte = *ptr++;
+ if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y)))
+ _screen->putPixel(x, y, drawMask, curByte, priority, 0);
+
+ if (x == leftX) {
+ ptr += sourcePixelSkipPerRow;
+ x = rightX;
+ y++;
+ }
- x--;
+ x--;
+ }
}
}
@@ -427,7 +510,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
memcpy(&EGApalettes[i], &vector_defaultEGApalette, sizeof(vector_defaultEGApalette));
memcpy(&EGApriority, &vector_defaultEGApriority, sizeof(vector_defaultEGApriority));
- if (strcmp(g_sci->getGameID(), "iceman") == 0) {
+ if (g_sci->getGameId() == GID_ICEMAN) {
// WORKAROUND: we remove certain visual&priority lines in underwater rooms of iceman, when not dithering the
// picture. Normally those lines aren't shown, because they share the same color as the dithered
// fill color combination. When not dithering, those lines would appear and get distracting.
@@ -518,10 +601,30 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
}
break;
+ // Pattern opcodes are handled in sierra sci1.1+ as actual NOPs and normally they definitely should not occur
+ // inside picture data for such games
case PIC_OP_SET_PATTERN:
+ if (_resourceType >= SCI_PICTURE_TYPE_SCI11) {
+ if (g_sci->getGameId() == GID_SQ4) {
+ // WORKAROUND: For SQ4 / for some pictures handle this like a terminator
+ // This picture includes garbage data, first a set pattern w/o parameter and then short pattern
+ // I guess that garbage is a left over from the sq4-floppy (sci1) to sq4-cd (sci1.1) conversion
+ switch (_resourceId) {
+ case 35:
+ case 381:
+ case 376:
+ return;
+ default:
+ break;
+ }
+ }
+ error("pic-operation set pattern inside sci1.1+ vector data");
+ }
pattern_Code = data[curPos++];
break;
case PIC_OP_SHORT_PATTERNS:
+ if (_resourceType >= SCI_PICTURE_TYPE_SCI11)
+ error("pic-operation short pattern inside sci1.1+ vector data");
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
vectorGetAbsCoords(data, curPos, x, y);
vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
@@ -532,6 +635,8 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
}
break;
case PIC_OP_MEDIUM_PATTERNS:
+ if (_resourceType >= SCI_PICTURE_TYPE_SCI11)
+ error("pic-operation medium pattern inside sci1.1+ vector data");
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
vectorGetAbsCoords(data, curPos, x, y);
vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
@@ -542,6 +647,8 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
}
break;
case PIC_OP_ABSOLUTE_PATTERN:
+ if (_resourceType >= SCI_PICTURE_TYPE_SCI11)
+ error("pic-operation absolute pattern inside sci1.1+ vector data");
while (vectorIsNonOpcode(data[curPos])) {
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
vectorGetAbsCoords(data, curPos, x, y);
@@ -585,7 +692,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
vectorGetAbsCoordsNoMirror(data, curPos, x, y);
size = READ_LE_UINT16(data + curPos); curPos += 2;
_priority = pic_priority; // set global priority so the cel gets drawn using current priority as well
- drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y, false);
+ drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y, 0);
curPos += size;
break;
case PIC_OPX_EGA_SET_PRIORITY_TABLE:
@@ -625,9 +732,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
vectorGetAbsCoordsNoMirror(data, curPos, x, y);
size = READ_LE_UINT16(data + curPos); curPos += 2;
_priority = pic_priority; // set global priority so the cel gets drawn using current priority as well
- if (pic_priority == 255)
- _priority = 0; // if priority not set, use priority 0
- drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y, false);
+ drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y, 0);
curPos += size;
break;
case PIC_OPX_VGA_PRIORITY_TABLE_EQDIST:
diff --git a/engines/sci/graphics/picture.h b/engines/sci/graphics/picture.h
index 3374c33b52..7cd0d71b67 100644
--- a/engines/sci/graphics/picture.h
+++ b/engines/sci/graphics/picture.h
@@ -32,6 +32,12 @@ namespace Sci {
#define SCI_PATTERN_CODE_USE_TEXTURE 0x20
#define SCI_PATTERN_CODE_PENSIZE 0x07
+enum {
+ SCI_PICTURE_TYPE_REGULAR = 0,
+ SCI_PICTURE_TYPE_SCI11 = 1,
+ SCI_PICTURE_TYPE_SCI32 = 2
+};
+
class GfxPorts;
class GfxScreen;
class GfxPalette;
@@ -50,14 +56,18 @@ public:
#ifdef ENABLE_SCI32
int16 getSci32celCount();
- void drawSci32Vga(int16 celNo = -1);
+ int16 getSci32celY(int16 celNo);
+ int16 getSci32celX(int16 celNo);
+ int16 getSci32celWidth(int16 celNo);
+ int16 getSci32celPriority(int16 celNo);
+ void drawSci32Vga(int16 celNo, int16 callerX, int16 callerY, int16 pictureX, bool mirrored);
#endif
private:
void initData(GuiResourceId resourceId);
void reset();
void drawSci11Vga();
- void drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 callerX, int16 callerY, bool hasSci32Header);
+ void drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX);
void drawVectorData(byte *data, int size);
bool vectorIsNonOpcode(byte pixel);
void vectorGetAbsCoords(byte *data, int &curPos, int16 &x, int16 &y);
@@ -80,6 +90,7 @@ private:
int16 _resourceId;
Resource *_resource;
+ int _resourceType;
int16 _animationNr;
bool _mirroredFlag;
diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp
index 1208f8ed65..8f4fe094a8 100644
--- a/engines/sci/graphics/portrait.cpp
+++ b/engines/sci/graphics/portrait.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "common/archive.h"
#include "common/util.h"
#include "common/stack.h"
#include "graphics/primitives.h"
@@ -30,7 +31,6 @@
#include "sci/sci.h"
#include "sci/event.h"
#include "sci/engine/state.h"
-#include "sci/graphics/gui.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/palette.h"
#include "sci/graphics/portrait.h"
@@ -38,8 +38,8 @@
namespace Sci {
-Portrait::Portrait(ResourceManager *resMan, SciEvent *event, SciGui *gui, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName)
- : _resMan(resMan), _event(event), _gui(gui), _screen(screen), _palette(palette), _audio(audio), _resourceName(resourceName) {
+Portrait::Portrait(ResourceManager *resMan, EventManager *event, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName)
+ : _resMan(resMan), _event(event), _screen(screen), _palette(palette), _audio(audio), _resourceName(resourceName) {
init();
}
@@ -166,7 +166,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint
// Do animation depending on sync resource till audio is done playing
uint16 syncCue;
int timerPosition, curPosition;
- sciEvent curEvent;
+ SciEvent curEvent;
bool userAbort = false;
while ((syncOffset < syncResource->size - 2) && (!userAbort)) {
@@ -181,8 +181,8 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint
// Wait till syncTime passed, then show specific animation bitmap
do {
- _gui->wait(1);
- curEvent = _event->get(SCI_EVENT_ANY);
+ g_sci->getEngineState()->wait(1);
+ curEvent = _event->getSciEvent(SCI_EVENT_ANY);
if (curEvent.type == SCI_EVENT_MOUSE_PRESS ||
(curEvent.type == SCI_EVENT_KEYBOARD && curEvent.data == SCI_KEY_ESC) ||
g_engine->shouldQuit())
diff --git a/engines/sci/graphics/portrait.h b/engines/sci/graphics/portrait.h
index 4b22e209a3..7da9425c9d 100644
--- a/engines/sci/graphics/portrait.h
+++ b/engines/sci/graphics/portrait.h
@@ -42,7 +42,7 @@ struct PortraitBitmap {
*/
class Portrait {
public:
- Portrait(ResourceManager *resMan, SciEvent *event, SciGui *gui, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName);
+ Portrait(ResourceManager *resMan, EventManager *event, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName);
~Portrait();
void setupAudio(uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq);
@@ -56,8 +56,7 @@ private:
void bitsShow();
ResourceManager *_resMan;
- SciEvent *_event;
- SciGui *_gui;
+ EventManager *_event;
GfxPalette *_palette;
GfxScreen *_screen;
AudioPlayer *_audio;
diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp
index ab3291dd79..0a0e49235e 100644
--- a/engines/sci/graphics/ports.cpp
+++ b/engines/sci/graphics/ports.cpp
@@ -27,7 +27,9 @@
#include "sci/sci.h"
#include "sci/engine/features.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
+#include "sci/engine/selector.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/paint16.h"
#include "sci/graphics/animate.h"
@@ -50,18 +52,22 @@ GfxPorts::GfxPorts(SegManager *segMan, GfxScreen *screen)
}
GfxPorts::~GfxPorts() {
- // TODO: Clear _windowList and delete all stuff in it?
+ // reset frees all windows but _picWind
+ reset();
+ freeWindow(_picWind);
+ delete _wmgrPort;
delete _menuPort;
}
-void GfxPorts::init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, GfxText16 *text16, Common::String gameId) {
+void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *text16) {
int16 offTop = 10;
_usesOldGfxFunctions = usesOldGfxFunctions;
- _gui = gui;
_paint16 = paint16;
_text16 = text16;
+ _freeCounter = 0;
+
// _menuPort has actually hardcoded id 0xFFFF. Its not meant to be known to windowmanager according to sierra sci
_menuPort = new Port(0xFFFF);
openPort(_menuPort);
@@ -85,37 +91,103 @@ void GfxPorts::init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16,
else
_styleUser = SCI_WINDOWMGR_STYLE_USER | SCI_WINDOWMGR_STYLE_TRANSPARENT;
- // Jones, Slater and Hoyle 3 were called with parameter -Nw 0 0 200 320.
- // Mother Goose (SCI1) uses -Nw 0 0 159 262. The game will later use SetPort so we don't need to set the other fields.
+ // Jones, Slater, Hoyle 3&4 and Crazy Nicks Laura Bow/Kings Quest were
+ // called with parameter -Nw 0 0 200 320.
+ // Mother Goose (SCI1) uses -Nw 0 0 159 262. The game will later use
+ // SetPort so we don't need to set the other fields.
// This actually meant not skipping the first 10 pixellines in windowMgrPort
- if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY))
+ switch (g_sci->getGameId()) {
+ case GID_JONES:
+ case GID_SLATER:
+ case GID_HOYLE3:
+ case GID_HOYLE4:
+ case GID_CNICK_LAURABOW:
+ case GID_CNICK_KQ:
offTop = 0;
+ break;
+ case GID_MOTHERGOOSE:
+ // TODO: if mother goose EGA also uses offTop we can simply remove this check altogether
+ switch (getSciVersion()) {
+ case SCI_VERSION_1_EARLY:
+ case SCI_VERSION_1_1:
+ offTop = 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ case GID_FAIRYTALES:
+ // Mixed-Up Fairy Tales (& its demo) uses -w 26 0 200 320. If we don't
+ // also do this we will get not-fully-removed windows everywhere.
+ offTop = 26;
+ break;
+ default:
+ offTop = 10;
+ break;
+ }
openPort(_wmgrPort);
setPort(_wmgrPort);
// SCI0 games till kq4 (.502 - not including) did not adjust against _wmgrPort in kNewWindow
// We leave _wmgrPort top at 0, so the adjustment wont get done
- if (!g_sci->_features->usesOldGfxFunctions())
+ if (!g_sci->_features->usesOldGfxFunctions()) {
setOrigin(0, offTop);
- _wmgrPort->rect.bottom = _screen->getHeight() - offTop;
+ _wmgrPort->rect.bottom = _screen->getHeight() - offTop;
+ } else {
+ _wmgrPort->rect.bottom = _screen->getHeight();
+ }
_wmgrPort->rect.right = _screen->getWidth();
_wmgrPort->rect.moveTo(0, 0);
_wmgrPort->curTop = 0;
_wmgrPort->curLeft = 0;
_windowList.push_front(_wmgrPort);
- _picWind = newWindow(Common::Rect(0, offTop, _screen->getWidth(), _screen->getHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true);
+ _picWind = addWindow(Common::Rect(0, offTop, _screen->getWidth(), _screen->getHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true);
// For SCI0 games till kq4 (.502 - not including) we set _picWind top to offTop instead
// Because of the menu/status bar
if (g_sci->_features->usesOldGfxFunctions())
_picWind->top = offTop;
- priorityBandsMemoryActive = false;
-
kernelInitPriorityBands();
}
+// Removes any windows from windowList
+// is used when restoring/restarting the game
+// Sierra SCI actually saved the whole windowList, it seems we don't need to do this at all
+// but in some games there are still windows active when restoring. Leaving those windows open
+// would create all sorts of issues, that's why we remove them
+void GfxPorts::reset() {
+ setPort(_picWind);
+
+ // free everything after _picWind
+ for (uint id = PORTS_FIRSTSCRIPTWINDOWID; id < _windowsById.size(); id++) {
+ Window *window = (Window *)_windowsById[id];
+ if (window)
+ freeWindow(window);
+ }
+ _freeCounter = 0;
+ _windowList.clear();
+ _windowList.push_front(_wmgrPort);
+ _windowList.push_back(_picWind);
+}
+
void GfxPorts::kernelSetActive(uint16 portId) {
+ if (_freeCounter) {
+ // Windows waiting to get freed
+ for (uint id = PORTS_FIRSTSCRIPTWINDOWID; id < _windowsById.size(); id++) {
+ Window *window = (Window *)_windowsById[id];
+ if (window) {
+ if (window->counterTillFree) {
+ window->counterTillFree--;
+ if (!window->counterTillFree) {
+ freeWindow(window);
+ _freeCounter--;
+ }
+ }
+ }
+ }
+ }
+
switch (portId) {
case 0:
setPort(_wmgrPort);
@@ -123,8 +195,13 @@ void GfxPorts::kernelSetActive(uint16 portId) {
case 0xFFFF:
setPort(_menuPort);
break;
- default:
- setPort(getPortById(portId));
+ default: {
+ Port *newPort = getPortById(portId);
+ if (newPort)
+ setPort(newPort);
+ else
+ error("GfxPorts::kernelSetActive was requested to set invalid port id %d", portId);
+ }
};
}
@@ -149,10 +226,10 @@ reg_t GfxPorts::kernelGetActive() {
reg_t GfxPorts::kernelNewWindow(Common::Rect dims, Common::Rect restoreRect, uint16 style, int16 priority, int16 colorPen, int16 colorBack, const char *title) {
Window *wnd = NULL;
- if (restoreRect.top != 0 && restoreRect.left != 0 && restoreRect.height() != 0 && restoreRect.width() != 0)
- wnd = newWindow(dims, &restoreRect, title, style, priority, false);
+ if (restoreRect.bottom != 0 && restoreRect.right != 0)
+ wnd = addWindow(dims, &restoreRect, title, style, priority, false);
else
- wnd = newWindow(dims, NULL, title, style, priority, false);
+ wnd = addWindow(dims, NULL, title, style, priority, false);
wnd->penClr = colorPen;
wnd->backClr = colorBack;
drawWindow(wnd);
@@ -162,7 +239,15 @@ reg_t GfxPorts::kernelNewWindow(Common::Rect dims, Common::Rect restoreRect, uin
void GfxPorts::kernelDisposeWindow(uint16 windowId, bool reanimate) {
Window *wnd = (Window *)getPortById(windowId);
- disposeWindow(wnd, reanimate);
+ if (wnd) {
+ if (!wnd->counterTillFree) {
+ removeWindow(wnd, reanimate);
+ } else {
+ error("kDisposeWindow: used already disposed window id %d", windowId);
+ }
+ } else {
+ error("kDisposeWindow: used unknown window id %d", windowId);
+ }
}
int16 GfxPorts::isFrontWindow(Window *pWnd) {
@@ -199,9 +284,9 @@ void GfxPorts::endUpdate(Window *wnd) {
setPort(oldPort);
}
-Window *GfxPorts::newWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw) {
+Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw) {
// Find an unused window/port id
- uint id = 1;
+ uint id = PORTS_FIRSTWINDOWID;
while (id < _windowsById.size() && _windowsById[id]) {
++id;
}
@@ -213,7 +298,7 @@ Window *GfxPorts::newWindow(const Common::Rect &dims, const Common::Rect *restor
Common::Rect r;
if (!pwnd) {
- warning("Can't open window!");
+ error("Can't open window!");
return 0;
}
@@ -226,8 +311,10 @@ Window *GfxPorts::newWindow(const Common::Rect &dims, const Common::Rect *restor
r = dims;
if (r.width() > _screen->getWidth()) {
- // We get invalid dimensions at least at the end of sq3 (script bug!)
- warning("fixing too large window, given left&right was %d, %d", dims.left, dims.right);
+ // We get invalid dimensions at least at the end of sq3 (script bug!).
+ // Same happens very often in lsl5, sierra sci didnt fix it but it looked awful.
+ // Also happens frequently in the demo of GK1.
+ warning("Fixing too large window, left: %d, right: %d", dims.left, dims.right);
r.left = 0;
r.right = _screen->getWidth() - 1;
if ((style != _styleUser) && !(style & SCI_WINDOWMGR_STYLE_NOFRAME))
@@ -342,22 +429,40 @@ void GfxPorts::drawWindow(Window *pWnd) {
if (!(wndStyle & SCI_WINDOWMGR_STYLE_TRANSPARENT))
_paint16->fillRect(r, GFX_SCREEN_MASK_VISUAL, pWnd->backClr);
- _paint16->bitsShow(pWnd->restoreRect);
+ _paint16->bitsShow(pWnd->dims);
}
setPort(oldport);
}
-void GfxPorts::disposeWindow(Window *pWnd, bool reanimate) {
+void GfxPorts::removeWindow(Window *pWnd, bool reanimate) {
setPort(_wmgrPort);
_paint16->bitsRestore(pWnd->hSaved1);
+ pWnd->hSaved1 = NULL_REG;
_paint16->bitsRestore(pWnd->hSaved2);
+ pWnd->hSaved2 = NULL_REG;
if (!reanimate)
_paint16->bitsShow(pWnd->restoreRect);
else
_paint16->kernelGraphRedrawBox(pWnd->restoreRect);
_windowList.remove(pWnd);
setPort(_windowList.back());
- _windowsById[pWnd->id] = 0;
+ // We will actually free this window after 10 kSetPort-calls
+ // Sierra sci freed the pointer immediately, but pointer to that port
+ // still worked till the memory got overwritten. Some games depend
+ // on this (dispose a window and then kSetPort to it again for once)
+ // Those are actually script bugs, but patching all of those out
+ // would be quite a hassle and this just keeps compatibility
+ // (examples: hoyle 4 game menu and sq4cd inventory)
+ pWnd->counterTillFree = 10;
+ _freeCounter++;
+}
+
+void GfxPorts::freeWindow(Window *pWnd) {
+ if (!pWnd->hSaved1.isNull())
+ _segMan->freeHunkEntry(pWnd->hSaved1);
+ if (!pWnd->hSaved2.isNull())
+ _segMan->freeHunkEntry(pWnd->hSaved1);
+ _windowsById[pWnd->id] = NULL;
delete pWnd;
}
@@ -377,13 +482,9 @@ void GfxPorts::updateWindow(Window *wnd) {
}
Port *GfxPorts::getPortById(uint16 id) {
- if (id > _windowsById.size())
- error("getPortById() received invalid id");
- return _windowsById[id];
+ return (id < _windowsById.size()) ? _windowsById[id] : NULL;
}
-
-
Port *GfxPorts::setPort(Port *newPort) {
Port *oldPort = _curPort;
_curPort = newPort;
@@ -495,6 +596,11 @@ void GfxPorts::priorityBandsInit(int16 bandCount, int16 top, int16 bottom) {
// We fill space that is left over with the highest band (hardcoded 200 limit, because this algo isnt meant to be used on hires)
for (y = _priorityBottom; y < 200; y++)
_priorityBands[y] = _priorityBandCount;
+
+ // adjust, if bottom is 200 (one over the actual screen range) - we could otherwise go possible out of bounds
+ // sierra sci also adjust accordingly
+ if (_priorityBottom == 200)
+ _priorityBottom--;
}
void GfxPorts::priorityBandsInit(byte *data) {
@@ -510,22 +616,14 @@ void GfxPorts::priorityBandsInit(byte *data) {
_priorityBands[i++] = inx;
}
-// Gets used by picture class to remember priority bands data from sci1.1 pictures that need to get applied when
-// transitioning to that picture
-void GfxPorts::priorityBandsRemember(byte *data) {
- int bandNo;
- for (bandNo = 0; bandNo < 14; bandNo++) {
- priorityBandsMemory[bandNo] = READ_LE_UINT16(data);
+// Gets used to read priority bands data from sci1.1 pictures
+void GfxPorts::priorityBandsInitSci11(byte *data) {
+ byte priorityBands[14];
+ for (int bandNo = 0; bandNo < 14; bandNo++) {
+ priorityBands[bandNo] = READ_LE_UINT16(data);
data += 2;
}
- priorityBandsMemoryActive = true;
-}
-
-void GfxPorts::priorityBandsRecall() {
- if (priorityBandsMemoryActive) {
- priorityBandsInit((byte *)&priorityBandsMemory);
- priorityBandsMemoryActive = false;
- }
+ priorityBandsInit(priorityBands);
}
void GfxPorts::kernelInitPriorityBands() {
diff --git a/engines/sci/graphics/ports.h b/engines/sci/graphics/ports.h
index 0876d9e442..42a0a5d4b4 100644
--- a/engines/sci/graphics/ports.h
+++ b/engines/sci/graphics/ports.h
@@ -36,6 +36,9 @@ class GfxPaint16;
class GfxScreen;
class GfxText16;
+#define PORTS_FIRSTWINDOWID 2
+#define PORTS_FIRSTSCRIPTWINDOWID 3
+
/**
* Ports class, includes all port managment for SCI0->SCI1.1 games. Ports are some sort of windows in SCI
* this class also handles adjusting coordinates to a specific port
@@ -45,7 +48,8 @@ public:
GfxPorts(SegManager *segMan, GfxScreen *screen);
~GfxPorts();
- void init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, GfxText16 *text16, Common::String gameId);
+ void init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *text16);
+ void reset();
void kernelSetActive(uint16 portId);
Common::Rect kernelGetPicWindow(int16 &picTop, int16 &picLeft);
@@ -57,9 +61,10 @@ public:
int16 isFrontWindow(Window *wnd);
void beginUpdate(Window *wnd);
void endUpdate(Window *wnd);
- Window *newWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw);
+ Window *addWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw);
void drawWindow(Window *wnd);
- void disposeWindow(Window *pWnd, bool reanimate);
+ void removeWindow(Window *pWnd, bool reanimate);
+ void freeWindow(Window *pWnd);
void updateWindow(Window *wnd);
Port *getPortById(uint16 id);
@@ -81,8 +86,7 @@ public:
void priorityBandsInit(int16 bandCount, int16 top, int16 bottom);
void priorityBandsInit(byte *data);
- void priorityBandsRemember(byte *data);
- void priorityBandsRecall();
+ void priorityBandsInitSci11(byte *data);
void kernelInitPriorityBands();
void kernelGraphAdjustPriority(int top, int bottom);
@@ -102,7 +106,6 @@ private:
typedef Common::List<Port *> PortList;
SegManager *_segMan;
- SciGui *_gui;
GfxPaint16 *_paint16;
GfxScreen *_screen;
GfxText16 *_text16;
@@ -111,6 +114,9 @@ private:
uint16 _styleUser;
+ // counts windows that got disposed but are not freed yet
+ uint16 _freeCounter;
+
/** The list of open 'windows' (and ports), in visual order. */
PortList _windowList;
@@ -122,9 +128,6 @@ private:
// Priority Bands related variables
int16 _priorityTop, _priorityBottom, _priorityBandCount;
byte _priorityBands[200];
-
- byte priorityBandsMemory[14];
- bool priorityBandsMemoryActive;
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/robot.cpp b/engines/sci/graphics/robot.cpp
index 2f711eb58a..1572a0a9ec 100644
--- a/engines/sci/graphics/robot.cpp
+++ b/engines/sci/graphics/robot.cpp
@@ -28,25 +28,42 @@
#include "sci/graphics/screen.h"
#include "sci/graphics/robot.h"
+#include "common/file.h"
+
namespace Sci {
#ifdef ENABLE_SCI32
-Robot::Robot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId)
+GfxRobot::GfxRobot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId)
: _resMan(resMan), _screen(screen), _resourceId(resourceId) {
assert(resourceId != -1);
initData(resourceId);
+ _resourceData = 0;
}
-Robot::~Robot() {
- _resMan->unlockResource(_resource);
+GfxRobot::~GfxRobot() {
+ delete[] _resourceData;
}
-void Robot::initData(GuiResourceId resourceId) {
- _resource = _resMan->findResource(ResourceId(kResourceTypeRobot, resourceId), true);
- if (!_resource) {
- error("robot resource %d not found", resourceId);
+void GfxRobot::initData(GuiResourceId resourceId) {
+ char fileName[10];
+ sprintf(fileName, "%d.rbt", resourceId);
+
+ Common::File robotFile;
+ if (robotFile.open(fileName)) {
+ _resourceData = new byte[robotFile.size()];
+ robotFile.read(_resourceData, robotFile.size());
+ robotFile.close();
+ } else {
+ warning("Unable to open robot file %s", fileName);
+ return;
+ }
+
+ byte version = _resourceData[6];
+
+ if (version != 4 && version != 5) {
+ warning("Robot version %d isn't supported yet", version);
+ return;
}
- _resourceData = _resource->data;
// sample data:
// Header - 14 bytes
@@ -152,13 +169,16 @@ void Robot::initData(GuiResourceId resourceId) {
// ^ ??
// 00000120: 70 70 70 70 70 70 70 70-70 70 70 70 70 70 70 70 pppppppppppppppp
- _frameCount = READ_LE_UINT16(_resourceData + 12);
- _frameSize = READ_LE_UINT32(_resourceData + 34);
+ _frameCount = READ_LE_UINT16(_resourceData + 14);
+ //_frameSize = READ_LE_UINT32(_resourceData + 34);
+ byte hasSound = _resourceData[25];
+
+ debug("Robot %d, %d frames, sound: %d\n", resourceId, _frameCount, hasSound);
}
// TODO: just trying around in here...
-void Robot::draw() {
+void GfxRobot::draw() {
byte *bitmapData = _resourceData + ROBOT_FILE_STARTOFDATA;
int x, y;
//int frame;
diff --git a/engines/sci/graphics/robot.h b/engines/sci/graphics/robot.h
index 009b76a91c..3ea9a7f735 100644
--- a/engines/sci/graphics/robot.h
+++ b/engines/sci/graphics/robot.h
@@ -31,10 +31,10 @@ namespace Sci {
#define ROBOT_FILE_STARTOFDATA 58
#ifdef ENABLE_SCI32
-class Robot {
+class GfxRobot {
public:
- Robot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId);
- ~Robot();
+ GfxRobot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId);
+ ~GfxRobot();
void draw();
@@ -45,7 +45,6 @@ private:
GfxScreen *_screen;
GuiResourceId _resourceId;
- Resource *_resource;
byte *_resourceData;
uint16 _width;
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index 7ca9e33509..839b9975c5 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -35,8 +35,35 @@
namespace Sci {
-GfxScreen::GfxScreen(ResourceManager *resMan, int16 width, int16 height, int upscaledHires) :
- _resMan(resMan), _width(width), _height(height), _upscaledHires(upscaledHires) {
+GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
+
+ // Scale the screen, if needed
+ _upscaledHires = GFX_SCREEN_UPSCALED_DISABLED;
+
+ // King's Quest 6 and Gabriel Knight 1 have hires content, gk1/cd was able
+ // to provide that under DOS as well, but as gk1/floppy does support
+ // upscaled hires scriptswise, but doesn't actually have the hires content
+ // we need to limit it to platform windows.
+ if (g_sci->getPlatform() == Common::kPlatformWindows) {
+ if (g_sci->getGameId() == GID_KQ6)
+ _upscaledHires = GFX_SCREEN_UPSCALED_640x440;
+#ifdef ENABLE_SCI32
+ if (g_sci->getGameId() == GID_GK1)
+ _upscaledHires = GFX_SCREEN_UPSCALED_640x480;
+#endif
+ }
+
+ if (_resMan->detectHires()) {
+ _width = 640;
+ _height = 480;
+ } else {
+ _width = 320;
+ _height = 200;
+ }
+
+ // Japanese versions of games use hi-res font on upscaled version of the game.
+ if ((g_sci->getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1))
+ _upscaledHires = GFX_SCREEN_UPSCALED_640x400;
_pixels = _width * _height;
@@ -80,8 +107,9 @@ GfxScreen::GfxScreen(ResourceManager *resMan, int16 width, int16 height, int ups
_unditherState = true;
if (_resMan->isVGA() || (_resMan->isAmiga32color())) {
- // It's not 100% accurate to set white to be 255 for amiga 32-color games
- // 255 is defined as white in our sci at all times, so it doesnt matter
+ // It is not 100% accurate to set white to be 255 for Amiga 32-color
+ // games. But 255 is defined as white in our SCI at all times, so it
+ // doesn't matter.
_colorWhite = 255;
if (getSciVersion() >= SCI_VERSION_1_1)
_colorDefaultVectorData = 255;
@@ -93,7 +121,18 @@ GfxScreen::GfxScreen(ResourceManager *resMan, int16 width, int16 height, int ups
}
// Initialize the actual screen
- initGraphics(_displayWidth, _displayHeight, _displayWidth > 320);
+
+ if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) {
+ // For SCI1.1 Mac, we need to expand the screen to accommodate for
+ // the icon bar. Of course, both KQ6 and QFG1 VGA differ in size.
+ if (g_sci->getGameId() == GID_KQ6)
+ initGraphics(_displayWidth, _displayHeight + 26, _displayWidth > 320);
+ else if (g_sci->getGameId() == GID_QFG1VGA)
+ initGraphics(_displayWidth, _displayHeight + 20, _displayWidth > 320);
+ else
+ error("Unknown SCI1.1 Mac game");
+ } else
+ initGraphics(_displayWidth, _displayHeight, _displayWidth > 320);
}
GfxScreen::~GfxScreen() {
@@ -130,7 +169,10 @@ void GfxScreen::copyRectToScreen(const Common::Rect &rect) {
}
}
-// This copies a rect to screen w/o scaling adjustment and is only meant to be used on hires graphics used in upscaled hires mode
+/**
+ * This copies a rect to screen w/o scaling adjustment and is only meant to be
+ * used on hires graphics used in upscaled hires mode.
+ */
void GfxScreen::copyDisplayRectToScreen(const Common::Rect &rect) {
if (!_upscaledHires)
error("copyDisplayRectToScreen: not in upscaled hires mode");
@@ -181,15 +223,42 @@ void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority,
_controlScreen[offset] = control;
}
-// This will just change a pixel directly on displayscreen. Its supposed to get only used on upscaled-Hires games where
-// hires content needs to get drawn ONTO the upscaled display screen (like japanese fonts, hires portraits, etc.)
+/**
+ * This is used to put font pixels onto the screen - we adjust differently, so that we won't
+ * do triple pixel lines in any case on upscaled hires. That way the font will not get distorted
+ * Sierra SCI didn't do this
+ */
+void GfxScreen::putFontPixel(int startingY, int x, int y, byte color) {
+ int offset = (startingY + y) * _width + x;
+
+ _visualScreen[offset] = color;
+ if (!_upscaledHires) {
+ _displayScreen[offset] = color;
+ } else {
+ int displayOffset = (_upscaledMapping[startingY] + y * 2) * _displayWidth + x * 2;
+ _displayScreen[displayOffset] = color;
+ _displayScreen[displayOffset + 1] = color;
+ displayOffset += _displayWidth;
+ _displayScreen[displayOffset] = color;
+ _displayScreen[displayOffset + 1] = color;
+ }
+}
+
+/**
+ * This will just change a pixel directly on displayscreen. It is supposed to be
+ * only used on upscaled-Hires games where hires content needs to get drawn ONTO
+ * the upscaled display screen (like japanese fonts, hires portraits, etc.).
+ */
void GfxScreen::putPixelOnDisplay(int x, int y, byte color) {
int offset = y * _displayWidth + x;
_displayScreen[offset] = color;
}
-// Sierra's Bresenham line drawing
-// WARNING: Do not just blindly replace this with Graphics::drawLine(), as it seems to create issues with flood fill
+/**
+ * Sierra's Bresenham line drawing.
+ * WARNING: Do not replace this with Graphics::drawLine(), as this causes issues
+ * with flood fill, due to small difference in the Bresenham logic.
+ */
void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) {
int16 left = startPoint.x;
int16 top = startPoint.y;
@@ -252,7 +321,8 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte
}
}
-// We put hires kanji chars onto upscaled background, so we need to adjust coordinates. Caller gives use low-res ones
+// We put hires kanji chars onto upscaled background, so we need to adjust
+// coordinates. Caller gives use low-res ones.
void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color) {
byte *displayPtr = _displayScreen + y * _displayWidth * 2 + x * 2;
// we don't use outline, so color 0 is actually not used
@@ -389,6 +459,11 @@ void GfxScreen::bitsRestore(byte *memoryPtr) {
if (!_upscaledHires)
error("bitsRestore() called w/o being in upscaled hires mode");
bitsRestoreScreen(rect, memoryPtr, _displayScreen, _displayWidth);
+ // WORKAROUND - we are not sure what sierra is doing. If we don't do this here, portraits won't get fully removed
+ // from screen. Some lowres showBits() call is used for that and it's not covering the whole area
+ // We would need to find out inside the kq6 windows interpreter, but this here works already and seems not to have
+ // any side-effects. The whole hires is hacked into the interpreter, so maybe this is even right.
+ copyDisplayRectToScreen(rect);
}
}
@@ -424,7 +499,19 @@ void GfxScreen::bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr) {
}
}
-void GfxScreen::setPalette(Palette*pal) {
+void GfxScreen::getPalette(Palette *pal) {
+ // just copy palette to system
+ byte bpal[4 * 256];
+ // Get current palette, update it and put back
+ g_system->grabPalette(bpal, 0, 256);
+ for (int16 i = 1; i < 255; i++) {
+ pal->colors[i].r = bpal[i * 4];
+ pal->colors[i].g = bpal[i * 4 + 1];
+ pal->colors[i].b = bpal[i * 4 + 2];
+ }
+}
+
+void GfxScreen::setPalette(Palette *pal) {
// just copy palette to system
byte bpal[4 * 256];
// Get current palette, update it and put back
@@ -447,6 +534,22 @@ void GfxScreen::setVerticalShakePos(uint16 shakePos) {
g_system->setShakePos(shakePos * 2);
}
+void GfxScreen::kernelShakeScreen(uint16 shakeCount, uint16 directions) {
+ while (shakeCount--) {
+ if (directions & SCI_SHAKE_DIRECTION_VERTICAL)
+ setVerticalShakePos(10);
+ // TODO: horizontal shakes
+ g_system->updateScreen();
+ g_sci->getEngineState()->wait(3);
+
+ if (directions & SCI_SHAKE_DIRECTION_VERTICAL)
+ setVerticalShakePos(0);
+
+ g_system->updateScreen();
+ g_sci->getEngineState()->wait(3);
+ }
+}
+
void GfxScreen::dither(bool addToFlag) {
int y, x;
byte color, ditheredColor;
@@ -546,19 +649,20 @@ void GfxScreen::debugShowMap(int mapNo) {
copyToScreen();
}
-void GfxScreen::scale2x(byte *src, byte *dst, int16 srcWidth, int16 srcHeight) {
- int newWidth = srcWidth * 2;
- byte *srcPtr = src;
+void GfxScreen::scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight) {
+ const int newWidth = srcWidth * 2;
+ const byte *srcPtr = src;
for (int y = 0; y < srcHeight; y++) {
for (int x = 0; x < srcWidth; x++) {
- int destOffset = y * 2 * newWidth + x * 2;
- dst[destOffset] = *srcPtr;
- dst[destOffset + 1] = *srcPtr;
- dst[destOffset + newWidth] = *srcPtr;
- dst[destOffset + newWidth + 1] = *srcPtr;
- srcPtr++;
+ const byte color = *srcPtr++;
+ dst[0] = color;
+ dst[1] = color;
+ dst[newWidth] = color;
+ dst[newWidth + 1] = color;
+ dst += 2;
}
+ dst += newWidth;
}
}
@@ -567,6 +671,24 @@ void GfxScreen::adjustToUpscaledCoordinates(int16 &y, int16 &x) {
y = _upscaledMapping[y];
}
+void GfxScreen::adjustBackUpscaledCoordinates(int16 &y, int16 &x) {
+ switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_640x400:
+ x /= 2;
+ y /= 2;
+ break;
+ case GFX_SCREEN_UPSCALED_640x440:
+ x /= 2;
+ y = (y * 5) / 11;
+ break;
+ case GFX_SCREEN_UPSCALED_640x480:
+ x /= 2;
+ y = (y * 5) / 12;
+ default:
+ break;
+ }
+}
+
int16 GfxScreen::kernelPicNotValid(int16 newPicNotValid) {
int16 oldPicNotValid;
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h
index b2479e9735..97f5736289 100644
--- a/engines/sci/graphics/screen.h
+++ b/engines/sci/graphics/screen.h
@@ -50,16 +50,21 @@ enum GfxScreenMasks {
GFX_SCREEN_MASK_ALL = GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY|GFX_SCREEN_MASK_CONTROL
};
-#define SCI_SCREEN_UNDITHERMEMORIAL_SIZE 256
+enum {
+ SCI_SCREEN_UNDITHERMEMORIAL_SIZE = 256
+};
/**
- * Screen class, actually creates 3 (4) screens internally - which is visual/display (for the user),
- * priority (contains priority information) and control (contains control information). Handles all operations to it
- * and copies parts of visual/display screen to the actual screen, so the user can really see it.
+ * Screen class, actually creates 3 (4) screens internally:
+ * - visual/display (for the user),
+ * - priority (contains priority information) and
+ * - control (contains control information).
+ * Handles all operations to it and copies parts of visual/display screen to
+ * the actual screen, so the user can really see it.
*/
class GfxScreen {
public:
- GfxScreen(ResourceManager *resMan, int16 width = 320, int16 height = 200, int upscaledHires = GFX_SCREEN_UPSCALED_DISABLED);
+ GfxScreen(ResourceManager *resMan);
~GfxScreen();
uint16 getWidth() { return _width; }
@@ -78,15 +83,16 @@ public:
byte getDrawingMask(byte color, byte prio, byte control);
void putPixel(int x, int y, byte drawMask, byte color, byte prio, byte control);
+ void putFontPixel(int startingY, int x, int y, byte color);
void putPixelOnDisplay(int x, int y, byte color);
void drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte prio, byte control);
void drawLine(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control) {
drawLine(Common::Point(left, top), Common::Point(right, bottom), color, prio, control);
}
- int getUpscaledHires() {
+ int getUpscaledHires() const {
return _upscaledHires;
}
- bool getUnditherState() {
+ bool getUnditherState() const {
return _unditherState;
}
void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color);
@@ -100,13 +106,13 @@ public:
void bitsGetRect(byte *memoryPtr, Common::Rect *destRect);
void bitsRestore(byte *memoryPtr);
- void setPalette(Palette*pal);
-
- void setVerticalShakePos(uint16 shakePos);
+ void getPalette(Palette *pal);
+ void setPalette(Palette *pal);
- void scale2x(byte *src, byte *dst, int16 srcWidth, int16 srcHeight);
+ void scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight);
void adjustToUpscaledCoordinates(int16 &y, int16 &x);
+ void adjustBackUpscaledCoordinates(int16 &y, int16 &x);
void dither(bool addToFlag);
void debugUnditherSetState(bool flag);
@@ -118,6 +124,7 @@ public:
int _picNotValidSci11; // another variable that is used by kPicNotValid in sci1.1
int16 kernelPicNotValid(int16 newPicNotValid);
+ void kernelShakeScreen(uint16 shakeCount, uint16 direction);
private:
uint16 _width;
@@ -135,30 +142,39 @@ private:
void bitsSaveScreen(Common::Rect rect, byte *screen, uint16 screenWidth, byte *&memoryPtr);
void bitsSaveDisplayScreen(Common::Rect rect, byte *&memoryPtr);
+ void setVerticalShakePos(uint16 shakePos);
+
bool _unditherState;
int16 _unditherMemorial[SCI_SCREEN_UNDITHERMEMORIAL_SIZE];
- // these screens have the real resolution of the game engine (320x200 for SCI0/SCI1/SCI11 games, 640x480 for SCI2 games)
- // SCI0 games will be dithered in here at any time
+ // These screens have the real resolution of the game engine (320x200 for
+ // SCI0/SCI1/SCI11 games, 640x480 for SCI2 games). SCI0 games will be
+ // dithered in here at any time.
byte *_visualScreen;
byte *_priorityScreen;
byte *_controlScreen;
- // this screen is the one that is actually displayed to the user. It may be 640x400 for japanese SCI1 games
- // SCI0 games may be undithered in here. Only read from this buffer for Save/ShowBits usage.
+ // This screen is the one that is actually displayed to the user. It may be
+ // 640x400 for japanese SCI1 games. SCI0 games may be undithered in here.
+ // Only read from this buffer for Save/ShowBits usage.
byte *_displayScreen;
Common::Rect getScaledRect(Common::Rect rect);
ResourceManager *_resMan;
- // this is a pointer to the currently active screen (changing it only required for debug purposes)
+ /**
+ * Pointer to the currently active screen (changing it only required for
+ * debug purposes).
+ */
byte *_activeScreen;
- // this variable defines, if upscaled hires is active and what upscaled mode is used
+ // This variable defines, if upscaled hires is active and what upscaled mode
+ // is used.
int _upscaledHires;
- // this here holds a translation for vertical coordinates between native (visual) and actual (display) screen
+ // This here holds a translation for vertical coordinates between native
+ // (visual) and actual (display) screen.
int _upscaledMapping[SCI_SCREEN_UPSCALEDMAXHEIGHT + 1];
};
diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp
index 952d13fbbd..fc07febe14 100644
--- a/engines/sci/graphics/text16.cpp
+++ b/engines/sci/graphics/text16.cpp
@@ -73,28 +73,6 @@ void GfxText16::SetFont(GuiResourceId fontId) {
_ports->_curPort->fontHeight = _font->getHeight();
}
-void GfxText16::CodeSetFonts(int argc, reg_t *argv) {
- int i;
-
- delete _codeFonts;
- _codeFontsCount = argc;
- _codeFonts = new GuiResourceId[argc];
- for (i = 0; i < argc; i++) {
- _codeFonts[i] = (GuiResourceId)argv[i].toUint16();
- }
-}
-
-void GfxText16::CodeSetColors(int argc, reg_t *argv) {
- int i;
-
- delete _codeColors;
- _codeColorsCount = argc;
- _codeColors = new uint16[argc];
- for (i = 0; i < argc; i++) {
- _codeColors[i] = argv[i].toUint16();
- }
-}
-
void GfxText16::ClearChar(int16 chr) {
if (_ports->_curPort->penMode != 1)
return;
@@ -106,10 +84,10 @@ void GfxText16::ClearChar(int16 chr) {
_paint16->eraseRect(rect);
}
-// This internal function gets called as soon as a '|' is found in a text
-// It will process the encountered code and set new font/set color
-// We only support one-digit codes currently, don't know if multi-digit codes are possible
-// Returns textcode character count
+// This internal function gets called as soon as a '|' is found in a text. It
+// will process the encountered code and set new font/set color. We only support
+// one-digit codes currently, don't know if multi-digit codes are possible.
+// Returns textcode character count.
int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int16 orgPenColor) {
const char *textCode = text;
int16 textCodeSize = 0;
@@ -155,15 +133,17 @@ int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int1
static const uint16 text16_punctuationSjis[] = {
0x9F82, 0xA182, 0xA382, 0xA582, 0xA782, 0xC182, 0xA782, 0xC182, 0xE182, 0xE382, 0xE582, 0xEC82,
0x4083, 0x4283, 0x4483, 0x4683, 0x4883, 0x6283, 0x8383, 0x8583, 0x8783, 0x8E83, 0x9583, 0x9683,
- 0x5B81, 0x4181, 0x4281, 0x7681, 0x7881, 0x4981, 0x4881, 0 };
+ 0x5B81, 0x4181, 0x4281, 0x7681, 0x7881, 0x4981, 0x4881, 0
+};
-// return max # of chars to fit maxwidth with full words, does not include breaking space
+// return max # of chars to fit maxwidth with full words, does not include
+// breaking space
int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId) {
uint16 curChar = 0;
int16 maxChars = 0, curCharCount = 0;
uint16 width = 0;
- GuiResourceId oldFontId = GetFontId();
- int16 oldPenColor = _ports->_curPort->penClr;
+ GuiResourceId previousFontId = GetFontId();
+ int16 previousPenColor = _ports->_curPort->penClr;
GetFont();
if (!_font)
@@ -179,7 +159,7 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF
case 0x7C:
if (getSciVersion() >= SCI_VERSION_1_1) {
curCharCount++;
- curCharCount += CodeProcessing(text, orgFontId, oldPenColor);
+ curCharCount += CodeProcessing(text, orgFontId, previousPenColor);
continue;
}
break;
@@ -200,8 +180,8 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF
curCharCount++;
// and it's also meant to pass through here
case 0:
- SetFont(oldFontId);
- _ports->penColor(oldPenColor);
+ SetFont(previousFontId);
+ _ports->penColor(previousPenColor);
return curCharCount;
case ' ':
@@ -217,9 +197,10 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF
uint16 nextChar;
- // we remove the last char only, if maxWidth was actually equal width before adding the last char
- // otherwise we won't get the same cutting as in sierra pc98 sci
- // note: changing the while() instead will NOT WORK. it would break all sorts of regular sci games
+ // We remove the last char only, if maxWidth was actually equal width
+ // before adding the last char. Otherwise we won't get the same cutting
+ // as in sierra pc98 sci. Note: changing the while() instead will NOT
+ // WORK. it would break all sorts of regular sci games.
if (maxWidth == (width - _font->getCharWidth(curChar))) {
maxChars--;
if (curChar > 0xFF)
@@ -245,15 +226,15 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF
}
}
}
- SetFont(oldFontId);
- _ports->penColor(oldPenColor);
+ SetFont(previousFontId);
+ _ports->penColor(previousPenColor);
return maxChars;
}
-void GfxText16::Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) {
+void GfxText16::Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight, bool restoreFont) {
uint16 curChar;
- GuiResourceId oldFontId = GetFontId();
- int16 oldPenColor = _ports->_curPort->penClr;
+ GuiResourceId previousFontId = GetFontId();
+ int16 previousPenColor = _ports->_curPort->penClr;
textWidth = 0; textHeight = 0;
@@ -283,13 +264,18 @@ void GfxText16::Width(const char *text, int16 from, int16 len, GuiResourceId org
}
}
}
- SetFont(oldFontId);
- _ports->penColor(oldPenColor);
+ // When calculating size, we do not restore font because we need the current (code modified) font active
+ // If we are drawing this is called inbetween, so font needs to get restored
+ // If we are calculating size of just one fixed string (::StringWidth), then we need to restore
+ if (restoreFont) {
+ SetFont(previousFontId);
+ _ports->penColor(previousPenColor);
+ }
return;
}
void GfxText16::StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) {
- Width(str, 0, (int16)strlen(str), orgFontId, textWidth, textHeight);
+ Width(str, 0, (int16)strlen(str), orgFontId, textWidth, textHeight, true);
}
void GfxText16::ShowString(const char *str, GuiResourceId orgFontId, int16 orgPenColor) {
@@ -300,14 +286,16 @@ void GfxText16::DrawString(const char *str, GuiResourceId orgFontId, int16 orgPe
}
int16 GfxText16::Size(Common::Rect &rect, const char *text, GuiResourceId fontId, int16 maxWidth) {
- GuiResourceId oldFontId = GetFontId();
- int16 oldPenColor = _ports->_curPort->penClr;
+ GuiResourceId previousFontId = GetFontId();
+ int16 previousPenColor = _ports->_curPort->penClr;
int16 charCount;
int16 maxTextWidth = 0, textWidth;
int16 totalHeight = 0, textHeight;
if (fontId != -1)
SetFont(fontId);
+ else
+ fontId = previousFontId;
if (g_sci->getLanguage() == Common::JA_JPN)
SwitchToFont900OnSjis(text);
@@ -315,7 +303,7 @@ int16 GfxText16::Size(Common::Rect &rect, const char *text, GuiResourceId fontId
rect.top = rect.left = 0;
if (maxWidth < 0) { // force output as single line
- StringWidth(text, oldFontId, textWidth, textHeight);
+ StringWidth(text, fontId, textWidth, textHeight);
rect.bottom = textHeight;
rect.right = textWidth;
} else {
@@ -324,10 +312,10 @@ int16 GfxText16::Size(Common::Rect &rect, const char *text, GuiResourceId fontId
rect.right = (maxWidth ? maxWidth : 192);
const char *curPos = text;
while (*curPos) {
- charCount = GetLongest(curPos, rect.right, oldFontId);
+ charCount = GetLongest(curPos, rect.right, fontId);
if (charCount == 0)
break;
- Width(curPos, 0, charCount, oldFontId, textWidth, textHeight);
+ Width(curPos, 0, charCount, fontId, textWidth, textHeight, false);
maxTextWidth = MAX(textWidth, maxTextWidth);
totalHeight += textHeight;
curPos += charCount;
@@ -337,8 +325,8 @@ int16 GfxText16::Size(Common::Rect &rect, const char *text, GuiResourceId fontId
rect.bottom = totalHeight;
rect.right = maxWidth ? maxWidth : MIN(rect.right, maxTextWidth);
}
- SetFont(oldFontId);
- _ports->penColor(oldPenColor);
+ SetFont(previousFontId);
+ _ports->penColor(previousPenColor);
return rect.right;
}
@@ -403,12 +391,14 @@ void GfxText16::Box(const char *text, int16 bshow, const Common::Rect &rect, Tex
int16 textWidth, maxTextWidth, textHeight, charCount;
int16 offset = 0;
int16 hline = 0;
- GuiResourceId orgFontId = GetFontId();
- int16 orgPenColor = _ports->_curPort->penClr;
+ GuiResourceId previousFontId = GetFontId();
+ int16 previousPenColor = _ports->_curPort->penClr;
bool doubleByteMode = false;
if (fontId != -1)
SetFont(fontId);
+ else
+ fontId = previousFontId;
if (g_sci->getLanguage() == Common::JA_JPN) {
if (SwitchToFont900OnSjis(text))
@@ -417,10 +407,10 @@ void GfxText16::Box(const char *text, int16 bshow, const Common::Rect &rect, Tex
maxTextWidth = 0;
while (*text) {
- charCount = GetLongest(text, rect.width(), orgFontId);
+ charCount = GetLongest(text, rect.width(), fontId);
if (charCount == 0)
break;
- Width(text, 0, charCount, orgFontId, textWidth, textHeight);
+ Width(text, 0, charCount, fontId, textWidth, textHeight, true);
maxTextWidth = MAX<int16>(maxTextWidth, textWidth);
switch (alignment) {
case SCI_TEXT16_ALIGNMENT_RIGHT:
@@ -439,9 +429,9 @@ void GfxText16::Box(const char *text, int16 bshow, const Common::Rect &rect, Tex
_ports->moveTo(rect.left + offset, rect.top + hline);
if (bshow) {
- Show(text, 0, charCount, orgFontId, orgPenColor);
+ Show(text, 0, charCount, fontId, previousPenColor);
} else {
- Draw(text, 0, charCount, orgFontId, orgPenColor);
+ Draw(text, 0, charCount, fontId, previousPenColor);
}
hline += textHeight;
@@ -449,15 +439,18 @@ void GfxText16::Box(const char *text, int16 bshow, const Common::Rect &rect, Tex
if (*text == ' ')
text++; // skip over breaking space
}
- SetFont(orgFontId);
- _ports->penColor(orgPenColor);
+ SetFont(previousFontId);
+ _ports->penColor(previousPenColor);
if (doubleByteMode) {
- // kanji is written by pc98 rom to screen directly. Because of GetLongest() behaviour (not cutting off the last
- // char, that causes a new line), results in the script thinking that the text would need less space. The coordinate
- // adjustment in fontsjis.cpp handles the incorrect centering because of that and this code actually shows all of
- // the chars - if we don't do this, the scripts will only show most of the chars, but the last few pixels won't get
- // shown most of the time.
+ // Kanji is written by pc98 rom to screen directly. Because of
+ // GetLongest() behaviour (not cutting off the last char, that causes a
+ // new line), results in the script thinking that the text would need
+ // less space. The coordinate adjustment in fontsjis.cpp handles the
+ // incorrect centering because of that and this code actually shows all
+ // of the chars - if we don't do this, the scripts will only show most
+ // of the chars, but the last few pixels won't get shown most of the
+ // time.
Common::Rect kanjiRect = rect;
_ports->offsetRect(kanjiRect);
kanjiRect.left &= 0xFFC;
@@ -470,15 +463,16 @@ void GfxText16::Box(const char *text, int16 bshow, const Common::Rect &rect, Tex
}
void GfxText16::Draw_String(const char *text) {
- GuiResourceId orgFontId = GetFontId();
- int16 orgPenColor = _ports->_curPort->penClr;
+ GuiResourceId previousFontId = GetFontId();
+ int16 previousPenColor = _ports->_curPort->penClr;
- Draw(text, 0, strlen(text), orgFontId, orgPenColor);
- SetFont(orgFontId);
- _ports->penColor(orgPenColor);
+ Draw(text, 0, strlen(text), previousFontId, previousPenColor);
+ SetFont(previousFontId);
+ _ports->penColor(previousPenColor);
}
-// Sierra did this in their PC98 interpreter only, they identify a text as being sjis and then switch to font 900
+// Sierra did this in their PC98 interpreter only, they identify a text as being
+// sjis and then switch to font 900
bool GfxText16::SwitchToFont900OnSjis(const char *text) {
byte firstChar = (*(const byte *)text++);
if (((firstChar >= 0x81) && (firstChar <= 0x9F)) || ((firstChar >= 0xE0) && (firstChar <= 0xEF))) {
@@ -488,4 +482,35 @@ bool GfxText16::SwitchToFont900OnSjis(const char *text) {
return false;
}
+void GfxText16::kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) {
+ Common::Rect rect(0, 0, 0, 0);
+ Size(rect, text, font, maxWidth);
+ *textWidth = rect.width();
+ *textHeight = rect.height();
+}
+
+// Used SCI1+ for text codes
+void GfxText16::kernelTextFonts(int argc, reg_t *argv) {
+ int i;
+
+ delete _codeFonts;
+ _codeFontsCount = argc;
+ _codeFonts = new GuiResourceId[argc];
+ for (i = 0; i < argc; i++) {
+ _codeFonts[i] = (GuiResourceId)argv[i].toUint16();
+ }
+}
+
+// Used SCI1+ for text codes
+void GfxText16::kernelTextColors(int argc, reg_t *argv) {
+ int i;
+
+ delete _codeColors;
+ _codeColorsCount = argc;
+ _codeColors = new uint16[argc];
+ for (i = 0; i < argc; i++) {
+ _codeColors[i] = argv[i].toUint16();
+ }
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/text16.h b/engines/sci/graphics/text16.h
index 2885fc928b..9b8b6d9f19 100644
--- a/engines/sci/graphics/text16.h
+++ b/engines/sci/graphics/text16.h
@@ -48,14 +48,12 @@ public:
GfxFont *GetFont();
void SetFont(GuiResourceId fontId);
- void CodeSetFonts(int argc, reg_t *argv);
- void CodeSetColors(int argc, reg_t *argv);
int16 CodeProcessing(const char *&text, GuiResourceId orgFontId, int16 orgPenColor);
void ClearChar(int16 chr);
int16 GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId);
- void Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight);
+ void Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight, bool restoreFont);
void StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight);
void ShowString(const char *str, GuiResourceId orgFontId, int16 orgPenColor);
void DrawString(const char *str, GuiResourceId orgFontId, int16 orgPenColor);
@@ -67,6 +65,10 @@ public:
GfxFont *_font;
+ void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
+ void kernelTextFonts(int argc, reg_t *argv);
+ void kernelTextColors(int argc, reg_t *argv);
+
private:
void init();
bool SwitchToFont900OnSjis(const char *text);
diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp
index 1976326aa9..abb5e74cbd 100644
--- a/engines/sci/graphics/transitions.cpp
+++ b/engines/sci/graphics/transitions.cpp
@@ -31,15 +31,14 @@
#include "sci/sci.h"
#include "sci/engine/state.h"
-#include "sci/graphics/gui.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/palette.h"
#include "sci/graphics/transitions.h"
namespace Sci {
-GfxTransitions::GfxTransitions(SciGui *gui, GfxScreen *screen, GfxPalette *palette, bool isVGA)
- : _gui(gui), _screen(screen), _palette(palette), _isVGA(isVGA) {
+GfxTransitions::GfxTransitions(GfxScreen *screen, GfxPalette *palette, bool isVGA)
+ : _screen(screen), _palette(palette), _isVGA(isVGA) {
init();
}
@@ -159,7 +158,8 @@ void GfxTransitions::doit(Common::Rect picRect) {
}
if (_blackoutFlag) {
- // We need to find out what transition we are supposed to use for blackout
+ // We need to find out what transition we are supposed to use for
+ // blackout
translationEntry = translateNumber(_number, blackoutTransitionIDs);
if (translationEntry) {
doTransition(translationEntry->newId, true);
@@ -168,12 +168,15 @@ void GfxTransitions::doit(Common::Rect picRect) {
}
}
+ _palette->palVaryPrepareForTransition();
+
// Now we do the actual transition to the new screen
doTransition(_number, false);
if (picRect.bottom != _screen->getHeight()) {
// TODO: this is a workaround for lsl6 not showing menubar when playing
- // There is some new code in the sierra sci in ShowPic that seems to do something similar to this
+ // There is some new code in the sierra sci in ShowPic that seems to do
+ // something similar to this
_screen->copyToScreen();
g_system->updateScreen();
}
@@ -181,8 +184,8 @@ void GfxTransitions::doit(Common::Rect picRect) {
_screen->_picNotValid = 0;
}
-// This may get called twice, if blackoutFlag is set. It will get once called with blackoutFlag set and another time
-// with no blackoutFlag.
+// This may get called twice, if blackoutFlag is set. It will get once called
+// with blackoutFlag set and another time with no blackoutFlag.
void GfxTransitions::doTransition(int16 number, bool blackoutFlag) {
if (number != SCI_TRANSITIONS_FADEPALETTE) {
setNewPalette(blackoutFlag);
@@ -193,7 +196,7 @@ void GfxTransitions::doTransition(int16 number, bool blackoutFlag) {
verticalRollFromCenter(blackoutFlag);
break;
case SCI_TRANSITIONS_VERTICALROLL_TOCENTER:
- verticalRollFromCenter(blackoutFlag);
+ verticalRollToCenter(blackoutFlag);
break;
case SCI_TRANSITIONS_HORIZONTALROLL_FROMCENTER:
horizontalRollFromCenter(blackoutFlag);
@@ -277,7 +280,8 @@ void GfxTransitions::copyRectToScreen(const Common::Rect rect, bool blackoutFlag
}
}
-// Note: dont do too many steps in here, otherwise cpu will crap out because of the load
+// Note: don't do too many steps in here, otherwise cpu will crap out because of
+// the load
void GfxTransitions::fadeOut() {
byte oldPalette[4 * 256], workPalette[4 * 256];
int16 stepNr, colorNr;
@@ -291,23 +295,24 @@ void GfxTransitions::fadeOut() {
workPalette[colorNr * 4 + 2] = oldPalette[colorNr * 4 + 2] * stepNr / 100;
}
g_system->setPalette(workPalette + 4, 1, 254);
- _gui->wait(2);
+ g_sci->getEngineState()->wait(2);
}
}
-// Note: dont do too many steps in here, otherwise cpu will crap out because of the load
+// Note: don't do too many steps in here, otherwise cpu will crap out because of
+// the load
void GfxTransitions::fadeIn() {
int16 stepNr;
for (stepNr = 0; stepNr <= 100; stepNr += 10) {
_palette->kernelSetIntensity(1, 255, stepNr, true);
- _gui->wait(2);
+ g_sci->getEngineState()->wait(2);
}
}
-// pixelates the new picture over the old one - works against the whole screen
+// Pixelates the new picture over the old one - works against the whole screen.
// TODO: it seems this needs to get applied on _picRect only if possible
-void GfxTransitions::pixelation (bool blackoutFlag) {
+void GfxTransitions::pixelation(bool blackoutFlag) {
uint16 mask = 0x40, stepNr = 0;
Common::Rect pixelRect;
@@ -327,7 +332,7 @@ void GfxTransitions::pixelation (bool blackoutFlag) {
} while (mask != 0x40);
}
-// like pixelation but uses 8x8 blocks - works against the whole screen
+// Like pixelation but uses 8x8 blocks - works against the whole screen.
// TODO: it seems this needs to get applied on _picRect only if possible
void GfxTransitions::blocks(bool blackoutFlag) {
uint16 mask = 0x40, stepNr = 0;
@@ -349,7 +354,8 @@ void GfxTransitions::blocks(bool blackoutFlag) {
} while (mask != 0x40);
}
-// directly shows new screen starting up/down/left/right and going to the opposite direction - works on _picRect area only
+// Directly shows new screen starting up/down/left/right and going to the
+// opposite direction - works on _picRect area only
void GfxTransitions::straight(int16 number, bool blackoutFlag) {
int16 stepNr = 0;
Common::Rect newScreenRect = _picRect;
@@ -401,38 +407,39 @@ void GfxTransitions::straight(int16 number, bool blackoutFlag) {
}
}
-// scroll old screen (up/down/left/right) and insert new screen that way - works on _picRect area only
+void GfxTransitions::scrollCopyOldToScreen(Common::Rect screenRect, int16 x, int16 y) {
+ byte *oldScreenPtr = _oldScreen;
+ int16 screenWidth = _screen->getDisplayWidth();
+ if (_screen->getUpscaledHires()) {
+ _screen->adjustToUpscaledCoordinates(screenRect.top, screenRect.left);
+ _screen->adjustToUpscaledCoordinates(screenRect.bottom, screenRect.right);
+ _screen->adjustToUpscaledCoordinates(y, x);
+ }
+ oldScreenPtr += screenRect.left + screenRect.top * screenWidth;
+ g_system->copyRectToScreen(oldScreenPtr, screenWidth, x, y, screenRect.width(), screenRect.height());
+}
+
+// Scroll old screen (up/down/left/right) and insert new screen that way - works
+// on _picRect area only.
void GfxTransitions::scroll(int16 number) {
int16 screenWidth, screenHeight;
- byte *oldScreenPtr;
int16 stepNr = 0;
Common::Rect oldMoveRect = _picRect;
+ Common::Rect oldScreenRect = _picRect;
Common::Rect newMoveRect = _picRect;
Common::Rect newScreenRect = _picRect;
_screen->copyFromScreen(_oldScreen);
screenWidth = _screen->getDisplayWidth(); screenHeight = _screen->getDisplayHeight();
- oldScreenPtr = _oldScreen + _picRect.left + _picRect.top * screenWidth;
- if (_screen->getUpscaledHires()) {
- oldScreenPtr += _picRect.left + _picRect.top * screenWidth;
- }
-
switch (number) {
case SCI_TRANSITIONS_SCROLL_LEFT:
newScreenRect.right = newScreenRect.left;
newMoveRect.left = newMoveRect.right;
while (oldMoveRect.left < oldMoveRect.right) {
- oldScreenPtr++;
- if (_screen->getUpscaledHires())
- oldScreenPtr++;
- oldMoveRect.right--;
- if (oldMoveRect.right > oldMoveRect.left) {
- if (!_screen->getUpscaledHires())
- g_system->copyRectToScreen(oldScreenPtr, screenWidth, oldMoveRect.left, oldMoveRect.top, oldMoveRect.width(), oldMoveRect.height());
- else
- g_system->copyRectToScreen(oldScreenPtr, screenWidth, oldMoveRect.left * 2, oldMoveRect.top * 2, oldMoveRect.width() * 2, oldMoveRect.height() * 2);
- }
+ oldMoveRect.right--; oldScreenRect.left++;
+ if (oldMoveRect.right > oldMoveRect.left)
+ scrollCopyOldToScreen(oldScreenRect, oldMoveRect.left, oldMoveRect.top);
newScreenRect.right++; newMoveRect.left--;
_screen->copyRectToScreen(newScreenRect, newMoveRect.left, newMoveRect.top);
if ((stepNr & 1) == 0) {
@@ -440,20 +447,20 @@ void GfxTransitions::scroll(int16 number) {
}
stepNr++;
}
- if ((stepNr & 1) == 0)
- g_system->updateScreen();
+ if ((stepNr & 1) == 0) {
+ if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) {
+ g_system->updateScreen();
+ g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis();
+ }
+ }
break;
case SCI_TRANSITIONS_SCROLL_RIGHT:
newScreenRect.left = newScreenRect.right;
while (oldMoveRect.left < oldMoveRect.right) {
- oldMoveRect.left++;
- if (oldMoveRect.right > oldMoveRect.left) {
- if (!_screen->getUpscaledHires())
- g_system->copyRectToScreen(oldScreenPtr, screenWidth, oldMoveRect.left, oldMoveRect.top, oldMoveRect.width(), oldMoveRect.height());
- else
- g_system->copyRectToScreen(oldScreenPtr, screenWidth, oldMoveRect.left * 2, oldMoveRect.top * 2, oldMoveRect.width() * 2, oldMoveRect.height() * 2);
- }
+ oldMoveRect.left++; oldScreenRect.right--;
+ if (oldMoveRect.right > oldMoveRect.left)
+ scrollCopyOldToScreen(oldScreenRect, oldMoveRect.left, oldMoveRect.top);
newScreenRect.left--;
_screen->copyRectToScreen(newScreenRect, newMoveRect.left, newMoveRect.top);
if ((stepNr & 1) == 0) {
@@ -461,24 +468,21 @@ void GfxTransitions::scroll(int16 number) {
}
stepNr++;
}
- if ((stepNr & 1) == 0)
- g_system->updateScreen();
+ if ((stepNr & 1) == 0) {
+ if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) {
+ g_system->updateScreen();
+ g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis();
+ }
+ }
break;
case SCI_TRANSITIONS_SCROLL_UP:
newScreenRect.bottom = newScreenRect.top;
newMoveRect.top = newMoveRect.bottom;
while (oldMoveRect.top < oldMoveRect.bottom) {
- oldScreenPtr += screenWidth;
- if (_screen->getUpscaledHires())
- oldScreenPtr += screenWidth;
- oldMoveRect.top++;
- if (oldMoveRect.top < oldMoveRect.bottom) {
- if (!_screen->getUpscaledHires())
- g_system->copyRectToScreen(oldScreenPtr, screenWidth, _picRect.left, _picRect.top, oldMoveRect.width(), oldMoveRect.height());
- else
- g_system->copyRectToScreen(oldScreenPtr, screenWidth, _picRect.left * 2, _picRect.top * 2, oldMoveRect.width() * 2, oldMoveRect.height() * 2);
- }
+ oldMoveRect.top++; oldScreenRect.top++;
+ if (oldMoveRect.top < oldMoveRect.bottom)
+ scrollCopyOldToScreen(oldScreenRect, _picRect.left, _picRect.top);
newScreenRect.bottom++; newMoveRect.top--;
_screen->copyRectToScreen(newScreenRect, newMoveRect.left, newMoveRect.top);
updateScreenAndWait(3);
@@ -488,13 +492,9 @@ void GfxTransitions::scroll(int16 number) {
case SCI_TRANSITIONS_SCROLL_DOWN:
newScreenRect.top = newScreenRect.bottom;
while (oldMoveRect.top < oldMoveRect.bottom) {
- oldMoveRect.top++;
- if (oldMoveRect.top < oldMoveRect.bottom) {
- if (!_screen->getUpscaledHires())
- g_system->copyRectToScreen(oldScreenPtr, screenWidth, oldMoveRect.left, oldMoveRect.top, oldMoveRect.width(), oldMoveRect.height());
- else
- g_system->copyRectToScreen(oldScreenPtr, screenWidth, oldMoveRect.left * 2, oldMoveRect.top * 2, oldMoveRect.width() * 2, oldMoveRect.height() * 2);
- }
+ oldMoveRect.top++; oldScreenRect.bottom--;
+ if (oldMoveRect.top < oldMoveRect.bottom)
+ scrollCopyOldToScreen(oldScreenRect, oldMoveRect.left, oldMoveRect.top);
newScreenRect.top--;
_screen->copyRectToScreen(newScreenRect, _picRect.left, _picRect.top);
updateScreenAndWait(3);
@@ -503,7 +503,8 @@ void GfxTransitions::scroll(int16 number) {
}
}
-// vertically displays new screen starting from center - works on _picRect area only
+// Vertically displays new screen starting from center - works on _picRect area
+// only
void GfxTransitions::verticalRollFromCenter(bool blackoutFlag) {
Common::Rect leftRect = Common::Rect(_picRect.left + (_picRect.width() / 2) -1, _picRect.top, _picRect.left + (_picRect.width() / 2), _picRect.bottom);
Common::Rect rightRect = Common::Rect(leftRect.right, _picRect.top, leftRect.right + 1, _picRect.bottom);
@@ -519,10 +520,11 @@ void GfxTransitions::verticalRollFromCenter(bool blackoutFlag) {
}
}
-// vertically displays new screen starting from edges - works on _picRect area only
+// Vertically displays new screen starting from edges - works on _picRect area
+// only
void GfxTransitions::verticalRollToCenter(bool blackoutFlag) {
Common::Rect leftRect = Common::Rect(_picRect.left, _picRect.top, _picRect.left + 1, _picRect.bottom);
- Common::Rect rightRect = Common::Rect(leftRect.right - 1, _picRect.top, leftRect.right, _picRect.bottom);
+ Common::Rect rightRect = Common::Rect(_picRect.right - 1, _picRect.top, _picRect.right, _picRect.bottom);
while (leftRect.left < rightRect.right) {
copyRectToScreen(leftRect, blackoutFlag); leftRect.translate(1, 0);
@@ -531,7 +533,8 @@ void GfxTransitions::verticalRollToCenter(bool blackoutFlag) {
}
}
-// horizontally displays new screen starting from center - works on _picRect area only
+// Horizontally displays new screen starting from center - works on _picRect
+// area only
void GfxTransitions::horizontalRollFromCenter(bool blackoutFlag) {
Common::Rect upperRect = Common::Rect(_picRect.left, _picRect.top + (_picRect.height() / 2) - 1, _picRect.right, _picRect.top + (_picRect.height() / 2));
Common::Rect lowerRect = Common::Rect(upperRect.left, upperRect.bottom, upperRect.right, upperRect.bottom + 1);
@@ -547,7 +550,8 @@ void GfxTransitions::horizontalRollFromCenter(bool blackoutFlag) {
}
}
-// horizontally displays new screen starting from upper and lower edge - works on _picRect area only
+// Horizontally displays new screen starting from upper and lower edge - works
+// on _picRect area only
void GfxTransitions::horizontalRollToCenter(bool blackoutFlag) {
Common::Rect upperRect = Common::Rect(_picRect.left, _picRect.top, _picRect.right, _picRect.top + 1);
Common::Rect lowerRect = Common::Rect(upperRect.left, _picRect.bottom - 1, upperRect.right, _picRect.bottom);
@@ -559,8 +563,8 @@ void GfxTransitions::horizontalRollToCenter(bool blackoutFlag) {
}
}
-// diagonally displays new screen starting from center - works on _picRect area only
-// assumes that height of rect is larger than width
+// Diagonally displays new screen starting from center - works on _picRect area
+// only. Assumes that height of rect is larger than width.
void GfxTransitions::diagonalRollFromCenter(bool blackoutFlag) {
int16 halfHeight = _picRect.height() / 2;
Common::Rect upperRect(_picRect.left + halfHeight - 2, _picRect.top + halfHeight, _picRect.right - halfHeight + 1, _picRect.top + halfHeight + 1);
@@ -589,8 +593,8 @@ void GfxTransitions::diagonalRollFromCenter(bool blackoutFlag) {
}
}
-// diagonally displays new screen starting from edges - works on _picRect area only
-// assumes that height of rect is larger than width
+// Diagonally displays new screen starting from edges - works on _picRect area
+// only. Assumes that height of rect is larger than width.
void GfxTransitions::diagonalRollToCenter(bool blackoutFlag) {
Common::Rect upperRect(_picRect.left, _picRect.top, _picRect.right, _picRect.top + 1);
Common::Rect lowerRect(_picRect.left, _picRect.bottom - 1, _picRect.right, _picRect.bottom);
diff --git a/engines/sci/graphics/transitions.h b/engines/sci/graphics/transitions.h
index 9a1a412d5b..233638ffda 100644
--- a/engines/sci/graphics/transitions.h
+++ b/engines/sci/graphics/transitions.h
@@ -65,7 +65,7 @@ class Screen;
*/
class GfxTransitions {
public:
- GfxTransitions(SciGui *gui, GfxScreen *screen, GfxPalette *palette, bool isVGA);
+ GfxTransitions(GfxScreen *screen, GfxPalette *palette, bool isVGA);
~GfxTransitions();
void setup(int16 number, bool blackoutFlag);
@@ -83,6 +83,7 @@ private:
void pixelation(bool blackoutFlag);
void blocks(bool blackoutFlag);
void straight(int16 number, bool blackoutFlag);
+ void scrollCopyOldToScreen(Common::Rect screenRect, int16 x, int16 y);
void scroll(int16 number);
void verticalRollFromCenter(bool blackoutFlag);
void verticalRollToCenter(bool blackoutFlag);
@@ -92,7 +93,6 @@ private:
void diagonalRollToCenter(bool blackoutFlag);
void updateScreenAndWait(int msec);
- SciGui *_gui;
GfxScreen *_screen;
GfxPalette *_palette;
diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp
index 2ba14fbd8f..1c865f6bcf 100644
--- a/engines/sci/graphics/view.cpp
+++ b/engines/sci/graphics/view.cpp
@@ -28,6 +28,7 @@
#include "sci/engine/state.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/view.h"
namespace Sci {
@@ -35,6 +36,7 @@ namespace Sci {
GfxView::GfxView(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId)
: _resMan(resMan), _screen(screen), _palette(palette), _resourceId(resourceId) {
assert(resourceId != -1);
+ _coordAdjuster = g_sci->_gfxCoordAdjuster;
initData(resourceId);
}
@@ -62,6 +64,7 @@ void GfxView::initData(GuiResourceId resourceId) {
error("view resource %d not found", resourceId);
}
_resourceData = _resource->data;
+ _resourceSize = _resource->size;
byte *celData, *loopData;
uint16 celOffset;
@@ -75,12 +78,32 @@ void GfxView::initData(GuiResourceId resourceId) {
byte seekEntry;
bool isEGA = false;
bool isCompressed = true;
+ ViewType curViewType = _resMan->getViewType();
_loopCount = 0;
_embeddedPal = false;
_EGAmapping = NULL;
+ _isSci2Hires = false;
+ _isScaleable = true;
+
+ // we adjust inside getCelRect for SCI0EARLY (that version didn't have the +1 when calculating bottom)
+ _adjustForSci0Early = getSciVersion() == SCI_VERSION_0_EARLY ? -1 : 0;
+
+ // If we find an SCI1/SCI1.1 view (not amiga), we switch to that type for
+ // EGA. This could get used to make view patches for EGA games, where the
+ // new views include more colors. Users could manually adjust old views to
+ // make them look better (like removing dithered colors that aren't caught
+ // by our undithering or even improve the graphics overall).
+ if (curViewType == kViewEga) {
+ if (_resourceData[1] == 0x80) {
+ curViewType = kViewVga;
+ } else {
+ if (READ_LE_UINT16(_resourceData + 4) == 1)
+ curViewType = kViewVga11;
+ }
+ }
- switch (_resMan->getViewType()) {
+ switch (curViewType) {
case kViewEga: // View-format SCI0 (and Amiga 16 colors)
isEGA = true;
case kViewAmiga: // View-format Amiga (32 colors)
@@ -95,19 +118,21 @@ void GfxView::initData(GuiResourceId resourceId) {
palOffset = READ_LE_UINT16(_resourceData + 6);
if (palOffset && palOffset != 0x100) {
- // Some SCI0/SCI01 games also have an offset set. It seems that it points to a 16-byte mapping table
- // but on those games using that mapping will actually screw things up.
- // On the other side: vga sci1 games have this pointing to a VGA palette
- // and ega sci1 games have this pointing to a 8x16 byte mapping table that needs to get applied then
+ // Some SCI0/SCI01 games also have an offset set. It seems that it
+ // points to a 16-byte mapping table but on those games using that
+ // mapping will actually screw things up. On the other side: VGA
+ // SCI1 games have this pointing to a VGA palette and EGA SCI1 games
+ // have this pointing to a 8x16 byte mapping table that needs to get
+ // applied then.
if (!isEGA) {
- _palette->createFromData(&_resourceData[palOffset], &_viewPalette);
+ _palette->createFromData(&_resourceData[palOffset], _resourceSize - palOffset, &_viewPalette);
_embeddedPal = true;
} else {
// Only use the EGA-mapping, when being SCI1
if (getSciVersion() >= SCI_VERSION_1_EGA) {
_EGAmapping = &_resourceData[palOffset];
for (EGAmapNr = 0; EGAmapNr < SCI_VIEW_EGAMAPPING_COUNT; EGAmapNr++) {
- if (memcmp(_EGAmapping, EGAmappingStraight, SCI_VIEW_EGAMAPPING_SIZE)!=0)
+ if (memcmp(_EGAmapping, EGAmappingStraight, SCI_VIEW_EGAMAPPING_SIZE) != 0)
break;
_EGAmapping += SCI_VIEW_EGAMAPPING_SIZE;
}
@@ -141,8 +166,8 @@ void GfxView::initData(GuiResourceId resourceId) {
// For EGA
// Width:WORD Height:WORD DisplaceX:BYTE DisplaceY:BYTE ClearKey:BYTE EGAData starts now directly
cel = &_loop[loopNo].cel[celNo];
- cel->width = READ_LE_UINT16(celData);
- cel->height = READ_LE_UINT16(celData + 2);
+ cel->scriptWidth = cel->width = READ_LE_UINT16(celData);
+ cel->scriptHeight = cel->height = READ_LE_UINT16(celData + 2);
cel->displaceX = (signed char)celData[4];
cel->displaceY = celData[5];
cel->clearKey = celData[6];
@@ -168,13 +193,30 @@ void GfxView::initData(GuiResourceId resourceId) {
break;
case kViewVga11: // View-format SCI1.1+
- // HeaderSize:WORD LoopCount:BYTE Unknown:BYTE Version:WORD Unknown:WORD PaletteOffset:WORD
- headerSize = READ_SCI11ENDIAN_UINT16(_resourceData + 0) + 2; // headerSize is not part of the header, so its added
+ // HeaderSize:WORD LoopCount:BYTE Flags:BYTE Version:WORD Unknown:WORD PaletteOffset:WORD
+ headerSize = READ_SCI11ENDIAN_UINT16(_resourceData + 0) + 2; // headerSize is not part of the header, so it's added
assert(headerSize >= 16);
_loopCount = _resourceData[2];
assert(_loopCount);
+ _isSci2Hires = _resourceData[5] == 1 ? true : false;
palOffset = READ_SCI11ENDIAN_UINT32(_resourceData + 8);
- // FIXME: After LoopCount there is another byte and its set for view 50 within Laura Bow 2 CD, check what it means
+ // flags is actually a bit-mask
+ // it seems it was only used for some early sci1.1 games (or even just laura bow 2)
+ // later interpreters dont support it at all anymore
+ // we assume that if flags is 0h the view does not support flags and default to scaleable
+ // if it's 1h then we assume that the view is not to be scaled
+ // if it's 40h then we assume that the view is scaleable
+ switch (_resourceData[3]) {
+ case 1:
+ _isScaleable = false;
+ break;
+ case 0x40:
+ case 0:
+ break; // don't do anything, we already have _isScaleable set
+ default:
+ error("unsupported flags byte inside sci1.1 view");
+ break;
+ }
loopData = _resourceData + headerSize;
loopSize = _resourceData[12];
@@ -183,7 +225,7 @@ void GfxView::initData(GuiResourceId resourceId) {
assert(celSize >= 32);
if (palOffset) {
- _palette->createFromData(&_resourceData[palOffset], &_viewPalette);
+ _palette->createFromData(&_resourceData[palOffset], _resourceSize - palOffset, &_viewPalette);
_embeddedPal = true;
}
@@ -210,8 +252,8 @@ void GfxView::initData(GuiResourceId resourceId) {
_loop[loopNo].cel = new CelInfo[celCount];
for (celNo = 0; celNo < celCount; celNo++) {
cel = &_loop[loopNo].cel[celNo];
- cel->width = READ_SCI11ENDIAN_UINT16(celData);
- cel->height = READ_SCI11ENDIAN_UINT16(celData + 2);
+ cel->scriptWidth = cel->width = READ_SCI11ENDIAN_UINT16(celData);
+ cel->scriptHeight = cel->height = READ_SCI11ENDIAN_UINT16(celData + 2);
cel->displaceX = READ_SCI11ENDIAN_UINT16(celData + 4);
cel->displaceY = READ_SCI11ENDIAN_UINT16(celData + 6);
@@ -221,6 +263,9 @@ void GfxView::initData(GuiResourceId resourceId) {
cel->offsetEGA = 0;
cel->offsetRLE = READ_SCI11ENDIAN_UINT32(celData + 24);
cel->offsetLiteral = READ_SCI11ENDIAN_UINT32(celData + 28);
+ // GK1-hires content is actually uncompressed, we need to swap both so that we process it as such
+ if ((cel->offsetRLE) && (!cel->offsetLiteral))
+ SWAP(cel->offsetRLE, cel->offsetLiteral);
cel->rawBitmap = 0;
if (_loop[loopNo].mirrorFlag)
@@ -229,6 +274,29 @@ void GfxView::initData(GuiResourceId resourceId) {
celData += celSize;
}
}
+#ifdef ENABLE_SCI32
+ // adjust width/height returned to scripts
+ switch (getSciVersion()) {
+ case SCI_VERSION_2:
+ if (_isSci2Hires) {
+ for (loopNo = 0; loopNo < _loopCount; loopNo++) {
+ for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++) {
+ _screen->adjustBackUpscaledCoordinates(_loop[loopNo].cel[celNo].scriptWidth, _loop[loopNo].cel[celNo].scriptHeight);
+ }
+ }
+ }
+ break;
+
+ case SCI_VERSION_2_1:
+ for (loopNo = 0; loopNo < _loopCount; loopNo++) {
+ for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++) {
+ _coordAdjuster->fromDisplayToScript(_loop[loopNo].cel[celNo].scriptHeight, _loop[loopNo].cel[celNo].scriptWidth);
+ }
+ }
+ default:
+ break;
+ }
+#endif
break;
default:
@@ -236,65 +304,72 @@ void GfxView::initData(GuiResourceId resourceId) {
}
}
-GuiResourceId GfxView::getResourceId() {
+GuiResourceId GfxView::getResourceId() const {
return _resourceId;
}
-int16 GfxView::getWidth(int16 loopNo, int16 celNo) {
- loopNo = CLIP<int16>(loopNo, 0, _loopCount - 1);
- celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1);
- return _loopCount ? _loop[loopNo].cel[celNo].width : 0;
+int16 GfxView::getWidth(int16 loopNo, int16 celNo) const {
+ return _loopCount ? getCelInfo(loopNo, celNo)->width : 0;
}
-int16 GfxView::getHeight(int16 loopNo, int16 celNo) {
- loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
- celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1);
- return _loopCount ? _loop[loopNo].cel[celNo].height : 0;
+int16 GfxView::getHeight(int16 loopNo, int16 celNo) const {
+ return _loopCount ? getCelInfo(loopNo, celNo)->height : 0;
}
-CelInfo *GfxView::getCelInfo(int16 loopNo, int16 celNo) {
+const CelInfo *GfxView::getCelInfo(int16 loopNo, int16 celNo) const {
+ assert(_loopCount);
loopNo = CLIP<int16>(loopNo, 0, _loopCount - 1);
celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1);
- return _loopCount ? &_loop[loopNo].cel[celNo] : NULL;
+ return &_loop[loopNo].cel[celNo];
}
-LoopInfo *GfxView::getLoopInfo(int16 loopNo) {
+uint16 GfxView::getCelCount(int16 loopNo) const {
+ assert(_loopCount);
loopNo = CLIP<int16>(loopNo, 0, _loopCount - 1);
- return _loopCount ? &_loop[loopNo] : NULL;
+ return _loop[loopNo].celCount;
}
-void GfxView::getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect *outRect) {
- CelInfo *celInfo = getCelInfo(loopNo, celNo);
- if (celInfo) {
- outRect->left = x + celInfo->displaceX - (celInfo->width >> 1);
- outRect->right = outRect->left + celInfo->width;
- outRect->bottom = y + celInfo->displaceY - z + 1;
- outRect->top = outRect->bottom - celInfo->height;
- }
+Palette *GfxView::getPalette() {
+ return _embeddedPal ? &_viewPalette : NULL;
}
-void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect *outRect) {
+bool GfxView::isSci2Hires() {
+ return _isSci2Hires;
+}
+
+bool GfxView::isScaleable() {
+ return _isScaleable;
+}
+
+void GfxView::getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect &outRect) const {
+ const CelInfo *celInfo = getCelInfo(loopNo, celNo);
+ outRect.left = x + celInfo->displaceX - (celInfo->width >> 1);
+ outRect.right = outRect.left + celInfo->width;
+ outRect.bottom = y + celInfo->displaceY - z + 1 + _adjustForSci0Early;
+ outRect.top = outRect.bottom - celInfo->height;
+}
+
+void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect &outRect) const {
int16 scaledDisplaceX, scaledDisplaceY;
int16 scaledWidth, scaledHeight;
- CelInfo *celInfo = getCelInfo(loopNo, celNo);
- if (celInfo) {
- // Scaling displaceX/Y, Width/Height
- scaledDisplaceX = (celInfo->displaceX * scaleX) >> 7;
- scaledDisplaceY = (celInfo->displaceY * scaleY) >> 7;
- scaledWidth = (celInfo->width * scaleX) >> 7;
- scaledHeight = (celInfo->height * scaleY) >> 7;
- scaledWidth = CLIP<int16>(scaledWidth, 0, _screen->getWidth());
- scaledHeight = CLIP<int16>(scaledHeight, 0, _screen->getHeight());
-
- outRect->left = x + scaledDisplaceX - (scaledWidth >> 1);
- outRect->right = outRect->left + scaledWidth;
- outRect->bottom = y + scaledDisplaceY - z + 1;
- outRect->top = outRect->bottom - scaledHeight;
- }
+ const CelInfo *celInfo = getCelInfo(loopNo, celNo);
+
+ // Scaling displaceX/Y, Width/Height
+ scaledDisplaceX = (celInfo->displaceX * scaleX) >> 7;
+ scaledDisplaceY = (celInfo->displaceY * scaleY) >> 7;
+ scaledWidth = (celInfo->width * scaleX) >> 7;
+ scaledHeight = (celInfo->height * scaleY) >> 7;
+ scaledWidth = CLIP<int16>(scaledWidth, 0, _screen->getWidth());
+ scaledHeight = CLIP<int16>(scaledHeight, 0, _screen->getHeight());
+
+ outRect.left = x + scaledDisplaceX - (scaledWidth >> 1);
+ outRect.right = outRect.left + scaledWidth;
+ outRect.bottom = y + scaledDisplaceY - z + 1;
+ outRect.top = outRect.bottom - scaledHeight;
}
void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount) {
- CelInfo *celInfo = getCelInfo(loopNo, celNo);
+ const CelInfo *celInfo = getCelInfo(loopNo, celNo);
byte *rlePtr;
byte *literalPtr;
uint32 pixelNo = 0, runLength;
@@ -309,78 +384,42 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou
memset(outPtr + pixelNo, pixel & 0x0F, MIN<uint32>(runLength, pixelCount - pixelNo));
pixelNo += runLength;
}
- return;
- }
-
- rlePtr = _resourceData + celInfo->offsetRLE;
- if (!celInfo->offsetLiteral) { // no additional literal data
- if (_resMan->isAmiga32color()) {
- // decompression for amiga views
- while (pixelNo < pixelCount) {
- pixel = *rlePtr++;
- if (pixel & 0x07) { // fill with color
- runLength = pixel & 0x07;
- pixel = pixel >> 3;
- while (runLength-- && pixelNo < pixelCount) {
- outPtr[pixelNo++] = pixel;
- }
- } else { // fill with transparent
- runLength = pixel >> 3;
- pixelNo += runLength;
- }
- }
- return;
- } else {
- // decompression for data that has just one combined stream
- while (pixelNo < pixelCount) {
- pixel = *rlePtr++;
- runLength = pixel & 0x3F;
- switch (pixel & 0xC0) {
- case 0: // copy bytes as-is
- while (runLength-- && pixelNo < pixelCount)
- outPtr[pixelNo++] = *rlePtr++;
- break;
- case 0x80: // fill with color
- memset(outPtr + pixelNo, *rlePtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
- pixelNo += runLength;
- break;
- case 0xC0: // fill with transparent
- pixelNo += runLength;
- break;
- }
- }
- return;
- }
} else {
- literalPtr = _resourceData + celInfo->offsetLiteral;
- if (celInfo->offsetRLE) {
- if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) {
- // Crazy-Ass compression for SCI1.1+ Mac
+ // We fill the buffer with transparent pixels, so that we can later skip
+ // over pixels to automatically have them transparent
+ // Also some RLE compressed cels are possibly ending with the last
+ // non-transparent pixel (is this even possible with the current code?)
+ memset(outPtr, _loop[loopNo].cel[celNo].clearKey, pixelCount);
+
+ rlePtr = _resourceData + celInfo->offsetRLE;
+ if (!celInfo->offsetLiteral) { // no additional literal data
+ if (_resMan->isAmiga32color()) {
+ // decompression for amiga views
while (pixelNo < pixelCount) {
- uint32 pixelLine = pixelNo;
- runLength = *rlePtr++;
- pixelNo += runLength;
- runLength = *rlePtr++;
- while (runLength-- && pixelNo < pixelCount) {
- outPtr[pixelNo] = *literalPtr++;
- if (outPtr[pixelNo] == 255)
- outPtr[pixelNo] = 0;
- pixelNo++;
+ pixel = *rlePtr++;
+ if (pixel & 0x07) { // fill with color
+ runLength = pixel & 0x07;
+ pixel = pixel >> 3;
+ while (runLength-- && pixelNo < pixelCount) {
+ outPtr[pixelNo++] = pixel;
+ }
+ } else { // fill with transparent
+ runLength = pixel >> 3;
+ pixelNo += runLength;
}
- pixelNo = pixelLine + celInfo->width;
}
} else {
- // decompression for data that has separate rle and literal streams
+ // decompression for data that has just one combined stream
while (pixelNo < pixelCount) {
pixel = *rlePtr++;
runLength = pixel & 0x3F;
switch (pixel & 0xC0) {
case 0: // copy bytes as-is
while (runLength-- && pixelNo < pixelCount)
- outPtr[pixelNo++] = *literalPtr++;
+ outPtr[pixelNo++] = *rlePtr++;
break;
case 0x80: // fill with color
- memset(outPtr + pixelNo, *literalPtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
+ memset(outPtr + pixelNo, *rlePtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
pixelNo += runLength;
break;
case 0xC0: // fill with transparent
@@ -390,15 +429,53 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou
}
}
} else {
- // literal stream only, so no compression
- memcpy(outPtr, literalPtr, pixelCount);
+ literalPtr = _resourceData + celInfo->offsetLiteral;
+ if (celInfo->offsetRLE) {
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) {
+ // compression for SCI1.1+ Mac
+ while (pixelNo < pixelCount) {
+ uint32 pixelLine = pixelNo;
+ runLength = *rlePtr++;
+ pixelNo += runLength;
+ runLength = *rlePtr++;
+ while (runLength-- && pixelNo < pixelCount) {
+ outPtr[pixelNo] = *literalPtr++;
+ if (outPtr[pixelNo] == 255)
+ outPtr[pixelNo] = 0;
+ pixelNo++;
+ }
+ pixelNo = pixelLine + celInfo->width;
+ }
+ } else {
+ // decompression for data that has separate rle and literal streams
+ while (pixelNo < pixelCount) {
+ pixel = *rlePtr++;
+ runLength = pixel & 0x3F;
+ switch (pixel & 0xC0) {
+ case 0: // copy bytes as-is
+ while (runLength-- && pixelNo < pixelCount)
+ outPtr[pixelNo++] = *literalPtr++;
+ break;
+ case 0x80: // fill with color
+ memset(outPtr + pixelNo, *literalPtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
+ pixelNo += runLength;
+ break;
+ case 0xC0: // fill with transparent
+ pixelNo += runLength;
+ break;
+ }
+ }
+ }
+ } else {
+ // literal stream only, so no compression
+ memcpy(outPtr, literalPtr, pixelCount);
+ pixelNo = pixelCount;
+ }
}
- return;
}
- error("Unable to decompress view");
}
-byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
+const byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1);
if (_loop[loopNo].cel[celNo].rawBitmap)
@@ -411,9 +488,7 @@ byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
_loop[loopNo].cel[celNo].rawBitmap = new byte[pixelCount];
byte *pBitmap = _loop[loopNo].cel[celNo].rawBitmap;
- // Some RLE compressed cels end with the last non-transparent pixel, thats why we fill it up here
- // FIXME: change this to fill the remaining bytes within unpackCel()
- memset(pBitmap, _loop[loopNo].cel[celNo].clearKey, pixelCount);
+ // unpack the actual cel bitmap data
unpackCel(loopNo, celNo, pBitmap, pixelCount);
if (!_resMan->isVGA()) {
@@ -429,17 +504,21 @@ byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
return _loop[loopNo].cel[celNo].rawBitmap;
}
-// Called after unpacking an EGA cel, this will try to undither (parts) of the cel if the dithering in here
-// matches dithering used by the current picture
+/**
+ * Called after unpacking an EGA cel, this will try to undither (parts) of the
+ * cel if the dithering in here matches dithering used by the current picture.
+ */
void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte clearKey) {
int16 *unditherMemorial = _screen->unditherGetMemorial();
- // It makes no sense to go further, if no memorial data from current picture is available
+ // It makes no sense to go further, if no memorial data from current picture
+ // is available
if (!unditherMemorial)
return;
// Makes no sense to process bitmaps that are 3 pixels wide or less
- if (width <= 3) return;
+ if (width <= 3)
+ return;
// If EGA mapping is used for this view, dont do undithering as well
if (_EGAmapping)
@@ -453,7 +532,8 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
memset(&bitmapMemorial, 0, sizeof(bitmapMemorial));
- // Count all seemingly dithered pixel-combinations as soon as at least 4 pixels are adjacent
+ // Count all seemingly dithered pixel-combinations as soon as at least 4
+ // pixels are adjacent
curPtr = bitmapPtr;
for (y = 0; y < height; y++) {
color1 = curPtr[0]; color2 = (curPtr[1] << 4) | curPtr[2];
@@ -466,17 +546,20 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
}
}
- // Now compare both memorial tables to find out matching dithering-combinations
+ // Now compare both memorial tables to find out matching
+ // dithering-combinations
bool unditherTable[SCI_SCREEN_UNDITHERMEMORIAL_SIZE];
byte color, unditherCount = 0;
memset(&unditherTable, false, sizeof(unditherTable));
for (color = 0; color < 255; color++) {
if ((bitmapMemorial[color] > 5) && (unditherMemorial[color] > 200)) {
- // match found, check if colorKey is contained -> if so, we ignore of course
+ // match found, check if colorKey is contained -> if so, we ignore
+ // of course
color1 = color & 0x0F; color2 = color >> 4;
if ((color1 != clearKey) && (color2 != clearKey) && (color1 != color2)) {
// so set this and the reversed color-combination for undithering
- unditherTable[color] = true; unditherTable[(color1 << 4) | color2] = true;
+ unditherTable[color] = true;
+ unditherTable[(color1 << 4) | color2] = true;
unditherCount++;
}
}
@@ -493,8 +576,9 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
for (x = 1; x < width; x++) {
color = (color << 4) | curPtr[1];
if (unditherTable[color]) {
- // some color with black? turn colors around otherwise it wont be the right color at all
- if ((color & 0xF0)==0)
+ // Some color with black? Turn colors around, otherwise it won't
+ // be the right color at all.
+ if ((color & 0xF0) == 0)
color = (color << 4) | (color >> 4);
curPtr[0] = color; curPtr[1] = color;
}
@@ -504,15 +588,15 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
}
}
-void GfxView::draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires) {
- Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette;
- CelInfo *celInfo = getCelInfo(loopNo, celNo);
- byte *bitmap = getBitmap(loopNo, celNo);
- int16 celHeight = celInfo->height, celWidth = celInfo->width;
- int16 width, height;
- byte clearKey = celInfo->clearKey;
- byte color;
- byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY;
+void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated,
+ int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires) {
+ const Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette;
+ const CelInfo *celInfo = getCelInfo(loopNo, celNo);
+ const byte *bitmap = getBitmap(loopNo, celNo);
+ const int16 celHeight = celInfo->height;
+ const int16 celWidth = celInfo->width;
+ const byte clearKey = celInfo->clearKey;
+ const byte drawMask = (priority == 255) ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY;
int x, y;
if (_embeddedPal) {
@@ -520,24 +604,27 @@ void GfxView::draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRe
_palette->set(&_viewPalette, false);
}
- width = MIN(clipRect.width(), celWidth);
- height = MIN(clipRect.height(), celHeight);
+ const int16 width = MIN(clipRect.width(), celWidth);
+ const int16 height = MIN(clipRect.height(), celHeight);
bitmap += (clipRect.top - rect.top) * celWidth + (clipRect.left - rect.left);
if (!_EGAmapping) {
for (y = 0; y < height; y++, bitmap += celWidth) {
for (x = 0; x < width; x++) {
- color = bitmap[x];
+ const byte color = bitmap[x];
if (color != clearKey) {
+ const int x2 = clipRectTranslated.left + x;
+ const int y2 = clipRectTranslated.top + y;
if (!upscaledHires) {
- if (priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y))
- _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, palette->mapping[color], priority, 0);
+ if (priority >= _screen->getPriority(x2, y2))
+ _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0);
} else {
- // UpscaledHires means view is hires and is supposed to get drawn onto lowres screen
- // FIXME(?): we can't read priority directly with the hires coordinates. may not be needed at all
- // in kq6
- _screen->putPixelOnDisplay(clipRectTranslated.left + x, clipRectTranslated.top + y, palette->mapping[color]);
+ // UpscaledHires means view is hires and is supposed to
+ // get drawn onto lowres screen.
+ // FIXME(?): we can't read priority directly with the
+ // hires coordinates. may not be needed at all in kq6
+ _screen->putPixelOnDisplay(x2, y2, palette->mapping[color]);
}
}
}
@@ -546,30 +633,34 @@ void GfxView::draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRe
byte *EGAmapping = _EGAmapping + (EGAmappingNr * SCI_VIEW_EGAMAPPING_SIZE);
for (y = 0; y < height; y++, bitmap += celWidth) {
for (x = 0; x < width; x++) {
- color = EGAmapping[bitmap[x]];
- if (color != clearKey && priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y))
- _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, color, priority, 0);
+ const byte color = EGAmapping[bitmap[x]];
+ const int x2 = clipRectTranslated.left + x;
+ const int y2 = clipRectTranslated.top + y;
+ if (color != clearKey && priority >= _screen->getPriority(x2, y2))
+ _screen->putPixel(x2, y2, drawMask, color, priority, 0);
}
}
}
}
-// We don't fully follow sierra sci here, I did the scaling algo myself and it's definitely not pixel-perfect
-// with the one sierra is using. It shouldn't matter because the scaled cel rect is definitely the same as in sierra sci
-void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY) {
- Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette;
- CelInfo *celInfo = getCelInfo(loopNo, celNo);
- byte *bitmap = getBitmap(loopNo, celNo);
- int16 celHeight = celInfo->height, celWidth = celInfo->width;
- byte clearKey = celInfo->clearKey;
- byte color;
- byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY;
- int x, y;
- uint16 scalingX[320];
- uint16 scalingY[200];
+/**
+ * We don't fully follow sierra sci here, I did the scaling algo myself and it
+ * is definitely not pixel-perfect with the one sierra is using. It shouldn't
+ * matter because the scaled cel rect is definitely the same as in sierra sci.
+ */
+void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated,
+ int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY) {
+ const Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette;
+ const CelInfo *celInfo = getCelInfo(loopNo, celNo);
+ const byte *bitmap = getBitmap(loopNo, celNo);
+ const int16 celHeight = celInfo->height;
+ const int16 celWidth = celInfo->width;
+ const byte clearKey = celInfo->clearKey;
+ const byte drawMask = (priority == 255) ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY;
+ uint16 scalingX[640];
+ uint16 scalingY[480];
int16 scaledWidth, scaledHeight;
- int16 pixelNo, scaledPixel, scaledPixelNo, prevScaledPixelNo;
- uint16 offsetX, offsetY;
+ int pixelNo, scaledPixel, scaledPixelNo, prevScaledPixelNo;
if (_embeddedPal) {
// Merge view palette in...
@@ -582,65 +673,63 @@ void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect
scaledHeight = CLIP<int16>(scaledHeight, 0, _screen->getHeight());
// Do we really need to do this?!
- memset(scalingX, 0, sizeof(scalingX));
- memset(scalingY, 0, sizeof(scalingY));
+ //memset(scalingX, 0, sizeof(scalingX));
+ //memset(scalingY, 0, sizeof(scalingY));
// Create height scaling table
pixelNo = 0;
scaledPixel = scaledPixelNo = prevScaledPixelNo = 0;
while (pixelNo < celHeight) {
scaledPixelNo = scaledPixel >> 7;
- if (prevScaledPixelNo < scaledPixelNo)
- memset(&scalingY[prevScaledPixelNo], pixelNo, scaledPixelNo - prevScaledPixelNo);
- scalingY[scaledPixelNo] = pixelNo;
- prevScaledPixelNo = scaledPixelNo + 1;
+ assert(scaledPixelNo < ARRAYSIZE(scalingY));
+ for (; prevScaledPixelNo <= scaledPixelNo; prevScaledPixelNo++)
+ scalingY[prevScaledPixelNo] = pixelNo;
pixelNo++;
scaledPixel += scaleY;
}
+ pixelNo--;
scaledPixelNo++;
- if (scaledPixelNo < scaledHeight)
- memset(&scalingY[scaledPixelNo], pixelNo - 1, scaledHeight - scaledPixelNo);
+ for (; scaledPixelNo < scaledHeight; scaledPixelNo++)
+ scalingY[scaledPixelNo] = pixelNo;
// Create width scaling table
pixelNo = 0;
scaledPixel = scaledPixelNo = prevScaledPixelNo = 0;
while (pixelNo < celWidth) {
scaledPixelNo = scaledPixel >> 7;
- if (prevScaledPixelNo < scaledPixelNo)
- memset(&scalingX[prevScaledPixelNo], pixelNo, scaledPixelNo - prevScaledPixelNo);
- scalingX[scaledPixelNo] = pixelNo;
- prevScaledPixelNo = scaledPixelNo + 1;
+ assert(scaledPixelNo < ARRAYSIZE(scalingX));
+ for (; prevScaledPixelNo <= scaledPixelNo; prevScaledPixelNo++)
+ scalingX[prevScaledPixelNo] = pixelNo;
pixelNo++;
scaledPixel += scaleX;
}
+ pixelNo--;
scaledPixelNo++;
- if (scaledPixelNo < scaledWidth)
- memset(&scalingX[scaledPixelNo], pixelNo - 1, scaledWidth - scaledPixelNo);
+ for (; scaledPixelNo < scaledWidth; scaledPixelNo++)
+ scalingX[scaledPixelNo] = pixelNo;
scaledWidth = MIN(clipRect.width(), scaledWidth);
scaledHeight = MIN(clipRect.height(), scaledHeight);
- offsetY = clipRect.top - rect.top;
- offsetX = clipRect.left - rect.left;
+ const int16 offsetY = clipRect.top - rect.top;
+ const int16 offsetX = clipRect.left - rect.left;
- for (y = 0; y < scaledHeight; y++) {
- for (x = 0; x < scaledWidth; x++) {
- color = bitmap[scalingY[y + offsetY] * celWidth + scalingX[x + offsetX]];
- if (color != clearKey && priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y)) {
- _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, palette->mapping[color], priority, 0);
+ // Happens in SQ6, first room
+ if (offsetX < 0 || offsetY < 0)
+ return;
+
+ assert(scaledHeight + offsetY <= ARRAYSIZE(scalingY));
+ assert(scaledWidth + offsetX <= ARRAYSIZE(scalingX));
+ for (int y = 0; y < scaledHeight; y++) {
+ for (int x = 0; x < scaledWidth; x++) {
+ const byte color = bitmap[scalingY[y + offsetY] * celWidth + scalingX[x + offsetX]];
+ const int x2 = clipRectTranslated.left + x;
+ const int y2 = clipRectTranslated.top + y;
+ if (color != clearKey && priority >= _screen->getPriority(x2, y2)) {
+ _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0);
}
}
}
}
-uint16 GfxView::getCelCount(int16 loopNo) {
- if ((loopNo < 0) || (loopNo >= _loopCount))
- return 0;
- return _loop[loopNo].celCount;
-}
-
-Palette *GfxView::getPalette() {
- return _embeddedPal ? &_viewPalette : &_palette->_sysPalette;
-}
-
} // End of namespace Sci
diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h
index a2050dc9d5..990a7e2f71 100644
--- a/engines/sci/graphics/view.h
+++ b/engines/sci/graphics/view.h
@@ -30,6 +30,7 @@ namespace Sci {
struct CelInfo {
int16 width, height;
+ int16 scriptWidth, scriptHeight;
int16 displaceX;
int16 displaceY;
byte clearKey;
@@ -60,39 +61,53 @@ public:
GfxView(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId);
~GfxView();
- GuiResourceId getResourceId();
- int16 getWidth(int16 loopNo, int16 celNo);
- int16 getHeight(int16 loopNo, int16 celNo);
- CelInfo *getCelInfo(int16 loopNo, int16 celNo);
- LoopInfo *getLoopInfo(int16 loopNo);
- void getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect *outRect);
- void getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect *outRect);
- byte *getBitmap(int16 loopNo, int16 celNo);
- void draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires);
- void drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY);
+ GuiResourceId getResourceId() const;
+ int16 getWidth(int16 loopNo, int16 celNo) const;
+ int16 getHeight(int16 loopNo, int16 celNo) const;
+ const CelInfo *getCelInfo(int16 loopNo, int16 celNo) const;
+ void getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect &outRect) const;
+ void getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect &outRect) const;
+ const byte *getBitmap(int16 loopNo, int16 celNo);
+ void draw(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires);
+ void drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY);
uint16 getLoopCount() const { return _loopCount; }
- uint16 getCelCount(int16 loopNo);
+ uint16 getCelCount(int16 loopNo) const;
Palette *getPalette();
+ bool isScaleable();
+ bool isSci2Hires();
+
private:
void initData(GuiResourceId resourceId);
void unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount);
void unditherBitmap(byte *bitmap, int16 width, int16 height, byte clearKey);
ResourceManager *_resMan;
+ GfxCoordAdjuster *_coordAdjuster;
GfxScreen *_screen;
GfxPalette *_palette;
GuiResourceId _resourceId;
Resource *_resource;
byte *_resourceData;
+ int _resourceSize;
uint16 _loopCount;
LoopInfo *_loop;
bool _embeddedPal;
Palette _viewPalette;
+ // set for SCI2 views in gk1/windows, means that views are hires and should be handled accordingly
+ bool _isSci2Hires;
+
byte *_EGAmapping;
+
+ // this is set for sci0early to adjust for the getCelRect() change
+ int16 _adjustForSci0Early;
+
+ // this is not set for some views in laura bow 2 floppy and signals that the view shall never get scaled
+ // even if scaleX/Y are set (inside kAnimate)
+ bool _isScaleable;
};
} // End of namespace Sci
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index 8c4d666ba7..238209c446 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -6,10 +6,10 @@ MODULE_OBJS := \
detection.o \
event.o \
resource.o \
+ resource_audio.o \
sci.o \
util.o \
engine/features.o \
- engine/game.o \
engine/gc.o \
engine/kernel.o \
engine/kevent.o \
@@ -25,16 +25,19 @@ MODULE_OBJS := \
engine/kscripts.o \
engine/ksound.o \
engine/kstring.o \
+ engine/kvideo.o \
engine/message.o \
engine/savegame.o \
engine/script.o \
engine/scriptdebug.o \
+ engine/script_patches.o \
engine/selector.o \
engine/seg_manager.o \
engine/segment.o \
engine/state.o \
engine/static_selectors.o \
engine/vm.o \
+ engine/workarounds.o \
graphics/animate.o \
graphics/cache.o \
graphics/compare.o \
@@ -43,7 +46,7 @@ MODULE_OBJS := \
graphics/cursor.o \
graphics/font.o \
graphics/fontsjis.o \
- graphics/gui.o \
+ graphics/maciconbar.o \
graphics/menu.o \
graphics/paint.o \
graphics/paint16.o \
@@ -63,24 +66,18 @@ MODULE_OBJS := \
sound/music.o \
sound/soundcmd.o \
sound/drivers/adlib.o \
- sound/drivers/amiga.o \
+ sound/drivers/amigamac.o \
sound/drivers/fb01.o \
sound/drivers/midi.o \
sound/drivers/pcjr.o \
- sound/iterator/core.o \
- sound/iterator/iterator.o \
- sound/iterator/songlib.o \
video/seq_decoder.o
ifdef ENABLE_SCI32
MODULE_OBJS += \
- engine/kernel32.o \
graphics/frameout.o \
- graphics/gui32.o \
graphics/paint32.o \
- graphics/robot.o \
- video/vmd_decoder.o
+ graphics/robot.o
endif
# This module can be built as a plugin
diff --git a/engines/sci/parser/grammar.cpp b/engines/sci/parser/grammar.cpp
index 1cfe84076f..6f37b49919 100644
--- a/engines/sci/parser/grammar.cpp
+++ b/engines/sci/parser/grammar.cpp
@@ -258,6 +258,11 @@ void Vocabulary::freeRuleList(ParseRuleList *list) {
static ParseRuleList *_vocab_add_rule(ParseRuleList *list, ParseRule *rule) {
if (!rule)
return list;
+ if (!rule->_data.size()) {
+ // Special case for qfg2 demo
+ warning("no rule contents on _vocab_add_rule()");
+ return list;
+ }
ParseRuleList *new_elem = new ParseRuleList(rule);
@@ -417,44 +422,44 @@ ParseRuleList *Vocabulary::buildGNF(bool verbose) {
return tlist;
}
-static int _vbpt_pareno(parse_tree_node_t *nodes, int *pos, int base) {
+static int _vbpt_pareno(ParseTreeNode *nodes, int *pos, int base) {
// Opens parentheses
- nodes[base].content.branches[0] = (*pos) + 1;
+ nodes[base].left = &nodes[(*pos) + 1];
nodes[++(*pos)].type = kParseTreeBranchNode;
- nodes[*pos].content.branches[0] = 0;
- nodes[*pos].content.branches[1] = 0;
+ nodes[*pos].left = 0;
+ nodes[*pos].right = 0;
return *pos;
}
-static int _vbpt_parenc(parse_tree_node_t *nodes, int *pos, int paren) {
+static int _vbpt_parenc(ParseTreeNode *nodes, int *pos, int paren) {
// Closes parentheses for appending
- nodes[paren].content.branches[1] = ++(*pos);
+ nodes[paren].right = &nodes[++(*pos)];
nodes[*pos].type = kParseTreeBranchNode;
- nodes[*pos].content.branches[0] = 0;
- nodes[*pos].content.branches[1] = 0;
+ nodes[*pos].left = 0;
+ nodes[*pos].right = 0;
return *pos;
}
-static int _vbpt_append(parse_tree_node_t *nodes, int *pos, int base, int value) {
+static int _vbpt_append(ParseTreeNode *nodes, int *pos, int base, int value) {
// writes one value to an existing base node and creates a successor node for writing
- nodes[base].content.branches[0] = ++(*pos);
+ nodes[base].left = &nodes[++(*pos)];
nodes[*pos].type = kParseTreeLeafNode;
- nodes[*pos].content.value = value;
- nodes[base].content.branches[1] = ++(*pos);
+ nodes[*pos].value = value;
+ nodes[base].right = &nodes[++(*pos)];
nodes[*pos].type = kParseTreeBranchNode;
- nodes[*pos].content.branches[0] = 0;
- nodes[*pos].content.branches[1] = 0;
+ nodes[*pos].left = 0;
+ nodes[*pos].right = 0;
return *pos;
}
-static int _vbpt_terminate(parse_tree_node_t *nodes, int *pos, int base, int value) {
+static int _vbpt_terminate(ParseTreeNode *nodes, int *pos, int base, int value) {
// Terminates, overwriting a nextwrite forknode
nodes[base].type = kParseTreeLeafNode;
- nodes[base].content.value = value;
+ nodes[base].value = value;
return *pos;
}
-static int _vbpt_write_subexpression(parse_tree_node_t *nodes, int *pos, ParseRule *rule, uint rulepos, int writepos) {
+static int _vbpt_write_subexpression(ParseTreeNode *nodes, int *pos, ParseRule *rule, uint rulepos, int writepos) {
uint token;
while ((token = ((rulepos < rule->_data.size()) ? rule->_data[rulepos++] : TOKEN_CPAREN)) != TOKEN_CPAREN) {
@@ -560,15 +565,15 @@ int Vocabulary::parseGNF(const ResultWordList &words, bool verbose) {
int temp, pos;
_parserNodes[0].type = kParseTreeBranchNode;
- _parserNodes[0].content.branches[0] = 1;
- _parserNodes[0].content.branches[1] = 2;
+ _parserNodes[0].left = &_parserNodes[1];
+ _parserNodes[0].right = &_parserNodes[2];
_parserNodes[1].type = kParseTreeLeafNode;
- _parserNodes[1].content.value = 0x141;
+ _parserNodes[1].value = 0x141;
_parserNodes[2].type = kParseTreeBranchNode;
- _parserNodes[2].content.branches[0] = 0;
- _parserNodes[2].content.branches[1] = 0;
+ _parserNodes[2].left = 0;
+ _parserNodes[2].right = 0;
pos = 2;
diff --git a/engines/sci/parser/said.cpp b/engines/sci/parser/said.cpp
index 5cd1310ad3..9c07be2dff 100644
--- a/engines/sci/parser/said.cpp
+++ b/engines/sci/parser/said.cpp
@@ -1,111 +1,3 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
- simplifying the original so-called "semantic" parser. */
-
-/* All symbols defined below should begin with yy or YY, to avoid
- infringing on user name space. This should be done even for local
- variables, as they might otherwise be expanded by user macros.
- There are some unavoidable exceptions within include files to
- define necessary library symbols; they are noted "INFRINGES ON
- USER NAME SPACE" below. */
-
-/* Identify Bison output. */
-#define YYBISON 1
-
-/* Bison version. */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name. */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers. */
-#define YYPURE 0
-
-/* Using locations. */
-#define YYLSP_NEEDED 0
-
-
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- WGROUP = 258,
- YY_COMMA = 259,
- YY_AMP = 260,
- YY_SLASH = 261,
- YY_PARENO = 262,
- YY_PARENC = 263,
- YY_BRACKETSO = 264,
- YY_BRACKETSC = 265,
- YY_HASH = 266,
- YY_LT = 267,
- YY_GT = 268,
- YY_BRACKETSO_LT = 269,
- YY_BRACKETSO_SLASH = 270,
- YY_LT_BRACKETSO = 271,
- YY_LT_PARENO = 272
- };
-#endif
-/* Tokens. */
-#define WGROUP 258
-#define YY_COMMA 259
-#define YY_AMP 260
-#define YY_SLASH 261
-#define YY_PARENO 262
-#define YY_PARENC 263
-#define YY_BRACKETSO 264
-#define YY_BRACKETSC 265
-#define YY_HASH 266
-#define YY_LT 267
-#define YY_GT 268
-#define YY_BRACKETSO_LT 269
-#define YY_BRACKETSO_SLASH 270
-#define YY_LT_BRACKETSO 271
-#define YY_LT_PARENO 272
-
-
-
-
-/* Copy the first part of user declarations. */
-
-
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
@@ -133,14 +25,6 @@
#include "sci/engine/state.h"
-
-// Bison generates an empty switch statement that gives a warning in MSVC.
-// This disables that warning.
-#ifdef _MSC_VER
-#pragma warning(disable:4065)
-#endif
-
-
namespace Sci {
#define SAID_BRANCH_NULL 0
@@ -150,25 +34,8 @@ namespace Sci {
// Maximum number of words to be expected in a parsed sentence
#define AUGMENT_MAX_WORDS 64
-
-#define ANYWORD 0xfff
-
-#define WORD_TYPE_BASE 0x141
-#define WORD_TYPE_REF 0x144
-#define WORD_TYPE_SYNTACTIC_SUGAR 0x145
-
-#define AUGMENT_SENTENCE_PART_BRACKETS 0x152
-
-// Minor numbers
-#define AUGMENT_SENTENCE_MINOR_MATCH_PHRASE 0x14c
-#define AUGMENT_SENTENCE_MINOR_MATCH_WORD 0x153
-#define AUGMENT_SENTENCE_MINOR_RECURSE 0x144
-#define AUGMENT_SENTENCE_MINOR_PARENTHESES 0x14f
-
-
-#undef YYDEBUG /*1*/
-//#define SAID_DEBUG*/
-//#define SCI_DEBUG_PARSE_TREE_AUGMENTATION // uncomment to debug parse tree augmentation
+// uncomment to debug parse tree augmentation
+//#define SCI_DEBUG_PARSE_TREE_AUGMENTATION
#ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION
@@ -179,2305 +46,1084 @@ void print_nothing(...) { }
#endif
-static char *said_parse_error;
-
static int said_token;
static int said_tokens_nr;
static int said_tokens[MAX_SAID_TOKENS];
-static int said_blessed; // increminated by said_top_branch
-static int said_tree_pos; // Set to 0 if we're out of space
-#define SAID_TREE_START 4; // Reserve space for the 4 top nodes
+static int said_tree_pos;
+#define SAID_TREE_START 4 // Reserve space for the 4 top nodes
+
+enum SaidToken {
+ TOKEN_COMMA = 0xF000,
+ TOKEN_AMP = 0xF100,
+ TOKEN_SLASH = 0xF200,
+ TOKEN_PARENO = 0xF300,
+ TOKEN_PARENC = 0xF400,
+ TOKEN_BRACKETO = 0xF500,
+ TOKEN_BRACKETC = 0xF600,
+ TOKEN_HASH = 0xF700,
+ TOKEN_LT = 0xF800,
+ TOKEN_GT = 0xF900,
+ TOKEN_TERM = 0xFF00
+};
-#define VALUE_IGNORE -424242
+enum SaidWord {
+ WORD_NONE = 0x0ffe,
+ WORD_ANY = 0x0fff
+};
-static parse_tree_node_t said_tree[VOCAB_TREE_NODES];
-typedef int wgroup_t;
-typedef int tree_t;
-typedef int said_spec_t;
-static tree_t said_aug_branch(int, int, tree_t, tree_t);
-static tree_t said_attach_branch(tree_t, tree_t);
-/*
-static tree_t said_wgroup_branch(wgroup_t);
-*/
-static said_spec_t said_top_branch(tree_t);
-static tree_t said_paren(tree_t, tree_t);
-static tree_t said_value(int, tree_t);
-static tree_t said_terminal(int);
+// TODO: maybe turn this into a proper n-ary tree instead of an
+// n-ary tree implemented in terms of a binary tree.
+// (Together with _parserNodes in Vocabulary)
-static int yylex();
+static ParseTreeNode said_tree[VOCAB_TREE_NODES];
-static int yyerror(const char *s) {
- said_parse_error = strdup(s);
- return 1; /* Abort */
-}
+typedef int wgroup_t;
+typedef int said_spec_t;
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
+static ParseTreeNode* said_next_node() {
+ assert(said_tree_pos > 0 && said_tree_pos < VOCAB_TREE_NODES);
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
+ return &said_tree[said_tree_pos++];
+}
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
+static ParseTreeNode* said_leaf_node(ParseTreeNode* pos, int value) {
+ pos->type = kParseTreeLeafNode;
+ pos->value = value;
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
+ return pos;
+}
+static ParseTreeNode* said_word_node(ParseTreeNode* pos, int value) {
+ pos->type = kParseTreeWordNode;
+ pos->value = value;
+ return pos;
+}
-/* Copy the second part of user declarations. */
+static ParseTreeNode* said_branch_node(ParseTreeNode* pos,
+ ParseTreeNode* left,
+ ParseTreeNode* right) {
+ pos->type = kParseTreeBranchNode;
+ pos->left = left;
+ pos->right = right;
+ return pos;
+}
-/* Line 216 of yacc.c. */
+static ParseTreeNode* said_branch_attach_left(ParseTreeNode* pos,
+ ParseTreeNode* left) {
+ pos->type = kParseTreeBranchNode;
+ pos->left = left;
+ return pos;
-#ifdef short
-# undef short
-#endif
+}
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
+static ParseTreeNode* said_branch_attach_right(ParseTreeNode* pos,
+ ParseTreeNode* right) {
+ pos->type = kParseTreeBranchNode;
+ pos->right = right;
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
+ return pos;
+}
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
+/*
+ pos
+ / \
+ . \
+ *
+ / \
+ / 0
+ *
+ / \
+ / \
+ / subtree
+ major / \
+ / .
+ minor
+
+ . = unchanged child node
+ * = new branch node
+ 0 = NULL child node. (Location for future siblings of the subtree)
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-# define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# else
-# define YYSIZE_T unsigned int
-# endif
-#endif
+*/
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if YYENABLE_NLS
-# if ENABLE_NLS
-# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
-# endif
-# endif
-# ifndef YY_
-# define YY_(msgid) msgid
-# endif
-#endif
+static bool said_attach_subtree(ParseTreeNode* pos, int major, int minor,
+ ParseTreeNode* subtree) {
+ bool retval = true;
-/* Suppress unused-variable warnings by "using" E. */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
+ said_branch_attach_right(pos,
+ said_branch_node(said_next_node(),
+ said_branch_node(said_next_node(),
+ said_leaf_node(said_next_node(), major),
+ said_branch_attach_left(subtree,
+ said_leaf_node(said_next_node(), minor))),
+ 0));
-/* Identity function, used to suppress warnings about constant conditions. */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
- int i;
-#endif
-{
- return i;
+ return retval;
}
-#endif
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols. */
-
-# ifdef YYSTACK_USE_ALLOCA
-# if YYSTACK_USE_ALLOCA
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
-# elif defined __BUILTIN_VA_ARG_INCR
-# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-# elif defined _AIX
-# define YYSTACK_ALLOC __alloca
-# elif defined _MSC_VER
-# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-# define alloca _alloca
-# else
-# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
-# endif
-# endif
-# endif
-# endif
-# endif
-
-# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-# ifndef YYSTACK_ALLOC_MAXIMUM
- /* The OS might guarantee only one guard page at the bottom of the stack,
- and a page size can be as small as 4096 bytes. So we cannot safely
- invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
- to allow for a few compiler-allocated temporary stack slots. */
-# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-# endif
-# else
-# define YYSTACK_ALLOC YYMALLOC
-# define YYSTACK_FREE YYFREE
-# ifndef YYSTACK_ALLOC_MAXIMUM
-# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-# endif
-# if (defined __cplusplus && ! defined _STDLIB_H \
- && ! ((defined YYMALLOC || defined malloc) \
- && (defined YYFREE || defined free)))
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
-# endif
-# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
-# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# ifndef YYFREE
-# define YYFREE free
-# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
- && (! defined __cplusplus \
- || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member. */
-union yyalloc
-{
- yytype_int16 yyss;
- YYSTYPE yyvs;
- };
-
-/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
- N elements. */
-# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
- + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-# else
-# define YYCOPY(To, From, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (YYID (0))
-# endif
-# endif
-
-/* Relocate STACK from its old location to the new one. The
- local variables YYSIZE and YYSTACKSIZE give the old and new number of
- elements in the stack, and YYPTR gives the new location of the
- stack. Advance YYPTR to a properly aligned location for the next
- stack. */
-# define YYSTACK_RELOCATE(Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack, Stack, yysize); \
- Stack = &yyptr->Stack; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
- while (YYID (0))
-#endif
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 23
-/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 80
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 18
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 13
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 35
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 69
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
-#define YYUNDEFTOK 2
-#define YYMAXUTOK 272
-
-#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const yytype_uint8 yytranslate[] =
-{
- 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17
-};
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const yytype_uint8 yyprhs[] =
-{
- 0, 0, 3, 6, 10, 15, 16, 18, 19, 21,
- 24, 29, 31, 34, 39, 41, 43, 45, 49, 51,
- 55, 59, 64, 70, 73, 75, 77, 79, 83, 88,
- 92, 97, 100, 105, 109, 112
-};
+/*****************/
+/**** Parsing ****/
+/*****************/
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yytype_int8 yyrhs[] =
-{
- 19, 0, -1, 21, 20, -1, 21, 22, 20, -1,
- 21, 22, 23, 20, -1, -1, 13, -1, -1, 27,
- -1, 6, 27, -1, 15, 6, 27, 10, -1, 6,
- -1, 6, 27, -1, 15, 6, 27, 10, -1, 6,
- -1, 3, -1, 26, -1, 9, 26, 10, -1, 24,
- -1, 7, 27, 8, -1, 26, 4, 26, -1, 26,
- 14, 29, 10, -1, 26, 4, 9, 26, 10, -1,
- 25, 28, -1, 25, -1, 28, -1, 29, -1, 14,
- 29, 10, -1, 29, 14, 29, 10, -1, 12, 24,
- 30, -1, 17, 7, 27, 8, -1, 12, 26, -1,
- 16, 9, 26, 10, -1, 12, 26, 30, -1, 12,
- 26, -1, 17, 7, 27, 8, -1
-};
+static bool parseSpec(ParseTreeNode* parentNode);
+static bool parsePart2(ParseTreeNode* parentNode, bool& nonempty);
+static bool parsePart3(ParseTreeNode* parentNode, bool& nonempty);
+static bool parseSlash(ParseTreeNode* parentNode);
+static bool parseExpr(ParseTreeNode* parentNode);
+static bool parseRef(ParseTreeNode* parentNode);
+static bool parseComma(ParseTreeNode* parentNode);
+static bool parseList(ParseTreeNode* parentNode);
+static bool parseListEntry(ParseTreeNode* parentNode);
+static bool parseWord(ParseTreeNode* parentNode);
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const yytype_uint8 yyrline[] =
+static bool parseWord(ParseTreeNode* parentNode)
{
- 0, 130, 130, 132, 134, 140, 141, 148, 149, 155,
- 157, 159, 165, 167, 169, 174, 179, 181, 186, 188,
- 190, 192, 194, 199, 201, 203, 208, 210, 212, 217,
- 219, 221, 223, 228, 230, 232
-};
-#endif
+ int token = said_tokens[said_token];
+ if (token & 0x8000)
+ return false;
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
- "$end", "error", "$undefined", "WGROUP", "YY_COMMA", "YY_AMP",
- "YY_SLASH", "YY_PARENO", "YY_PARENC", "YY_BRACKETSO", "YY_BRACKETSC",
- "YY_HASH", "YY_LT", "YY_GT", "YY_BRACKETSO_LT", "YY_BRACKETSO_SLASH",
- "YY_LT_BRACKETSO", "YY_LT_PARENO", "$accept", "saidspec", "optcont",
- "leftspec", "midspec", "rightspec", "word", "cwordset", "wordset",
- "expr", "cwordrefset", "wordrefset", "recref", 0
-};
-#endif
+ said_token++;
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
-static const yytype_uint16 yytoknum[] =
-{
- 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265, 266, 267, 268, 269, 270, 271, 272
-};
-# endif
+ ParseTreeNode* newNode = said_word_node(said_next_node(), token);
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
-{
- 0, 18, 19, 19, 19, 20, 20, 21, 21, 22,
- 22, 22, 23, 23, 23, 24, 25, 25, 26, 26,
- 26, 26, 26, 27, 27, 27, 28, 28, 28, 29,
- 29, 29, 29, 30, 30, 30
-};
+ parentNode->right = newNode;
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
-{
- 0, 2, 2, 3, 4, 0, 1, 0, 1, 2,
- 4, 1, 2, 4, 1, 1, 1, 3, 1, 3,
- 3, 4, 5, 2, 1, 1, 1, 3, 4, 3,
- 4, 2, 4, 3, 2, 4
-};
+ return true;
+}
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
- STATE-NUM when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const yytype_uint8 yydefact[] =
+static bool parsePart2(ParseTreeNode* parentNode, bool& nonempty)
{
- 7, 15, 0, 0, 0, 0, 0, 0, 0, 5,
- 18, 24, 16, 8, 25, 26, 0, 0, 18, 31,
- 0, 0, 0, 1, 11, 6, 0, 2, 5, 23,
- 0, 0, 0, 19, 17, 0, 0, 29, 27, 0,
- 0, 9, 0, 14, 0, 3, 5, 0, 20, 0,
- 0, 34, 0, 32, 30, 0, 12, 0, 4, 0,
- 21, 28, 33, 0, 10, 0, 22, 35, 13
-};
+ // Store current state for rolling back if we fail
+ int curToken = said_token;
+ int curTreePos = said_tree_pos;
+ ParseTreeNode* curRightChild = parentNode->right;
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yytype_int8 yydefgoto[] =
-{
- -1, 8, 27, 9, 28, 46, 10, 11, 12, 13,
- 14, 15, 37
-};
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -24
-static const yytype_int8 yypact[] =
-{
- -1, -24, -1, 62, 62, 54, 1, 5, 18, 38,
- -24, 47, 3, -24, -24, 12, 23, 15, -3, 3,
- 28, 62, -1, -24, -1, -24, 42, -24, 39, -24,
- 53, 54, 54, -24, -24, 62, 50, -24, -24, 29,
- 41, -24, -1, -1, 52, -24, 55, 62, 3, 57,
- 63, 20, -1, -24, -24, 64, -24, -1, -24, 32,
- -24, -24, -24, 67, -24, 66, -24, -24, -24
-};
+ nonempty = true;
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int8 yypgoto[] =
-{
- -24, -24, -23, -24, -24, -24, 68, -24, 0, -2,
- 69, -4, 26
-};
+ bool found;
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If zero, do what YYDEFACT says.
- If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -1
-static const yytype_uint8 yytable[] =
-{
- 16, 20, 1, 17, 19, 45, 2, 30, 3, 35,
- 21, 4, 22, 5, 36, 6, 7, 31, 23, 30,
- 40, 39, 41, 58, 30, 34, 32, 49, 50, 31,
- 48, 33, 35, 30, 31, 51, 30, 36, 38, 53,
- 55, 56, 66, 31, 24, 43, 31, 59, 42, 54,
- 63, 25, 25, 26, 44, 65, 1, 52, 57, 4,
- 2, 5, 47, 6, 7, 1, 4, 60, 25, 2,
- 6, 7, 18, 61, 64, 67, 68, 62, 0, 0,
- 29
-};
+ found = parseSlash(newNode);
-static const yytype_int8 yycheck[] =
-{
- 2, 5, 3, 3, 4, 28, 7, 4, 9, 12,
- 9, 12, 7, 14, 17, 16, 17, 14, 0, 4,
- 22, 21, 24, 46, 4, 10, 14, 31, 32, 14,
- 30, 8, 12, 4, 14, 35, 4, 17, 10, 10,
- 42, 43, 10, 14, 6, 6, 14, 47, 6, 8,
- 52, 13, 13, 15, 15, 57, 3, 7, 6, 12,
- 7, 14, 9, 16, 17, 3, 12, 10, 13, 7,
- 16, 17, 4, 10, 10, 8, 10, 51, -1, -1,
- 11
-};
+ if (found) {
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const yytype_uint8 yystos[] =
-{
- 0, 3, 7, 9, 12, 14, 16, 17, 19, 21,
- 24, 25, 26, 27, 28, 29, 27, 26, 24, 26,
- 29, 9, 7, 0, 6, 13, 15, 20, 22, 28,
- 4, 14, 14, 8, 10, 12, 17, 30, 10, 26,
- 27, 27, 6, 6, 15, 20, 23, 9, 26, 29,
- 29, 26, 7, 10, 8, 27, 27, 6, 20, 26,
- 10, 10, 30, 27, 10, 27, 10, 8, 10
-};
-
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
-
-#define YYFAIL goto yyerrlab
-
-#define YYRECOVERING() (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY && yylen == 1) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK (1); \
- goto yybackup; \
- } \
- else \
- { \
- yyerror (YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (YYID (0))
-
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
- If N is 0, then set CURRENT to the empty location which ends
- the previous symbol: RHS[0] (always defined). */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
- while (YYID (0))
-#endif
+ said_attach_subtree(parentNode, 0x142, 0x14a, newNode);
+ return true;
-/* YY_LOCATION_PRINT -- Print the location on the stream.
- This macro was not mandated originally: define only if we know
- we won't break user code: when these are the locations we know. */
+ } else if (said_tokens[said_token] == TOKEN_BRACKETO) {
+ said_token++;
+
+ found = parsePart2(newNode, nonempty);
-#ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
-# define YY_LOCATION_PRINT(File, Loc) \
- fprintf (File, "%d.%d-%d.%d", \
- (Loc).first_line, (Loc).first_column, \
- (Loc).last_line, (Loc).last_column)
-# else
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
+ if (found) {
+ if (said_tokens[said_token] == TOKEN_BRACKETC) {
+ said_token++;
-/* YYLEX -- calling `yylex' with the right arguments. */
+ said_attach_subtree(parentNode, 0x152, 0x142, newNode);
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
+ return true;
+ }
+ }
-/* Enable debugging if requested. */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-# define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yy_symbol_print (stderr, \
- Type, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
-{
- if (!yyvaluep)
- return;
-# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
- YYUSE (yyoutput);
-# endif
- switch (yytype)
- {
- default:
- break;
- }
-}
+ }
+ // CHECKME: this doesn't look right if the [] section matched partially
+ // Should the below 'if' be an 'else if' ?
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+ if (said_tokens[said_token] == TOKEN_SLASH) {
+ said_token++;
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
-{
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+ nonempty = false;
- yy_symbol_value_print (yyoutput, yytype, yyvaluep);
- YYFPRINTF (yyoutput, ")");
-}
+ return true;
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included). |
-`------------------------------------------------------------------*/
+ }
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
- yytype_int16 *bottom;
- yytype_int16 *top;
-#endif
-{
- YYFPRINTF (stderr, "Stack now");
- for (; bottom <= top; ++bottom)
- YYFPRINTF (stderr, " %d", *bottom);
- YYFPRINTF (stderr, "\n");
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
}
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (YYID (0))
+static bool parsePart3(ParseTreeNode* parentNode, bool& nonempty)
+{
+ // Store current state for rolling back if we fail
+ int curToken = said_token;
+ int curTreePos = said_tree_pos;
+ ParseTreeNode* curRightChild = parentNode->right;
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced. |
-`------------------------------------------------*/
+ bool found;
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
- YYSTYPE *yyvsp;
- int yyrule;
-#endif
-{
- int yynrhs = yyr2[yyrule];
- int yyi;
- unsigned long int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
- yyrule - 1, yylno);
- /* The symbols being reduced. */
- for (yyi = 0; yyi < yynrhs; yyi++)
- {
- fprintf (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
- &(yyvsp[(yyi + 1) - (yynrhs)])
- );
- fprintf (stderr, "\n");
- }
-}
+ nonempty = true;
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace. It is left uninitialized so that
- multiple parsers can coexist. */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
+ found = parseSlash(newNode);
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
- if the built-in stack extension method is used).
+ if (found) {
- Do not make this value too large; the results are undefined if
- YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
- evaluated with infinite-precision integer arithmetic. */
+ said_attach_subtree(parentNode, 0x143, 0x14a, newNode);
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
+ return true;
-
+ } else if (said_tokens[said_token] == TOKEN_BRACKETO) {
+ said_token++;
+
+ found = parsePart3(newNode, nonempty);
-#if YYERROR_VERBOSE
+ if (found) {
-# ifndef yystrlen
-# if defined __GLIBC__ && defined _STRING_H
-# define yystrlen strlen
-# else
-/* Return the length of YYSTR. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
- const char *yystr;
-#endif
-{
- YYSIZE_T yylen;
- for (yylen = 0; yystr[yylen]; yylen++)
- continue;
- return yylen;
-}
-# endif
-# endif
-
-# ifndef yystpcpy
-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-# define yystpcpy stpcpy
-# else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
- YYDEST. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-#endif
-{
- char *yyd = yydest;
- const char *yys = yysrc;
+ if (said_tokens[said_token] == TOKEN_BRACKETC) {
+ said_token++;
- while ((*yyd++ = *yys++) != '\0')
- continue;
+ said_attach_subtree(parentNode, 0x152, 0x143, newNode);
- return yyd - 1;
-}
-# endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
- quotes and backslashes, so that it's suitable for yyerror. The
- heuristic is that double-quoting is unnecessary unless the string
- contains an apostrophe, a comma, or backslash (other than
- backslash-backslash). YYSTR is taken from yytname. If YYRES is
- null, do not copy; instead, return the length of what the result
- would have been. */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
- if (*yystr == '"')
- {
- YYSIZE_T yyn = 0;
- char const *yyp = yystr;
-
- for (;;)
- switch (*++yyp)
- {
- case '\'':
- case ',':
- goto do_not_strip_quotes;
-
- case '\\':
- if (*++yyp != '\\')
- goto do_not_strip_quotes;
- /* Fall through. */
- default:
- if (yyres)
- yyres[yyn] = *yyp;
- yyn++;
- break;
-
- case '"':
- if (yyres)
- yyres[yyn] = '\0';
- return yyn;
- }
- do_not_strip_quotes: ;
- }
-
- if (! yyres)
- return yystrlen (yystr);
-
- return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
- YYCHAR while in state YYSTATE. Return the number of bytes copied,
- including the terminating null byte. If YYRESULT is null, do not
- copy anything; just return the number of bytes that would be
- copied. As a special case, return 0 if an ordinary "syntax error"
- message will do. Return YYSIZE_MAXIMUM if overflow occurs during
- size calculation. */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
- int yyn = yypact[yystate];
-
- if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
- return 0;
- else
- {
- int yytype = YYTRANSLATE (yychar);
- YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
- YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
- int yysize_overflow = 0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- int yyx;
-
-# if 0
- /* This is so xgettext sees the translatable formats that are
- constructed on the fly. */
- YY_("syntax error, unexpected %s");
- YY_("syntax error, unexpected %s, expecting %s");
- YY_("syntax error, unexpected %s, expecting %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
- char *yyfmt;
- char const *yyf;
- static char const yyunexpected[] = "syntax error, unexpected %s";
- static char const yyexpecting[] = ", expecting %s";
- static char const yyor[] = " or %s";
- char yyformat[sizeof yyunexpected
- + sizeof yyexpecting - 1
- + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
- * (sizeof yyor - 1))];
- char const *yyprefix = yyexpecting;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 1;
-
- yyarg[0] = yytname[yytype];
- yyfmt = yystpcpy (yyformat, yyunexpected);
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- yyformat[sizeof yyunexpected - 1] = '\0';
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (0, yytname[yyx]);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
- yyfmt = yystpcpy (yyfmt, yyprefix);
- yyprefix = yyor;
- }
-
- yyf = YY_(yyformat);
- yysize1 = yysize + yystrlen (yyf);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
-
- if (yysize_overflow)
- return YYSIZE_MAXIMUM;
-
- if (yyresult)
- {
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- char *yyp = yyresult;
- int yyi = 0;
- while ((*yyp = *yyf) != '\0')
- {
- if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyf += 2;
- }
- else
- {
- yyp++;
- yyf++;
+ return true;
+ }
}
- }
+
}
- return yysize;
- }
-}
-#endif /* YYERROR_VERBOSE */
-
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol. |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
- const char *yymsg;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
-{
- YYUSE (yyvaluep);
- if (!yymsg)
- yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+ // CHECKME: this doesn't look right if the [] section matched partially
+ // Should the below 'if' be an 'else if' ?
- switch (yytype)
- {
+ if (said_tokens[said_token] == TOKEN_SLASH) {
+ said_token++;
- default:
- break;
- }
-}
-
+ nonempty = false;
-/* Prevent warnings from -Wmissing-prototypes. */
+ return true;
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
+ }
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
-/* The look-ahead symbol. */
-int yychar;
+static bool parseSlash(ParseTreeNode* parentNode)
+{
+ // Store current state for rolling back if we fail
+ int curToken = said_token;
+ int curTreePos = said_tree_pos;
+ ParseTreeNode* curRightChild = parentNode->right;
-/* The semantic value of the look-ahead symbol. */
-YYSTYPE yylval;
+ if (said_tokens[said_token] == TOKEN_SLASH) {
+ said_token++;
-/* Number of syntax errors so far. */
-int yynerrs;
+ bool found = parseExpr(parentNode);
+ if (found)
+ return true;
+ }
-/*----------.
-| yyparse. |
-`----------*/
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-#endif
-#endif
+static bool parseRef(ParseTreeNode* parentNode)
{
-
- int yystate;
- int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Look-ahead token as an internal (translated) token number. */
- int yytoken = 0;
-#if YYERROR_VERBOSE
- /* Buffer for error messages, and its allocated size. */
- char yymsgbuf[128];
- char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
- /* Three stacks and their tools:
- `yyss': related to states,
- `yyvs': related to semantic values,
- `yyls': related to locations.
-
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
-
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss = yyssa;
- yytype_int16 *yyssp;
-
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+ // Store current state for rolling back if we fail
+ int curToken = said_token;
+ int curTreePos = said_tree_pos;
+ ParseTreeNode* curRightChild = parentNode->right;
- YYSIZE_T yystacksize = YYINITDEPTH;
-
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
+ ParseTreeNode* newParent = parentNode;
- /* The number of symbols on the RHS of the reduced rule.
- Keep to zero when no symbol should be popped. */
- int yylen = 0;
+ bool found;
- YYDPRINTF ((stderr, "Starting parse\n"));
+ if (said_tokens[said_token] == TOKEN_LT) {
+ said_token++;
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
+ found = parseList(newNode);
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
+ if (found) {
- yyssp = yyss;
- yyvsp = yyvs;
+ said_attach_subtree(newParent, 0x144, 0x14f, newNode);
- goto yysetstate;
+ newParent = newParent->right;
+
+ newNode = said_branch_node(said_next_node(), 0, 0);
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
-`------------------------------------------------------------*/
- yynewstate:
- /* In all cases, when you get here, the value and location stacks
- have just been pushed. So pushing a state here evens the stacks. */
- yyssp++;
-
- yysetstate:
- *yyssp = yystate;
-
- if (yyss + yystacksize - 1 <= yyssp)
- {
- /* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
- {
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
-
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
-
- &yystacksize);
-
- yyss = yyss1;
- yyvs = yyvs1;
- }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyexhaustedlab;
-# else
- /* Extend the stack our own way. */
- if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
- yystacksize *= 2;
- if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
-
- {
- yytype_int16 *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss);
- YYSTACK_RELOCATE (yyvs);
-
-# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
- }
-# endif
-#endif /* no yyoverflow */
-
- yyssp = yyss + yysize - 1;
- yyvsp = yyvs + yysize - 1;
-
-
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
-
- if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
- }
-
- YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
- goto yybackup;
-
-/*-----------.
-| yybackup. |
-`-----------*/
-yybackup:
-
- /* Do appropriate processing given the current state. Read a
- look-ahead token if we need one and don't already have one. */
-
- /* First try to decide what to do without reference to look-ahead token. */
- yyn = yypact[yystate];
- if (yyn == YYPACT_NINF)
- goto yydefault;
-
- /* Not known => get a look-ahead token if don't already have one. */
-
- /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
- if (yychar == YYEMPTY)
- {
- YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
- }
-
- if (yychar <= YYEOF)
- {
- yychar = yytoken = YYEOF;
- YYDPRINTF ((stderr, "Now at end of input.\n"));
- }
- else
- {
- yytoken = YYTRANSLATE (yychar);
- YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
- }
-
- /* If the proper action on seeing token YYTOKEN is to reduce or to
- detect an error, take that action. */
- yyn += yytoken;
- if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
- goto yydefault;
- yyn = yytable[yyn];
- if (yyn <= 0)
- {
- if (yyn == 0 || yyn == YYTABLE_NINF)
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
+ found = parseRef(newNode);
- if (yyn == YYFINAL)
- YYACCEPT;
+ if (found) {
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
+ said_attach_subtree(newParent, 0x141, 0x144, newNode);
- /* Shift the look-ahead token. */
- YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+ }
- /* Discard the shifted token unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
+ return true;
- yystate = yyn;
- *++yyvsp = yylval;
+ }
- goto yynewstate;
+ }
+ // NB: This is not an "else if'.
+ // If there is a "< [ ... ]", that is parsed as "< ..."
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state. |
-`-----------------------------------------------------------*/
-yydefault:
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
- goto yyreduce;
+ if (said_tokens[said_token] == TOKEN_BRACKETO) {
+ said_token++;
+
+ found = parseRef(newNode);
+ if (found) {
-/*-----------------------------.
-| yyreduce -- Do a reduction. |
-`-----------------------------*/
-yyreduce:
- /* yyn is the number of a rule to reduce with. */
- yylen = yyr2[yyn];
+ if (said_tokens[said_token] == TOKEN_BRACKETC) {
+ said_token++;
- /* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
+ said_attach_subtree(parentNode, 0x152, 0x144, newNode);
- Otherwise, the following line sets YYVAL to garbage.
- This behavior is undocumented and Bison
- users should not rely upon it. Assigning to YYVAL
- unconditionally makes the parser a bit smaller, and it avoids a
- GCC warning that YYVAL may be used uninitialized. */
- yyval = yyvsp[1-yylen];
+ return true;
+ }
+ }
+ }
- YY_REDUCE_PRINT (yyn);
- switch (yyn)
- {
- case 2:
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
- { (yyval) = said_top_branch(said_attach_branch((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]))); ;}
- break;
+static bool parseComma(ParseTreeNode* parentNode)
+{
+ // Store current state for rolling back if we fail
+ int curToken = said_token;
+ int curTreePos = said_tree_pos;
+ ParseTreeNode* curRightChild = parentNode->right;
- case 3:
+ if (said_tokens[said_token] == TOKEN_COMMA) {
+ said_token++;
- { (yyval) = said_top_branch(said_attach_branch((yyvsp[(1) - (3)]), said_attach_branch((yyvsp[(2) - (3)]), (yyvsp[(3) - (3)])))); ;}
- break;
+ bool found = parseList(parentNode);
- case 4:
+ if (found)
+ return true;
- { (yyval) = said_top_branch(said_attach_branch((yyvsp[(1) - (4)]), said_attach_branch((yyvsp[(2) - (4)]), said_attach_branch((yyvsp[(3) - (4)]), (yyvsp[(4) - (4)]))))); ;}
- break;
+ }
- case 5:
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
- { (yyval) = SAID_BRANCH_NULL; ;}
- break;
+static bool parseListEntry(ParseTreeNode* parentNode)
+{
+ // Store current state for rolling back if we fail
+ int curToken = said_token;
+ int curTreePos = said_tree_pos;
+ ParseTreeNode* curRightChild = parentNode->right;
- case 6:
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
- { (yyval) = said_paren(said_value(0x14b, said_value(0xf900, said_terminal(0xf900))), SAID_BRANCH_NULL); ;}
- break;
+ bool found;
- case 7:
+ if (said_tokens[said_token] == TOKEN_BRACKETO) {
+ said_token++;
- { (yyval) = SAID_BRANCH_NULL; ;}
- break;
+ found = parseExpr(newNode);
- case 8:
+ if (found) {
- { (yyval) = said_paren(said_value(0x141, said_value(0x149, (yyvsp[(1) - (1)]))), SAID_BRANCH_NULL); ;}
- break;
+ if (said_tokens[said_token] == TOKEN_BRACKETC) {
+ said_token++;
- case 9:
+ said_attach_subtree(parentNode, 0x152, 0x14c, newNode);
- { (yyval) = said_aug_branch(0x142, 0x14a, (yyvsp[(2) - (2)]), SAID_BRANCH_NULL); ;}
- break;
+ return true;
+ }
+ }
- case 10:
+ } else if (said_tokens[said_token] == TOKEN_PARENO) {
+ said_token++;
- { (yyval) = said_aug_branch(0x152, 0x142, said_aug_branch(0x142, 0x14a, (yyvsp[(3) - (4)]), SAID_BRANCH_NULL), SAID_BRANCH_NULL); ;}
- break;
+ found = parseExpr(newNode);
- case 11:
+ if (found) {
- { (yyval) = SAID_BRANCH_NULL; ;}
- break;
+ if (said_tokens[said_token] == TOKEN_PARENC) {
+ said_token++;
- case 12:
+ said_attach_subtree(parentNode, 0x141, 0x14c, newNode);
- { (yyval) = said_aug_branch(0x143, 0x14a, (yyvsp[(2) - (2)]), SAID_BRANCH_NULL); ;}
- break;
+ return true;
+ }
+ }
- case 13:
+ } else if (parseWord(newNode)) {
- { (yyval) = said_aug_branch(0x152, 0x143, said_aug_branch(0x143, 0x14a, (yyvsp[(3) - (4)]), SAID_BRANCH_NULL), SAID_BRANCH_NULL); ;}
- break;
+ said_attach_subtree(parentNode, 0x141, 0x153, newNode);
- case 14:
+ return true;
- { (yyval) = SAID_BRANCH_NULL; ;}
- break;
+ }
- case 15:
- { (yyval) = said_paren(said_value(0x141, said_value(0x153, said_terminal((yyvsp[(1) - (1)])))), SAID_BRANCH_NULL); ;}
- break;
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
- case 16:
+static bool parseList(ParseTreeNode* parentNode)
+{
+ // Store current state for rolling back if we fail
+ int curToken = said_token;
+ int curTreePos = said_tree_pos;
+ ParseTreeNode* curRightChild = parentNode->right;
- { (yyval) = said_aug_branch(0x141, 0x14f, (yyvsp[(1) - (1)]), SAID_BRANCH_NULL); ;}
- break;
+ bool found;
- case 17:
+ ParseTreeNode* newParent = parentNode;
- { (yyval) = said_aug_branch(0x141, 0x14f, said_aug_branch(0x152, 0x14c, said_aug_branch(0x141, 0x14f, (yyvsp[(2) - (3)]), SAID_BRANCH_NULL), SAID_BRANCH_NULL), SAID_BRANCH_NULL); ;}
- break;
+ found = parseListEntry(newParent);
- case 18:
+ if (found) {
- { (yyval) = (yyvsp[(1) - (1)]); ;}
- break;
+ newParent = newParent->right;
- case 19:
+ found = parseComma(newParent);
- { (yyval) = said_aug_branch(0x141, 0x14c, (yyvsp[(2) - (3)]), SAID_BRANCH_NULL); ;}
- break;
+ return true;
- case 20:
+ }
- { (yyval) = said_attach_branch((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)])); ;}
- break;
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
- case 21:
+static bool parseExpr(ParseTreeNode* parentNode)
+{
+ // Store current state for rolling back if we fail
+ int curToken = said_token;
+ int curTreePos = said_tree_pos;
+ ParseTreeNode* curRightChild = parentNode->right;
- { (yyval) = said_attach_branch((yyvsp[(1) - (4)]), (yyvsp[(3) - (4)])); ;}
- break;
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
- case 22:
+ bool ret = false;
+ bool found;
- { (yyval) = said_attach_branch((yyvsp[(1) - (5)]), (yyvsp[(3) - (5)])); ;}
- break;
+ ParseTreeNode* newParent = parentNode;
- case 23:
+ found = parseList(newNode);
- { (yyval) = said_attach_branch((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)])); ;}
- break;
+ if (found) {
+ ret = true;
- case 24:
+ said_attach_subtree(newParent, 0x141, 0x14F, newNode);
- { (yyval) = (yyvsp[(1) - (1)]); ;}
- break;
+ newParent = newParent->right;
- case 25:
+ }
- { (yyval) = (yyvsp[(1) - (1)]); ;}
- break;
+ found = parseRef(newParent);
- case 26:
+ if (found || ret)
+ return true;
- { (yyval) = (yyvsp[(1) - (1)]); ;}
- break;
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
- case 27:
+static bool parseSpec(ParseTreeNode* parentNode)
+{
+ // Store current state for rolling back if we fail
+ int curToken = said_token;
+ int curTreePos = said_tree_pos;
+ ParseTreeNode* curRightChild = parentNode->right;
- { (yyval) = said_aug_branch(0x152, 0x144, (yyvsp[(2) - (3)]), SAID_BRANCH_NULL); ;}
- break;
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
- case 28:
+ bool ret = false;
- { (yyval) = said_attach_branch((yyvsp[(1) - (4)]), said_aug_branch(0x152, 0x144, (yyvsp[(3) - (4)]), SAID_BRANCH_NULL)); ;}
- break;
+ bool found;
- case 29:
+ ParseTreeNode* newParent = parentNode;
- { (yyval) = said_aug_branch(0x144, 0x14f, (yyvsp[(2) - (3)]), (yyvsp[(3) - (3)])); ;}
- break;
+ found = parseExpr(newNode);
- case 30:
+ if (found) {
+ // Sentence part 1 found
+ said_attach_subtree(newParent, 0x141, 0x149, newNode);
- { (yyval) = said_aug_branch(0x144, 0x14f, said_aug_branch(0x141, 0x144, (yyvsp[(2) - (4)]), SAID_BRANCH_NULL), SAID_BRANCH_NULL); ;}
- break;
+ newParent = newParent->right;
- case 31:
+ ret = true;
+ }
- { (yyval) = said_aug_branch(0x144, 0x14f, (yyvsp[(2) - (2)]), SAID_BRANCH_NULL); ;}
- break;
+ bool nonempty;
- case 32:
+ found = parsePart2(newParent, nonempty);
- { (yyval) = said_aug_branch(0x152, 0x144, said_aug_branch(0x144, 0x14f, (yyvsp[(3) - (4)]), SAID_BRANCH_NULL), SAID_BRANCH_NULL); ;}
- break;
+ if (found) {
- case 33:
+ ret = true;
- { (yyval) = said_aug_branch(0x141, 0x144, said_aug_branch(0x144, 0x14f, (yyvsp[(2) - (3)]), SAID_BRANCH_NULL), (yyvsp[(3) - (3)])); ;}
- break;
+ if (nonempty) // non-empty part found
+ newParent = newParent->right;
- case 34:
- { (yyval) = said_aug_branch(0x141, 0x144, said_aug_branch(0x144, 0x14f, (yyvsp[(2) - (2)]), SAID_BRANCH_NULL), SAID_BRANCH_NULL); ;}
- break;
+ found = parsePart3(newParent, nonempty);
- case 35:
+ if (found) {
- { (yyval) = said_aug_branch(0x141, 0x14c, (yyvsp[(2) - (4)]), SAID_BRANCH_NULL); ;}
- break;
+ if (nonempty)
+ newParent = newParent->right;
+ }
+ }
+ if (said_tokens[said_token] == TOKEN_GT) {
+ said_token++;
-/* Line 1267 of yacc.c. */
+ newNode = said_branch_node(said_next_node(), 0,
+ said_leaf_node(said_next_node(), TOKEN_GT));
- default: break;
- }
- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+ said_attach_subtree(newParent, 0x14B, TOKEN_GT, newNode);
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
+ }
- *++yyvsp = yyval;
+ if (ret)
+ return true;
- /* Now `shift' the result of the reduction. Determine what state
- that goes to, based on the state we popped back to and the rule
- number reduced by. */
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
- yyn = yyr1[yyn];
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
+static bool buildSaidTree() {
+ said_branch_node(said_tree, &said_tree[1], &said_tree[2]);
+ said_leaf_node(&said_tree[1], 0x141); // Magic number #1
+ said_branch_node(&said_tree[2], &said_tree[3], 0);
+ said_leaf_node(&said_tree[3], 0x13f); // Magic number #2
- goto yynewstate;
+ said_tree_pos = SAID_TREE_START;
+ bool ret = parseSpec(&said_tree[2]);
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
- /* If not already recovering from an error, report this error. */
- if (!yyerrstatus)
- {
- ++yynerrs;
-#if ! YYERROR_VERBOSE
- yyerror (YY_("syntax error"));
-#else
- {
- YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
- if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
- {
- YYSIZE_T yyalloc = 2 * yysize;
- if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
- yyalloc = YYSTACK_ALLOC_MAXIMUM;
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yyalloc);
- if (yymsg)
- yymsg_alloc = yyalloc;
- else
- {
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- }
- }
-
- if (0 < yysize && yysize <= yymsg_alloc)
- {
- (void) yysyntax_error (yymsg, yystate, yychar);
- yyerror (yymsg);
- }
- else
- {
- yyerror (YY_("syntax error"));
- if (yysize != 0)
- goto yyexhaustedlab;
- }
- }
-#endif
- }
+ if (!ret)
+ return false;
+ if (said_tokens[said_token] != TOKEN_TERM) {
+ // No terminator, so parse error.
+ // Rollback
+ said_tree[2].right = 0;
+ said_token = 0;
+ said_tree_pos = SAID_TREE_START;
+ return false;
+ }
- if (yyerrstatus == 3)
- {
- /* If just tried and failed to reuse look-ahead token after an
- error, discard it. */
+ return true;
+}
- if (yychar <= YYEOF)
- {
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
- YYABORT;
- }
- else
- {
- yydestruct ("Error: discarding",
- yytoken, &yylval);
- yychar = YYEMPTY;
- }
- }
-
- /* Else will try to reuse look-ahead token after shifting the error
- token. */
- goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR. |
-`---------------------------------------------------*/
-yyerrorlab:
-
- /* Pacify compilers like GCC when the user code never invokes
- YYERROR and the label yyerrorlab therefore never appears in user
- code. */
- if (/*CONSTCOND*/ 0)
- goto yyerrorlab;
-
- /* Do not reclaim the symbols of the rule which action triggered
- this YYERROR. */
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
- yystate = *yyssp;
- goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR. |
-`-------------------------------------------------------------*/
-yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
-
- for (;;)
- {
- yyn = yypact[yystate];
- if (yyn != YYPACT_NINF)
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
+static int said_parse_spec(const byte *spec) {
+ int nextitem;
- /* Pop the current state because it cannot handle the error token. */
- if (yyssp == yyss)
- YYABORT;
+ said_token = 0;
+ said_tokens_nr = 0;
+ said_tree_pos = SAID_TREE_START;
- yydestruct ("Error: popping",
- yystos[yystate], yyvsp);
- YYPOPSTACK (1);
- yystate = *yyssp;
- YY_STACK_PRINT (yyss, yyssp);
- }
+ do {
+ nextitem = *spec++;
+ if (nextitem < SAID_FIRST)
+ said_tokens[said_tokens_nr++] = nextitem << 8 | *spec++;
+ else
+ said_tokens[said_tokens_nr++] = SAID_LONG(nextitem);
- if (yyn == YYFINAL)
- YYACCEPT;
+ } while ((nextitem != SAID_TERM) && (said_tokens_nr < MAX_SAID_TOKENS));
- *++yyvsp = yylval;
+ if (nextitem != SAID_TERM) {
+ warning("SAID spec is too long");
+ return 1;
+ }
+ if (!buildSaidTree()) {
+ warning("Error while parsing SAID spec");
+ return 1;
+ }
- /* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+ return 0;
+}
- yystate = yyn;
- goto yynewstate;
+/**********************/
+/**** Augmentation ****/
+/**********************/
+static bool dontclaim;
+static int outputDepth;
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here. |
-`-------------------------------------*/
-yyacceptlab:
- yyresult = 0;
- goto yyreturn;
+enum ScanSaidType {
+ SCAN_SAID_AND = 0,
+ SCAN_SAID_OR = 1
+};
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here. |
-`-----------------------------------*/
-yyabortlab:
- yyresult = 1;
- goto yyreturn;
+static int matchTrees(ParseTreeNode* parseT, ParseTreeNode* saidT);
+static int scanSaidChildren(ParseTreeNode* parseT, ParseTreeNode* saidT,
+ ScanSaidType type);
+static int scanParseChildren(ParseTreeNode* parseT, ParseTreeNode* saidT);
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here. |
-`-------------------------------------------------*/
-yyexhaustedlab:
- yyerror (YY_("memory exhausted"));
- yyresult = 2;
- /* Fall through. */
-#endif
-yyreturn:
- if (yychar != YYEOF && yychar != YYEMPTY)
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval);
- /* Do not reclaim the symbols of the rule which action triggered
- this YYABORT or YYACCEPT. */
- YYPOPSTACK (yylen);
- YY_STACK_PRINT (yyss, yyssp);
- while (yyssp != yyss)
- {
- yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp);
- YYPOPSTACK (1);
- }
-#ifndef yyoverflow
- if (yyss != yyssa)
- YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
-#endif
- /* Make sure YYID is used. */
- return YYID (yyresult);
+static int node_major(ParseTreeNode* node) {
+ assert(node->type == kParseTreeBranchNode);
+ assert(node->left->type == kParseTreeLeafNode);
+ return node->left->value;
+}
+static int node_minor(ParseTreeNode* node) {
+ assert(node->type == kParseTreeBranchNode);
+ assert(node->right->type == kParseTreeBranchNode);
+ assert(node->right->left->type == kParseTreeLeafNode);
+ return node->right->left->value;
+}
+static bool node_is_terminal(ParseTreeNode* node) {
+ return (node->right->right &&
+ node->right->right->type != kParseTreeBranchNode);
+}
+static int node_terminal_value(ParseTreeNode* node) {
+ assert(node_is_terminal(node));
+ return node->right->right->value;
+}
+#ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION
+static void node_print_desc(ParseTreeNode* node) {
+ assert(node);
+ assert(node->left);
+ if (node->left->type == kParseTreeBranchNode) {
+ scidprintf("< ");
+ node_print_desc(node->left);
+ scidprintf(", ...>");
+ } else {
+ if (node_is_terminal(node)) {
+ scidprintf("(%03x %03x %03x)", node_major(node),
+ node_minor(node),
+ node_terminal_value(node));
+ } else {
+ scidprintf("(%03x %03x <...>)", node_major(node),
+ node_minor(node));
+ }
+ }
}
+#else
+static void node_print_desc(ParseTreeNode*) { }
+#endif
+static int matchTrees(ParseTreeNode* parseT, ParseTreeNode* saidT)
+{
+ outputDepth++;
+ scidprintf("%*smatchTrees on ", outputDepth, "");
+ node_print_desc(parseT);
+ scidprintf(" and ");
+ node_print_desc(saidT);
+ scidprintf("\n");
-int parse_yy_token_lookup[] = {YY_COMMA, YY_AMP, YY_SLASH, YY_PARENO, YY_PARENC, YY_BRACKETSO, YY_BRACKETSC, YY_HASH, YY_LT, YY_GT};
+ bool inParen = node_minor(saidT) == 0x14F || node_minor(saidT) == 0x150;
+ bool inBracket = node_major(saidT) == 0x152;
-static int yylex() {
- int retval = said_tokens[said_token++];
+ int ret;
- if (retval < SAID_LONG(SAID_FIRST)) {
- yylval = retval;
- retval = WGROUP;
- } else {
- retval >>= 8;
-
- if (retval == SAID_TERM)
- retval = 0;
- else {
- assert(retval >= SAID_FIRST);
- retval = parse_yy_token_lookup[retval - SAID_FIRST];
- if (retval == YY_BRACKETSO) {
- if ((said_tokens[said_token] >> 8) == SAID_LT)
- retval = YY_BRACKETSO_LT;
- else
- if ((said_tokens[said_token] >> 8) == SAID_SLASH)
- retval = YY_BRACKETSO_SLASH;
- } else if (retval == YY_LT && (said_tokens[said_token] >> 8) == SAID_BRACKO) {
- retval = YY_LT_BRACKETSO;
- } else if (retval == YY_LT && (said_tokens[said_token] >> 8) == SAID_PARENO) {
- retval = YY_LT_PARENO;
- }
- }
+ if (node_major(parseT) != 0x141 &&
+ node_major(saidT) != 0x141 && node_major(saidT) != 0x152 &&
+ node_major(saidT) != node_major(parseT))
+ {
+ ret = -1;
}
- return retval;
-}
+ // parse major is 0x141 and/or
+ // said major is 0x141/0x152 and/or
+ // said major is parse major
-static int said_next_node() {
- return ((said_tree_pos == 0) || (said_tree_pos >= VOCAB_TREE_NODES)) ? said_tree_pos = 0 : said_tree_pos++;
-}
+ else if (node_is_terminal(saidT) && node_is_terminal(parseT) ) {
-#define SAID_NEXT_NODE said_next_node()
+ // both saidT and parseT are terminals
-static int said_leaf_node(tree_t pos, int value) {
- said_tree[pos].type = kParseTreeLeafNode;
+ int said_val = node_terminal_value(saidT);
+ int parse_val = node_terminal_value(parseT);
- if (value != VALUE_IGNORE)
- said_tree[pos].content.value = value;
+ if (said_val != WORD_NONE &&
+ (said_val == parse_val || said_val == WORD_ANY ||
+ parse_val == WORD_ANY))
+ ret = 1;
+ else
+ ret = -1;
- return pos;
-}
+ scidprintf("%*smatchTrees matching terminals: %03x vs %03x (%d)\n",
+ outputDepth, "", parse_val, said_val, ret);
-static int said_branch_node(tree_t pos, int left, int right) {
- said_tree[pos].type = kParseTreeBranchNode;
+ } else if (node_is_terminal(saidT) && !node_is_terminal(parseT)) {
- if (left != VALUE_IGNORE)
- said_tree[pos].content.branches[0] = left;
+ // saidT is a terminal, but parseT isn't
- if (right != VALUE_IGNORE)
- said_tree[pos].content.branches[1] = right;
+ if (node_major(parseT) == 0x141 ||
+ node_major(parseT) == node_major(saidT))
+ ret = scanParseChildren(parseT->right->right, saidT);
+ else
+ ret = 0;
- return pos;
-}
+ } else if (node_is_terminal(parseT)) {
-static tree_t said_paren(tree_t t1, tree_t t2) {
- if (t1)
- return said_branch_node(SAID_NEXT_NODE, t1, t2);
- else
- return t2;
-}
+ // parseT is a terminal, but saidT isn't
-static tree_t said_value(int val, tree_t t) {
- return said_branch_node(SAID_NEXT_NODE, said_leaf_node(SAID_NEXT_NODE, val), t);
+ if (node_major(saidT) == 0x141 || node_major(saidT) == 0x152 ||
+ node_major(saidT) == node_major(parseT))
+ ret = scanSaidChildren(parseT, saidT->right->right,
+ inParen ? SCAN_SAID_OR : SCAN_SAID_AND );
+ else
+ ret = 0;
-}
+ } else if (node_major(saidT) != 0x141 && node_major(saidT) != 0x152 &&
+ node_major(saidT) != node_major(parseT)) {
-static tree_t said_terminal(int val) {
- return said_leaf_node(SAID_NEXT_NODE, val);
-}
+ // parseT and saidT both aren't terminals
+ // said major is not 0x141 or 0x152 or parse major
-static tree_t said_aug_branch(int n1, int n2, tree_t t1, tree_t t2) {
- int retval;
+ ret = scanParseChildren(parseT->right->right, saidT);
- retval = said_branch_node(SAID_NEXT_NODE,
- said_branch_node(SAID_NEXT_NODE,
- said_leaf_node(SAID_NEXT_NODE, n1),
- said_branch_node(SAID_NEXT_NODE,
- said_leaf_node(SAID_NEXT_NODE, n2),
- t1)
- ),
- t2);
-
-#ifdef SAID_DEBUG
- fprintf(stderr, "AUG(0x%x, 0x%x, [%04x], [%04x]) = [%04x]\n", n1, n2, t1, t2, retval);
-#endif
+ } else {
- return retval;
-}
+ // parseT and saidT are both not terminals,
+ // said major 0x141 or 0x152 or equal to parse major
-static tree_t said_attach_branch(tree_t base, tree_t attacheant) {
-#ifdef SAID_DEBUG
- fprintf(stderr, "ATT2([%04x], [%04x]) = [%04x]\n", base, attacheant, base);
-#endif
+ ret = scanSaidChildren(parseT->right->right, saidT->right->right,
+ inParen ? SCAN_SAID_OR : SCAN_SAID_AND);
- if (!attacheant)
- return base;
- if (!base)
- return attacheant;
+ }
- if (!base)
- return 0; // Happens if we're out of space
+ if (inBracket && ret == 0) {
+ scidprintf("%*smatchTrees changing ret to 1 due to brackets\n",
+ outputDepth, "");
+ ret = 1;
+ }
- said_branch_node(base, VALUE_IGNORE, attacheant);
+ scidprintf("%*smatchTrees returning %d\n", outputDepth, "", ret);
+ outputDepth--;
- return base;
+ return ret;
}
-static said_spec_t said_top_branch(tree_t first) {
-#ifdef SAID_DEBUG
- fprintf(stderr, "TOP([%04x])\n", first);
-#endif
- said_branch_node(0, 1, 2);
- said_leaf_node(1, 0x141); // Magic number #1
- said_branch_node(2, 3, first);
- said_leaf_node(3, 0x13f); // Magic number #2
- ++said_blessed;
+static int scanSaidChildren(ParseTreeNode* parseT, ParseTreeNode* saidT,
+ ScanSaidType type) {
+ outputDepth++;
+ scidprintf("%*sscanSaid(%s) on ", outputDepth, "",
+ type == SCAN_SAID_OR ? "OR" : "AND");
+ node_print_desc(parseT);
+ scidprintf(" and ");
+ node_print_desc(saidT);
+ scidprintf("\n");
- return 0;
-}
+ int ret = 1;
-static int said_parse_spec(byte *spec) {
- int nextitem;
+ assert(!(type == SCAN_SAID_OR && !saidT));
- said_parse_error = NULL;
- said_token = 0;
- said_tokens_nr = 0;
- said_blessed = 0;
+ while (saidT) {
+ assert(saidT->type == kParseTreeBranchNode);
- said_tree_pos = SAID_TREE_START;
+ ParseTreeNode* saidChild = saidT->left;
+ assert(saidChild);
- do {
- nextitem = *spec++;
- if (nextitem < SAID_FIRST)
- said_tokens[said_tokens_nr++] = nextitem << 8 | *spec++;
- else
- said_tokens[said_tokens_nr++] = SAID_LONG(nextitem);
+ if (node_major(saidChild) != 0x145) {
- } while ((nextitem != SAID_TERM) && (said_tokens_nr < MAX_SAID_TOKENS));
+ ret = scanParseChildren(parseT, saidChild);
- if (nextitem == SAID_TERM)
- yyparse();
- else {
- warning("SAID spec is too long");
- return 1;
- }
+ if (type == SCAN_SAID_AND && ret != 1)
+ break;
- if (said_parse_error) {
- warning("Error while parsing SAID spec: %s", said_parse_error);
- free(said_parse_error);
- return 1;
- }
+ if (type == SCAN_SAID_OR && ret == 1)
+ break;
- if (said_tree_pos == 0) {
- warning("Out of tree space while parsing SAID spec");
- return 1;
- }
+ }
+
+ saidT = saidT->right;
- if (said_blessed != 1) {
- warning("Found multiple top branches");
- return 1;
}
+ scidprintf("%*sscanSaid returning %d\n", outputDepth, "", ret);
- return 0;
+ outputDepth--;
+ return ret;
}
-/**********************/
-/**** Augmentation ****/
-/**********************/
-
-// primitive functions
-#define AUG_READ_BRANCH(a, br, p) \
- if (tree[p].type != kParseTreeBranchNode) \
- return 0; \
- a = tree[p].content.branches[br];
+static int scanParseChildren(ParseTreeNode* parseT, ParseTreeNode* saidT) {
-#define AUG_READ_VALUE(a, p) \
- if (tree[p].type != kParseTreeLeafNode) \
- return 0; \
- a = tree[p].content.value;
+ outputDepth++;
+ scidprintf("%*sscanParse on ", outputDepth, "");
+ node_print_desc(parseT);
+ scidprintf(" and ");
+ node_print_desc(saidT);
+ scidprintf("\n");
-#define AUG_ASSERT(i) \
- if (!i) return 0;
-
-static int aug_get_next_sibling(parse_tree_node_t *tree, int pos, int *first, int *second) {
- // Returns the next sibling relative to the specified position in 'tree',
- // sets *first and *second to its augment node values, returns the new position
- // or 0 if there was no next sibling
- int seek, valpos;
+ if (node_major(saidT) == 0x14B) {
+ dontclaim = true;
+ scidprintf("%*sscanParse returning 1 (0x14B)\n", outputDepth, "");
+ outputDepth--;
+ return 1;
+ }
- AUG_READ_BRANCH(pos, 1, pos);
- AUG_ASSERT(pos);
- AUG_READ_BRANCH(seek, 0, pos);
- AUG_ASSERT(seek);
+ bool inParen = node_minor(saidT) == 0x14F || node_minor(saidT) == 0x150;
+ bool inBracket = node_major(saidT) == 0x152;
- // Now retrieve first value
- AUG_READ_BRANCH(valpos, 0, seek);
- AUG_ASSERT(valpos);
- AUG_READ_VALUE(*first, valpos);
+ int ret;
- // Get second value
- AUG_READ_BRANCH(seek, 1, seek);
- AUG_ASSERT(seek);
- AUG_READ_BRANCH(valpos, 0, seek);
- AUG_ASSERT(valpos);
- AUG_READ_VALUE(*second, valpos);
+ // descend further down saidT before actually scanning parseT
+ if ((node_major(saidT) == 0x141 || node_major(saidT) == 0x152) &&
+ !node_is_terminal(saidT)) {
- return pos;
-}
+ ret = scanSaidChildren(parseT, saidT->right->right,
+ inParen ? SCAN_SAID_OR : SCAN_SAID_AND );
-static int aug_get_wgroup(parse_tree_node_t *tree, int pos) {
- // Returns 0 if pos in tree is not the root of a 3-element list, otherwise
- // it returns the last element (which, in practice, is the word group
- int val;
+ } else if (parseT && parseT->left->type == kParseTreeBranchNode) {
- AUG_READ_BRANCH(pos, 0, pos);
- AUG_ASSERT(pos);
- AUG_READ_BRANCH(pos, 1, pos);
- AUG_ASSERT(pos);
- AUG_READ_BRANCH(pos, 1, pos);
- AUG_ASSERT(pos);
- AUG_READ_VALUE(val, pos);
+ ret = 0;
+ int subresult = 0;
- return val;
-}
+ while (parseT) {
+ assert(parseT->type == kParseTreeBranchNode);
-static int aug_get_base_node(parse_tree_node_t *tree) {
- int startpos = 0;
- AUG_READ_BRANCH(startpos, 1, startpos);
+ ParseTreeNode* parseChild = parseT->left;
+ assert(parseChild);
- return startpos;
-}
+ scidprintf("%*sscanning next: ", outputDepth, "");
+ node_print_desc(parseChild);
+ scidprintf("\n");
-// semi-primitive functions
+ if (node_major(parseChild) == node_major(saidT) ||
+ node_major(parseChild) == 0x141)
+ subresult = matchTrees(parseChild, saidT);
-static int aug_get_first_child(parse_tree_node_t *tree, int pos, int *first, int *second) {
- // like aug_get_next_sibling, except that it recurses into the tree and
- // finds the first child (usually *not* Ayanami Rei) of the current branch
- // rather than its next sibling.
- AUG_READ_BRANCH(pos, 0, pos);
- AUG_ASSERT(pos);
- AUG_READ_BRANCH(pos, 1, pos);
- AUG_ASSERT(pos);
+ if (subresult != 0)
+ ret = subresult;
- return aug_get_next_sibling(tree, pos, first, second);
-}
+ if (ret == 1)
+ break;
-static void aug_find_words_recursively(parse_tree_node_t *tree, int startpos, int *base_words, int *base_words_nr,
- int *ref_words, int *ref_words_nr, int maxwords, int refbranch) {
- // Finds and lists all base (141) and reference (144) words */
- int major, minor;
- int word;
- int pos = aug_get_first_child(tree, startpos, &major, &minor);
+ parseT = parseT->right;
- //if (major == WORD_TYPE_REF)
- // refbranch = 1;
+ }
- while (pos) {
- if ((word = aug_get_wgroup(tree, pos))) { // found a word
- if (!refbranch && major == WORD_TYPE_BASE) {
- if ((*base_words_nr) == maxwords) {
- warning("Out of regular words");
- return; // return gracefully
- }
+ // ret is now:
+ // 1 if ANY matchTrees(parseSibling, saidTree) returned 1
+ // ELSE: -1 if ANY returned -1
+ // ELSE: 0
- base_words[*base_words_nr] = word; // register word
- ++(*base_words_nr);
+ } else {
- }
- if (major == WORD_TYPE_REF || refbranch) {
- if ((*ref_words_nr) == maxwords) {
- warning("Out of reference words");
- return; // return gracefully
- }
+ ret = matchTrees(parseT, saidT);
- ref_words[*ref_words_nr] = word; // register word
- ++(*ref_words_nr);
+ }
- }
- if (major != WORD_TYPE_SYNTACTIC_SUGAR && major != WORD_TYPE_BASE && major != WORD_TYPE_REF)
- warning("aug_find_words_recursively(): Unknown word type %03x", major);
+ if (inBracket && ret == 0) {
+ scidprintf("%*sscanParse changing ret to 1 due to brackets\n",
+ outputDepth, "");
+ ret = 1;
+ }
- } else // Did NOT find a word group: Attempt to recurse
- aug_find_words_recursively(tree, pos, base_words, base_words_nr,
- ref_words, ref_words_nr, maxwords, refbranch || major == WORD_TYPE_REF);
+ scidprintf("%*sscanParse returning %d\n", outputDepth, "", ret);
+ outputDepth--;
- pos = aug_get_next_sibling(tree, pos, &major, &minor);
- }
+ return ret;
}
-static void aug_find_words(parse_tree_node_t *tree, int startpos, int *base_words, int *base_words_nr,
- int *ref_words, int *ref_words_nr, int maxwords) {
- // initializing wrapper for aug_find_words_recursively()
- *base_words_nr = 0;
- *ref_words_nr = 0;
- aug_find_words_recursively(tree, startpos, base_words, base_words_nr, ref_words, ref_words_nr, maxwords, 0);
-}
+static int augment_parse_nodes(ParseTreeNode *parseT, ParseTreeNode *saidT) {
+ outputDepth = 0;
+ scidprintf("augment_parse_nodes on ");
+ node_print_desc(parseT);
+ scidprintf(" and ");
+ node_print_desc(saidT);
+ scidprintf("\n");
+ dontclaim = false;
-static int aug_contains_word(int *list, int length, int word) {
- int i;
+ int ret = matchTrees(parseT, saidT);
- if (word == ANYWORD)
- return (length);
+ scidprintf("matchTrees returned %d\n", ret);
- for (i = 0; i < length; i++)
- if (list[i] == word)
- return 1;
+ if (ret != 1)
+ return 0;
- return 0;
+ if (dontclaim)
+ return SAID_PARTIAL_MATCH;
+
+ return 1;
}
-static int augment_sentence_expression(parse_tree_node_t *saidt, int augment_pos, parse_tree_node_t *parset,
- int parse_branch, int major, int minor, int *base_words, int base_words_nr,
- int *ref_words, int ref_words_nr);
+/*******************/
+/**** Main code ****/
+/*******************/
-static int augment_match_expression_p(parse_tree_node_t *saidt, int augment_pos, parse_tree_node_t *parset,
- int parse_basepos, int major, int minor,
- int *base_words, int base_words_nr, int *ref_words, int ref_words_nr) {
- int cmajor, cminor, cpos;
- cpos = aug_get_first_child(saidt, augment_pos, &cmajor, &cminor);
- if (!cpos) {
- warning("augment_match_expression_p(): Empty condition");
- return 1;
- }
+int said(EngineState *s, const byte *spec, bool verbose) {
+ int retval;
+ Vocabulary *voc = g_sci->getVocabulary();
- scidprintf("Attempting to match (%03x %03x (%03x %03x\n", major, minor, cmajor, cminor);
-
- if ((major == WORD_TYPE_BASE) && (minor == AUGMENT_SENTENCE_MINOR_RECURSE))
- return augment_match_expression_p(saidt, cpos, parset, parse_basepos, cmajor, cminor,
- base_words, base_words_nr, ref_words, ref_words_nr);
-
- switch (major) {
-
- case WORD_TYPE_BASE:
- while (cpos) {
- if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_WORD) {
- int word = aug_get_wgroup(saidt, cpos);
- scidprintf("Looking for word %03x\n", word);
-
- if (aug_contains_word(base_words, base_words_nr, word))
- return 1;
- } else if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_PHRASE) {
- if (augment_sentence_expression(saidt, cpos, parset, parse_basepos, cmajor, cminor,
- base_words, base_words_nr, ref_words, ref_words_nr))
- return 1;
- } else if (cminor == AUGMENT_SENTENCE_MINOR_PARENTHESES) {
- int gc_major, gc_minor;
- int gchild = aug_get_first_child(saidt, cpos, &gc_major, &gc_minor);
-
- while (gchild) {
- if (augment_match_expression_p(saidt, cpos, parset, parse_basepos, major,
- minor, base_words, base_words_nr,
- ref_words, ref_words_nr))
- return 1;
- gchild = aug_get_next_sibling(saidt, gchild, &gc_major, &gc_minor);
- }
- } else
- warning("augment_match_expression_p(): Unknown type 141 minor number %3x", cminor);
-
- cpos = aug_get_next_sibling(saidt, cpos, &cmajor, &cminor);
+ ParseTreeNode *parse_tree_ptr = voc->_parserNodes;
- }
- break;
-
- case WORD_TYPE_REF:
- while (cpos) {
- if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_WORD) {
- int word = aug_get_wgroup(saidt, cpos);
- scidprintf("Looking for refword %03x\n", word);
-
- if (aug_contains_word(ref_words, ref_words_nr, word))
- return 1;
- } else if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_PHRASE) {
- if (augment_match_expression_p(saidt, cpos, parset, parse_basepos, cmajor, cminor,
- base_words, base_words_nr, ref_words, ref_words_nr))
- return 1;
- } else if (cminor == AUGMENT_SENTENCE_MINOR_PARENTHESES) {
- int gc_major, gc_minor;
- int gchild = aug_get_first_child(saidt, cpos, &gc_major, &gc_minor);
-
- while (gchild) {
- if (augment_match_expression_p(saidt, cpos, parset, parse_basepos, major,
- minor, base_words, base_words_nr,
- ref_words, ref_words_nr))
- return 1;
- gchild = aug_get_next_sibling(saidt, gchild, &gc_major, &gc_minor);
- }
- } else
- warning("augment_match_expression_p(): Unknown type 144 minor number %3x", cminor);
-
- cpos = aug_get_next_sibling(saidt, cpos, &cmajor, &cminor);
+ if (voc->parserIsValid) {
+ if (said_parse_spec(spec))
+ return SAID_NO_MATCH;
- }
- break;
+ if (verbose)
+ vocab_dump_parse_tree("Said-tree", said_tree);
+ retval = augment_parse_nodes(parse_tree_ptr, said_tree);
- case AUGMENT_SENTENCE_PART_BRACKETS:
- if (augment_match_expression_p(saidt, cpos, parset, parse_basepos, cmajor, cminor,
- base_words, base_words_nr, ref_words, ref_words_nr))
- return 1;
+ if (!retval)
+ return SAID_NO_MATCH;
+ else if (retval != SAID_PARTIAL_MATCH)
+ return SAID_FULL_MATCH;
+ else
+ return SAID_PARTIAL_MATCH;
+ }
- scidprintf("Didn't match subexpression; checking sub-bracked predicate %03x\n", cmajor);
+ return SAID_NO_MATCH;
+}
- switch (cmajor) {
- case WORD_TYPE_BASE:
- if (!base_words_nr)
- return 1;
- break;
- case WORD_TYPE_REF:
- if (!ref_words_nr)
- return 1;
- break;
+/*
- default:
- warning("augment_match_expression_p(): (subp1) Unkonwn sub-bracket predicate %03x", cmajor);
- }
+Some test expressions for in the ScummVM debugging console, using
+Codename: ICEMAN's vocabulary:
- break;
- default:
- warning("augment_match_expression_p(): Unknown predicate %03x", major);
- }
+said green board & [!*] / 8af < 1f6
+True
- scidprintf("augment_match_expression_p(): Generic failure\n");
+said get green board & [!*] / 8af < 1f6
+False
- return 0;
-}
+said green board & [!*] / 8af [< 1f6 ]
+True
-static int augment_sentence_expression(parse_tree_node_t *saidt, int augment_pos, parse_tree_node_t *parset,
- int parse_branch, int major, int minor, int *base_words, int base_words_nr,
- int *ref_words, int ref_words_nr) {
- int check_major, check_minor;
- int check_pos = aug_get_first_child(saidt, augment_pos, &check_major, &check_minor);
- do {
- if (!(augment_match_expression_p(saidt, check_pos, parset, parse_branch, check_major, check_minor,
- base_words, base_words_nr, ref_words, ref_words_nr)))
- return 0;
- } while ((check_pos = aug_get_next_sibling(saidt, check_pos, &check_major, &check_minor)));
+said climb up & 19b , 426 [< 142 ] [/ 81e ]
+True
- return 1;
-}
+said climb up ladder & 19b , 426 [< 142 ] [/ 81e ]
+True
-static int augment_sentence_part(parse_tree_node_t *saidt, int augment_pos, parse_tree_node_t *parset, int parse_basepos, int major, int minor) {
- int pmajor, pminor;
- int parse_branch = parse_basepos;
- int optional = 0;
- int foundwords = 0;
+said climb down & 19b , 426 [< 142 ] [/ 81e ]
+False
- scidprintf("Augmenting (%03x %03x\n", major, minor);
+said climb up tree & 19b , 426 [< 142 ] [/ 81e ]
+False
- if (major == AUGMENT_SENTENCE_PART_BRACKETS) { // '[/ foo]' is true if '/foo' or if there
- // exists no x for which '/x' is true
- if ((augment_pos = aug_get_first_child(saidt, augment_pos, &major, &minor))) {
- scidprintf("Optional part: Now augmenting (%03x %03x\n", major, minor);
- optional = 1;
- } else {
- scidprintf("Matched empty optional expression\n");
- return 1;
- }
- }
+said climb up & 19b , 446 , 426 [< 143 ] [/ 81e ]
+False
- if ((major < 0x141) || (major > 0x143)) {
- scidprintf("augment_sentence_part(): Unexpected sentence part major number %03x\n", major);
- return 0;
- }
+said climb down & 19b , 446 , 426 [< 143 ] [/ 81e ]
+True
- while ((parse_branch = aug_get_next_sibling(parset, parse_branch, &pmajor, &pminor))) {
- if (pmajor == major) { // found matching sentence part
- int success;
- int base_words_nr;
- int ref_words_nr;
- int base_words[AUGMENT_MAX_WORDS];
- int ref_words[AUGMENT_MAX_WORDS];
-#ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION
- int i;
-#endif
+said use green device & 1a5 / 8c1 [< 21d ]
+False
- scidprintf("Found match with pminor = %03x\n", pminor);
- aug_find_words(parset, parse_branch, base_words, &base_words_nr, ref_words, &ref_words_nr, AUGMENT_MAX_WORDS);
- foundwords |= (ref_words_nr | base_words_nr);
-#ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION
- printf("%d base words:", base_words_nr);
- for (i = 0; i < base_words_nr; i++)
- printf(" %03x", base_words[i]);
- printf("\n%d reference words:", ref_words_nr);
- for (i = 0; i < ref_words_nr; i++)
- printf(" %03x", ref_words[i]);
- printf("\n");
-#endif
+said use electronic device & 1a5 / 8c1 [< 21d ]
+True
- success = augment_sentence_expression(saidt, augment_pos, parset, parse_basepos, major, minor,
- base_words, base_words_nr, ref_words, ref_words_nr);
+said use device & 1a5 / 8c1 [< 21d ]
+True
- if (success) {
- scidprintf("SUCCESS on augmenting (%03x %03x\n", major, minor);
- return 1;
- }
- }
- }
+said eat & 429 [/ !* ]
+True
- if (optional && (foundwords == 0)) {
- scidprintf("Found no words and optional branch => SUCCESS on augmenting (%03x %03x\n", major, minor);
- return 1;
- }
- scidprintf("FAILURE on augmenting (%03x %03x\n", major, minor);
+said eat ladder & 429 [/ !* ]
+False
- return 0;
-}
+said look at the ladder & 3f8 / 81e [< !* ]
+True
-static int augment_parse_nodes(parse_tree_node_t *parset, parse_tree_node_t *saidt) {
- int augment_basepos = 0;
- int parse_basepos;
- int major, minor;
- int dontclaim = 0;
+said look at the green ladder & 3f8 / 81e [< !* ]
+False
- parse_basepos = aug_get_base_node(parset);
- if (!parse_basepos) {
- warning("augment_parse_nodes(): Parse tree is corrupt");
- return 0;
- }
+said look green book & / 7f6 [< 8d2 ]
+False
- augment_basepos = aug_get_base_node(saidt);
- if (!augment_basepos) {
- warning("augment_parse_nodes(): Said tree is corrupt");
- return 0;
- }
+said look green book & 3f8 [< ca ]
+True
- while ((augment_basepos = aug_get_next_sibling(saidt, augment_basepos, &major, &minor))) {
- if ((major == 0x14b) && (minor == SAID_LONG(SAID_GT)))
- dontclaim = 1; // special case
- else // normal sentence part
- if (!(augment_sentence_part(saidt, augment_basepos, parset, parse_basepos, major, minor))) {
- scidprintf("Returning failure\n");
- return 0; // fail
- }
- }
+said get a blue board for the green ladder & 3f9 / 8af [ < 1f6 ] / 81e < 1f6
+False
- scidprintf("Returning success with dontclaim=%d\n", dontclaim);
+said get a board for the green ladder & 3f9 / 8af [ < 1f6 ] / 81e < 1f6
+True
- if (dontclaim)
- return SAID_PARTIAL_MATCH;
- else
- return 1; // full match
-}
+said get a blue board & 3f9 / 8af [ < 1f6 ]
+False
+said get up & ( 3f8 , 3f9 ) [ < ( 142 , 143 ) ]
+True
-/*******************/
-/**** Main code ****/
-/*******************/
+said get left & ( 3f8 , 3f9 ) [ < ( 142 , 143 ) ]
+False
-int said(EngineState *s, byte *spec, bool verbose) {
- int retval;
+said look down & ( 3f8 , 3f9 ) [ < ( 142 , 143 ) ]
+True
- parse_tree_node_t *parse_tree_ptr = s->_voc->_parserNodes;
+said get & ( 3f8 , 3f9 ) [ < ( 142 , 143 ) ]
+True
- if (s->_voc->parserIsValid) {
- if (said_parse_spec(spec)) {
- printf("Offending spec was: ");
- s->_voc->decipherSaidBlock(spec);
- return SAID_NO_MATCH;
- }
+said put washer on shaft & 455 , ( 3fa < cb ) / 8c6
+True
- if (verbose)
- vocab_dump_parse_tree("Said-tree", said_tree); // Nothing better to do yet
- retval = augment_parse_nodes(parse_tree_ptr, &(said_tree[0]));
+said depth correct & [!*] < 8b1 / 22
+True
- if (!retval)
- return SAID_NO_MATCH;
- else if (retval != SAID_PARTIAL_MATCH)
- return SAID_FULL_MATCH;
- else
- return SAID_PARTIAL_MATCH;
- }
+said depth acknowledged & / 46d , 460 , 44d < 8b1
+True
- return SAID_NO_MATCH;
-}
+said depth confirmed & / 46d , 460 , 44d < 8b1
+True
+
+said depth attained & / 46d , 460 , 44d < 8b1
+True
+
+
+*/
-#ifdef SAID_DEBUG_PROGRAM
-int main (int argc, char *argv) {
- byte block[] = {0x01, 0x00, 0xf8, 0xf5, 0x02, 0x01, 0xf6, 0xf2, 0x02, 0x01, 0xf2, 0x01, 0x03, 0xff};
- EngineState s;
- s.parser_valid = 1;
- said(&s, block);
-}
-#endif
} // End of namespace Sci
diff --git a/engines/sci/parser/said.y b/engines/sci/parser/said.y
deleted file mode 100644
index 27486c5794..0000000000
--- a/engines/sci/parser/said.y
+++ /dev/null
@@ -1,838 +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 "sci/engine/state.h"
-
-
-// Bison generates an empty switch statement that gives a warning in MSVC.
-// This disables that warning.
-#ifdef _MSC_VER
-#pragma warning(disable:4065)
-#endif
-
-
-namespace Sci {
-
-#define SAID_BRANCH_NULL 0
-
-#define MAX_SAID_TOKENS 128
-
-// Maximum number of words to be expected in a parsed sentence
-#define AUGMENT_MAX_WORDS 64
-
-
-#define ANYWORD 0xfff
-
-#define WORD_TYPE_BASE 0x141
-#define WORD_TYPE_REF 0x144
-#define WORD_TYPE_SYNTACTIC_SUGAR 0x145
-
-#define AUGMENT_SENTENCE_PART_BRACKETS 0x152
-
-// Minor numbers
-#define AUGMENT_SENTENCE_MINOR_MATCH_PHRASE 0x14c
-#define AUGMENT_SENTENCE_MINOR_MATCH_WORD 0x153
-#define AUGMENT_SENTENCE_MINOR_RECURSE 0x144
-#define AUGMENT_SENTENCE_MINOR_PARENTHESES 0x14f
-
-
-#undef YYDEBUG /*1*/
-//#define SAID_DEBUG*/
-//#define SCI_DEBUG_PARSE_TREE_AUGMENTATION // uncomment to debug parse tree augmentation
-
-
-#ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION
-#define scidprintf printf
-#else
-void print_nothing(...) { }
-#define scidprintf print_nothing
-#endif
-
-
-static char *said_parse_error;
-
-static int said_token;
-static int said_tokens_nr;
-static int said_tokens[MAX_SAID_TOKENS];
-static int said_blessed; // increminated by said_top_branch
-
-static int said_tree_pos; // Set to 0 if we're out of space
-#define SAID_TREE_START 4; // Reserve space for the 4 top nodes
-
-#define VALUE_IGNORE -424242
-
-static parse_tree_node_t said_tree[VOCAB_TREE_NODES];
-
-typedef int wgroup_t;
-typedef int tree_t;
-typedef int said_spec_t;
-
-static tree_t said_aug_branch(int, int, tree_t, tree_t);
-static tree_t said_attach_branch(tree_t, tree_t);
-/*
-static tree_t said_wgroup_branch(wgroup_t);
-*/
-static said_spec_t said_top_branch(tree_t);
-static tree_t said_paren(tree_t, tree_t);
-static tree_t said_value(int, tree_t);
-static tree_t said_terminal(int);
-
-static int yylex();
-
-static int yyerror(const char *s) {
- said_parse_error = strdup(s);
- return 1; /* Abort */
-}
-
-%}
-
-%token WGROUP /* Word group */
-%token YY_COMMA /* 0xf0 */
-%token YY_AMP /* 0xf1 */
-%token YY_SLASH /* 0xf2 */
-%token YY_PARENO /* 0xf3 */
-%token YY_PARENC /* 0xf4 */
-%token YY_BRACKETSO /* 0xf5 */
-%token YY_BRACKETSC /* 0xf6 */
-%token YY_HASH /* 0xf7 */
-%token YY_LT /* 0xf8 */
-%token YY_GT /* 0xf9 */
-%token YY_BRACKETSO_LT /* special token used to imitate LR(2) behaviour */
-%token YY_BRACKETSO_SLASH /* special token used to imitate LR(2) behaviour */
-%token YY_LT_BRACKETSO /* special token used to imitate LR(2) behaviour */
-%token YY_LT_PARENO /* special token used to imitate LR(2) behaviour */
-
-%%
-
-saidspec : leftspec optcont
- { $$ = said_top_branch(said_attach_branch($1, $2)); }
- | leftspec midspec optcont
- { $$ = said_top_branch(said_attach_branch($1, said_attach_branch($2, $3))); }
- | leftspec midspec rightspec optcont
- { $$ = said_top_branch(said_attach_branch($1, said_attach_branch($2, said_attach_branch($3, $4)))); }
- ;
-
-
-optcont : /* empty */
- { $$ = SAID_BRANCH_NULL; }
- | YY_GT
- { $$ = said_paren(said_value(0x14b, said_value(0xf900, said_terminal(0xf900))), SAID_BRANCH_NULL); }
- ;
-
-
-
-leftspec : /* empty */
- { $$ = SAID_BRANCH_NULL; }
- | expr
- { $$ = said_paren(said_value(0x141, said_value(0x149, $1)), SAID_BRANCH_NULL); }
- ;
-
-
-
-midspec : YY_SLASH expr
- { $$ = said_aug_branch(0x142, 0x14a, $2, SAID_BRANCH_NULL); }
- | YY_BRACKETSO_SLASH YY_SLASH expr YY_BRACKETSC
- { $$ = said_aug_branch(0x152, 0x142, said_aug_branch(0x142, 0x14a, $3, SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
- | YY_SLASH
- { $$ = SAID_BRANCH_NULL; }
- ;
-
-
-
-rightspec : YY_SLASH expr
- { $$ = said_aug_branch(0x143, 0x14a, $2, SAID_BRANCH_NULL); }
- | YY_BRACKETSO_SLASH YY_SLASH expr YY_BRACKETSC
- { $$ = said_aug_branch(0x152, 0x143, said_aug_branch(0x143, 0x14a, $3, SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
- | YY_SLASH
- { $$ = SAID_BRANCH_NULL; }
- ;
-
-
-word : WGROUP
- { $$ = said_paren(said_value(0x141, said_value(0x153, said_terminal($1))), SAID_BRANCH_NULL); }
- ;
-
-
-cwordset : wordset
- { $$ = said_aug_branch(0x141, 0x14f, $1, SAID_BRANCH_NULL); }
- | YY_BRACKETSO wordset YY_BRACKETSC
- { $$ = said_aug_branch(0x141, 0x14f, said_aug_branch(0x152, 0x14c, said_aug_branch(0x141, 0x14f, $2, SAID_BRANCH_NULL), SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
- ;
-
-
-wordset : word
- { $$ = $1; }
- | YY_PARENO expr YY_PARENC
- { $$ = said_aug_branch(0x141, 0x14c, $2, SAID_BRANCH_NULL); }
- | wordset YY_COMMA wordset
- { $$ = said_attach_branch($1, $3); }
- | wordset YY_BRACKETSO_LT wordrefset YY_BRACKETSC
- { $$ = said_attach_branch($1, $3); }
- | wordset YY_COMMA YY_BRACKETSO wordset YY_BRACKETSC
- { $$ = said_attach_branch($1, $3); }
- ;
-
-
-expr : cwordset cwordrefset
- { $$ = said_attach_branch($1, $2); }
- | cwordset
- { $$ = $1; }
- | cwordrefset
- { $$ = $1; }
- ;
-
-
-cwordrefset : wordrefset
- { $$ = $1; }
- | YY_BRACKETSO_LT wordrefset YY_BRACKETSC
- { $$ = said_aug_branch(0x152, 0x144, $2, SAID_BRANCH_NULL); }
- | wordrefset YY_BRACKETSO_LT wordrefset YY_BRACKETSC
- { $$ = said_attach_branch($1, said_aug_branch(0x152, 0x144, $3, SAID_BRANCH_NULL)); }
- ;
-
-
-wordrefset : YY_LT word recref
- { $$ = said_aug_branch(0x144, 0x14f, $2, $3); }
- | YY_LT_PARENO YY_PARENO expr YY_PARENC
- { $$ = said_aug_branch(0x144, 0x14f, said_aug_branch(0x141, 0x144, $2, SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
- | YY_LT wordset
- { $$ = said_aug_branch(0x144, 0x14f, $2, SAID_BRANCH_NULL); }
- | YY_LT_BRACKETSO YY_BRACKETSO wordset YY_BRACKETSC
- { $$ = said_aug_branch(0x152, 0x144, said_aug_branch(0x144, 0x14f, $3, SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
- ;
-
-
-recref : YY_LT wordset recref
- { $$ = said_aug_branch(0x141, 0x144, said_aug_branch(0x144, 0x14f, $2, SAID_BRANCH_NULL), $3); }
- | YY_LT wordset
- { $$ = said_aug_branch(0x141, 0x144, said_aug_branch(0x144, 0x14f, $2, SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
- | YY_LT_PARENO YY_PARENO expr YY_PARENC
- { $$ = said_aug_branch(0x141, 0x14c, $2, SAID_BRANCH_NULL); }
- ;
-
-%%
-
-int parse_yy_token_lookup[] = {YY_COMMA, YY_AMP, YY_SLASH, YY_PARENO, YY_PARENC, YY_BRACKETSO, YY_BRACKETSC, YY_HASH, YY_LT, YY_GT};
-
-static int yylex() {
- int retval = said_tokens[said_token++];
-
- if (retval < SAID_LONG(SAID_FIRST)) {
- yylval = retval;
- retval = WGROUP;
- } else {
- retval >>= 8;
-
- if (retval == SAID_TERM)
- retval = 0;
- else {
- assert(retval >= SAID_FIRST);
- retval = parse_yy_token_lookup[retval - SAID_FIRST];
- if (retval == YY_BRACKETSO) {
- if ((said_tokens[said_token] >> 8) == SAID_LT)
- retval = YY_BRACKETSO_LT;
- else
- if ((said_tokens[said_token] >> 8) == SAID_SLASH)
- retval = YY_BRACKETSO_SLASH;
- } else if (retval == YY_LT && (said_tokens[said_token] >> 8) == SAID_BRACKO) {
- retval = YY_LT_BRACKETSO;
- } else if (retval == YY_LT && (said_tokens[said_token] >> 8) == SAID_PARENO) {
- retval = YY_LT_PARENO;
- }
- }
- }
-
- return retval;
-}
-
-static int said_next_node() {
- return ((said_tree_pos == 0) || (said_tree_pos >= VOCAB_TREE_NODES)) ? said_tree_pos = 0 : said_tree_pos++;
-}
-
-#define SAID_NEXT_NODE said_next_node()
-
-static int said_leaf_node(tree_t pos, int value) {
- said_tree[pos].type = kParseTreeLeafNode;
-
- if (value != VALUE_IGNORE)
- said_tree[pos].content.value = value;
-
- return pos;
-}
-
-static int said_branch_node(tree_t pos, int left, int right) {
- said_tree[pos].type = kParseTreeBranchNode;
-
- if (left != VALUE_IGNORE)
- said_tree[pos].content.branches[0] = left;
-
- if (right != VALUE_IGNORE)
- said_tree[pos].content.branches[1] = right;
-
- return pos;
-}
-
-static tree_t said_paren(tree_t t1, tree_t t2) {
- if (t1)
- return said_branch_node(SAID_NEXT_NODE, t1, t2);
- else
- return t2;
-}
-
-static tree_t said_value(int val, tree_t t) {
- return said_branch_node(SAID_NEXT_NODE, said_leaf_node(SAID_NEXT_NODE, val), t);
-
-}
-
-static tree_t said_terminal(int val) {
- return said_leaf_node(SAID_NEXT_NODE, val);
-}
-
-static tree_t said_aug_branch(int n1, int n2, tree_t t1, tree_t t2) {
- int retval;
-
- retval = said_branch_node(SAID_NEXT_NODE,
- said_branch_node(SAID_NEXT_NODE,
- said_leaf_node(SAID_NEXT_NODE, n1),
- said_branch_node(SAID_NEXT_NODE,
- said_leaf_node(SAID_NEXT_NODE, n2),
- t1)
- ),
- t2);
-
-#ifdef SAID_DEBUG
- fprintf(stderr, "AUG(0x%x, 0x%x, [%04x], [%04x]) = [%04x]\n", n1, n2, t1, t2, retval);
-#endif
-
- return retval;
-}
-
-static tree_t said_attach_branch(tree_t base, tree_t attacheant) {
-#ifdef SAID_DEBUG
- fprintf(stderr, "ATT2([%04x], [%04x]) = [%04x]\n", base, attacheant, base);
-#endif
-
- if (!attacheant)
- return base;
- if (!base)
- return attacheant;
-
- if (!base)
- return 0; // Happens if we're out of space
-
- said_branch_node(base, VALUE_IGNORE, attacheant);
-
- return base;
-}
-
-static said_spec_t said_top_branch(tree_t first) {
-#ifdef SAID_DEBUG
- fprintf(stderr, "TOP([%04x])\n", first);
-#endif
- said_branch_node(0, 1, 2);
- said_leaf_node(1, 0x141); // Magic number #1
- said_branch_node(2, 3, first);
- said_leaf_node(3, 0x13f); // Magic number #2
-
- ++said_blessed;
-
- return 0;
-}
-
-static int said_parse_spec(byte *spec) {
- int nextitem;
-
- said_parse_error = NULL;
- said_token = 0;
- said_tokens_nr = 0;
- said_blessed = 0;
-
- said_tree_pos = SAID_TREE_START;
-
- do {
- nextitem = *spec++;
- if (nextitem < SAID_FIRST)
- said_tokens[said_tokens_nr++] = nextitem << 8 | *spec++;
- else
- said_tokens[said_tokens_nr++] = SAID_LONG(nextitem);
-
- } while ((nextitem != SAID_TERM) && (said_tokens_nr < MAX_SAID_TOKENS));
-
- if (nextitem == SAID_TERM)
- yyparse();
- else {
- warning("SAID spec is too long");
- return 1;
- }
-
- if (said_parse_error) {
- warning("Error while parsing SAID spec: %s", said_parse_error);
- free(said_parse_error);
- return 1;
- }
-
- if (said_tree_pos == 0) {
- warning("Out of tree space while parsing SAID spec");
- return 1;
- }
-
- if (said_blessed != 1) {
- warning("Found multiple top branches");
- return 1;
- }
-
- return 0;
-}
-
-/**********************/
-/**** Augmentation ****/
-/**********************/
-
-// primitive functions
-
-#define AUG_READ_BRANCH(a, br, p) \
- if (tree[p].type != kParseTreeBranchNode) \
- return 0; \
- a = tree[p].content.branches[br];
-
-#define AUG_READ_VALUE(a, p) \
- if (tree[p].type != kParseTreeLeafNode) \
- return 0; \
- a = tree[p].content.value;
-
-#define AUG_ASSERT(i) \
- if (!i) return 0;
-
-static int aug_get_next_sibling(parse_tree_node_t *tree, int pos, int *first, int *second) {
- // Returns the next sibling relative to the specified position in 'tree',
- // sets *first and *second to its augment node values, returns the new position
- // or 0 if there was no next sibling
- int seek, valpos;
-
- AUG_READ_BRANCH(pos, 1, pos);
- AUG_ASSERT(pos);
- AUG_READ_BRANCH(seek, 0, pos);
- AUG_ASSERT(seek);
-
- // Now retrieve first value
- AUG_READ_BRANCH(valpos, 0, seek);
- AUG_ASSERT(valpos);
- AUG_READ_VALUE(*first, valpos);
-
- // Get second value
- AUG_READ_BRANCH(seek, 1, seek);
- AUG_ASSERT(seek);
- AUG_READ_BRANCH(valpos, 0, seek);
- AUG_ASSERT(valpos);
- AUG_READ_VALUE(*second, valpos);
-
- return pos;
-}
-
-static int aug_get_wgroup(parse_tree_node_t *tree, int pos) {
- // Returns 0 if pos in tree is not the root of a 3-element list, otherwise
- // it returns the last element (which, in practice, is the word group
- int val;
-
- AUG_READ_BRANCH(pos, 0, pos);
- AUG_ASSERT(pos);
- AUG_READ_BRANCH(pos, 1, pos);
- AUG_ASSERT(pos);
- AUG_READ_BRANCH(pos, 1, pos);
- AUG_ASSERT(pos);
- AUG_READ_VALUE(val, pos);
-
- return val;
-}
-
-static int aug_get_base_node(parse_tree_node_t *tree) {
- int startpos = 0;
- AUG_READ_BRANCH(startpos, 1, startpos);
-
- return startpos;
-}
-
-// semi-primitive functions
-
-static int aug_get_first_child(parse_tree_node_t *tree, int pos, int *first, int *second) {
- // like aug_get_next_sibling, except that it recurses into the tree and
- // finds the first child (usually *not* Ayanami Rei) of the current branch
- // rather than its next sibling.
- AUG_READ_BRANCH(pos, 0, pos);
- AUG_ASSERT(pos);
- AUG_READ_BRANCH(pos, 1, pos);
- AUG_ASSERT(pos);
-
- return aug_get_next_sibling(tree, pos, first, second);
-}
-
-static void aug_find_words_recursively(parse_tree_node_t *tree, int startpos, int *base_words, int *base_words_nr,
- int *ref_words, int *ref_words_nr, int maxwords, int refbranch) {
- // Finds and lists all base (141) and reference (144) words */
- int major, minor;
- int word;
- int pos = aug_get_first_child(tree, startpos, &major, &minor);
-
- //if (major == WORD_TYPE_REF)
- // refbranch = 1;
-
- while (pos) {
- if ((word = aug_get_wgroup(tree, pos))) { // found a word
- if (!refbranch && major == WORD_TYPE_BASE) {
- if ((*base_words_nr) == maxwords) {
- warning("Out of regular words");
- return; // return gracefully
- }
-
- base_words[*base_words_nr] = word; // register word
- ++(*base_words_nr);
-
- }
- if (major == WORD_TYPE_REF || refbranch) {
- if ((*ref_words_nr) == maxwords) {
- warning("Out of reference words");
- return; // return gracefully
- }
-
- ref_words[*ref_words_nr] = word; // register word
- ++(*ref_words_nr);
-
- }
- if (major != WORD_TYPE_SYNTACTIC_SUGAR && major != WORD_TYPE_BASE && major != WORD_TYPE_REF)
- warning("aug_find_words_recursively(): Unknown word type %03x", major);
-
- } else // Did NOT find a word group: Attempt to recurse
- aug_find_words_recursively(tree, pos, base_words, base_words_nr,
- ref_words, ref_words_nr, maxwords, refbranch || major == WORD_TYPE_REF);
-
- pos = aug_get_next_sibling(tree, pos, &major, &minor);
- }
-}
-
-
-static void aug_find_words(parse_tree_node_t *tree, int startpos, int *base_words, int *base_words_nr,
- int *ref_words, int *ref_words_nr, int maxwords) {
- // initializing wrapper for aug_find_words_recursively()
- *base_words_nr = 0;
- *ref_words_nr = 0;
-
- aug_find_words_recursively(tree, startpos, base_words, base_words_nr, ref_words, ref_words_nr, maxwords, 0);
-}
-
-
-static int aug_contains_word(int *list, int length, int word) {
- int i;
-
- if (word == ANYWORD)
- return (length);
-
- for (i = 0; i < length; i++)
- if (list[i] == word)
- return 1;
-
- return 0;
-}
-
-
-static int augment_sentence_expression(parse_tree_node_t *saidt, int augment_pos, parse_tree_node_t *parset,
- int parse_branch, int major, int minor, int *base_words, int base_words_nr,
- int *ref_words, int ref_words_nr);
-
-static int augment_match_expression_p(parse_tree_node_t *saidt, int augment_pos, parse_tree_node_t *parset,
- int parse_basepos, int major, int minor,
- int *base_words, int base_words_nr, int *ref_words, int ref_words_nr) {
- int cmajor, cminor, cpos;
- cpos = aug_get_first_child(saidt, augment_pos, &cmajor, &cminor);
- if (!cpos) {
- warning("augment_match_expression_p(): Empty condition");
- return 1;
- }
-
- scidprintf("Attempting to match (%03x %03x (%03x %03x\n", major, minor, cmajor, cminor);
-
- if ((major == WORD_TYPE_BASE) && (minor == AUGMENT_SENTENCE_MINOR_RECURSE))
- return augment_match_expression_p(saidt, cpos, parset, parse_basepos, cmajor, cminor,
- base_words, base_words_nr, ref_words, ref_words_nr);
-
- switch (major) {
-
- case WORD_TYPE_BASE:
- while (cpos) {
- if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_WORD) {
- int word = aug_get_wgroup(saidt, cpos);
- scidprintf("Looking for word %03x\n", word);
-
- if (aug_contains_word(base_words, base_words_nr, word))
- return 1;
- } else if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_PHRASE) {
- if (augment_sentence_expression(saidt, cpos, parset, parse_basepos, cmajor, cminor,
- base_words, base_words_nr, ref_words, ref_words_nr))
- return 1;
- } else if (cminor == AUGMENT_SENTENCE_MINOR_PARENTHESES) {
- int gc_major, gc_minor;
- int gchild = aug_get_first_child(saidt, cpos, &gc_major, &gc_minor);
-
- while (gchild) {
- if (augment_match_expression_p(saidt, cpos, parset, parse_basepos, major,
- minor, base_words, base_words_nr,
- ref_words, ref_words_nr))
- return 1;
- gchild = aug_get_next_sibling(saidt, gchild, &gc_major, &gc_minor);
- }
- } else
- warning("augment_match_expression_p(): Unknown type 141 minor number %3x", cminor);
-
- cpos = aug_get_next_sibling(saidt, cpos, &cmajor, &cminor);
-
- }
- break;
-
- case WORD_TYPE_REF:
- while (cpos) {
- if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_WORD) {
- int word = aug_get_wgroup(saidt, cpos);
- scidprintf("Looking for refword %03x\n", word);
-
- if (aug_contains_word(ref_words, ref_words_nr, word))
- return 1;
- } else if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_PHRASE) {
- if (augment_match_expression_p(saidt, cpos, parset, parse_basepos, cmajor, cminor,
- base_words, base_words_nr, ref_words, ref_words_nr))
- return 1;
- } else if (cminor == AUGMENT_SENTENCE_MINOR_PARENTHESES) {
- int gc_major, gc_minor;
- int gchild = aug_get_first_child(saidt, cpos, &gc_major, &gc_minor);
-
- while (gchild) {
- if (augment_match_expression_p(saidt, cpos, parset, parse_basepos, major,
- minor, base_words, base_words_nr,
- ref_words, ref_words_nr))
- return 1;
- gchild = aug_get_next_sibling(saidt, gchild, &gc_major, &gc_minor);
- }
- } else
- warning("augment_match_expression_p(): Unknown type 144 minor number %3x", cminor);
-
- cpos = aug_get_next_sibling(saidt, cpos, &cmajor, &cminor);
-
- }
- break;
-
- case AUGMENT_SENTENCE_PART_BRACKETS:
- if (augment_match_expression_p(saidt, cpos, parset, parse_basepos, cmajor, cminor,
- base_words, base_words_nr, ref_words, ref_words_nr))
- return 1;
-
- scidprintf("Didn't match subexpression; checking sub-bracked predicate %03x\n", cmajor);
-
- switch (cmajor) {
- case WORD_TYPE_BASE:
- if (!base_words_nr)
- return 1;
- break;
-
- case WORD_TYPE_REF:
- if (!ref_words_nr)
- return 1;
- break;
-
- default:
- warning("augment_match_expression_p(): (subp1) Unkonwn sub-bracket predicate %03x", cmajor);
- }
-
- break;
-
- default:
- warning("augment_match_expression_p(): Unknown predicate %03x", major);
-
- }
-
- scidprintf("augment_match_expression_p(): Generic failure\n");
-
- return 0;
-}
-
-static int augment_sentence_expression(parse_tree_node_t *saidt, int augment_pos, parse_tree_node_t *parset,
- int parse_branch, int major, int minor, int *base_words, int base_words_nr,
- int *ref_words, int ref_words_nr) {
- int check_major, check_minor;
- int check_pos = aug_get_first_child(saidt, augment_pos, &check_major, &check_minor);
- do {
- if (!(augment_match_expression_p(saidt, check_pos, parset, parse_branch, check_major, check_minor,
- base_words, base_words_nr, ref_words, ref_words_nr)))
- return 0;
- } while ((check_pos = aug_get_next_sibling(saidt, check_pos, &check_major, &check_minor)));
-
- return 1;
-}
-
-static int augment_sentence_part(parse_tree_node_t *saidt, int augment_pos, parse_tree_node_t *parset, int parse_basepos, int major, int minor) {
- int pmajor, pminor;
- int parse_branch = parse_basepos;
- int optional = 0;
- int foundwords = 0;
-
- scidprintf("Augmenting (%03x %03x\n", major, minor);
-
- if (major == AUGMENT_SENTENCE_PART_BRACKETS) { // '[/ foo]' is true if '/foo' or if there
- // exists no x for which '/x' is true
- if ((augment_pos = aug_get_first_child(saidt, augment_pos, &major, &minor))) {
- scidprintf("Optional part: Now augmenting (%03x %03x\n", major, minor);
- optional = 1;
- } else {
- scidprintf("Matched empty optional expression\n");
- return 1;
- }
- }
-
- if ((major < 0x141) || (major > 0x143)) {
- scidprintf("augment_sentence_part(): Unexpected sentence part major number %03x\n", major);
- return 0;
- }
-
- while ((parse_branch = aug_get_next_sibling(parset, parse_branch, &pmajor, &pminor))) {
- if (pmajor == major) { // found matching sentence part
- int success;
- int base_words_nr;
- int ref_words_nr;
- int base_words[AUGMENT_MAX_WORDS];
- int ref_words[AUGMENT_MAX_WORDS];
-#ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION
- int i;
-#endif
-
- scidprintf("Found match with pminor = %03x\n", pminor);
- aug_find_words(parset, parse_branch, base_words, &base_words_nr, ref_words, &ref_words_nr, AUGMENT_MAX_WORDS);
- foundwords |= (ref_words_nr | base_words_nr);
-#ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION
- printf("%d base words:", base_words_nr);
- for (i = 0; i < base_words_nr; i++)
- printf(" %03x", base_words[i]);
- printf("\n%d reference words:", ref_words_nr);
- for (i = 0; i < ref_words_nr; i++)
- printf(" %03x", ref_words[i]);
- printf("\n");
-#endif
-
- success = augment_sentence_expression(saidt, augment_pos, parset, parse_basepos, major, minor,
- base_words, base_words_nr, ref_words, ref_words_nr);
-
- if (success) {
- scidprintf("SUCCESS on augmenting (%03x %03x\n", major, minor);
- return 1;
- }
- }
- }
-
- if (optional && (foundwords == 0)) {
- scidprintf("Found no words and optional branch => SUCCESS on augmenting (%03x %03x\n", major, minor);
- return 1;
- }
- scidprintf("FAILURE on augmenting (%03x %03x\n", major, minor);
-
- return 0;
-}
-
-static int augment_parse_nodes(parse_tree_node_t *parset, parse_tree_node_t *saidt) {
- int augment_basepos = 0;
- int parse_basepos;
- int major, minor;
- int dontclaim = 0;
-
- parse_basepos = aug_get_base_node(parset);
- if (!parse_basepos) {
- warning("augment_parse_nodes(): Parse tree is corrupt");
- return 0;
- }
-
- augment_basepos = aug_get_base_node(saidt);
- if (!augment_basepos) {
- warning("augment_parse_nodes(): Said tree is corrupt");
- return 0;
- }
-
- while ((augment_basepos = aug_get_next_sibling(saidt, augment_basepos, &major, &minor))) {
- if ((major == 0x14b) && (minor == SAID_LONG(SAID_GT)))
- dontclaim = 1; // special case
- else // normal sentence part
- if (!(augment_sentence_part(saidt, augment_basepos, parset, parse_basepos, major, minor))) {
- scidprintf("Returning failure\n");
- return 0; // fail
- }
- }
-
- scidprintf("Returning success with dontclaim=%d\n", dontclaim);
-
- if (dontclaim)
- return SAID_PARTIAL_MATCH;
- else
- return 1; // full match
-}
-
-
-/*******************/
-/**** Main code ****/
-/*******************/
-
-int said(EngineState *s, byte *spec, bool verbose) {
- int retval;
-
- parse_tree_node_t *parse_tree_ptr = s->_voc->_parserNodes;
-
- if (s->_voc->parserIsValid) {
- if (said_parse_spec(spec)) {
- printf("Offending spec was: ");
- s->_voc->decipherSaidBlock(spec);
- return SAID_NO_MATCH;
- }
-
- if (verbose)
- vocab_dump_parse_tree("Said-tree", said_tree); // Nothing better to do yet
- retval = augment_parse_nodes(parse_tree_ptr, &(said_tree[0]));
-
- if (!retval)
- return SAID_NO_MATCH;
- else if (retval != SAID_PARTIAL_MATCH)
- return SAID_FULL_MATCH;
- else
- return SAID_PARTIAL_MATCH;
- }
-
- return SAID_NO_MATCH;
-}
-
-
-#ifdef SAID_DEBUG_PROGRAM
-int main (int argc, char *argv) {
- byte block[] = {0x01, 0x00, 0xf8, 0xf5, 0x02, 0x01, 0xf6, 0xf2, 0x02, 0x01, 0xf2, 0x01, 0x03, 0xff};
- EngineState s;
-
- s.parser_valid = 1;
- said(&s, block);
-}
-#endif
-
-} // End of namespace Sci
diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp
index 00448f5d51..20436d5b30 100644
--- a/engines/sci/parser/vocabulary.cpp
+++ b/engines/sci/parser/vocabulary.cpp
@@ -33,71 +33,34 @@
namespace Sci {
-#if 0
-
-#define VOCAB_RESOURCE_CLASSES 996
-/**
- * Vocabulary class names.
- * These strange names were taken from an SCI01 interpreter.
- */
-const char *class_names[] = {"",
- "",
- "conj", // conjunction
- "ass", // ?
- "pos", // preposition ?
- "art", // article
- "adj", // adjective
- "pron", // pronoun
- "noun", // noun
- "auxv", // auxillary verb
- "adv", // adverb
- "verb", // verb
- "",
- "",
- "",
- ""
- };
-
-int *vocab_get_classes(ResourceManager *resMan, int* count) {
- Resource* r;
- int *c;
- unsigned int i;
-
- if ((r = resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_CLASSES), 0)) == NULL)
- return 0;
-
- c = (int *)malloc(sizeof(int) * r->size / 2);
- for (i = 2; i < r->size; i += 4) {
- c[i/4] = READ_LE_UINT16(r->data + i);
- }
- *count = r->size / 4;
-
- return c;
-}
-
-int vocab_get_class_count(ResourceManager *resMan) {
- Resource* r;
-
- if ((r = resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_CLASSES), 0)) == 0)
- return 0;
-
- return r->size / 4;
-}
-
-#endif
-
-Vocabulary::Vocabulary(ResourceManager *resMan) : _resMan(resMan) {
+Vocabulary::Vocabulary(ResourceManager *resMan, bool foreign) : _resMan(resMan), _foreign(foreign) {
_parserRules = NULL;
- _vocabVersion = kVocabularySCI0;
memset(_parserNodes, 0, sizeof(_parserNodes));
// Mark parse tree as unused
_parserNodes[0].type = kParseTreeLeafNode;
- _parserNodes[0].content.value = 0;
+ _parserNodes[0].value = 0;
_synonyms.clear(); // No synonyms
debug(2, "Initializing vocabulary");
+ if (_resMan->testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB))) {
+ _vocabVersion = kVocabularySCI0;
+ _resourceIdWords = VOCAB_RESOURCE_SCI0_MAIN_VOCAB;
+ _resourceIdSuffixes = VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB;
+ _resourceIdBranches = VOCAB_RESOURCE_SCI0_PARSE_TREE_BRANCHES;
+ } else {
+ _vocabVersion = kVocabularySCI1;
+ _resourceIdWords = VOCAB_RESOURCE_SCI1_MAIN_VOCAB;
+ _resourceIdSuffixes = VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB;
+ _resourceIdBranches = VOCAB_RESOURCE_SCI1_PARSE_TREE_BRANCHES;
+ }
+
+ if (_foreign) {
+ _resourceIdWords += 10;
+ _resourceIdSuffixes += 10;
+ _resourceIdBranches += 10;
+ }
if (getSciVersion() <= SCI_VERSION_1_EGA && loadParserWords()) {
loadSuffixes();
@@ -119,27 +82,46 @@ Vocabulary::~Vocabulary() {
freeSuffixes();
}
-bool Vocabulary::loadParserWords() {
+void Vocabulary::reset() {
+ parserIsValid = false; // Invalidate parser
+ parser_event = NULL_REG; // Invalidate parser event
+ parser_base = make_reg(g_sci->getEngineState()->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE);
+}
- char currentword[256] = ""; // They're not going to use words longer than 255 ;-)
- int currentwordpos = 0;
+bool Vocabulary::loadParserWords() {
+ char currentWord[VOCAB_MAX_WORDLENGTH] = "";
+ int currentWordPos = 0;
// First try to load the SCI0 vocab resource.
- Resource *resource = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB), 0);
+ Resource *resource = _resMan->findResource(ResourceId(kResourceTypeVocab, _resourceIdWords), 0);
if (!resource) {
- warning("SCI0: Could not find a main vocabulary, trying SCI01");
- resource = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB), 0);
- _vocabVersion = kVocabularySCI1;
+ warning("Could not find a main vocabulary");
+ return false; // NOT critical: SCI1 games and some demos don't have one!
}
- if (!resource) {
- warning("SCI1: Could not find a main vocabulary");
- return false; // NOT critical: SCI1 games and some demos don't have one!
+ VocabularyVersions resourceType = _vocabVersion;
+
+ if (resourceType == kVocabularySCI0) {
+ if (resource->size < 26 * 2) {
+ warning("Invalid main vocabulary encountered: Much too small");
+ return false;
+ }
+ // Check the alphabet-offset table for any content
+ int alphabetNr;
+ for (alphabetNr = 0; alphabetNr < 26; alphabetNr++) {
+ if (READ_LE_UINT16(resource->data + alphabetNr * 2))
+ break;
+ }
+ // If all of them were empty, we are definitely seeing SCI01 vocab in disguise (e.g. pq2 japanese)
+ if (alphabetNr == 26) {
+ warning("SCI0: Found SCI01 vocabulary in disguise");
+ resourceType = kVocabularySCI1;
+ }
}
unsigned int seeker;
- if (_vocabVersion == kVocabularySCI1)
+ if (resourceType == kVocabularySCI1)
seeker = 255 * 2; // vocab.900 starts with 255 16-bit pointers which we don't use
else
seeker = 26 * 2; // vocab.000 starts with 26 16-bit pointers which we don't use
@@ -155,13 +137,13 @@ bool Vocabulary::loadParserWords() {
while (seeker < resource->size) {
byte c;
- currentwordpos = resource->data[seeker++]; // Parts of previous words may be re-used
+ currentWordPos = resource->data[seeker++]; // Parts of previous words may be re-used
- if (_vocabVersion == kVocabularySCI1) {
+ if (resourceType == kVocabularySCI1) {
c = 1;
- while (seeker < resource->size && currentwordpos < 255 && c) {
+ while (seeker < resource->size && currentWordPos < 255 && c) {
c = resource->data[seeker++];
- currentword[currentwordpos++] = c;
+ currentWord[currentWordPos++] = c;
}
if (seeker == resource->size) {
warning("SCI1: Vocabulary not usable, disabling");
@@ -171,11 +153,11 @@ bool Vocabulary::loadParserWords() {
} else {
do {
c = resource->data[seeker++];
- currentword[currentwordpos++] = c & 0x7f; // 0x80 is used to terminate the string
+ currentWord[currentWordPos++] = c & 0x7f; // 0x80 is used to terminate the string
} while (c < 0x80);
}
- currentword[currentwordpos] = 0;
+ currentWord[currentWordPos] = 0;
// Now decode class and group:
c = resource->data[seeker + 1];
@@ -184,7 +166,7 @@ bool Vocabulary::loadParserWords() {
newWord._group = (resource->data[seeker + 2]) | ((c & 0x0f) << 8);
// Add the word to the list
- _parserWords[currentword] = newWord;
+ _parserWords[currentWord] = newWord;
seeker += 3;
}
@@ -195,23 +177,20 @@ bool Vocabulary::loadParserWords() {
const char *Vocabulary::getAnyWordFromGroup(int group) {
if (group == VOCAB_MAGIC_NUMBER_GROUP)
return "{number}";
+ if (group == VOCAB_MAGIC_NOTHING_GROUP)
+ return "{nothing}";
- for (WordMap::const_iterator i = _parserWords.begin(); i != _parserWords.end(); ++i)
+ for (WordMap::const_iterator i = _parserWords.begin(); i != _parserWords.end(); ++i) {
if (i->_value._group == group)
return i->_key.c_str();
+ }
return "{invalid}";
}
bool Vocabulary::loadSuffixes() {
// Determine if we can find a SCI1 suffix vocabulary first
- Resource* resource = NULL;
-
- if (_vocabVersion == kVocabularySCI0)
- resource = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB), 1);
- else
- resource = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB), 1);
-
+ Resource* resource = _resMan->findResource(ResourceId(kResourceTypeVocab, _resourceIdSuffixes), 1);
if (!resource)
return false; // No vocabulary found
@@ -224,7 +203,7 @@ bool Vocabulary::loadSuffixes() {
suffix.alt_suffix_length = strlen(suffix.alt_suffix);
seeker += suffix.alt_suffix_length + 1; // Hit end of string
- suffix.class_mask = (int16)READ_BE_UINT16(resource->data + seeker);
+ suffix.result_class = (int16)READ_BE_UINT16(resource->data + seeker);
seeker += 2;
// Beginning of next string - skip leading '*'
@@ -234,7 +213,7 @@ bool Vocabulary::loadSuffixes() {
suffix.word_suffix_length = strlen(suffix.word_suffix);
seeker += suffix.word_suffix_length + 1;
- suffix.result_class = (int16)READ_BE_UINT16(resource->data + seeker);
+ suffix.class_mask = (int16)READ_BE_UINT16(resource->data + seeker);
seeker += 3; // Next entry
_parserSuffixes.push_back(suffix);
@@ -244,13 +223,7 @@ bool Vocabulary::loadSuffixes() {
}
void Vocabulary::freeSuffixes() {
- Resource* resource = NULL;
-
- if (_vocabVersion == kVocabularySCI0)
- resource = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB), 0);
- else
- resource = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB), 0);
-
+ Resource* resource = _resMan->findResource(ResourceId(kResourceTypeVocab, _resourceIdSuffixes), 0);
if (resource)
_resMan->unlockResource(resource);
@@ -258,12 +231,7 @@ void Vocabulary::freeSuffixes() {
}
bool Vocabulary::loadBranches() {
- Resource *resource = NULL;
-
- if (_vocabVersion == kVocabularySCI0)
- resource = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_PARSE_TREE_BRANCHES), 0);
- else
- resource = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_PARSE_TREE_BRANCHES), 0);
+ Resource *resource = _resMan->findResource(ResourceId(kResourceTypeVocab, _resourceIdBranches), 0);
_parserBranches.clear();
@@ -296,7 +264,7 @@ bool Vocabulary::loadBranches() {
return true;
}
-
+// we assume that *word points to an already lowercased word
ResultWord Vocabulary::lookupWord(const char *word, int word_len) {
Common::String tempword(word, word_len);
@@ -323,7 +291,7 @@ ResultWord Vocabulary::lookupWord(const char *word, int word_len) {
int suff_index = word_len - suffix->alt_suffix_length;
// Offset of the start of the suffix
- if (scumm_strnicmp(suffix->alt_suffix, word + suff_index, suffix->alt_suffix_length) == 0) { // Suffix matched!
+ if (strncmp(suffix->alt_suffix, word + suff_index, suffix->alt_suffix_length) == 0) { // Suffix matched!
// Terminate word at suffix start position...:
Common::String tempword2(word, MIN(word_len, suff_index));
@@ -353,82 +321,109 @@ ResultWord Vocabulary::lookupWord(const char *word, int word_len) {
return retval;
}
-void Vocabulary::decipherSaidBlock(byte *addr) {
- byte nextitem;
+void Vocabulary::debugDecipherSaidBlock(const byte *addr) {
+ bool first = true;
+ uint16 nextItem;
do {
- nextitem = *addr++;
-
- if (nextitem < 0xf0) {
- nextitem = nextitem << 8 | *addr++;
- printf(" %s[%03x]", getAnyWordFromGroup(nextitem), nextitem);
-
- nextitem = 42; // Make sure that group 0xff doesn't abort
- } else switch (nextitem) {
- case 0xf0:
- printf(" ,");
- break;
- case 0xf1:
- printf(" &");
- break;
- case 0xf2:
- printf(" /");
- break;
- case 0xf3:
- printf(" (");
- break;
- case 0xf4:
- printf(" )");
- break;
- case 0xf5:
- printf(" [");
- break;
- case 0xf6:
- printf(" ]");
- break;
- case 0xf7:
- printf(" #");
- break;
- case 0xf8:
- printf(" <");
- break;
- case 0xf9:
- printf(" >");
- break;
- case 0xff:
- break;
+ nextItem = *addr++;
+ if (nextItem != 0xff) {
+ if ((!first) && (nextItem != 0xf0))
+ printf(" ");
+ first = false;
+
+ if (nextItem < 0xf0) {
+ nextItem = nextItem << 8 | *addr++;
+ printf("%s{%03x}", getAnyWordFromGroup(nextItem), nextItem);
+
+ nextItem = 0; // Make sure that group 0xff doesn't abort
+ } else switch (nextItem) {
+ case 0xf0:
+ printf(",");
+ break;
+ case 0xf1:
+ printf("&");
+ break;
+ case 0xf2:
+ printf("/");
+ break;
+ case 0xf3:
+ printf("(");
+ break;
+ case 0xf4:
+ printf(")");
+ break;
+ case 0xf5:
+ printf("[");
+ break;
+ case 0xf6:
+ printf("]");
+ break;
+ case 0xf7:
+ printf("#");
+ break;
+ case 0xf8:
+ printf("<");
+ break;
+ case 0xf9:
+ printf(">");
+ break;
+ case 0xff:
+ break;
}
- } while (nextitem != 0xff);
-
- printf("\n");
+ }
+ } while (nextItem != 0xff);
}
+static const byte lowerCaseMap[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, // 0x00
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, // 0x10
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, // 0x20
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, // 0x30
+ 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', // 0x40
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, // 0x50
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, // 0x60
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, // 0x70
+ 0x87, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x84, 0x86, // 0x80
+ //^^ ^^^^ ^^^^
+ 0x82, 0x91, 0x91, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x94, 0x81, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, // 0x90
+ //^^ ^^^^ ^^^^ ^^^^
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, // 0xa0
+ // ^^^^
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, // 0xb0
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, // 0xc0
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, // 0xd0
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, // 0xe0
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff // 0xf0
+};
+
bool Vocabulary::tokenizeString(ResultWordList &retval, const char *sentence, char **error) {
- const char *lastword = sentence;
+ char currentWord[VOCAB_MAX_WORDLENGTH] = "";
int pos_in_sentence = 0;
- char c;
- int wordlen = 0;
+ unsigned char c;
+ int wordLen = 0;
*error = NULL;
do {
c = sentence[pos_in_sentence++];
-
- if (isalnum(c) || (c == '-' && wordlen))
- ++wordlen;
+ if (isalnum(c) || (c == '-' && wordLen) || (c >= 0x80)) {
+ currentWord[wordLen] = lowerCaseMap[c];
+ ++wordLen;
+ }
// Continue on this word */
// Words may contain a '-', but may not
// start with one.
else {
- if (wordlen) { // Finished a word?
+ if (wordLen) { // Finished a word?
- ResultWord lookup_result = lookupWord(lastword, wordlen);
+ ResultWord lookup_result = lookupWord(currentWord, wordLen);
// Look it up
if (lookup_result._class == -1) { // Not found?
- *error = (char *)calloc(wordlen + 1, 1);
- strncpy(*error, lastword, wordlen); // Set the offending word
+ *error = (char *)calloc(wordLen + 1, 1);
+ strncpy(*error, currentWord, wordLen); // Set the offending word
retval.clear();
return false; // And return with error
}
@@ -437,8 +432,7 @@ bool Vocabulary::tokenizeString(ResultWordList &retval, const char *sentence, ch
retval.push_back(lookup_result);
}
- lastword = sentence + pos_in_sentence;
- wordlen = 0;
+ wordLen = 0;
}
} while (c); // Until terminator is hit
@@ -447,7 +441,7 @@ bool Vocabulary::tokenizeString(ResultWordList &retval, const char *sentence, ch
}
void Vocabulary::printSuffixes() const {
- char word_buf[256], alt_buf[256];
+ char word_buf[VOCAB_MAX_WORDLENGTH], alt_buf[VOCAB_MAX_WORDLENGTH];
Console *con = g_sci->getSciDebugger();
int i = 0;
@@ -476,30 +470,25 @@ void Vocabulary::printParserWords() const {
con->DebugPrintf("\n");
}
-void _vocab_recursive_ptree_dump_treelike(parse_tree_node_t *nodes, int nr, int prevnr) {
- if ((nr > VOCAB_TREE_NODES)/* || (nr < prevnr)*/) {
- printf("Error(%04x)", nr);
- return;
- }
+void _vocab_recursive_ptree_dump_treelike(ParseTreeNode *tree) {
+ assert(tree);
- if (nodes[nr].type == kParseTreeLeafNode)
- //printf("[%03x]%04x", nr, nodes[nr].content.value);
- printf("%x", nodes[nr].content.value);
+ if (tree->type == kParseTreeLeafNode)
+ printf("%x", tree->value);
else {
- int lbranch = nodes[nr].content.branches[0];
- int rbranch = nodes[nr].content.branches[1];
- //printf("<[%03x]", nr);
+ ParseTreeNode* lbranch = tree->left;
+ ParseTreeNode* rbranch = tree->right;
printf("<");
if (lbranch)
- _vocab_recursive_ptree_dump_treelike(nodes, lbranch, nr);
+ _vocab_recursive_ptree_dump_treelike(lbranch);
else
printf("NULL");
printf(",");
if (rbranch)
- _vocab_recursive_ptree_dump_treelike(nodes, rbranch, nr);
+ _vocab_recursive_ptree_dump_treelike(rbranch);
else
printf("NULL");
@@ -507,55 +496,52 @@ void _vocab_recursive_ptree_dump_treelike(parse_tree_node_t *nodes, int nr, int
}
}
-void _vocab_recursive_ptree_dump(parse_tree_node_t *nodes, int nr, int prevnr, int blanks) {
- int lbranch = nodes[nr].content.branches[0];
- int rbranch = nodes[nr].content.branches[1];
- int i;
+void _vocab_recursive_ptree_dump(ParseTreeNode *tree, int blanks) {
+ assert(tree);
- if (nodes[nr].type == kParseTreeLeafNode) {
- printf("vocab_dump_parse_tree: Error: consp is nil for element %03x\n", nr);
- return;
- }
+ ParseTreeNode* lbranch = tree->left;
+ ParseTreeNode* rbranch = tree->right;
+ int i;
- if ((nr > VOCAB_TREE_NODES)/* || (nr < prevnr)*/) {
- printf("Error(%04x))", nr);
+ if (tree->type == kParseTreeLeafNode) {
+ printf("vocab_dump_parse_tree: Error: consp is nil\n");
return;
}
if (lbranch) {
- if (nodes[lbranch].type == kParseTreeBranchNode) {
+ if (lbranch->type == kParseTreeBranchNode) {
printf("\n");
for (i = 0; i < blanks; i++)
printf(" ");
printf("(");
- _vocab_recursive_ptree_dump(nodes, lbranch, nr, blanks + 1);
+ _vocab_recursive_ptree_dump(lbranch, blanks + 1);
printf(")\n");
for (i = 0; i < blanks; i++)
printf(" ");
} else
- printf("%x", nodes[lbranch].content.value);
+ printf("%x", lbranch->value);
printf(" ");
}/* else printf ("nil");*/
if (rbranch) {
- if (nodes[rbranch].type == kParseTreeBranchNode)
- _vocab_recursive_ptree_dump(nodes, rbranch, nr, blanks);
+ if (rbranch->type == kParseTreeBranchNode)
+ _vocab_recursive_ptree_dump(rbranch, blanks);
else
- printf("%x", nodes[rbranch].content.value);
+ printf("%x", rbranch->value);
}/* else printf("nil");*/
}
-void vocab_dump_parse_tree(const char *tree_name, parse_tree_node_t *nodes) {
+void vocab_dump_parse_tree(const char *tree_name, ParseTreeNode *nodes) {
//_vocab_recursive_ptree_dump_treelike(nodes, 0, 0);
printf("(setq %s \n'(", tree_name);
- _vocab_recursive_ptree_dump(nodes, 0, 0, 1);
+ _vocab_recursive_ptree_dump(nodes, 1);
printf("))\n");
}
void Vocabulary::dumpParseTree() {
//_vocab_recursive_ptree_dump_treelike(nodes, 0, 0);
printf("(setq parse-tree \n'(");
- _vocab_recursive_ptree_dump(_parserNodes, 0, 0, 1);
+ _vocab_recursive_ptree_dump(_parserNodes, 1);
printf("))\n");
}
@@ -575,10 +561,10 @@ void Vocabulary::printParserNodes(int num) {
for (int i = 0; i < num; i++) {
con->DebugPrintf(" Node %03x: ", i);
if (_parserNodes[i].type == kParseTreeLeafNode)
- con->DebugPrintf("Leaf: %04x\n", _parserNodes[i].content.value);
+ con->DebugPrintf("Leaf: %04x\n", _parserNodes[i].value);
else
- con->DebugPrintf("Branch: ->%04x, ->%04x\n", _parserNodes[i].content.branches[0],
- _parserNodes[i].content.branches[1]);
+ con->DebugPrintf("Branch: ->%04x, ->%04x\n", _parserNodes[i].left,
+ _parserNodes[i].right);
}
}
@@ -591,7 +577,7 @@ int Vocabulary::parseNodes(int *i, int *pos, int type, int nr, int argc, const c
if (type == kParseNumber) {
_parserNodes[*pos += 1].type = kParseTreeLeafNode;
- _parserNodes[*pos].content.value = nr;
+ _parserNodes[*pos].value = nr;
return *pos;
}
if (type == kParseEndOfInput) {
@@ -623,7 +609,15 @@ int Vocabulary::parseNodes(int *i, int *pos, int type, int nr, int argc, const c
}
}
- if ((newPos = _parserNodes[oldPos].content.branches[j] = parseNodes(i, pos, nextToken, nextValue, argc, argv)) == -1)
+ newPos = parseNodes(i, pos, nextToken, nextValue, argc, argv);
+
+ if (j == 0)
+ _parserNodes[oldPos].left = &_parserNodes[newPos];
+ else
+ _parserNodes[oldPos].right = &_parserNodes[newPos];
+
+
+ if (newPos == -1)
return -1;
}
diff --git a/engines/sci/parser/vocabulary.h b/engines/sci/parser/vocabulary.h
index dccef0f5f3..d4df8af715 100644
--- a/engines/sci/parser/vocabulary.h
+++ b/engines/sci/parser/vocabulary.h
@@ -73,13 +73,16 @@ enum {
kParseNumber = 4
};
+#define VOCAB_MAX_WORDLENGTH 256
+
/* Anywords are ignored by the parser */
#define VOCAB_CLASS_ANYWORD 0xff
/* This word class is used for numbers */
#define VOCAB_MAGIC_NUMBER_GROUP 0xffd /* 0xffe ? */
+#define VOCAB_MAGIC_NOTHING_GROUP 0xffe
-/* Number of nodes for each parse_tree_node structure */
+/* Number of nodes for each ParseTreeNode structure */
#define VOCAB_TREE_NODES 500
#define VOCAB_TREE_NODE_LAST_WORD_STORAGE 0x140
@@ -115,7 +118,7 @@ struct ResultWord {
typedef Common::List<ResultWord> ResultWordList;
-typedef Common::HashMap<Common::String, ResultWord, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> WordMap;
+typedef Common::HashMap<Common::String, ResultWord, Common::CaseSensitiveString_Hash, Common::CaseSensitiveString_EqualTo> WordMap;
struct ParseRuleList;
@@ -149,16 +152,16 @@ struct parse_tree_branch_t {
};
enum ParseTypes {
- kParseTreeLeafNode = 0,
- kParseTreeBranchNode = 1
+ kParseTreeWordNode = 4,
+ kParseTreeLeafNode = 5,
+ kParseTreeBranchNode = 6
};
-struct parse_tree_node_t {
+struct ParseTreeNode {
ParseTypes type; /**< leaf or branch */
- union {
- int value; /**< For leaves */
- short branches[2]; /**< For branches */
- } content;
+ int value; /**< For leaves */
+ ParseTreeNode* left; /**< Left child, for branches */
+ ParseTreeNode* right; /**< Right child, for branches */
};
enum VocabularyVersions {
@@ -168,9 +171,12 @@ enum VocabularyVersions {
class Vocabulary {
public:
- Vocabulary(ResourceManager *resMan);
+ Vocabulary(ResourceManager *resMan, bool foreign);
~Vocabulary();
+ // reset parser status
+ void reset();
+
/**
* Gets any word from the specified group. For debugging only.
* @param group Group number
@@ -229,7 +235,7 @@ public:
* For debugging only.
* @param pos pointer to the data to dump
*/
- void decipherSaidBlock(byte *pos);
+ void debugDecipherSaidBlock(const byte *pos);
/**
* Prints the parser suffixes to the debug console.
@@ -301,6 +307,11 @@ private:
ResourceManager *_resMan;
VocabularyVersions _vocabVersion;
+ bool _foreign;
+ uint16 _resourceIdWords;
+ uint16 _resourceIdSuffixes;
+ uint16 _resourceIdBranches;
+
// Parser-related lists
SuffixList _parserSuffixes;
ParseRuleList *_parserRules; /**< GNF rules used in the parser algorithm */
@@ -310,7 +321,7 @@ private:
public:
// Accessed by said()
- parse_tree_node_t _parserNodes[VOCAB_TREE_NODES]; /**< The parse tree */
+ ParseTreeNode _parserNodes[VOCAB_TREE_NODES]; /**< The parse tree */
// Parser data:
reg_t parser_base; /**< Base address for the parser error reporting mechanism */
@@ -323,7 +334,7 @@ public:
* @param tree_name Name of the tree to dump (free-form)
* @param nodes The nodes containing the parse tree
*/
-void vocab_dump_parse_tree(const char *tree_name, parse_tree_node_t *nodes);
+void vocab_dump_parse_tree(const char *tree_name, ParseTreeNode *nodes);
@@ -334,7 +345,7 @@ void vocab_dump_parse_tree(const char *tree_name, parse_tree_node_t *nodes);
* @param verbose Whether to display the parse tree after building it
* @return 1 on a match, 0 otherwise
*/
-int said(EngineState *s, byte *spec, bool verbose);
+int said(EngineState *s, const byte *spec, bool verbose);
} // End of namespace Sci
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 4888dbd4cb..17dc7171dd 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -26,9 +26,11 @@
// Resource library
#include "common/file.h"
+#include "common/fs.h"
#include "common/macresman.h"
#include "sci/resource.h"
+#include "sci/resource_intern.h"
#include "sci/util.h"
namespace Sci {
@@ -45,18 +47,6 @@ struct resource_index_t {
uint16 wSize;
};
-struct ResourceSource {
- ResSourceType source_type;
- bool scanned;
- Common::String location_name; // FIXME: Replace by FSNode ?
- const Common::FSNode *resourceFile;
- int volume_number;
- ResourceSource *associated_map;
- uint32 audioCompressionType;
- int32 *audioCompressionOffsetMapping;
- Common::MacResManager macResMan;
-};
-
//////////////////////////////////////////////////////////////////////
static SciVersion s_sciVersion = SCI_VERSION_NONE; // FIXME: Move this inside a suitable class, e.g. SciEngine
@@ -118,32 +108,81 @@ static const char *sci_error_types[] = {
"SCI version is unsupported"
};
-// These are the 20 resource types supported by SCI1.1
-static const char *resourceTypeNames[] = {
+static const char *s_resourceTypeNames[] = {
"view", "pic", "script", "text", "sound",
"memory", "vocab", "font", "cursor",
"patch", "bitmap", "palette", "cdaudio",
"audio", "sync", "message", "map", "heap",
- "audio36", "sync36", "", "", "robot"
+ "audio36", "sync36", "xlate", "robot", "vmd",
+ "chunk", "macibin", "macibis", "macpict"
};
-static const char *resourceTypeSuffixes[] = {
+static const char *s_resourceTypeSuffixes[] = {
"v56", "p56", "scr", "tex", "snd",
- " ", "voc", "fon", "cur", "pat",
+ "", "voc", "fon", "cur", "pat",
"bit", "pal", "cda", "aud", "syn",
- "msg", "map", "hep", "aud", "syn",
- "trn", " ", "rbt"
-};
+ "msg", "map", "hep", "", "",
+ "trn", "rbt", "vmd", "chk", "",
+ "", ""
+};
const char *getResourceTypeName(ResourceType restype) {
if (restype != kResourceTypeInvalid)
- return resourceTypeNames[restype];
+ return s_resourceTypeNames[restype];
else
return "invalid";
}
+static const ResourceType s_resTypeMapSci0[] = {
+ kResourceTypeView, kResourceTypePic, kResourceTypeScript, kResourceTypeText, // 0x00-0x03
+ kResourceTypeSound, kResourceTypeMemory, kResourceTypeVocab, kResourceTypeFont, // 0x04-0x07
+ kResourceTypeCursor, kResourceTypePatch, kResourceTypeBitmap, kResourceTypePalette, // 0x08-0x0B
+ kResourceTypeCdAudio, kResourceTypeAudio, kResourceTypeSync, kResourceTypeMessage, // 0x0C-0x0F
+ kResourceTypeMap, kResourceTypeHeap, kResourceTypeAudio36, kResourceTypeSync36, // 0x10-0x13
+ kResourceTypeTranslation // 0x14
+};
+
+#ifdef ENABLE_SCI32
+// TODO: 12 should be "Wave", but SCI seems to just store it in Audio resources
+static const ResourceType s_resTypeMapSci21[] = {
+ kResourceTypeView, kResourceTypePic, kResourceTypeScript, kResourceTypeText, // 0x00-0x03
+ kResourceTypeSound, kResourceTypeMemory, kResourceTypeVocab, kResourceTypeFont, // 0x04-0x07
+ kResourceTypeCursor, kResourceTypePatch, kResourceTypeBitmap, kResourceTypePalette, // 0x08-0x0B
+ kResourceTypeInvalid, kResourceTypeAudio, kResourceTypeSync, kResourceTypeMessage, // 0x0C-0x0F
+ kResourceTypeMap, kResourceTypeHeap, kResourceTypeChunk, kResourceTypeAudio36, // 0x10-0x13
+ kResourceTypeSync36, kResourceTypeTranslation, kResourceTypeRobot, kResourceTypeVMD // 0x14-0x17
+};
+#endif
+
+ResourceType ResourceManager::convertResType(byte type) {
+ type &= 0x7f;
+
+ if (_mapVersion != kResVersionSci32) {
+ // SCI0 - SCI2
+ if (type < ARRAYSIZE(s_resTypeMapSci0))
+ return s_resTypeMapSci0[type];
+ } else {
+ // SCI2.1+
+#ifdef ENABLE_SCI32
+ if (type < ARRAYSIZE(s_resTypeMapSci21)) {
+ // LSL6 hires doesn't have the chunk resource type, to match
+ // the resource types of the lowres version, thus we use the
+ // older resource types here
+ if (g_sci && g_sci->getGameId() == GID_LSL6HIRES)
+ return s_resTypeMapSci0[type];
+ else
+ return s_resTypeMapSci21[type];
+ }
+#else
+ error("SCI32 support not compiled in");
+#endif
+ }
+
+ return kResourceTypeInvalid;
+}
+
//-- Resource main functions --
-Resource::Resource() {
+Resource::Resource(ResourceManager *resMan, ResourceId id) : _resMan(resMan), _id(id) {
data = NULL;
size = 0;
_fileOffset = 0;
@@ -156,7 +195,7 @@ Resource::Resource() {
Resource::~Resource() {
delete[] data;
- if (_source && _source->source_type == kSourcePatch)
+ if (_source && _source->getSourceType() == kSourcePatch)
delete _source;
}
@@ -167,101 +206,76 @@ void Resource::unalloc() {
}
void Resource::writeToStream(Common::WriteStream *stream) const {
- stream->writeByte(_id.type | 0x80); // 0x80 is required by old sierra sci, otherwise it wont accept the patch file
+ stream->writeByte(getType() | 0x80); // 0x80 is required by old sierra sci, otherwise it wont accept the patch file
stream->writeByte(_headerSize);
if (_headerSize > 0)
stream->write(_header, _headerSize);
stream->write(data, size);
}
-uint32 Resource::getAudioCompressionType() {
- return _source->audioCompressionType;
+uint32 Resource::getAudioCompressionType() const {
+ return _source->getAudioCompressionType();
}
-//-- resMan helper functions --
+uint32 AudioVolumeResourceSource::getAudioCompressionType() const {
+ return _audioCompressionType;
+}
-// Resource source list management
-ResourceSource *ResourceManager::addExternalMap(const char *file_name, int volume_nr) {
- ResourceSource *newsrc = new ResourceSource();
+ResourceSource::ResourceSource(ResSourceType type, const Common::String &name, int volNum, const Common::FSNode *resFile)
+ : _sourceType(type), _name(name), _volumeNumber(volNum), _resourceFile(resFile) {
+ _scanned = false;
+}
- newsrc->source_type = kSourceExtMap;
- newsrc->location_name = file_name;
- newsrc->resourceFile = 0;
- newsrc->scanned = false;
- newsrc->associated_map = NULL;
- newsrc->volume_number = volume_nr;
+ResourceSource::~ResourceSource() {
+}
- _sources.push_back(newsrc);
- return newsrc;
+MacResourceForkResourceSource::MacResourceForkResourceSource(const Common::String &name, int volNum)
+ : ResourceSource(kSourceMacResourceFork, name, volNum) {
+ _macResMan = new Common::MacResManager();
+ assert(_macResMan);
}
-ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile) {
- ResourceSource *newsrc = new ResourceSource();
+MacResourceForkResourceSource::~MacResourceForkResourceSource() {
+ delete _macResMan;
+}
+
+//-- resMan helper functions --
+
+// Resource source list management
- newsrc->source_type = kSourceExtMap;
- newsrc->location_name = mapFile->getName();
- newsrc->resourceFile = mapFile;
- newsrc->scanned = false;
- newsrc->associated_map = NULL;
- newsrc->volume_number = 0;
+ResourceSource *ResourceManager::addExternalMap(const Common::String &filename, int volume_nr) {
+ ResourceSource *newsrc = new ExtMapResourceSource(filename, volume_nr);
_sources.push_back(newsrc);
return newsrc;
}
-ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const char *filename, int number) {
- ResourceSource *newsrc = new ResourceSource();
-
- newsrc->source_type = type;
- newsrc->scanned = false;
- newsrc->location_name = filename;
- newsrc->resourceFile = 0;
- newsrc->volume_number = number;
- newsrc->associated_map = map;
- newsrc->audioCompressionType = 0;
- newsrc->audioCompressionOffsetMapping = NULL;
- if (type == kSourceAudioVolume)
- checkIfAudioVolumeIsCompressed(newsrc);
+ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, int volume_nr) {
+ ResourceSource *newsrc = new ExtMapResourceSource(mapFile->getName(), volume_nr, mapFile);
_sources.push_back(newsrc);
return newsrc;
}
-ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const Common::FSNode *resFile, int number) {
- ResourceSource *newsrc = new ResourceSource();
-
- newsrc->source_type = type;
- newsrc->scanned = false;
- newsrc->location_name = resFile->getName();
- newsrc->resourceFile = resFile;
- newsrc->volume_number = number;
- newsrc->associated_map = map;
- newsrc->audioCompressionType = 0;
- newsrc->audioCompressionOffsetMapping = NULL;
- if (type == kSourceAudioVolume)
- checkIfAudioVolumeIsCompressed(newsrc);
+ResourceSource *ResourceManager::addSource(ResourceSource *newsrc) {
+ assert(newsrc);
_sources.push_back(newsrc);
return newsrc;
}
-ResourceSource *ResourceManager::addPatchDir(const char *dirname) {
- ResourceSource *newsrc = new ResourceSource();
-
- newsrc->source_type = kSourceDirectory;
- newsrc->scanned = false;
- newsrc->location_name = dirname;
+ResourceSource *ResourceManager::addPatchDir(const Common::String &dirname) {
+ ResourceSource *newsrc = new DirectoryResourceSource(dirname);
_sources.push_back(newsrc);
return 0;
}
-ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) {
+ResourceSource *ResourceManager::findVolume(ResourceSource *map, int volume_nr) {
for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) {
- ResourceSource *src = *it;
- if ((src->source_type == kSourceVolume || src->source_type == kSourceAudioVolume)
- && src->associated_map == map && src->volume_number == volume_nr)
+ ResourceSource *src = (*it)->findVolume(map, volume_nr);
+ if (src)
return src;
}
@@ -270,37 +284,9 @@ ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) {
// Resource manager constructors and operations
-void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) {
- Common::File *file = getVolumeFile(source->location_name.c_str());
- if (!file) {
- warning("Failed to open %s", source->location_name.c_str());
- return;
- }
- file->seek(0, SEEK_SET);
- uint32 compressionType = file->readUint32BE();
- switch (compressionType) {
- case MKID_BE('MP3 '):
- case MKID_BE('OGG '):
- case MKID_BE('FLAC'):
- // Detected a compressed audio volume
- source->audioCompressionType = compressionType;
- // Now read the whole offset mapping table for later usage
- int32 recordCount = file->readUint32LE();
- if (!recordCount)
- error("compressed audio volume doesn't contain any entries!");
- int32 *offsetMapping = new int32[(recordCount + 1) * 2];
- source->audioCompressionOffsetMapping = offsetMapping;
- for (int recordNo = 0; recordNo < recordCount; recordNo++) {
- *offsetMapping++ = file->readUint32LE();
- *offsetMapping++ = file->readUint32LE();
- }
- // Put ending zero
- *offsetMapping++ = 0;
- *offsetMapping++ = file->size();
- }
-}
+bool Resource::loadPatch(Common::SeekableReadStream *file) {
+ Resource *res = this;
-bool ResourceManager::loadPatch(Resource *res, Common::File &file) {
// We assume that the resource type matches res->type
// We also assume that the current file position is right at the actual data (behind resourceid/headersize byte)
@@ -315,12 +301,12 @@ bool ResourceManager::loadPatch(Resource *res, Common::File &file) {
unsigned int really_read;
if (res->_headerSize > 0) {
- really_read = file.read(res->_header, res->_headerSize);
+ really_read = file->read(res->_header, res->_headerSize);
if (really_read != res->_headerSize)
error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->_headerSize);
}
- really_read = file.read(res->data, res->size);
+ really_read = file->read(res->data, res->size);
if (really_read != res->size)
error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size);
@@ -328,87 +314,28 @@ bool ResourceManager::loadPatch(Resource *res, Common::File &file) {
return true;
}
-bool ResourceManager::loadFromPatchFile(Resource *res) {
+bool Resource::loadFromPatchFile() {
Common::File file;
- const char *filename = res->_source->location_name.c_str();
+ const Common::String &filename = _source->getLocationName();
if (file.open(filename) == false) {
- warning("Failed to open patch file %s", filename);
- res->unalloc();
+ warning("Failed to open patch file %s", filename.c_str());
+ unalloc();
return false;
}
// Skip resourceid and header size byte
file.seek(2, SEEK_SET);
- return loadPatch(res, file);
-}
-
-bool ResourceManager::loadFromWaveFile(Resource *res, Common::File &file) {
- res->data = new byte[res->size];
-
- uint32 really_read = file.read(res->data, res->size);
- if (really_read != res->size)
- error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size);
-
- res->_status = kResStatusAllocated;
- return true;
+ return loadPatch(&file);
}
-bool ResourceManager::loadFromAudioVolumeSCI11(Resource *res, Common::File &file) {
- // Check for WAVE files here
- uint32 riffTag = file.readUint32BE();
- if (riffTag == MKID_BE('RIFF')) {
- res->_headerSize = 0;
- res->size = file.readUint32LE();
- file.seek(-8, SEEK_CUR);
- return loadFromWaveFile(res, file);
- }
- file.seek(-4, SEEK_CUR);
-
- ResourceType type = (ResourceType)(file.readByte() & 0x7f);
- if (((res->_id.type == kResourceTypeAudio || res->_id.type == kResourceTypeAudio36) && (type != kResourceTypeAudio))
- || ((res->_id.type == kResourceTypeSync || res->_id.type == kResourceTypeSync36) && (type != kResourceTypeSync))) {
- warning("Resource type mismatch loading %s from %s", res->_id.toString().c_str(), file.getName());
- res->unalloc();
- return false;
- }
-
- res->_headerSize = file.readByte();
-
- if (type == kResourceTypeAudio) {
- if (res->_headerSize != 11 && res->_headerSize != 12) {
- warning("Unsupported audio header");
- res->unalloc();
- return false;
- }
-
- // Load sample size
- file.seek(7, SEEK_CUR);
- res->size = file.readUint32LE();
- // Adjust offset to point at the header data again
- file.seek(-11, SEEK_CUR);
- }
-
- return loadPatch(res, file);
-}
-
-bool ResourceManager::loadFromAudioVolumeSCI1(Resource *res, Common::File &file) {
- res->data = new byte[res->size];
-
- if (res->data == NULL) {
- error("Can't allocate %d bytes needed for loading %s", res->size, res->_id.toString().c_str());
- }
-
- unsigned int really_read = file.read(res->data, res->size);
- if (really_read != res->size)
- warning("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size);
-
- res->_status = kResStatusAllocated;
- return true;
-}
-
-Common::File *ResourceManager::getVolumeFile(const char *filename) {
+Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *source) {
Common::List<Common::File *>::iterator it = _volumeFiles.begin();
Common::File *file;
+ if (source->_resourceFile)
+ return source->_resourceFile->createReadStream();
+
+ const char *filename = source->getLocationName().c_str();
+
// check if file is already opened
while (it != _volumeFiles.end()) {
file = *it;
@@ -441,161 +368,182 @@ Common::File *ResourceManager::getVolumeFile(const char *filename) {
static uint32 resTypeToMacTag(ResourceType type);
void ResourceManager::loadResource(Resource *res) {
- if (res->_source->source_type == kSourcePatch && loadFromPatchFile(res))
- return;
+ res->_source->loadResource(this, res);
+}
+
+
+void PatchResourceSource::loadResource(ResourceManager *resMan, Resource *res) {
+ bool result = res->loadFromPatchFile();
+ if (!result) {
+ // TODO: We used to fallback to the "default" code here if loadFromPatchFile
+ // failed, but I am not sure whether that is really appropriate.
+ // In fact it looks like a bug to me, so I commented this out for now.
+ //ResourceSource::loadResource(res);
+ }
+}
- if (res->_source->source_type == kSourceMacResourceFork) {
- //error("ResourceManager::loadResource(): TODO: Mac resource fork ;)");
- Common::SeekableReadStream *stream = res->_source->macResMan.getResource(resTypeToMacTag(res->_id.type), res->_id.number);
+void MacResourceForkResourceSource::loadResource(ResourceManager *resMan, Resource *res) {
+ Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->getType()), res->getNumber());
- if (!stream)
- error("Could not get Mac resource fork resource");
+ if (!stream)
+ error("Could not get Mac resource fork resource: %s %d", getResourceTypeName(res->getType()), res->getNumber());
- int error = decompress(res, stream);
- if (error) {
- warning("Error %d occured while reading %s from Mac resource file: %s",
- error, res->_id.toString().c_str(), sci_error_types[error]);
+ int error = res->decompress(resMan->getVolVersion(), stream);
+ if (error) {
+ warning("Error %d occurred while reading %s from Mac resource file: %s",
+ error, res->_id.toString().c_str(), sci_error_types[error]);
+ res->unalloc();
+ }
+}
+
+Common::SeekableReadStream *ResourceSource::getVolumeFile(ResourceManager *resMan, Resource *res) {
+ Common::SeekableReadStream *fileStream = resMan->getVolumeFile(this);
+
+ if (!fileStream) {
+ warning("Failed to open %s", getLocationName().c_str());
+ if (res)
res->unalloc();
- }
- return;
}
- Common::File *file;
- // Either loading from volume or patch loading failed
- file = getVolumeFile(res->_source->location_name.c_str());
- if (!file) {
- warning("Failed to open %s", res->_source->location_name.c_str());
- res->unalloc();
+ return fileStream;
+}
+
+void WaveResourceSource::loadResource(ResourceManager *resMan, Resource *res) {
+ Common::SeekableReadStream *fileStream = getVolumeFile(resMan, res);
+ if (!fileStream)
return;
- }
- switch(res->_source->source_type) {
- case kSourceWave:
- file->seek(res->_fileOffset, SEEK_SET);
- loadFromWaveFile(res, *file);
+ fileStream->seek(res->_fileOffset, SEEK_SET);
+ res->loadFromWaveFile(fileStream);
+ if (_resourceFile)
+ delete fileStream;
+}
+
+void AudioVolumeResourceSource::loadResource(ResourceManager *resMan, Resource *res) {
+ Common::SeekableReadStream *fileStream = getVolumeFile(resMan, res);
+ if (!fileStream)
return;
- case kSourceAudioVolume:
- if (res->_source->audioCompressionType) {
- // this file is compressed, so lookup our offset in the offset-translation table and get the new offset
- // also calculate the compressed size by using the next offset
- int32 *mappingTable = res->_source->audioCompressionOffsetMapping;
- int32 compressedOffset = 0;
-
- do {
- if (*mappingTable == res->_fileOffset) {
- mappingTable++;
- compressedOffset = *mappingTable;
- // Go to next compressed offset and use that to calculate size of compressed sample
- switch (res->_id.type) {
- case kResourceTypeSync:
- case kResourceTypeSync36:
- // we should already have a (valid) size
- break;
- default:
- mappingTable += 2;
- res->size = *mappingTable - compressedOffset;
- }
+ if (_audioCompressionType) {
+ // this file is compressed, so lookup our offset in the offset-translation table and get the new offset
+ // also calculate the compressed size by using the next offset
+ int32 *mappingTable = _audioCompressionOffsetMapping;
+ int32 compressedOffset = 0;
+
+ do {
+ if (*mappingTable == res->_fileOffset) {
+ mappingTable++;
+ compressedOffset = *mappingTable;
+ // Go to next compressed offset and use that to calculate size of compressed sample
+ switch (res->getType()) {
+ case kResourceTypeSync:
+ case kResourceTypeSync36:
+ // we should already have a (valid) size
break;
+ default:
+ mappingTable += 2;
+ res->size = *mappingTable - compressedOffset;
}
- mappingTable += 2;
- } while (*mappingTable);
-
- if (!compressedOffset)
- error("could not translate offset to compressed offset in audio volume");
- file->seek(compressedOffset, SEEK_SET);
-
- switch (res->_id.type) {
- case kResourceTypeAudio:
- case kResourceTypeAudio36:
- // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1
- loadFromAudioVolumeSCI1(res, *file);
- return;
- default:
break;
}
- } else {
- // original file, directly seek to given offset and get SCI1/SCI1.1 audio resource
- file->seek(res->_fileOffset, SEEK_SET);
+ mappingTable += 2;
+ } while (*mappingTable);
+
+ if (!compressedOffset)
+ error("could not translate offset to compressed offset in audio volume");
+ fileStream->seek(compressedOffset, SEEK_SET);
+
+ switch (res->getType()) {
+ case kResourceTypeAudio:
+ case kResourceTypeAudio36:
+ // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1
+ res->loadFromAudioVolumeSCI1(fileStream);
+ if (_resourceFile)
+ delete fileStream;
+ return;
+ default:
+ break;
}
- if (getSciVersion() < SCI_VERSION_1_1)
- loadFromAudioVolumeSCI1(res, *file);
- else
- loadFromAudioVolumeSCI11(res, *file);
+ } else {
+ // original file, directly seek to given offset and get SCI1/SCI1.1 audio resource
+ fileStream->seek(res->_fileOffset, SEEK_SET);
+ }
+ if (getSciVersion() < SCI_VERSION_1_1)
+ res->loadFromAudioVolumeSCI1(fileStream);
+ else
+ res->loadFromAudioVolumeSCI11(fileStream);
+
+ if (_resourceFile)
+ delete fileStream;
+}
+
+void ResourceSource::loadResource(ResourceManager *resMan, Resource *res) {
+ Common::SeekableReadStream *fileStream = getVolumeFile(resMan, res);
+ if (!fileStream)
return;
- default:
- file->seek(res->_fileOffset, SEEK_SET);
- int error = decompress(res, file);
- if (error) {
- warning("Error %d occured while reading %s from resource file: %s",
- error, res->_id.toString().c_str(), sci_error_types[error]);
- res->unalloc();
- }
+ fileStream->seek(res->_fileOffset, SEEK_SET);
+
+ int error = res->decompress(resMan->getVolVersion(), fileStream);
+ if (error) {
+ warning("Error %d occurred while reading %s from resource file: %s",
+ error, res->_id.toString().c_str(), sci_error_types[error]);
+ res->unalloc();
}
+
+ if (_resourceFile)
+ delete fileStream;
}
Resource *ResourceManager::testResource(ResourceId id) {
return _resMap.getVal(id, NULL);
}
-int sci0_get_compression_method(Common::ReadStream &stream) {
- uint16 compressionMethod;
-
- stream.readUint16LE();
- stream.readUint16LE();
- stream.readUint16LE();
- compressionMethod = stream.readUint16LE();
- if (stream.err())
- return SCI_ERROR_IO_ERROR;
-
- return compressionMethod;
-}
-
int ResourceManager::addAppropriateSources() {
Common::ArchiveMemberList files;
- if (Common::File::exists("RESOURCE.MAP")) {
+ if (Common::File::exists("resource.map")) {
// SCI0-SCI2 file naming scheme
- ResourceSource *map = addExternalMap("RESOURCE.MAP");
+ ResourceSource *map = addExternalMap("resource.map");
- SearchMan.listMatchingMembers(files, "RESOURCE.0??");
+ SearchMan.listMatchingMembers(files, "resource.0??");
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
const Common::String name = (*x)->getName();
const char *dot = strrchr(name.c_str(), '.');
int number = atoi(dot + 1);
- addSource(map, kSourceVolume, name.c_str(), number);
+ addSource(new VolumeResourceSource(name, map, number));
}
#ifdef ENABLE_SCI32
// GK1CD hires content
- if (Common::File::exists("ALT.MAP") && Common::File::exists("RESOURCE.ALT"))
- addSource(addExternalMap("ALT.MAP", 10), kSourceVolume, "RESOURCE.ALT", 10);
+ if (Common::File::exists("alt.map") && Common::File::exists("resource.alt"))
+ addSource(new VolumeResourceSource("resource.alt", addExternalMap("alt.map", 10), 10));
#endif
} else if (Common::File::exists("Data1")) {
// Mac SCI1.1+ file naming scheme
- SearchMan.listMatchingMembers(files, "Data?");
+ SearchMan.listMatchingMembers(files, "Data?*");
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
Common::String filename = (*x)->getName();
- addSource(0, kSourceMacResourceFork, filename.c_str(), atoi(filename.c_str() + 4));
+ addSource(new MacResourceForkResourceSource(filename, atoi(filename.c_str() + 4)));
}
#ifdef ENABLE_SCI32
// Mac SCI32 games have extra folders for patches
addPatchDir("Robot Folder");
addPatchDir("Sound Folder");
addPatchDir("Voices Folder");
+ addPatchDir("Voices");
//addPatchDir("VMD Folder");
// There can also be a "Patches" resource fork with patches
if (Common::File::exists("Patches"))
- addSource(0, kSourceMacResourceFork, "Patches", 100);
+ addSource(new MacResourceForkResourceSource("Patches", 100));
} else {
// SCI2.1-SCI3 file naming scheme
Common::ArchiveMemberList mapFiles;
- SearchMan.listMatchingMembers(mapFiles, "RESMAP.0??");
- SearchMan.listMatchingMembers(files, "RESSCI.0??");
+ SearchMan.listMatchingMembers(mapFiles, "resmap.0??");
+ SearchMan.listMatchingMembers(files, "ressci.0??");
// We need to have the same number of maps as resource archives
if (mapFiles.empty() || files.empty() || mapFiles.size() != files.size())
@@ -610,16 +558,16 @@ int ResourceManager::addAppropriateSources() {
int resNumber = atoi(strrchr(resName.c_str(), '.') + 1);
if (mapNumber == resNumber) {
- addSource(addExternalMap(mapName.c_str(), mapNumber), kSourceVolume, resName.c_str(), mapNumber);
+ addSource(new VolumeResourceSource(resName, addExternalMap(mapName, mapNumber), mapNumber));
break;
}
}
}
// SCI2.1 resource patches
- if (Common::File::exists("RESMAP.PAT") && Common::File::exists("RESSCI.PAT")) {
+ if (Common::File::exists("resmap.pat") && Common::File::exists("ressci.pat")) {
// We add this resource with a map which surely won't exist
- addSource(addExternalMap("RESMAP.PAT", 100), kSourceVolume, "RESSCI.PAT", 100);
+ addSource(new VolumeResourceSource("ressci.pat", addExternalMap("resmap.pat", 100), 100));
}
}
#else
@@ -628,14 +576,22 @@ int ResourceManager::addAppropriateSources() {
#endif
addPatchDir(".");
- if (Common::File::exists("MESSAGE.MAP"))
- addSource(addExternalMap("MESSAGE.MAP"), kSourceVolume, "RESOURCE.MSG", 0);
+
+ if (Common::File::exists("message.map"))
+ addSource(new VolumeResourceSource("resource.msg", addExternalMap("message.map"), 0));
+
+ if (Common::File::exists("altres.map"))
+ addSource(new VolumeResourceSource("altres.000", addExternalMap("altres.map"), 0));
return 1;
}
int ResourceManager::addAppropriateSources(const Common::FSList &fslist) {
ResourceSource *map = 0;
+#ifdef ENABLE_SCI32
+ ResourceSource *sci21PatchMap = 0;
+ const Common::FSNode *sci21PatchRes = 0;
+#endif
// First, find resource.map
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
@@ -645,17 +601,33 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) {
Common::String filename = file->getName();
filename.toLowercase();
- // TODO: Load the SCI2.1+ maps (resmap.*) in concurrence with the volumes to
- // get the proper volume numbers from the maps.
- if (filename.contains("resource.map") || filename.contains("resmap.000")) {
+ if (filename.contains("resource.map"))
map = addExternalMap(file);
- break;
+
+ if (filename.contains("resmap.0")) {
+ const char *dot = strrchr(file->getName().c_str(), '.');
+ int number = atoi(dot + 1);
+ map = addExternalMap(file, number);
}
+
+#ifdef ENABLE_SCI32
+ // SCI2.1 resource patches
+ if (filename.contains("resmap.pat"))
+ sci21PatchMap = addExternalMap(file, 100);
+
+ if (filename.contains("ressci.pat"))
+ sci21PatchRes = file;
+#endif
}
if (!map)
return 0;
+#ifdef ENABLE_SCI32
+ if (sci21PatchMap && sci21PatchRes)
+ addSource(new VolumeResourceSource(sci21PatchRes->getName(), sci21PatchMap, 100, sci21PatchRes));
+#endif
+
// Now find all the resource.0?? files
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (file->isDirectory())
@@ -668,7 +640,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) {
const char *dot = strrchr(filename.c_str(), '.');
int number = atoi(dot + 1);
- addSource(map, kSourceVolume, file, number);
+ addSource(new VolumeResourceSource(file->getName(), map, number, file));
}
}
@@ -683,82 +655,137 @@ int ResourceManager::addInternalSources() {
Common::List<ResourceId>::iterator itr = resources->begin();
while (itr != resources->end()) {
- ResourceSource *src = addSource(NULL, kSourceIntMap, "MAP", itr->number);
+ ResourceSource *src = addSource(new IntMapResourceSource("MAP", itr->getNumber()));
- if ((itr->number == 65535) && Common::File::exists("RESOURCE.SFX"))
- addSource(src, kSourceAudioVolume, "RESOURCE.SFX", 0);
+ if ((itr->getNumber() == 65535) && Common::File::exists("RESOURCE.SFX"))
+ addSource(new AudioVolumeResourceSource(this, "RESOURCE.SFX", src, 0));
else if (Common::File::exists("RESOURCE.AUD"))
- addSource(src, kSourceAudioVolume, "RESOURCE.AUD", 0);
+ addSource(new AudioVolumeResourceSource(this, "RESOURCE.AUD", src, 0));
++itr;
}
+ delete resources;
return 1;
}
-void ResourceManager::addNewGMPatch(const Common::String &gameId) {
- Common::String gmPatchFile;
-
- if (gameId == "ecoquest")
- gmPatchFile = "ECO1GM.PAT";
- else if (gameId == "hoyle3")
- gmPatchFile = "HOY3GM.PAT";
- else if (gameId == "hoyle3")
- gmPatchFile = "HOY3GM.PAT";
- else if (gameId == "lsl1sci")
- gmPatchFile = "LL1_GM.PAT";
- else if (gameId == "lsl5")
- gmPatchFile = "LL5_GM.PAT";
- else if (gameId == "longbow")
- gmPatchFile = "ROBNGM.PAT";
- else if (gameId == "sq1sci")
- gmPatchFile = "SQ1_GM.PAT";
- else if (gameId == "sq4")
- gmPatchFile = "SQ4_GM.PAT";
- else if (gameId == "fairytales")
- gmPatchFile = "TALEGM.PAT";
-
- if (!gmPatchFile.empty() && Common::File::exists(gmPatchFile)) {
- ResourceSource *psrcPatch = new ResourceSource;
- psrcPatch->source_type = kSourcePatch;
- psrcPatch->location_name = gmPatchFile;
- processPatch(psrcPatch, kResourceTypePatch, 4);
- }
-}
-
void ResourceManager::scanNewSources() {
for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) {
ResourceSource *source = *it;
- if (!source->scanned) {
- source->scanned = true;
- switch (source->source_type) {
- case kSourceDirectory:
- readResourcePatches(source);
- readWaveAudioPatches();
- break;
- case kSourceExtMap:
- if (_mapVersion < kResVersionSci1Late)
- readResourceMapSCI0(source);
- else
- readResourceMapSCI1(source);
- break;
- case kSourceExtAudioMap:
- readAudioMapSCI1(source);
- break;
- case kSourceIntMap:
- readAudioMapSCI11(source);
- break;
- case kSourceMacResourceFork:
- readMacResourceFork(source);
- break;
- default:
- break;
- }
+ if (!source->_scanned) {
+ source->_scanned = true;
+ source->scanSource(this);
}
}
}
+void DirectoryResourceSource::scanSource(ResourceManager *resMan) {
+ resMan->readResourcePatches();
+
+ // We can't use getSciVersion() at this point, thus using _volVersion
+ if (resMan->_volVersion >= kResVersionSci11) // SCI1.1+
+ resMan->readResourcePatchesBase36();
+
+ resMan->readWaveAudioPatches();
+}
+
+void ExtMapResourceSource::scanSource(ResourceManager *resMan) {
+ if (resMan->_mapVersion < kResVersionSci1Late)
+ resMan->readResourceMapSCI0(this);
+ else
+ resMan->readResourceMapSCI1(this);
+}
+
+void ExtAudioMapResourceSource::scanSource(ResourceManager *resMan) {
+ resMan->readAudioMapSCI1(this);
+}
+
+void IntMapResourceSource::scanSource(ResourceManager *resMan) {
+ resMan->readAudioMapSCI11(this);
+}
+
+#ifdef ENABLE_SCI32
+
+// Chunk resources are resources that hold other resources. They are normally called
+// when using the kLoadChunk SCI2.1 kernel function. However, for example, the Lighthouse
+// SCI2.1 demo has a chunk but no scripts outside of the chunk.
+
+// A chunk resource is pretty straightforward in terms of layout
+// It begins with 11-byte entries in the header:
+// =========
+// b resType
+// w nEntry
+// dw offset
+// dw length
+
+ChunkResourceSource::ChunkResourceSource(const Common::String &name, uint16 number)
+ : ResourceSource(kSourceChunk, name) {
+
+ _number = 0;
+}
+
+void ChunkResourceSource::scanSource(ResourceManager *resMan) {
+ Resource *chunk = resMan->findResource(ResourceId(kResourceTypeChunk, _number), false);
+
+ if (!chunk)
+ error("Trying to load non-existent chunk");
+
+ byte *ptr = chunk->data;
+ uint32 firstOffset = 0;
+
+ for (;;) {
+ ResourceType type = resMan->convertResType(*ptr);
+ uint16 number = READ_LE_UINT16(ptr + 1);
+ ResourceId id(type, number);
+
+ ResourceEntry entry;
+ entry.offset = READ_LE_UINT32(ptr + 3);
+ entry.length = READ_LE_UINT32(ptr + 7);
+
+ _resMap[id] = entry;
+ ptr += 11;
+
+ debugC(kDebugLevelResMan, 2, "Found %s in chunk %d", id.toString().c_str(), _number);
+
+ resMan->updateResource(id, this, entry.length);
+
+ // There's no end marker to the data table, but the first resource
+ // begins directly after the entry table. So, when we hit the first
+ // resource, we're at the end of the entry table.
+
+ if (!firstOffset)
+ firstOffset = entry.offset;
+
+ if ((size_t)(ptr - chunk->data) >= firstOffset)
+ break;
+ }
+}
+
+void ChunkResourceSource::loadResource(ResourceManager *resMan, Resource *res) {
+ Resource *chunk = resMan->findResource(ResourceId(kResourceTypeChunk, _number), false);
+
+ if (!_resMap.contains(res->_id))
+ error("Trying to load non-existent resource from chunk %d: %s %d", _number, getResourceTypeName(res->_id.getType()), res->_id.getNumber());
+
+ ResourceEntry entry = _resMap[res->_id];
+ res->data = new byte[entry.length];
+ res->size = entry.length;
+ res->_header = 0;
+ res->_headerSize = 0;
+ res->_status = kResStatusAllocated;
+
+ // Copy the resource data over
+ memcpy(res->data, chunk->data + entry.offset, entry.length);
+}
+
+void ResourceManager::addResourcesFromChunk(uint16 id) {
+ addSource(new ChunkResourceSource(Common::String::printf("Chunk %d", id), id));
+ scanNewSources();
+}
+
+#endif
+
void ResourceManager::freeResourceSources() {
for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it)
delete *it;
@@ -767,13 +794,6 @@ void ResourceManager::freeResourceSources() {
}
ResourceManager::ResourceManager() {
- addAppropriateSources();
- init();
-}
-
-ResourceManager::ResourceManager(const Common::FSList &fslist) {
- addAppropriateSources(fslist);
- init();
}
void ResourceManager::init() {
@@ -828,8 +848,23 @@ void ResourceManager::init() {
debugC(1, kDebugLevelResMan, "resMan: Detected Amiga graphic resources");
break;
default:
- warning("resMan: Couldn't determine view type");
+ error("resMan: Couldn't determine view type");
}
+
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2_1) {
+ // If we have no scripts, but chunk 0 is present, open up the chunk
+ // to try to get to any scripts in there. The Lighthouse SCI2.1 demo
+ // does exactly this.
+
+ Common::List<ResourceId> *scriptList = listResources(kResourceTypeScript);
+
+ if (scriptList->empty() && testResource(ResourceId(kResourceTypeChunk, 0)))
+ addResourcesFromChunk(0);
+
+ delete scriptList;
+ }
+#endif
}
ResourceManager::~ResourceManager() {
@@ -907,7 +942,7 @@ Common::List<ResourceId> *ResourceManager::listResources(ResourceType type, int
ResourceMap::iterator itr = _resMap.begin();
while (itr != _resMap.end()) {
- if ((itr->_value->_id.type == type) && ((mapNumber == -1) || (itr->_value->_id.number == mapNumber)))
+ if ((itr->_value->getType() == type) && ((mapNumber == -1) || (itr->_value->getNumber() == mapNumber)))
resources->push_back(itr->_value->_id);
++itr;
}
@@ -925,7 +960,7 @@ Resource *ResourceManager::findResource(ResourceId id, bool lock) {
loadResource(retval);
else if (retval->_status == kResStatusEnqueued)
removeFromLRU(retval);
- // Unless an error occured, the resource is now either
+ // Unless an error occurred, the resource is now either
// locked or allocated, but never queued or freed.
freeOldResources();
@@ -954,7 +989,7 @@ void ResourceManager::unlockResource(Resource *res) {
assert(res);
if (res->_status != kResStatusLocked) {
- warning("[resMan] Attempt to unlock unlocked resource %s", res->_id.toString().c_str());
+ debugC(kDebugLevelResMan, 2, "[resMan] Attempt to unlock unlocked resource %s", res->_id.toString().c_str());
return;
}
@@ -988,26 +1023,25 @@ const char *ResourceManager::versionDescription(ResVersion version) const {
return "Version not valid";
}
-ResourceManager::ResVersion ResourceManager::detectMapVersion() {
+ResVersion ResourceManager::detectMapVersion() {
Common::SeekableReadStream *fileStream = 0;
- Common::File *file = 0;
byte buff[6];
ResourceSource *rsrc= 0;
for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) {
rsrc = *it;
- if (rsrc->source_type == kSourceExtMap) {
- if (rsrc->resourceFile) {
- fileStream = rsrc->resourceFile->createReadStream();
+ if (rsrc->getSourceType() == kSourceExtMap) {
+ if (rsrc->_resourceFile) {
+ fileStream = rsrc->_resourceFile->createReadStream();
} else {
- file = new Common::File();
- file->open(rsrc->location_name);
+ Common::File *file = new Common::File();
+ file->open(rsrc->getLocationName());
if (file->isOpen())
fileStream = file;
}
break;
- } else if (rsrc->source_type == kSourceMacResourceFork)
+ } else if (rsrc->getSourceType() == kSourceMacResourceFork)
return kResVersionSci11Mac;
}
@@ -1022,7 +1056,7 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() {
// check if 0 or 01 - try to read resources in SCI0 format and see if exists
fileStream->seek(0, SEEK_SET);
while (fileStream->read(buff, 6) == 6 && !(buff[0] == 0xFF && buff[1] == 0xFF && buff[2] == 0xFF)) {
- if (getVolume(rsrc, (buff[5] & 0xFC) >> 2) == NULL)
+ if (findVolume(rsrc, (buff[5] & 0xFC) >> 2) == NULL)
return kResVersionSci1Middle;
}
return kResVersionSci0Sci1Early;
@@ -1079,25 +1113,24 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() {
return kResVersionUnknown;
}
-ResourceManager::ResVersion ResourceManager::detectVolVersion() {
+ResVersion ResourceManager::detectVolVersion() {
Common::SeekableReadStream *fileStream = 0;
- Common::File *file = 0;
ResourceSource *rsrc;
for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) {
rsrc = *it;
- if (rsrc->source_type == kSourceVolume) {
- if (rsrc->resourceFile) {
- fileStream = rsrc->resourceFile->createReadStream();
+ if (rsrc->getSourceType() == kSourceVolume) {
+ if (rsrc->_resourceFile) {
+ fileStream = rsrc->_resourceFile->createReadStream();
} else {
- file = new Common::File();
- file->open(rsrc->location_name);
+ Common::File *file = new Common::File();
+ file->open(rsrc->getLocationName());
if (file->isOpen())
fileStream = file;
}
break;
- } else if (rsrc->source_type == kSourceMacResourceFork)
+ } else if (rsrc->getSourceType() == kSourceMacResourceFork)
return kResVersionSci11Mac;
}
@@ -1180,82 +1213,176 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() {
}
// version-agnostic patch application
-void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, int resnumber) {
- Common::File file;
- Resource *newrsc;
- ResourceId resId = ResourceId(restype, resnumber);
- byte patchtype, patch_data_offset;
- int fsize;
-
- if (resnumber == -1)
- return;
- if (!file.open(source->location_name)) {
- warning("ResourceManager::processPatch(): failed to open %s", source->location_name.c_str());
- return;
+void ResourceManager::processPatch(ResourceSource *source, ResourceType resourceType, uint16 resourceNr, uint32 tuple) {
+ Common::SeekableReadStream *fileStream = 0;
+ Resource *newrsc = 0;
+ ResourceId resId = ResourceId(resourceType, resourceNr, tuple);
+ ResourceType checkForType = resourceType;
+
+ // base36 encoded patches (i.e. audio36 and sync36) have the same type as their non-base36 encoded counterparts
+ if (checkForType == kResourceTypeAudio36)
+ checkForType = kResourceTypeAudio;
+ else if (checkForType == kResourceTypeSync36)
+ checkForType = kResourceTypeSync;
+
+ if (source->_resourceFile) {
+ fileStream = source->_resourceFile->createReadStream();
+ } else {
+ Common::File *file = new Common::File();
+ if (!file->open(source->getLocationName())) {
+ warning("ResourceManager::processPatch(): failed to open %s", source->getLocationName().c_str());
+ return;
+ }
+ fileStream = file;
}
- fsize = file.size();
+
+ int fsize = fileStream->size();
if (fsize < 3) {
- debug("Patching %s failed - file too small", source->location_name.c_str());
+ debug("Patching %s failed - file too small", source->getLocationName().c_str());
return;
}
- patchtype = file.readByte() & 0x7F;
- patch_data_offset = file.readByte();
+ byte patchType = convertResType(fileStream->readByte());
+ byte patchDataOffset = fileStream->readByte();
+
+ delete fileStream;
- if (patchtype != restype) {
- debug("Patching %s failed - resource type mismatch", source->location_name.c_str());
+ if (patchType != checkForType) {
+ debug("Patching %s failed - resource type mismatch", source->getLocationName().c_str());
+ return;
}
// Fixes SQ5/German, patch file special case logic taken from SCI View disassembly
- if (patch_data_offset & 0x80) {
- switch (patch_data_offset & 0x7F) {
+ if (patchDataOffset & 0x80) {
+ switch (patchDataOffset & 0x7F) {
case 0:
- patch_data_offset = 24;
+ patchDataOffset = 24;
break;
case 1:
- patch_data_offset = 2;
+ patchDataOffset = 2;
+ break;
+ case 4:
+ patchDataOffset = 8;
break;
default:
- warning("Resource patch unsupported special case %X", patch_data_offset);
+ error("Resource patch unsupported special case %X", patchDataOffset & 0x7F);
+ return;
}
}
- if (patch_data_offset + 2 >= fsize) {
+ if (patchDataOffset + 2 >= fsize) {
debug("Patching %s failed - patch starting at offset %d can't be in file of size %d",
- source->location_name.c_str(), patch_data_offset + 2, fsize);
+ source->getLocationName().c_str(), patchDataOffset + 2, fsize);
return;
}
- // Prepare destination, if neccessary
- if (_resMap.contains(resId) == false) {
- newrsc = new Resource;
- _resMap.setVal(resId, newrsc);
- } else
- newrsc = _resMap.getVal(resId);
+
// Overwrite everything, because we're patching
- newrsc->_id = resId;
- newrsc->_status = kResStatusNoMalloc;
- newrsc->_source = source;
- newrsc->size = fsize - patch_data_offset - 2;
- newrsc->_headerSize = patch_data_offset;
+ newrsc = updateResource(resId, source, fsize - patchDataOffset - 2);
+ newrsc->_headerSize = patchDataOffset;
newrsc->_fileOffset = 0;
- debugC(1, kDebugLevelResMan, "Patching %s - OK", source->location_name.c_str());
+
+
+ debugC(1, kDebugLevelResMan, "Patching %s - OK", source->getLocationName().c_str());
}
+void ResourceManager::readResourcePatchesBase36() {
+ // The base36 encoded audio36 and sync36 resources use a different naming scheme, because they
+ // cannot be described with a single resource number, but are a result of a
+ // <number, noun, verb, cond, seq> tuple. Please don't be confused with the normal audio patches
+ // (*.aud) and normal sync patches (*.syn). audio36 patches can be seen for example in the AUD
+ // folder of GK1CD, and are like this file: @0CS0M00.0X1. GK1CD is the first game where these
+ // have been observed. The actual audio36 and sync36 resources exist in SCI1.1 as well, but the
+ // first game where external patch files for them have been found is GK1CD. The names of these
+ // files are base36 encoded, and we handle their decoding here. audio36 files start with a '@',
+ // whereas sync36 start with a '#'. Mac versions begin with 'A' (probably meaning AIFF). Torin
+ // has several that begin with 'B'.
+
+ Common::String name, inputName;
+ Common::ArchiveMemberList files;
+ ResourceSource *psrcPatch;
+
+ for (int i = kResourceTypeAudio36; i <= kResourceTypeSync36; ++i) {
+ files.clear();
-void ResourceManager::readResourcePatches(ResourceSource *source) {
-// Note: since some SCI1 games(KQ5 floppy, SQ4) might use SCI0 naming scheme for patch files
-// this function tries to read patch file with any supported naming scheme,
-// regardless of s_sciVersion value
+ // audio36 resources start with a @, A, or B
+ // sync36 resources start with a #
+ if (i == kResourceTypeAudio36) {
+ SearchMan.listMatchingMembers(files, "@???????.???");
+ SearchMan.listMatchingMembers(files, "A???????.???");
+ SearchMan.listMatchingMembers(files, "B???????.???");
+ } else
+ SearchMan.listMatchingMembers(files, "#???????.???");
+
+ for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
+ name = (*x)->getName();
+
+ inputName = (*x)->getName();
+ inputName.toUppercase();
+ inputName.deleteChar(0); // delete the first character (type)
+ inputName.deleteChar(7); // delete the dot
+
+ // The base36 encoded resource contains the following:
+ // uint16 resourceId, byte noun, byte verb, byte cond, byte seq
+ uint16 resourceNr = strtol(Common::String(inputName.c_str(), 3).c_str(), 0, 36); // 3 characters
+ uint16 noun = strtol(Common::String(inputName.c_str() + 3, 2).c_str(), 0, 36); // 2 characters
+ uint16 verb = strtol(Common::String(inputName.c_str() + 5, 2).c_str(), 0, 36); // 2 characters
+ uint16 cond = strtol(Common::String(inputName.c_str() + 7, 2).c_str(), 0, 36); // 2 characters
+ uint16 seq = strtol(Common::String(inputName.c_str() + 9, 1).c_str(), 0, 36); // 1 character
+
+ // Check, if we got valid results
+ if ((noun <= 255) && (verb <= 255) && (cond <= 255) && (seq <= 255)) {
+ ResourceId resource36((ResourceType)i, resourceNr, noun, verb, cond, seq);
+
+ /*
+ if (i == kResourceTypeAudio36)
+ debug("audio36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str());
+ else
+ debug("sync36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str());
+ */
+
+ // Make sure that the audio patch is a valid resource
+ if (i == kResourceTypeAudio36) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name);
+ uint32 tag = stream->readUint32BE();
+
+ if (tag == MKID_BE('RIFF') || tag == MKID_BE('FORM')) {
+ delete stream;
+ processWavePatch(resource36, name);
+ continue;
+ }
+
+ // Check for SOL as well
+ tag = (tag << 16) | stream->readUint16BE();
+
+ if (tag != MKID_BE('SOL\0')) {
+ delete stream;
+ continue;
+ }
+
+ delete stream;
+ }
+
+ psrcPatch = new PatchResourceSource(name);
+ processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.getTuple());
+ }
+ }
+ }
+}
+
+void ResourceManager::readResourcePatches() {
+ // Note: since some SCI1 games(KQ5 floppy, SQ4) might use SCI0 naming scheme for patch files
+ // this function tries to read patch file with any supported naming scheme,
+ // regardless of s_sciVersion value
Common::String mask, name;
Common::ArchiveMemberList files;
- int number = -1;
+ uint16 resourceNr = 0;
const char *szResType;
ResourceSource *psrcPatch;
- for (int i = kResourceTypeView; i <= kResourceTypeRobot; ++i) {
- // TODO: add support for audio36 and sync36 files
- if (i == kResourceTypeAudio36 || i == kResourceTypeSync36)
+ for (int i = kResourceTypeView; i < kResourceTypeInvalid; ++i) {
+ // Ignore the types that can't be patched (and Robot/VMD is handled externally for now)
+ if (!s_resourceTypeSuffixes[i] || i == kResourceTypeRobot || i == kResourceTypeVMD)
continue;
files.clear();
@@ -1266,112 +1393,77 @@ void ResourceManager::readResourcePatches(ResourceSource *source) {
SearchMan.listMatchingMembers(files, mask);
// SCI1 and later naming - nnn.typ
mask = "*.";
- mask += resourceTypeSuffixes[i];
+ mask += s_resourceTypeSuffixes[i];
SearchMan.listMatchingMembers(files, mask);
+
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
bool bAdd = false;
name = (*x)->getName();
+
// SCI1 scheme
if (isdigit(name[0])) {
- number = atoi(name.c_str());
- bAdd = true;
+ char *end = 0;
+ resourceNr = strtol(name.c_str(), &end, 10);
+ bAdd = (*end == '.'); // Ensure the next character is the period
} else {
// SCI0 scheme
int resname_len = strlen(szResType);
if (scumm_strnicmp(name.c_str(), szResType, resname_len) == 0
&& !isalpha(name[resname_len + 1])) {
- number = atoi(name.c_str() + resname_len + 1);
+ resourceNr = atoi(name.c_str() + resname_len + 1);
bAdd = true;
}
}
if (bAdd) {
- psrcPatch = new ResourceSource;
- psrcPatch->source_type = kSourcePatch;
- psrcPatch->location_name = name;
- processPatch(psrcPatch, (ResourceType)i, number);
+ psrcPatch = new PatchResourceSource(name);
+ processPatch(psrcPatch, (ResourceType)i, resourceNr);
}
}
}
}
-void ResourceManager::readWaveAudioPatches() {
- // Here we do check for SCI1.1+ so we can patch wav files in as audio resources
- Common::ArchiveMemberList files;
- SearchMan.listMatchingMembers(files, "*.wav");
-
- for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
- Common::String name = (*x)->getName();
-
- if (isdigit(name[0])) {
- int number = atoi(name.c_str());
- ResourceSource *psrcPatch = new ResourceSource;
- psrcPatch->source_type = kSourceWave;
- psrcPatch->location_name = name;
- psrcPatch->volume_number = 0;
- psrcPatch->audioCompressionType = 0;
-
- ResourceId resId = ResourceId(kResourceTypeAudio, number);
-
- Resource *newrsc = NULL;
-
- // Prepare destination, if neccessary
- if (_resMap.contains(resId) == false) {
- newrsc = new Resource;
- _resMap.setVal(resId, newrsc);
- } else
- newrsc = _resMap.getVal(resId);
-
- // Get the size of the file
- Common::SeekableReadStream *stream = (*x)->createReadStream();
- uint32 fileSize = stream->size();
- delete stream;
-
- // Overwrite everything, because we're patching
- newrsc->_id = resId;
- newrsc->_status = kResStatusNoMalloc;
- newrsc->_source = psrcPatch;
- newrsc->size = fileSize;
- newrsc->_headerSize = 0;
- debugC(1, kDebugLevelResMan, "Patching %s - OK", psrcPatch->location_name.c_str());
- }
- }
-}
-
int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
- Common::File file;
- Resource *res;
+ Common::SeekableReadStream *fileStream = 0;
ResourceType type;
uint16 number, id;
uint32 offset;
- if (!file.open(map->location_name))
- return SCI_ERROR_RESMAP_NOT_FOUND;
+ if (map->_resourceFile) {
+ fileStream = map->_resourceFile->createReadStream();
+ if (!fileStream)
+ return SCI_ERROR_RESMAP_NOT_FOUND;
+ } else {
+ Common::File *file = new Common::File();
+ if (!file->open(map->getLocationName()))
+ return SCI_ERROR_RESMAP_NOT_FOUND;
+ fileStream = file;
+ }
- file.seek(0, SEEK_SET);
+ fileStream->seek(0, SEEK_SET);
byte bMask = (_mapVersion == kResVersionSci1Middle) ? 0xF0 : 0xFC;
byte bShift = (_mapVersion == kResVersionSci1Middle) ? 28 : 26;
do {
- id = file.readUint16LE();
- offset = file.readUint32LE();
+ id = fileStream->readUint16LE();
+ offset = fileStream->readUint32LE();
- if (file.eos() || file.err()) {
- warning("Error while reading %s", map->location_name.c_str());
+ if (fileStream->eos() || fileStream->err()) {
+ delete fileStream;
+ warning("Error while reading %s", map->getLocationName().c_str());
return SCI_ERROR_RESMAP_NOT_FOUND;
}
if (offset == 0xFFFFFFFF)
break;
- type = (ResourceType)(id >> 11);
+ type = convertResType(id >> 11);
number = id & 0x7FF;
ResourceId resId = ResourceId(type, number);
// adding a new resource
if (_resMap.contains(resId) == false) {
- res = new Resource;
- res->_source = getVolume(map, offset >> bShift);
- if (!res->_source) {
+ ResourceSource *source = findVolume(map, offset >> bShift);
+ if (!source) {
warning("Could not get volume for resource %d, VolumeID %d", id, offset >> bShift);
if (_mapVersion != _volVersion) {
warning("Retrying with the detected volume version instead");
@@ -1379,22 +1471,31 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
_mapVersion = _volVersion;
bMask = (_mapVersion == kResVersionSci1Middle) ? 0xF0 : 0xFC;
bShift = (_mapVersion == kResVersionSci1Middle) ? 28 : 26;
- res->_source = getVolume(map, offset >> bShift);
+ source = findVolume(map, offset >> bShift);
}
}
- res->_fileOffset = offset & (((~bMask) << 24) | 0xFFFFFF);
- res->_id = resId;
- _resMap.setVal(resId, res);
+
+ addResource(resId, source, offset & (((~bMask) << 24) | 0xFFFFFF));
}
- } while (!file.eos());
+ } while (!fileStream->eos());
+
+ delete fileStream;
return 0;
}
int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
- Common::File file;
- Resource *res;
- if (!file.open(map->location_name))
- return SCI_ERROR_RESMAP_NOT_FOUND;
+ Common::SeekableReadStream *fileStream = 0;
+
+ if (map->_resourceFile) {
+ fileStream = map->_resourceFile->createReadStream();
+ if (!fileStream)
+ return SCI_ERROR_RESMAP_NOT_FOUND;
+ } else {
+ Common::File *file = new Common::File();
+ if (!file->open(map->getLocationName()))
+ return SCI_ERROR_RESMAP_NOT_FOUND;
+ fileStream = file;
+ }
resource_index_t resMap[32];
memset(resMap, 0, sizeof(resource_index_t) * 32);
@@ -1405,8 +1506,8 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
// Read resource type and offsets to resource offsets block from .MAP file
// The last entry has type=0xFF (0x1F) and offset equals to map file length
do {
- type = file.readByte() & 0x1F;
- resMap[type].wOffset = file.readUint16LE();
+ type = fileStream->readByte() & 0x1F;
+ resMap[type].wOffset = fileStream->readUint16LE();
resMap[prevtype].wSize = (resMap[type].wOffset
- resMap[prevtype].wOffset) / nEntrySize;
prevtype = type;
@@ -1417,18 +1518,18 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
for (type = 0; type < 32; type++) {
if (resMap[type].wOffset == 0) // this resource does not exist in map
continue;
- file.seek(resMap[type].wOffset);
+ fileStream->seek(resMap[type].wOffset);
for (int i = 0; i < resMap[type].wSize; i++) {
- uint16 number = file.readUint16LE();
+ uint16 number = fileStream->readUint16LE();
int volume_nr = 0;
if (_mapVersion == kResVersionSci11) {
// offset stored in 3 bytes
- off = file.readUint16LE();
- off |= file.readByte() << 16;
+ off = fileStream->readUint16LE();
+ off |= fileStream->readByte() << 16;
off <<= 1;
} else {
// offset/volume stored in 4 bytes
- off = file.readUint32LE();
+ off = fileStream->readUint32LE();
if (_mapVersion < kResVersionSci11) {
volume_nr = off >> 28; // most significant 4 bits
off &= 0x0FFFFFFF; // least significant 28 bits
@@ -1436,26 +1537,30 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
// in SCI32 it's a plain offset
}
}
- if (file.eos() || file.err()) {
- warning("Error while reading %s", map->location_name.c_str());
+ if (fileStream->eos() || fileStream->err()) {
+ delete fileStream;
+ warning("Error while reading %s", map->getLocationName().c_str());
return SCI_ERROR_RESMAP_NOT_FOUND;
}
- resId = ResourceId((ResourceType)type, number);
+ resId = ResourceId(convertResType(type), number);
// adding new resource only if it does not exist
if (_resMap.contains(resId) == false) {
- res = new Resource;
- _resMap.setVal(resId, res);
- res->_id = resId;
-
// NOTE: We add the map's volume number here to the specified volume number
- // for SCI2.1 and SCI3 maps that are not RESMAP.000. The RESMAP.* files' numbers
+ // for SCI2.1 and SCI3 maps that are not resmap.000. The resmap.* files' numbers
// need to be used in concurrence with the volume specified in the map to get
// the actual resource file.
- res->_source = getVolume(map, volume_nr + map->volume_number);
- res->_fileOffset = off;
+ int mapVolumeNr = volume_nr + map->_volumeNumber;
+ ResourceSource *source = findVolume(map, mapVolumeNr);
+ // FIXME: this code has serious issues with multiple RESMAP.* files (like in unmodified gk2)
+ // adding a resource with source == NULL would crash later on
+ if (!source)
+ error("Unable to find volume for map %s volumeNr %d", map->getLocationName().c_str(), mapVolumeNr);
+ addResource(resId, source, off);
}
}
}
+
+ delete fileStream;
return 0;
}
@@ -1476,7 +1581,11 @@ struct {
{ MKID_BE('PAL '), kResourceTypePalette },
{ MKID_BE('snd '), kResourceTypeAudio },
{ MKID_BE('MSG '), kResourceTypeMessage },
- { MKID_BE('HEP '), kResourceTypeHeap }
+ { MKID_BE('HEP '), kResourceTypeHeap },
+ { MKID_BE('IBIN'), kResourceTypeMacIconBarPictN },
+ { MKID_BE('IBIS'), kResourceTypeMacIconBarPictS },
+ { MKID_BE('PICT'), kResourceTypeMacPict },
+ { MKID_BE('SYN '), kResourceTypeSync }
};
static uint32 resTypeToMacTag(ResourceType type) {
@@ -1487,11 +1596,11 @@ static uint32 resTypeToMacTag(ResourceType type) {
return 0;
}
-int ResourceManager::readMacResourceFork(ResourceSource *source) {
- if (!source->macResMan.open(source->location_name.c_str()))
- error("%s is not a valid Mac resource fork", source->location_name.c_str());
+void MacResourceForkResourceSource::scanSource(ResourceManager *resMan) {
+ if (!_macResMan->open(getLocationName().c_str()))
+ error("%s is not a valid Mac resource fork", getLocationName().c_str());
- Common::MacResTagArray tagArray = source->macResMan.getResTagArray();
+ Common::MacResTagArray tagArray = _macResMan->getResTagArray();
for (uint32 i = 0; i < tagArray.size(); i++) {
ResourceType type = kResourceTypeInvalid;
@@ -1506,306 +1615,59 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) {
if (type == kResourceTypeInvalid)
continue;
- Common::MacResIDArray idArray = source->macResMan.getResIDArray(tagArray[i]);
+ Common::MacResIDArray idArray = _macResMan->getResIDArray(tagArray[i]);
for (uint32 j = 0; j < idArray.size(); j++) {
- ResourceId resId = ResourceId(type, idArray[j]);
-
- Resource *newrsc = NULL;
+ // Get the size of the file
+ Common::SeekableReadStream *stream = _macResMan->getResource(tagArray[i], idArray[j]);
- // Prepare destination, if neccessary. Resource forks may contain patches.
- if (!_resMap.contains(resId)) {
- newrsc = new Resource;
- _resMap.setVal(resId, newrsc);
- } else
- newrsc = _resMap.getVal(resId);
+ // Some IBIS resources have a size of 0, so we skip them
+ if (!stream)
+ continue;
- // Get the size of the file
- Common::SeekableReadStream *stream = source->macResMan.getResource(tagArray[i], idArray[j]);
uint32 fileSize = stream->size();
delete stream;
- // Overwrite everything
- newrsc->_id = resId;
- newrsc->_status = kResStatusNoMalloc;
- newrsc->_source = source;
- newrsc->size = fileSize;
- newrsc->_headerSize = 0;
+ ResourceId resId = ResourceId(type, idArray[j]);
+
+ // Overwrite Resource instance. Resource forks may contain patches.
+ resMan->updateResource(resId, this, fileSize);
}
}
-
- return 0;
}
void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size) {
// Adding new resource only if it does not exist
if (_resMap.contains(resId) == false) {
- Resource *res = new Resource;
+ Resource *res = new Resource(this, resId);
_resMap.setVal(resId, res);
- res->_id = resId;
res->_source = src;
res->_fileOffset = offset;
res->size = size;
}
}
-void ResourceManager::removeAudioResource(ResourceId resId) {
- // Remove resource, unless it was loaded from a patch
- if (_resMap.contains(resId)) {
- Resource *res = _resMap.getVal(resId);
+Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src, uint32 size) {
+ // Update a patched resource, whether it exists or not
+ Resource *res = 0;
- if (res->_source->source_type == kSourceAudioVolume) {
- if (res->_status == kResStatusLocked) {
- warning("Failed to remove resource %s (still in use)", resId.toString().c_str());
- } else {
- if (res->_status == kResStatusEnqueued)
- removeFromLRU(res);
-
- _resMap.erase(resId);
- delete res;
- }
- }
- }
-}
-
-// Early SCI1.1 65535.MAP structure (uses RESOURCE.AUD):
-// =========
-// 6-byte entries:
-// w nEntry
-// dw offset
-
-// Late SCI1.1 65535.MAP structure (uses RESOURCE.SFX):
-// =========
-// 5-byte entries:
-// w nEntry
-// tb offset (cumulative)
-
-// Early SCI1.1 MAP structure:
-// ===============
-// 10-byte entries:
-// b noun
-// b verb
-// b cond
-// b seq
-// dw offset
-// w syncSize + syncAscSize
-
-// Late SCI1.1 MAP structure:
-// ===============
-// Header:
-// dw baseOffset
-// Followed by 7 or 11-byte entries:
-// b noun
-// b verb
-// b cond
-// b seq
-// tb cOffset (cumulative offset)
-// w syncSize (iff seq has bit 7 set)
-// w syncAscSize (iff seq has bit 6 set)
-
-int ResourceManager::readAudioMapSCI11(ResourceSource *map) {
- bool isEarly = true;
- uint32 offset = 0;
- Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->volume_number), false);
-
- if (!mapRes) {
- warning("Failed to open %i.MAP", map->volume_number);
- return SCI_ERROR_RESMAP_NOT_FOUND;
- }
-
- ResourceSource *src = getVolume(map, 0);
-
- if (!src)
- return SCI_ERROR_NO_RESOURCE_FILES_FOUND;
-
- byte *ptr = mapRes->data;
-
- if (map->volume_number == 65535) {
- // Heuristic to detect late SCI1.1 map format
- if ((mapRes->size >= 6) && (ptr[mapRes->size - 6] != 0xff))
- isEarly = false;
-
- while (ptr < mapRes->data + mapRes->size) {
- uint16 n = READ_LE_UINT16(ptr);
- ptr += 2;
-
- if (n == 0xffff)
- break;
-
- if (isEarly) {
- offset = READ_LE_UINT32(ptr);
- ptr += 4;
- } else {
- offset += READ_LE_UINT24(ptr);
- ptr += 3;
- }
-
- addResource(ResourceId(kResourceTypeAudio, n), src, offset);
- }
+ if (_resMap.contains(resId)) {
+ res = _resMap.getVal(resId);
} else {
- // Heuristic to detect late SCI1.1 map format
- if ((mapRes->size >= 11) && (ptr[mapRes->size - 11] == 0xff))
- isEarly = false;
-
- if (!isEarly) {
- offset = READ_LE_UINT32(ptr);
- ptr += 4;
- }
-
- while (ptr < mapRes->data + mapRes->size) {
- uint32 n = READ_BE_UINT32(ptr);
- int syncSize = 0;
- ptr += 4;
-
- if (n == 0xffffffff)
- break;
-
- if (isEarly) {
- offset = READ_LE_UINT32(ptr);
- ptr += 4;
- } else {
- offset += READ_LE_UINT24(ptr);
- ptr += 3;
- }
-
- if (isEarly || (n & 0x80)) {
- syncSize = READ_LE_UINT16(ptr);
- ptr += 2;
-
- if (syncSize > 0)
- addResource(ResourceId(kResourceTypeSync36, map->volume_number, n & 0xffffff3f), src, offset, syncSize);
- }
-
- if (n & 0x40) {
- syncSize += READ_LE_UINT16(ptr);
- ptr += 2;
- }
-
- addResource(ResourceId(kResourceTypeAudio36, map->volume_number, n & 0xffffff3f), src, offset + syncSize);
- }
- }
-
- return 0;
-}
-
-// AUDIOnnn.MAP contains 10-byte entries:
-// Early format:
-// w 5 bits resource type and 11 bits resource number
-// dw 7 bits volume number and 25 bits offset
-// dw size
-// Later format:
-// w nEntry
-// dw offset+volume (as in resource.map)
-// dw size
-// ending with 10 0xFFs
-int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) {
- Common::File file;
-
- if (!file.open(map->location_name))
- return SCI_ERROR_RESMAP_NOT_FOUND;
-
- bool oldFormat = (file.readUint16LE() >> 11) == kResourceTypeAudio;
- file.seek(0);
-
- while (1) {
- uint16 n = file.readUint16LE();
- uint32 offset = file.readUint32LE();
- uint32 size = file.readUint32LE();
-
- if (file.eos() || file.err()) {
- warning("Error while reading %s", map->location_name.c_str());
- return SCI_ERROR_RESMAP_NOT_FOUND;
- }
-
- if (n == 0xffff)
- break;
-
- byte volume_nr;
-
- if (oldFormat) {
- n &= 0x07ff; // Mask out resource type
- volume_nr = offset >> 25; // most significant 7 bits
- offset &= 0x01ffffff; // least significant 25 bits
- } else {
- volume_nr = offset >> 28; // most significant 4 bits
- offset &= 0x0fffffff; // least significant 28 bits
- }
-
- ResourceSource *src = getVolume(map, volume_nr);
-
- if (src) {
- if (unload)
- removeAudioResource(ResourceId(kResourceTypeAudio, n));
- else
- addResource(ResourceId(kResourceTypeAudio, n), src, offset, size);
- } else {
- warning("Failed to find audio volume %i", volume_nr);
- }
- }
-
- return 0;
-}
-
-void ResourceManager::setAudioLanguage(int language) {
- if (_audioMapSCI1) {
- if (_audioMapSCI1->volume_number == language) {
- // This language is already loaded
- return;
- }
-
- // We already have a map loaded, so we unload it first
- readAudioMapSCI1(_audioMapSCI1, true);
-
- // Remove all volumes that use this map from the source list
- Common::List<ResourceSource *>::iterator it = _sources.begin();
- while (it != _sources.end()) {
- ResourceSource *src = *it;
- if (src->associated_map == _audioMapSCI1) {
- it = _sources.erase(it);
- delete src;
- } else {
- ++it;
- }
- }
-
- // Remove the map itself from the source list
- _sources.remove(_audioMapSCI1);
- delete _audioMapSCI1;
-
- _audioMapSCI1 = NULL;
- }
-
- char filename[9];
- snprintf(filename, 9, "AUDIO%03d", language);
-
- Common::String fullname = Common::String(filename) + ".MAP";
- if (!Common::File::exists(fullname)) {
- warning("No audio map found for language %i", language);
- return;
- }
-
- _audioMapSCI1 = addSource(NULL, kSourceExtAudioMap, fullname.c_str(), language);
-
- // Search for audio volumes for this language and add them to the source list
- Common::ArchiveMemberList files;
- SearchMan.listMatchingMembers(files, Common::String(filename) + ".0??");
- for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
- const Common::String name = (*x)->getName();
- const char *dot = strrchr(name.c_str(), '.');
- int number = atoi(dot + 1);
-
- addSource(_audioMapSCI1, kSourceAudioVolume, name.c_str(), number);
+ res = new Resource(this, resId);
+ _resMap.setVal(resId, res);
}
- scanNewSources();
-}
+ res->_status = kResStatusNoMalloc;
+ res->_source = src;
+ res->_headerSize = 0;
+ res->size = size;
-int ResourceManager::getAudioLanguage() const {
- return (_audioMapSCI1 ? _audioMapSCI1->volume_number : 0);
+ return res;
}
-int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream *file,
- uint32&szPacked, ResourceCompression &compression) {
+int Resource::readResourceInfo(ResVersion volVersion, Common::SeekableReadStream *file,
+ uint32 &szPacked, ResourceCompression &compression) {
// SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes
// SCI1 volume format: {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes
// SCI1.1 volume format: {bResType wResNumber wPacked wUnpacked wCompression} = 9 bytes
@@ -1814,25 +1676,25 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream
uint32 wCompression, szUnpacked;
ResourceType type;
- switch (_volVersion) {
+ switch (volVersion) {
case kResVersionSci0Sci1Early:
case kResVersionSci1Middle:
w = file->readUint16LE();
- type = (ResourceType)(w >> 11);
+ type = _resMan->convertResType(w >> 11);
number = w & 0x7FF;
szPacked = file->readUint16LE() - 4;
szUnpacked = file->readUint16LE();
wCompression = file->readUint16LE();
break;
case kResVersionSci1Late:
- type = (ResourceType)(file->readByte() & 0x7F);
+ type = _resMan->convertResType(file->readByte());
number = file->readUint16LE();
szPacked = file->readUint16LE() - 4;
szUnpacked = file->readUint16LE();
wCompression = file->readUint16LE();
break;
case kResVersionSci11:
- type = (ResourceType)(file->readByte() & 0x7F);
+ type = _resMan->convertResType(file->readByte());
number = file->readUint16LE();
szPacked = file->readUint16LE();
szUnpacked = file->readUint16LE();
@@ -1841,15 +1703,15 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream
case kResVersionSci11Mac:
// Doesn't store this data in the resource. Fortunately,
// we already have this data.
- type = res->_id.type;
- number = res->_id.number;
+ type = getType();
+ number = getNumber();
szPacked = file->size();
szUnpacked = file->size();
wCompression = 0;
break;
#ifdef ENABLE_SCI32
case kResVersionSci32:
- type = (ResourceType)(file->readByte() & 0x7F);
+ type = _resMan->convertResType(file->readByte());
number = file->readUint16LE();
szPacked = file->readUint32LE();
szUnpacked = file->readUint32LE();
@@ -1864,8 +1726,8 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream
if ((file->eos() || file->err()))
return SCI_ERROR_IO_ERROR;
- res->_id = ResourceId(type, number);
- res->size = szUnpacked;
+ _id = ResourceId(type, number);
+ size = szUnpacked;
// checking compression method
switch (wCompression) {
@@ -1901,15 +1763,15 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream
return compression == kCompUnknown ? SCI_ERROR_UNKNOWN_COMPRESSION : 0;
}
-int ResourceManager::decompress(Resource *res, Common::SeekableReadStream *file) {
- int error;
+int Resource::decompress(ResVersion volVersion, Common::SeekableReadStream *file) {
+ int errorNum;
uint32 szPacked = 0;
ResourceCompression compression = kCompUnknown;
// fill resource info
- error = readResourceInfo(res, file, szPacked, compression);
- if (error)
- return error;
+ errorNum = readResourceInfo(volVersion, file, szPacked, compression);
+ if (errorNum)
+ return errorNum;
// getting a decompressor
Decompressor *dec = NULL;
@@ -1935,18 +1797,18 @@ int ResourceManager::decompress(Resource *res, Common::SeekableReadStream *file)
break;
#endif
default:
- warning("Resource %s: Compression method %d not supported", res->_id.toString().c_str(), compression);
+ error("Resource %s: Compression method %d not supported", _id.toString().c_str(), compression);
return SCI_ERROR_UNKNOWN_COMPRESSION;
}
- res->data = new byte[res->size];
- res->_status = kResStatusAllocated;
- error = res->data ? dec->unpack(file, res->data, szPacked, res->size) : SCI_ERROR_RESOURCE_TOO_BIG;
- if (error)
- res->unalloc();
+ data = new byte[size];
+ _status = kResStatusAllocated;
+ errorNum = data ? dec->unpack(file, data, szPacked, size) : SCI_ERROR_RESOURCE_TOO_BIG;
+ if (errorNum)
+ unalloc();
delete dec;
- return error;
+ return errorNum;
}
ResourceCompression ResourceManager::getViewCompression() {
@@ -1954,25 +1816,32 @@ ResourceCompression ResourceManager::getViewCompression() {
// Test 10 views to see if any are compressed
for (int i = 0; i < 1000; i++) {
- Common::File *file;
+ Common::SeekableReadStream *fileStream = 0;
Resource *res = testResource(ResourceId(kResourceTypeView, i));
if (!res)
continue;
- if (res->_source->source_type != kSourceVolume)
+ if (res->_source->getSourceType() != kSourceVolume)
continue;
- file = getVolumeFile(res->_source->location_name.c_str());
- if (!file)
+ fileStream = getVolumeFile(res->_source);
+
+ if (!fileStream)
continue;
- file->seek(res->_fileOffset, SEEK_SET);
+ fileStream->seek(res->_fileOffset, SEEK_SET);
uint32 szPacked;
ResourceCompression compression;
- if (readResourceInfo(res, file, szPacked, compression))
+ if (res->readResourceInfo(_volVersion, fileStream, szPacked, compression)) {
+ if (res->_source->_resourceFile)
+ delete fileStream;
continue;
+ }
+
+ if (res->_source->_resourceFile)
+ delete fileStream;
if (compression != kCompNone)
return compression;
@@ -1989,6 +1858,10 @@ ViewType ResourceManager::detectViewType() {
Resource *res = findResource(ResourceId(kResourceTypeView, i), 0);
if (res) {
+ // Skip views coming from patch files
+ if (res->_source->getSourceType() == kSourcePatch)
+ continue;
+
switch (res->data[1]) {
case 128:
// If the 2nd byte is 128, it's a VGA game
@@ -2044,6 +1917,7 @@ ViewType ResourceManager::detectViewType() {
}
}
+ // this may happen if there are serious system issues (or trying to add a broken game)
warning("resMan: Couldn't find any views");
return kViewUnknown;
}
@@ -2129,18 +2003,18 @@ void ResourceManager::detectSciVersion() {
return;
}
+ if (hasSci0Voc999()) {
+ s_sciVersion = SCI_VERSION_0_LATE;
+ return;
+ }
+
if (oldDecompressors) {
// It's either SCI_VERSION_0_LATE or SCI_VERSION_01
// We first check for SCI1 vocab.999
if (testResource(ResourceId(kResourceTypeVocab, 999))) {
- if (hasSci0Voc999()) {
- s_sciVersion = SCI_VERSION_0_LATE;
- return;
- } else {
- s_sciVersion = SCI_VERSION_01;
- return;
- }
+ s_sciVersion = SCI_VERSION_01;
+ return;
}
// If vocab.999 is missing, we try vocab.900
@@ -2154,7 +2028,7 @@ void ResourceManager::detectSciVersion() {
}
}
- warning("Failed to accurately determine SCI version");
+ error("Failed to accurately determine SCI version");
// No parser, we assume SCI_VERSION_01.
s_sciVersion = SCI_VERSION_01;
return;
@@ -2166,8 +2040,7 @@ void ResourceManager::detectSciVersion() {
return;
}
- // SCI_VERSION_1_EARLY EGA versions seem to be lacking a valid vocab.900.
- // If this turns out to be unreliable, we could do some pic resource checks instead.
+ // SCI_VERSION_1_EARLY EGA versions lack the parser vocab
s_sciVersion = SCI_VERSION_1_EARLY;
return;
case kResVersionSci1Middle:
@@ -2203,15 +2076,18 @@ bool ResourceManager::detectHires() {
// SCI32 picture
uint16 width = READ_LE_UINT16(res->data + 10);
uint16 height = READ_LE_UINT16(res->data + 12);
+ // Surely lowres (e.g. QFG4CD)
if ((width == 320) && ((height == 190) || (height == 200)))
return false;
+ // Surely hires
if ((width >= 600) || (height >= 400))
return true;
}
}
}
- warning("resMan: Couldn't detect hires");
+ // We haven't been able to find hires content
+
return false;
#else
error("no sci32 support");
@@ -2231,12 +2107,27 @@ bool ResourceManager::detectFontExtended() {
return false;
}
+// detects, if SCI1.1 game uses palette merging or copying - this is supposed to only get used on SCI1.1 games
+bool ResourceManager::detectForPaletteMergingForSci11() {
+ // Load palette 999 (default palette)
+ Resource *res = findResource(ResourceId(kResourceTypePalette, 999), false);
+
+ if ((res) && (res->size > 30)) {
+ byte *data = res->data;
+ // Old palette format used in palette resource? -> it's merging
+ if ((data[0] == 0 && data[1] == 1) || (data[0] == 0 && data[1] == 0 && READ_LE_UINT16(data + 29) == 0))
+ return true;
+ return false;
+ }
+ return false;
+}
+
// Functions below are based on PD code by Brian Provinciano (SCI Studio)
bool ResourceManager::hasOldScriptHeader() {
Resource *res = findResource(ResourceId(kResourceTypeScript, 0), 0);
if (!res) {
- warning("resMan: Failed to find script.000");
+ error("resMan: Failed to find script.000");
return false;
}
@@ -2329,248 +2220,98 @@ bool ResourceManager::hasSci1Voc900() {
return offset == res->size;
}
-SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) {
- Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true);
- int trackNr, channelNr;
- if (!resource)
- return;
-
- _innerResource = resource;
-
- byte *data, *data2;
- byte *dataEnd;
- Channel *channel, *sampleChannel;
-
- switch (_soundVersion) {
- case SCI_VERSION_0_EARLY:
- case SCI_VERSION_0_LATE:
- // SCI0 only has a header of 0x11/0x21 byte length and the actual midi track follows afterwards
- _trackCount = 1;
- _tracks = new Track[_trackCount];
- _tracks->digitalChannelNr = -1;
- _tracks->type = 0; // Not used for SCI0
- _tracks->channelCount = 1;
- // Digital sample data included? -> Add an additional channel
- if (resource->data[0] == 2)
- _tracks->channelCount++;
- _tracks->channels = new Channel[_tracks->channelCount];
- memset(_tracks->channels, 0, sizeof(Channel) * _tracks->channelCount);
- channel = &_tracks->channels[0];
- if (_soundVersion == SCI_VERSION_0_EARLY) {
- channel->data = resource->data + 0x11;
- channel->size = resource->size - 0x11;
- } else {
- channel->data = resource->data + 0x21;
- channel->size = resource->size - 0x21;
- }
- if (_tracks->channelCount == 2) {
- // Digital sample data included
- _tracks->digitalChannelNr = 1;
- sampleChannel = &_tracks->channels[1];
- // we need to find 0xFC (channel terminator) within the data
- data = channel->data;
- dataEnd = channel->data + channel->size;
- while ((data < dataEnd) && (*data != 0xfc))
- data++;
- // Skip any following 0xFCs as well
- while ((data < dataEnd) && (*data == 0xfc))
- data++;
- // Now adjust channels accordingly
- sampleChannel->data = data;
- sampleChannel->size = channel->size - (data - channel->data);
- channel->size = data - channel->data;
- // Read sample header information
- //Offset 14 in the header contains the frequency as a short integer. Offset 32 contains the sample length, also as a short integer.
- _tracks->digitalSampleRate = READ_LE_UINT16(sampleChannel->data + 14);
- _tracks->digitalSampleSize = READ_LE_UINT16(sampleChannel->data + 32);
- _tracks->digitalSampleStart = 0;
- _tracks->digitalSampleEnd = 0;
- sampleChannel->data += 44; // Skip over header
- sampleChannel->size -= 44;
- }
- break;
-
- case SCI_VERSION_1_EARLY:
- case SCI_VERSION_1_LATE:
- data = resource->data;
- // Count # of tracks
- _trackCount = 0;
- while ((*data++) != 0xFF) {
- _trackCount++;
- while (*data != 0xFF)
- data += 6;
- data++;
- }
- _tracks = new Track[_trackCount];
- data = resource->data;
- for (trackNr = 0; trackNr < _trackCount; trackNr++) {
- // Track info starts with track type:BYTE
- // Then the channel information gets appended Unknown:WORD, ChannelOffset:WORD, ChannelSize:WORD
- // 0xFF:BYTE as terminator to end that track and begin with another track type
- // Track type 0xFF is the marker signifying the end of the tracks
-
- _tracks[trackNr].type = *data++;
- // Counting # of channels used
- data2 = data;
- _tracks[trackNr].channelCount = 0;
- while (*data2 != 0xFF) {
- data2 += 6;
- _tracks[trackNr].channelCount++;
- }
- _tracks[trackNr].channels = new Channel[_tracks[trackNr].channelCount];
- _tracks[trackNr].digitalChannelNr = -1; // No digital sound associated
- _tracks[trackNr].digitalSampleRate = 0;
- _tracks[trackNr].digitalSampleSize = 0;
- _tracks[trackNr].digitalSampleStart = 0;
- _tracks[trackNr].digitalSampleEnd = 0;
- if (_tracks[trackNr].type != 0xF0) { // Digital track marker - not supported currently
- for (channelNr = 0; channelNr < _tracks[trackNr].channelCount; channelNr++) {
- channel = &_tracks[trackNr].channels[channelNr];
- channel->prio = READ_LE_UINT16(data);
- channel->data = resource->data + READ_LE_UINT16(data + 2) + 2;
- channel->size = READ_LE_UINT16(data + 4) - 2; // Not counting channel header
- channel->number = *(channel->data - 2);
- channel->poly = *(channel->data - 1);
- channel->time = channel->prev = 0;
- if (channel->number == 0xFE) { // Digital channel
- _tracks[trackNr].digitalChannelNr = channelNr;
- _tracks[trackNr].digitalSampleRate = READ_LE_UINT16(channel->data);
- _tracks[trackNr].digitalSampleSize = READ_LE_UINT16(channel->data + 2);
- _tracks[trackNr].digitalSampleStart = READ_LE_UINT16(channel->data + 4);
- _tracks[trackNr].digitalSampleEnd = READ_LE_UINT16(channel->data + 6);
- channel->data += 8; // Skip over header
- channel->size -= 8;
- }
- data += 6;
- }
- } else {
- // Skip over digital track
- data += 6;
- }
- data++; // Skipping 0xFF that closes channels list
- }
- break;
-
- default:
- error("SoundResource: SCI version %d is unsupported", _soundVersion);
- }
-}
-
-SoundResource::~SoundResource() {
- for (int trackNr = 0; trackNr < _trackCount; trackNr++)
- delete[] _tracks[trackNr].channels;
- delete[] _tracks;
+// Same function as Script::findBlock(). Slight code
+// duplication here, but this has been done to keep the resource
+// manager independent from the rest of the engine
+static byte *findSci0ExportsBlock(byte *buffer) {
+ byte *buf = buffer;
+ bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
- _resMan->unlockResource(_innerResource);
-}
+ if (oldScriptHeader)
+ buf += 2;
-#if 0
-SoundResource::Track* SoundResource::getTrackByNumber(uint16 number) {
- if (_soundVersion <= SCI_VERSION_0_LATE)
- return &_tracks[0];
+ do {
+ int seekerType = READ_LE_UINT16(buf);
- if (/*number >= 0 &&*/number < _trackCount)
- return &_tracks[number];
- return NULL;
-}
-#endif
+ if (seekerType == 0)
+ break;
+ if (seekerType == 7) // exports
+ return buf;
-SoundResource::Track *SoundResource::getTrackByType(byte type) {
- if (_soundVersion <= SCI_VERSION_0_LATE)
- return &_tracks[0];
+ int seekerSize = READ_LE_UINT16(buf + 2);
+ assert(seekerSize > 0);
+ buf += seekerSize;
+ } while (1);
- for (int trackNr = 0; trackNr < _trackCount; trackNr++) {
- if (_tracks[trackNr].type == type)
- return &_tracks[trackNr];
- }
return NULL;
}
-SoundResource::Track *SoundResource::getDigitalTrack() {
- for (int trackNr = 0; trackNr < _trackCount; trackNr++) {
- if (_tracks[trackNr].digitalChannelNr != -1)
- return &_tracks[trackNr];
- }
- return NULL;
-}
-
-// Gets the filter mask for SCI0 sound resources
-int SoundResource::getChannelFilterMask(int hardwareMask, bool wantsRhythm) {
- byte *data = _innerResource->data;
- int channelMask = 0;
-
- if (_soundVersion > SCI_VERSION_0_LATE)
- return 0;
+reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) {
+ Resource *script = findResource(ResourceId(kResourceTypeScript, 0), false);
- data++; // Skip over digital sample flag
+ if (!script)
+ return NULL_REG;
- for (int channelNr = 0; channelNr < 16; channelNr++) {
- channelMask = channelMask >> 1;
+ byte *offsetPtr = 0;
- byte flags;
+ if (getSciVersion() < SCI_VERSION_1_1) {
+ byte *buf = (getSciVersion() == SCI_VERSION_0_EARLY) ? script->data + 2 : script->data;
- if (_soundVersion == SCI_VERSION_0_EARLY) {
- // Each channel is specified by a single byte
- // Upper 4 bits of the byte is a voices count
- // Lower 4 bits -> bit 0 set: use for AdLib
- // bit 1 set: use for PCjr
- // bit 2 set: use for PC speaker
- // bit 3 set and bit 0 clear: control channel (15)
- // bit 3 set and bit 0 set: rhythm channel (9)
- // Note: control channel is dynamically assigned inside the drivers,
- // but seems to be fixed at 15 in the song data.
- flags = *data++;
-
- // Get device bits
- flags &= 0x7;
+ // Check if the first block is the exports block (in most cases, it is)
+ bool exportsIsFirst = (READ_LE_UINT16(buf + 4) == 7);
+ if (exportsIsFirst) {
+ offsetPtr = buf + 4 + 2;
} else {
- // Each channel is specified by 2 bytes
- // 1st byte is voices count
- // 2nd byte is play mask, which specifies if the channel is supposed to be played
- // by the corresponding hardware
-
- // Skip voice count
- data++;
-
- flags = *data++;
+ offsetPtr = findSci0ExportsBlock(script->data);
+ if (!offsetPtr)
+ error("Unable to find exports block from script 0");
+ offsetPtr += 4 + 2;
}
+ } else {
+ offsetPtr = script->data + 4 + 2 + 2;
+ }
+
+ int16 offset = !isSci11Mac() ? READ_LE_UINT16(offsetPtr) : READ_BE_UINT16(offsetPtr);
- bool play;
- switch (channelNr) {
- case 15:
- // Always play control channel
- play = true;
- break;
- case 9:
- // Play rhythm channel when requested
- play = wantsRhythm;
- break;
- default:
- // Otherwise check for flag
- play = flags & hardwareMask;
- }
+ // In SCI1.1 and newer, the heap is appended at the end of the script,
+ // so adjust the offset accordingly
+ if (getSciVersion() >= SCI_VERSION_1_1 && addSci11ScriptOffset) {
+ offset += script->size;
- if (play) {
- // This Channel is supposed to be played by the hardware
- channelMask |= 0x8000;
- }
+ // Ensure that the start of the heap is word-aligned - same as in Script::init()
+ if (script->size & 2)
+ offset++;
}
- return channelMask;
+ return make_reg(1, offset);
}
-byte SoundResource::getInitialVoiceCount(byte channel) {
- byte *data = _innerResource->data;
+Common::String ResourceManager::findSierraGameId() {
+ // In SCI0-SCI1, the heap is embedded in the script. In SCI1.1+, it's separated
+ Resource *heap = 0;
+ int nameSelector = 3;
- if (_soundVersion > SCI_VERSION_0_LATE)
- return 0; // TODO
+ if (getSciVersion() < SCI_VERSION_1_1) {
+ heap = findResource(ResourceId(kResourceTypeScript, 0), false);
+ } else {
+ heap = findResource(ResourceId(kResourceTypeHeap, 0), false);
+ nameSelector += 5;
+ }
- data++; // Skip over digital sample flag
+ if (!heap)
+ return "";
- if (_soundVersion == SCI_VERSION_0_EARLY)
- return data[channel] >> 4;
- else
- return data[channel * 2];
+ int16 gameObjectOffset = findGameObject(false).offset;
+
+ if (!gameObjectOffset)
+ return "";
+
+ // Seek to the name selector of the first export
+ byte *seeker = heap->data + READ_UINT16(heap->data + gameObjectOffset + nameSelector * 2);
+ Common::String sierraId;
+ sierraId += (const char *)seeker;
+
+ return sierraId;
}
} // End of namespace Sci
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index 48b5f095b1..48210b835f 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -23,21 +23,23 @@
*
*/
-#ifndef SCI_SCICORE_RESOURCE_H
-#define SCI_SCICORE_RESOURCE_H
+#ifndef SCI_RESOURCE_H
+#define SCI_RESOURCE_H
#include "common/str.h"
-#include "common/fs.h"
+#include "common/list.h"
+#include "common/hashmap.h"
#include "sci/graphics/helpers.h" // for ViewType
#include "sci/decompressor.h"
#include "sci/sci.h"
namespace Common {
-class ReadStream;
-class WriteStream;
class File;
+class FSList;
class FSNode;
+class WriteStream;
+class SeekableReadStream;
}
namespace Sci {
@@ -72,18 +74,6 @@ enum {
MAX_OPENED_VOLUMES = 5 ///< Max number of simultaneously opened volumes
};
-enum ResSourceType {
- kSourceDirectory = 0,
- kSourcePatch,
- kSourceVolume,
- kSourceExtMap,
- kSourceIntMap,
- kSourceAudioVolume,
- kSourceExtAudioMap,
- kSourceWave,
- kSourceMacResourceFork
-};
-
enum ResourceType {
kResourceTypeView = 0,
kResourceTypePic,
@@ -105,150 +95,221 @@ enum ResourceType {
kResourceTypeHeap,
kResourceTypeAudio36,
kResourceTypeSync36,
- kResourceTypeUnknown1, // Translation, currently unsupported
- kResourceTypeUnknown2,
+ kResourceTypeTranslation, // Currently unsupported
kResourceTypeRobot,
+ kResourceTypeVMD,
+ kResourceTypeChunk,
+
+ // Mac-only resources
+ kResourceTypeMacIconBarPictN, // IBIN resources (icon bar, not selected)
+ kResourceTypeMacIconBarPictS, // IBIS resources (icon bar, selected)
+ kResourceTypeMacPict, // PICT resources (inventory)
+
kResourceTypeInvalid
};
const char *getResourceTypeName(ResourceType restype);
+enum ResVersion {
+ kResVersionUnknown,
+ kResVersionSci0Sci1Early,
+ kResVersionSci1Middle,
+ kResVersionSci1Late,
+ kResVersionSci11,
+ kResVersionSci11Mac,
+ kResVersionSci32
+};
class ResourceManager;
-struct ResourceSource;
+class ResourceSource;
class ResourceId {
-public:
- ResourceType type;
- uint16 number;
- uint32 tuple; // Only used for audio36 and sync36
+ static inline ResourceType fixupType(ResourceType type) {
+ if (type >= kResourceTypeInvalid)
+ return kResourceTypeInvalid;
+ return type;
+ }
- ResourceId() : type(kResourceTypeInvalid), number(0), tuple(0) { }
+ ResourceType _type;
+ uint16 _number;
+ uint32 _tuple; // Only used for audio36 and sync36
+
+public:
+ ResourceId() : _type(kResourceTypeInvalid), _number(0), _tuple(0) { }
ResourceId(ResourceType type_, uint16 number_, uint32 tuple_ = 0)
- : type(type_), number(number_), tuple(tuple_) {
- if ((type < kResourceTypeView) || (type > kResourceTypeInvalid))
- type = kResourceTypeInvalid;
+ : _type(fixupType(type_)), _number(number_), _tuple(tuple_) {
}
ResourceId(ResourceType type_, uint16 number_, byte noun, byte verb, byte cond, byte seq)
- : type(type_), number(number_) {
- tuple = (noun << 24) | (verb << 16) | (cond << 8) | seq;
-
- if ((type < kResourceTypeView) || (type > kResourceTypeInvalid))
- type = kResourceTypeInvalid;
+ : _type(fixupType(type_)), _number(number_) {
+ _tuple = (noun << 24) | (verb << 16) | (cond << 8) | seq;
}
- Common::String toString() {
+ Common::String toString() const {
char buf[32];
- snprintf(buf, 32, "%s.%i", getResourceTypeName(type), number);
+ snprintf(buf, 32, "%s.%d", getResourceTypeName(_type), _number);
Common::String retStr = buf;
- if (tuple != 0) {
- snprintf(buf, 32, "(%i, %i, %i, %i)", tuple >> 24, (tuple >> 16) & 0xff, (tuple >> 8) & 0xff, tuple & 0xff);
+ if (_tuple != 0) {
+ snprintf(buf, 32, "(%d, %d, %d, %d)", _tuple >> 24, (_tuple >> 16) & 0xff, (_tuple >> 8) & 0xff, _tuple & 0xff);
retStr += buf;
}
return retStr;
}
-};
-struct ResourceIdHash : public Common::UnaryFunction<ResourceId, uint> {
- uint operator()(ResourceId val) const { return ((uint)((val.type << 16) | val.number)) ^ val.tuple; }
-};
+ inline ResourceType getType() const { return _type; }
+ inline uint16 getNumber() const { return _number; }
+ inline uint32 getTuple() const { return _tuple; }
-struct ResourceIdEqualTo : public Common::BinaryFunction<ResourceId, ResourceId, bool> {
- bool operator()(const ResourceId &x, const ResourceId &y) const { return (x.type == y.type) && (x.number == y.number) && (x.tuple == y.tuple); }
-};
+ inline uint hash() const {
+ return ((uint)((_type << 16) | _number)) ^ _tuple;
+ }
+
+ bool operator==(const ResourceId &other) const {
+ return (_type == other._type) && (_number == other._number) && (_tuple == other._tuple);
+ }
-struct ResourceIdLess : public Common::BinaryFunction<ResourceId, ResourceId, bool> {
- bool operator()(const ResourceId &x, const ResourceId &y) const {
- return (x.type < y.type) || ((x.type == y.type) && (x.number < y.number))
- || ((x.type == y.type) && (x.number == y.number) && (x.tuple < y.tuple));
+ bool operator<(const ResourceId &other) const {
+ return (_type < other._type) || ((_type == other._type) && (_number < other._number))
+ || ((_type == other._type) && (_number == other._number) && (_tuple < other._tuple));
}
};
+struct ResourceIdHash : public Common::UnaryFunction<ResourceId, uint> {
+ uint operator()(ResourceId val) const { return val.hash(); }
+};
+
/** Class for storing resources in memory */
class Resource {
friend class ResourceManager;
-public:
- Resource();
- ~Resource();
- void unalloc();
-// NOTE : Currently all member data has the same name and public visibility
-// to let the rest of the engine compile without changes
+ // FIXME: These 'friend' declarations are meant to be a temporary hack to
+ // ease transition to the ResourceSource class system.
+ friend class ResourceSource;
+ friend class PatchResourceSource;
+ friend class WaveResourceSource;
+ friend class AudioVolumeResourceSource;
+ friend class MacResourceForkResourceSource;
+#ifdef ENABLE_SCI32
+ friend class ChunkResourceSource;
+#endif
+
+// NOTE : Currently most member variables lack the underscore prefix and have
+// public visibility to let the rest of the engine compile without changes.
public:
- ResourceId _id;
byte *data;
uint32 size;
byte *_header;
uint32 _headerSize;
+public:
+ Resource(ResourceManager *resMan, ResourceId id);
+ ~Resource();
+ void unalloc();
+
+ inline ResourceType getType() const { return _id.getType(); }
+ inline uint16 getNumber() const { return _id.getNumber(); }
+ bool isLocked() const { return _status == kResStatusLocked; }
+ /**
+ * Write the resource to the specified stream.
+ * This method is used only by the "dump" debugger command.
+ */
void writeToStream(Common::WriteStream *stream) const;
- uint32 getAudioCompressionType();
+
+ // FIXME: This audio specific method is a hack. After all, why should a
+ // Resource have audio specific methods? But for now we keep this, as it
+ // eases transition.
+ uint32 getAudioCompressionType() const;
protected:
+ ResourceId _id; // TODO: _id could almost be made const, only readResourceInfo() modifies it...
int32 _fileOffset; /**< Offset in file */
ResourceStatus _status;
uint16 _lockers; /**< Number of places where this resource was locked */
ResourceSource *_source;
+ ResourceManager *_resMan;
+
+ bool loadPatch(Common::SeekableReadStream *file);
+ bool loadFromPatchFile();
+ bool loadFromWaveFile(Common::SeekableReadStream *file);
+ bool loadFromAudioVolumeSCI1(Common::SeekableReadStream *file);
+ bool loadFromAudioVolumeSCI11(Common::SeekableReadStream *file);
+ int decompress(ResVersion volVersion, Common::SeekableReadStream *file);
+ int readResourceInfo(ResVersion volVersion, Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression);
};
-typedef Common::HashMap<ResourceId, Resource *, ResourceIdHash, ResourceIdEqualTo> ResourceMap;
+typedef Common::HashMap<ResourceId, Resource *, ResourceIdHash> ResourceMap;
class ResourceManager {
-public:
- enum ResVersion {
- kResVersionUnknown,
- kResVersionSci0Sci1Early,
- kResVersionSci1Middle,
- kResVersionSci1Late,
- kResVersionSci11,
- kResVersionSci11Mac,
- kResVersionSci32
- };
+ // FIXME: These 'friend' declarations are meant to be a temporary hack to
+ // ease transition to the ResourceSource class system.
+ friend class ResourceSource;
+ friend class DirectoryResourceSource;
+ friend class PatchResourceSource;
+ friend class ExtMapResourceSource;
+ friend class IntMapResourceSource;
+ friend class AudioVolumeResourceSource;
+ friend class ExtAudioMapResourceSource;
+ friend class WaveResourceSource;
+ friend class MacResourceForkResourceSource;
+#ifdef ENABLE_SCI32
+ friend class ChunkResourceSource;
+#endif
+public:
/**
* Creates a new SCI resource manager.
*/
ResourceManager();
- ResourceManager(const Common::FSList &fslist);
~ResourceManager();
+
+ /**
+ * Initializes the resource manager.
+ */
+ void init();
+
+ int addAppropriateSources();
+ int addAppropriateSources(const Common::FSList &fslist); // TODO: Switch from FSList to Common::Archive?
+
/**
* Looks up a resource's data.
- * @param id: The resource type to look for
- * @param lock: non-zero iff the resource should be locked
- * @return (Resource *): The resource, or NULL if it doesn't exist
+ * @param id The resource type to look for
+ * @param lock non-zero iff the resource should be locked
+ * @return The resource, or NULL if it doesn't exist
* @note Locked resources are guaranteed not to have their contents freed until
* they are unlocked explicitly (by unlockResource).
*/
Resource *findResource(ResourceId id, bool lock);
- /* Unlocks a previously locked resource
- ** (Resource *) res: The resource to free
- ** Returns : ()
- */
+ /**
+ * Unlocks a previously locked resource.
+ * @param res The resource to free
+ */
void unlockResource(Resource *res);
- /* Tests whether a resource exists
- ** (ResourceId) id: Id of the resource to check
- ** Returns : (Resource *) non-NULL if the resource exists, NULL otherwise
- ** This function may often be much faster than finding the resource
- ** and should be preferred for simple tests.
- ** The resource object returned is, indeed, the resource in question, but
- ** it should be used with care, as it may be unallocated.
- ** Use scir_find_resource() if you want to use the data contained in the resource.
- */
+ /**
+ * Tests whether a resource exists.
+ *
+ * This function may often be much faster than finding the resource
+ * and should be preferred for simple tests.
+ * The resource object returned is, indeed, the resource in question, but
+ * it should be used with care, as it may be unallocated.
+ * Use scir_find_resource() if you want to use the data contained in the resource.
+ *
+ * @param id Id of the resource to check
+ * @return non-NULL if the resource exists, NULL otherwise
+ */
Resource *testResource(ResourceId id);
/**
* Returns a list of all resources of the specified type.
- * @param type: The resource type to look for
- * @param mapNumber: For audio36 and sync36, limit search to this map
- * @return: The resource list
+ * @param type The resource type to look for
+ * @param mapNumber For audio36 and sync36, limit search to this map
+ * @return The resource list
*/
Common::List<ResourceId> *listResources(ResourceType type, int mapNumber = -1);
@@ -260,18 +321,49 @@ public:
ViewType getViewType() const { return _viewType; }
const char *getMapVersionDesc() const { return versionDescription(_mapVersion); }
const char *getVolVersionDesc() const { return versionDescription(_volVersion); }
+ ResVersion getVolVersion() const { return _volVersion; }
/**
* Adds the appropriate GM patch from the Sierra MIDI utility as 4.pat, without
* requiring the user to rename the file to 4.pat. Thus, the original Sierra
* archive can be extracted in the extras directory, and the GM patches can be
- * applied per game, if applicable
+ * applied per game, if applicable.
*/
- void addNewGMPatch(const Common::String &gameId);
+ void addNewGMPatch(SciGameId gameId);
+
+#ifdef ENABLE_SCI32
+ /**
+ * Parses all resources from a SCI2.1 chunk resource and adds them to the
+ * resource manager.
+ */
+ void addResourcesFromChunk(uint16 id);
+#endif
bool detectHires();
// Detects, if standard font of current game includes extended characters (>0x80)
bool detectFontExtended();
+ // Detects, if SCI1.1 game uses palette merging
+ bool detectForPaletteMergingForSci11();
+
+ /**
+ * Finds the internal Sierra ID of the current game from script 0.
+ */
+ Common::String findSierraGameId();
+
+ /**
+ * Finds the location of the game object from script 0.
+ * @param addSci11ScriptOffset Adjust the return value for SCI1.1 and newer
+ * games. Needs to be false when the heap is accessed directly inside
+ * findSierraGameId().
+ */
+ reg_t findGameObject(bool addSci11ScriptOffset = true);
+
+ /**
+ * Converts a map resource type to our type
+ * @param sciType The type from the map/patch
+ * @return The ResourceType
+ */
+ ResourceType convertResType(byte type);
protected:
// Maximum number of bytes to allow being allocated for resources
@@ -290,89 +382,58 @@ protected:
ResourceMap _resMap;
Common::List<Common::File *> _volumeFiles; ///< list of opened volume files
ResourceSource *_audioMapSCI1; ///< Currently loaded audio map for SCI1
- ResVersion _volVersion; ///< RESOURCE.0xx version
- ResVersion _mapVersion; ///< RESOURCE.MAP version
-
- /**
- * Initializes the resource manager
- */
- void init();
+ ResVersion _volVersion; ///< resource.0xx version
+ ResVersion _mapVersion; ///< resource.map version
/**
* Add a path to the resource manager's list of sources.
* @return a pointer to the added source structure, or NULL if an error occurred.
*/
- ResourceSource *addPatchDir(const char *path);
+ ResourceSource *addPatchDir(const Common::String &path);
- ResourceSource *getVolume(ResourceSource *map, int volume_nr);
+ ResourceSource *findVolume(ResourceSource *map, int volume_nr);
/**
* Adds a source to the resource manager's list of sources.
- * @param map The map associated with this source
- * @param type The source type
- * @param filename The name of the source to add
- * @return A pointer to the added source structure, or NULL if an error occurred.
+ * @param source The new source to add
+ * @return A pointer to the added source structure, or NULL if an error occurred.
*/
- ResourceSource *addSource(ResourceSource *map, ResSourceType type, const char *filename,
- int number);
-
- ResourceSource *addSource(ResourceSource *map, ResSourceType type,
- const Common::FSNode *resFile, int number);
+ ResourceSource *addSource(ResourceSource *source);
/**
- * Add an external (i.e., separate file) map resource to the resource manager's list of sources.
- * @param file_name The name of the volume to add
+ * Add an external (i.e., separate file) map resource to the resource
+ * manager's list of sources.
+ * @param filename The name of the volume to add
* @param volume_nr The volume number the map starts at, 0 for <SCI2.1
* @return A pointer to the added source structure, or NULL if an error occurred.
*/
- ResourceSource *addExternalMap(const char *file_name, int volume_nr = 0);
-
- ResourceSource *addExternalMap(const Common::FSNode *mapFile);
-
- /**
- * Add an internal (i.e., resource) map to the resource manager's list of sources.
- * @param name The name of the resource to add
- * @param resNr The map resource number
- * @return A pointer to the added source structure, or NULL if an error occurred.
- */
- ResourceSource *addInternalMap(const char *name, int resNr);
+ ResourceSource *addExternalMap(const Common::String &filename, int volume_nr = 0);
- /**
- * Checks, if an audio volume got compressed by our tool. If that's the case, it will set audioCompressionType
- * and read in the offset translation table for later usage.
- */
- void checkIfAudioVolumeIsCompressed(ResourceSource *source);
+ ResourceSource *addExternalMap(const Common::FSNode *mapFile, int volume_nr = 0);
/**
* Scans newly registered resource sources for resources, earliest addition first.
- * @param detected_version: Pointer to the detected version number,
+ * @param detected_version Pointer to the detected version number,
* used during startup. May be NULL.
* @return One of SCI_ERROR_*.
*/
void scanNewSources();
- int addAppropriateSources();
- int addAppropriateSources(const Common::FSList &fslist);
+
int addInternalSources();
void freeResourceSources();
/**
- * Returns a string describing a ResVersion
- * @param version: The resource version
- * @return: The description of version
+ * Returns a string describing a ResVersion.
+ * @param version The resource version
+ * @return The description of version
*/
const char *versionDescription(ResVersion version) const;
- Common::File *getVolumeFile(const char *filename);
+ Common::SeekableReadStream *getVolumeFile(ResourceSource *source);
void loadResource(Resource *res);
- bool loadPatch(Resource *res, Common::File &file);
- bool loadFromPatchFile(Resource *res);
- bool loadFromWaveFile(Resource *res, Common::File &file);
- bool loadFromAudioVolumeSCI1(Resource *res, Common::File &file);
- bool loadFromAudioVolumeSCI11(Resource *res, Common::File &file);
void freeOldResources();
- int decompress(Resource *res, Common::SeekableReadStream *file);
- int readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32&szPacked, ResourceCompression &compression);
void addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size = 0);
+ Resource *updateResource(ResourceId resId, ResourceSource *src, uint32 size);
void removeAudioResource(ResourceId resId);
/**--- Resource map decoding functions ---*/
@@ -392,23 +453,16 @@ protected:
* @return 0 on success, an SCI_ERROR_* code otherwise
*/
int readResourceMapSCI1(ResourceSource *map);
-
- /**
- * Reads the SCI1.1+ resource file from a Mac resource fork.
- * @param source The source
- * @return 0 on success, an SCI_ERROR_* code otherwise
- */
- int readMacResourceFork(ResourceSource *source);
/**
- * Reads SCI1.1 audio map resources
+ * Reads SCI1.1 audio map resources.
* @param map The map
* @return 0 on success, an SCI_ERROR_* code otherwise
*/
int readAudioMapSCI11(ResourceSource *map);
/**
- * Reads SCI1 audio map files
+ * Reads SCI1 audio map files.
* @param map The map
* @param unload Unload the map instead of loading it
* @return 0 on success, an SCI_ERROR_* code otherwise
@@ -420,13 +474,15 @@ protected:
/**
* Reads patch files from a local directory.
*/
- void readResourcePatches(ResourceSource *source);
- void processPatch(ResourceSource *source, ResourceType restype, int resnumber);
+ void readResourcePatches();
+ void readResourcePatchesBase36();
+ void processPatch(ResourceSource *source, ResourceType resourceType, uint16 resourceNr, uint32 tuple = 0);
/**
- * Process wave files as patches for Audio resources
+ * Process wave files as patches for Audio resources.
*/
void readWaveAudioPatches();
+ void processWavePatch(ResourceId resourceId, Common::String name);
/**
* Applies to all versions before 0.000.395 (i.e. KQ4 old, XMAS 1988 and LSL2).
@@ -457,6 +513,7 @@ public:
uint16 prio;
uint16 size;
byte *data;
+ uint16 curPos;
long time;
byte prev;
};
@@ -492,4 +549,4 @@ private:
} // End of namespace Sci
-#endif // SCI_SCICORE_RESOURCE_H
+#endif // SCI_RESOURCE_H
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
new file mode 100644
index 0000000000..a25505fe47
--- /dev/null
+++ b/engines/sci/resource_audio.cpp
@@ -0,0 +1,783 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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$
+ *
+ */
+
+// Resource library
+
+#include "common/archive.h"
+#include "common/file.h"
+
+#include "sci/resource.h"
+#include "sci/resource_intern.h"
+#include "sci/util.h"
+
+namespace Sci {
+
+AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, const Common::String &name, ResourceSource *map, int volNum)
+ : VolumeResourceSource(name, map, volNum, kSourceAudioVolume) {
+
+ _audioCompressionType = 0;
+ _audioCompressionOffsetMapping = NULL;
+
+ /*
+ * Check if this audio volume got compressed by our tool. If that is the
+ * case, set _audioCompressionType and read in the offset translation
+ * table for later usage.
+ */
+
+ Common::SeekableReadStream *fileStream = getVolumeFile(resMan, 0);
+ if (!fileStream)
+ return;
+
+ fileStream->seek(0, SEEK_SET);
+ uint32 compressionType = fileStream->readUint32BE();
+ switch (compressionType) {
+ case MKID_BE('MP3 '):
+ case MKID_BE('OGG '):
+ case MKID_BE('FLAC'):
+ // Detected a compressed audio volume
+ _audioCompressionType = compressionType;
+ // Now read the whole offset mapping table for later usage
+ int32 recordCount = fileStream->readUint32LE();
+ if (!recordCount)
+ error("compressed audio volume doesn't contain any entries!");
+ int32 *offsetMapping = new int32[(recordCount + 1) * 2];
+ _audioCompressionOffsetMapping = offsetMapping;
+ for (int recordNo = 0; recordNo < recordCount; recordNo++) {
+ *offsetMapping++ = fileStream->readUint32LE();
+ *offsetMapping++ = fileStream->readUint32LE();
+ }
+ // Put ending zero
+ *offsetMapping++ = 0;
+ *offsetMapping++ = fileStream->size();
+ }
+
+ if (_resourceFile)
+ delete fileStream;
+}
+
+bool Resource::loadFromWaveFile(Common::SeekableReadStream *file) {
+ data = new byte[size];
+
+ uint32 really_read = file->read(data, size);
+ if (really_read != size)
+ error("Read %d bytes from %s but expected %d", really_read, _id.toString().c_str(), size);
+
+ _status = kResStatusAllocated;
+ return true;
+}
+
+bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) {
+ // Check for WAVE files here
+ uint32 riffTag = file->readUint32BE();
+ if (riffTag == MKID_BE('RIFF')) {
+ _headerSize = 0;
+ size = file->readUint32LE() + 8;
+ file->seek(-8, SEEK_CUR);
+ return loadFromWaveFile(file);
+ }
+ file->seek(-4, SEEK_CUR);
+
+ ResourceType type = _resMan->convertResType(file->readByte());
+ if (((getType() == kResourceTypeAudio || getType() == kResourceTypeAudio36) && (type != kResourceTypeAudio))
+ || ((getType() == kResourceTypeSync || getType() == kResourceTypeSync36) && (type != kResourceTypeSync))) {
+ warning("Resource type mismatch loading %s", _id.toString().c_str());
+ unalloc();
+ return false;
+ }
+
+ _headerSize = file->readByte();
+
+ if (type == kResourceTypeAudio) {
+ if (_headerSize != 7 && _headerSize != 11 && _headerSize != 12) {
+ warning("Unsupported audio header");
+ unalloc();
+ return false;
+ }
+
+ if (_headerSize != 7) { // Size is defined already from the map
+ // Load sample size
+ file->seek(7, SEEK_CUR);
+ size = file->readUint32LE();
+ // Adjust offset to point at the header data again
+ file->seek(-11, SEEK_CUR);
+ }
+ }
+
+ return loadPatch(file);
+}
+
+bool Resource::loadFromAudioVolumeSCI1(Common::SeekableReadStream *file) {
+ data = new byte[size];
+
+ if (data == NULL) {
+ error("Can't allocate %d bytes needed for loading %s", size, _id.toString().c_str());
+ }
+
+ unsigned int really_read = file->read(data, size);
+ if (really_read != size)
+ warning("Read %d bytes from %s but expected %d", really_read, _id.toString().c_str(), size);
+
+ _status = kResStatusAllocated;
+ return true;
+}
+
+void ResourceManager::addNewGMPatch(SciGameId gameId) {
+ Common::String gmPatchFile;
+
+ switch (gameId) {
+ case GID_ECOQUEST:
+ gmPatchFile = "ECO1GM.PAT";
+ break;
+ case GID_HOYLE3:
+ gmPatchFile = "HOY3GM.PAT";
+ break;
+ case GID_LSL1:
+ gmPatchFile = "LL1_GM.PAT";
+ break;
+ case GID_LSL5:
+ gmPatchFile = "LL5_GM.PAT";
+ break;
+ case GID_LONGBOW:
+ gmPatchFile = "ROBNGM.PAT";
+ break;
+ case GID_SQ1:
+ gmPatchFile = "SQ1_GM.PAT";
+ break;
+ case GID_SQ4:
+ gmPatchFile = "SQ4_GM.PAT";
+ break;
+ case GID_FAIRYTALES:
+ gmPatchFile = "TALEGM.PAT";
+ break;
+ default:
+ break;
+ }
+
+ if (!gmPatchFile.empty() && Common::File::exists(gmPatchFile)) {
+ ResourceSource *psrcPatch = new PatchResourceSource(gmPatchFile);
+ processPatch(psrcPatch, kResourceTypePatch, 4);
+ }
+}
+
+void ResourceManager::processWavePatch(ResourceId resourceId, Common::String name) {
+ ResourceSource *resSrc = new WaveResourceSource(name);
+ Common::File file;
+ file.open(name);
+
+ updateResource(resourceId, resSrc, file.size());
+
+ debugC(1, kDebugLevelResMan, "Patching %s - OK", name.c_str());
+}
+
+void ResourceManager::readWaveAudioPatches() {
+ // Here we do check for SCI1.1+ so we can patch wav files in as audio resources
+ Common::ArchiveMemberList files;
+ SearchMan.listMatchingMembers(files, "*.wav");
+
+ for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
+ Common::String name = (*x)->getName();
+
+ if (isdigit(name[0]))
+ processWavePatch(ResourceId(kResourceTypeAudio, atoi(name.c_str())), name);
+ }
+}
+
+void ResourceManager::removeAudioResource(ResourceId resId) {
+ // Remove resource, unless it was loaded from a patch
+ if (_resMap.contains(resId)) {
+ Resource *res = _resMap.getVal(resId);
+
+ if (res->_source->getSourceType() == kSourceAudioVolume) {
+ if (res->_status == kResStatusLocked) {
+ warning("Failed to remove resource %s (still in use)", resId.toString().c_str());
+ } else {
+ if (res->_status == kResStatusEnqueued)
+ removeFromLRU(res);
+
+ _resMap.erase(resId);
+ delete res;
+ }
+ }
+ }
+}
+
+// Early SCI1.1 65535.MAP structure (uses RESOURCE.AUD):
+// =========
+// 6-byte entries:
+// w nEntry
+// dw offset
+
+// Late SCI1.1 65535.MAP structure (uses RESOURCE.SFX):
+// =========
+// 5-byte entries:
+// w nEntry
+// tb offset (cumulative)
+
+// QFG3 Demo 0.MAP structure:
+// =========
+// 10-byte entries:
+// w nEntry
+// dw offset
+// dw size
+
+// LB2 Floppy/Mother Goose SCI1.1 0.MAP structure:
+// =========
+// 8-byte entries:
+// w nEntry
+// w 0xffff
+// dw offset
+
+// Early SCI1.1 MAP structure:
+// ===============
+// 10-byte entries:
+// b noun
+// b verb
+// b cond
+// b seq
+// dw offset
+// w syncSize + syncAscSize
+
+// Late SCI1.1 MAP structure:
+// ===============
+// Header:
+// dw baseOffset
+// Followed by 7 or 11-byte entries:
+// b noun
+// b verb
+// b cond
+// b seq
+// tb cOffset (cumulative offset)
+// w syncSize (iff seq has bit 7 set)
+// w syncAscSize (iff seq has bit 6 set)
+
+int ResourceManager::readAudioMapSCI11(ResourceSource *map) {
+ uint32 offset = 0;
+ Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->_volumeNumber), false);
+
+ if (!mapRes) {
+ warning("Failed to open %i.MAP", map->_volumeNumber);
+ return SCI_ERROR_RESMAP_NOT_FOUND;
+ }
+
+ ResourceSource *src = findVolume(map, 0);
+
+ if (!src)
+ return SCI_ERROR_NO_RESOURCE_FILES_FOUND;
+
+ byte *ptr = mapRes->data;
+
+ // Heuristic to detect entry size
+ uint32 entrySize = 0;
+ for (int i = mapRes->size - 1; i >= 0; --i) {
+ if (ptr[i] == 0xff)
+ entrySize++;
+ else
+ break;
+ }
+
+ if (map->_volumeNumber == 65535) {
+ while (ptr < mapRes->data + mapRes->size) {
+ uint16 n = READ_LE_UINT16(ptr);
+ ptr += 2;
+
+ if (n == 0xffff)
+ break;
+
+ if (entrySize == 6) {
+ offset = READ_LE_UINT32(ptr);
+ ptr += 4;
+ } else {
+ offset += READ_LE_UINT24(ptr);
+ ptr += 3;
+ }
+
+ addResource(ResourceId(kResourceTypeAudio, n), src, offset);
+ }
+ } else if (map->_volumeNumber == 0 && entrySize == 10 && ptr[3] == 0) {
+ // QFG3 demo format
+ // ptr[3] would be 'seq' in the normal format and cannot possibly be 0
+ while (ptr < mapRes->data + mapRes->size) {
+ uint16 n = READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ if (n == 0xffff)
+ break;
+
+ offset = READ_LE_UINT32(ptr);
+ ptr += 4;
+ uint32 size = READ_LE_UINT32(ptr);
+ ptr += 4;
+
+ addResource(ResourceId(kResourceTypeAudio, n), src, offset, size);
+ }
+ } else if (map->_volumeNumber == 0 && entrySize == 8 && READ_LE_UINT16(ptr + 2) == 0xffff) {
+ // LB2 Floppy/Mother Goose SCI1.1 format
+ Common::SeekableReadStream *stream = getVolumeFile(src);
+
+ while (ptr < mapRes->data + mapRes->size) {
+ uint16 n = READ_LE_UINT16(ptr);
+ ptr += 4;
+
+ if (n == 0xffff)
+ break;
+
+ offset = READ_LE_UINT32(ptr);
+ ptr += 4;
+
+ // The size is not stored in the map and the entries have no order.
+ // We need to dig into the audio resource in the volume to get the size.
+ stream->seek(offset + 1);
+ byte headerSize = stream->readByte();
+ assert(headerSize == 11 || headerSize == 12);
+
+ stream->skip(5);
+ uint32 size = stream->readUint32LE() + headerSize + 2;
+
+ addResource(ResourceId(kResourceTypeAudio, n), src, offset, size);
+ }
+ } else {
+ bool isEarly = (entrySize != 11);
+
+ if (!isEarly) {
+ offset = READ_LE_UINT32(ptr);
+ ptr += 4;
+ }
+
+ while (ptr < mapRes->data + mapRes->size) {
+ uint32 n = READ_BE_UINT32(ptr);
+ int syncSize = 0;
+ ptr += 4;
+
+ if (n == 0xffffffff)
+ break;
+
+ if (isEarly) {
+ offset = READ_LE_UINT32(ptr);
+ ptr += 4;
+ } else {
+ offset += READ_LE_UINT24(ptr);
+ ptr += 3;
+ }
+
+ if (isEarly || (n & 0x80)) {
+ syncSize = READ_LE_UINT16(ptr);
+ ptr += 2;
+
+ if (syncSize > 0)
+ addResource(ResourceId(kResourceTypeSync36, map->_volumeNumber, n & 0xffffff3f), src, offset, syncSize);
+ }
+
+ if (n & 0x40) {
+ // This seems to define the size of raw lipsync data (at least
+ // in kq6), may also just be general appended data.
+ syncSize += READ_LE_UINT16(ptr);
+ ptr += 2;
+ }
+
+ addResource(ResourceId(kResourceTypeAudio36, map->_volumeNumber, n & 0xffffff3f), src, offset + syncSize);
+ }
+ }
+
+ return 0;
+}
+
+// AUDIOnnn.MAP contains 10-byte entries:
+// Early format:
+// w 5 bits resource type and 11 bits resource number
+// dw 7 bits volume number and 25 bits offset
+// dw size
+// Later format:
+// w nEntry
+// dw offset+volume (as in resource.map)
+// dw size
+// ending with 10 0xFFs
+int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) {
+ Common::File file;
+
+ if (!file.open(map->getLocationName()))
+ return SCI_ERROR_RESMAP_NOT_FOUND;
+
+ bool oldFormat = (file.readUint16LE() >> 11) == kResourceTypeAudio;
+ file.seek(0);
+
+ while (1) {
+ uint16 n = file.readUint16LE();
+ uint32 offset = file.readUint32LE();
+ uint32 size = file.readUint32LE();
+
+ if (file.eos() || file.err()) {
+ warning("Error while reading %s", map->getLocationName().c_str());
+ return SCI_ERROR_RESMAP_NOT_FOUND;
+ }
+
+ if (n == 0xffff)
+ break;
+
+ byte volume_nr;
+
+ if (oldFormat) {
+ n &= 0x07ff; // Mask out resource type
+ volume_nr = offset >> 25; // most significant 7 bits
+ offset &= 0x01ffffff; // least significant 25 bits
+ } else {
+ volume_nr = offset >> 28; // most significant 4 bits
+ offset &= 0x0fffffff; // least significant 28 bits
+ }
+
+ ResourceSource *src = findVolume(map, volume_nr);
+
+ if (src) {
+ if (unload)
+ removeAudioResource(ResourceId(kResourceTypeAudio, n));
+ else
+ addResource(ResourceId(kResourceTypeAudio, n), src, offset, size);
+ } else {
+ warning("Failed to find audio volume %i", volume_nr);
+ }
+ }
+
+ return 0;
+}
+
+void ResourceManager::setAudioLanguage(int language) {
+ if (_audioMapSCI1) {
+ if (_audioMapSCI1->_volumeNumber == language) {
+ // This language is already loaded
+ return;
+ }
+
+ // We already have a map loaded, so we unload it first
+ readAudioMapSCI1(_audioMapSCI1, true);
+
+ // Remove all volumes that use this map from the source list
+ Common::List<ResourceSource *>::iterator it = _sources.begin();
+ while (it != _sources.end()) {
+ ResourceSource *src = *it;
+ if (src->findVolume(_audioMapSCI1, src->_volumeNumber)) {
+ it = _sources.erase(it);
+ delete src;
+ } else {
+ ++it;
+ }
+ }
+
+ // Remove the map itself from the source list
+ _sources.remove(_audioMapSCI1);
+ delete _audioMapSCI1;
+
+ _audioMapSCI1 = NULL;
+ }
+
+ char filename[9];
+ snprintf(filename, 9, "AUDIO%03d", language);
+
+ Common::String fullname = Common::String(filename) + ".MAP";
+ if (!Common::File::exists(fullname)) {
+ warning("No audio map found for language %i", language);
+ return;
+ }
+
+ _audioMapSCI1 = addSource(new ExtAudioMapResourceSource(fullname, language));
+
+ // Search for audio volumes for this language and add them to the source list
+ Common::ArchiveMemberList files;
+ SearchMan.listMatchingMembers(files, Common::String(filename) + ".0??");
+ for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
+ const Common::String name = (*x)->getName();
+ const char *dot = strrchr(name.c_str(), '.');
+ int number = atoi(dot + 1);
+
+ addSource(new AudioVolumeResourceSource(this, name, _audioMapSCI1, number));
+ }
+
+ scanNewSources();
+}
+
+int ResourceManager::getAudioLanguage() const {
+ return (_audioMapSCI1 ? _audioMapSCI1->_volumeNumber : 0);
+}
+
+SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) {
+ Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resourceNr), true);
+ int trackNr, channelNr;
+ if (!resource)
+ return;
+
+ _innerResource = resource;
+
+ byte *data, *data2;
+ byte *dataEnd;
+ Channel *channel, *sampleChannel;
+
+ switch (_soundVersion) {
+ case SCI_VERSION_0_EARLY:
+ case SCI_VERSION_0_LATE:
+ // SCI0 only has a header of 0x11/0x21 byte length and the actual midi track follows afterwards
+ _trackCount = 1;
+ _tracks = new Track[_trackCount];
+ _tracks->digitalChannelNr = -1;
+ _tracks->type = 0; // Not used for SCI0
+ _tracks->channelCount = 1;
+ // Digital sample data included? -> Add an additional channel
+ if (resource->data[0] == 2)
+ _tracks->channelCount++;
+ _tracks->channels = new Channel[_tracks->channelCount];
+ memset(_tracks->channels, 0, sizeof(Channel) * _tracks->channelCount);
+ channel = &_tracks->channels[0];
+ if (_soundVersion == SCI_VERSION_0_EARLY) {
+ channel->data = resource->data + 0x11;
+ channel->size = resource->size - 0x11;
+ } else {
+ channel->data = resource->data + 0x21;
+ channel->size = resource->size - 0x21;
+ }
+ if (_tracks->channelCount == 2) {
+ // Digital sample data included
+ _tracks->digitalChannelNr = 1;
+ sampleChannel = &_tracks->channels[1];
+ // we need to find 0xFC (channel terminator) within the data
+ data = channel->data;
+ dataEnd = channel->data + channel->size;
+ while ((data < dataEnd) && (*data != 0xfc))
+ data++;
+ // Skip any following 0xFCs as well
+ while ((data < dataEnd) && (*data == 0xfc))
+ data++;
+ // Now adjust channels accordingly
+ sampleChannel->data = data;
+ sampleChannel->size = channel->size - (data - channel->data);
+ channel->size = data - channel->data;
+ // Read sample header information
+ //Offset 14 in the header contains the frequency as a short integer. Offset 32 contains the sample length, also as a short integer.
+ _tracks->digitalSampleRate = READ_LE_UINT16(sampleChannel->data + 14);
+ _tracks->digitalSampleSize = READ_LE_UINT16(sampleChannel->data + 32);
+ _tracks->digitalSampleStart = 0;
+ _tracks->digitalSampleEnd = 0;
+ sampleChannel->data += 44; // Skip over header
+ sampleChannel->size -= 44;
+ }
+ break;
+
+ case SCI_VERSION_1_EARLY:
+ case SCI_VERSION_1_LATE:
+ case SCI_VERSION_2_1:
+ data = resource->data;
+ // Count # of tracks
+ _trackCount = 0;
+ while ((*data++) != 0xFF) {
+ _trackCount++;
+ while (*data != 0xFF)
+ data += 6;
+ data++;
+ }
+ _tracks = new Track[_trackCount];
+ data = resource->data;
+
+ byte channelCount;
+
+ for (trackNr = 0; trackNr < _trackCount; trackNr++) {
+ // Track info starts with track type:BYTE
+ // Then the channel information gets appended Unknown:WORD, ChannelOffset:WORD, ChannelSize:WORD
+ // 0xFF:BYTE as terminator to end that track and begin with another track type
+ // Track type 0xFF is the marker signifying the end of the tracks
+
+ _tracks[trackNr].type = *data++;
+ // Counting # of channels used
+ data2 = data;
+ channelCount = 0;
+ while (*data2 != 0xFF) {
+ data2 += 6;
+ channelCount++;
+ _tracks[trackNr].channelCount++;
+ }
+ _tracks[trackNr].channels = new Channel[channelCount];
+ _tracks[trackNr].channelCount = 0;
+ _tracks[trackNr].digitalChannelNr = -1; // No digital sound associated
+ _tracks[trackNr].digitalSampleRate = 0;
+ _tracks[trackNr].digitalSampleSize = 0;
+ _tracks[trackNr].digitalSampleStart = 0;
+ _tracks[trackNr].digitalSampleEnd = 0;
+ if (_tracks[trackNr].type != 0xF0) { // Digital track marker - not supported currently
+ channelNr = 0;
+ while (channelCount--) {
+ channel = &_tracks[trackNr].channels[channelNr];
+ channel->prio = READ_LE_UINT16(data);
+ uint dataOffset = READ_LE_UINT16(data + 2);
+ if (dataOffset < resource->size) {
+ channel->data = resource->data + dataOffset;
+ channel->size = READ_LE_UINT16(data + 4);
+ channel->curPos = 0;
+ channel->number = *channel->data;
+ channel->poly = *(channel->data + 1);
+ channel->time = channel->prev = 0;
+ channel->data += 2; // skip over header
+ channel->size -= 2; // remove header size
+ if (channel->number == 0xFE) { // Digital channel
+ _tracks[trackNr].digitalChannelNr = channelNr;
+ _tracks[trackNr].digitalSampleRate = READ_LE_UINT16(channel->data);
+ _tracks[trackNr].digitalSampleSize = READ_LE_UINT16(channel->data + 2);
+ _tracks[trackNr].digitalSampleStart = READ_LE_UINT16(channel->data + 4);
+ _tracks[trackNr].digitalSampleEnd = READ_LE_UINT16(channel->data + 6);
+ channel->data += 8; // Skip over header
+ channel->size -= 8;
+ }
+ _tracks[trackNr].channelCount++;
+ channelNr++;
+ } else {
+ warning("Invalid offset inside sound resource %d: track %d, channel %d", resourceNr, trackNr, channelNr);
+ }
+ data += 6;
+ }
+ } else {
+ // Skip over digital track
+ data += 6;
+ }
+ data++; // Skipping 0xFF that closes channels list
+ }
+ break;
+
+ default:
+ error("SoundResource: SCI version %d is unsupported", _soundVersion);
+ }
+}
+
+SoundResource::~SoundResource() {
+ for (int trackNr = 0; trackNr < _trackCount; trackNr++)
+ delete[] _tracks[trackNr].channels;
+ delete[] _tracks;
+
+ _resMan->unlockResource(_innerResource);
+}
+
+#if 0
+SoundResource::Track* SoundResource::getTrackByNumber(uint16 number) {
+ if (_soundVersion <= SCI_VERSION_0_LATE)
+ return &_tracks[0];
+
+ if (/*number >= 0 &&*/number < _trackCount)
+ return &_tracks[number];
+ return NULL;
+}
+#endif
+
+SoundResource::Track *SoundResource::getTrackByType(byte type) {
+ if (_soundVersion <= SCI_VERSION_0_LATE)
+ return &_tracks[0];
+
+ for (int trackNr = 0; trackNr < _trackCount; trackNr++) {
+ if (_tracks[trackNr].type == type)
+ return &_tracks[trackNr];
+ }
+ return NULL;
+}
+
+SoundResource::Track *SoundResource::getDigitalTrack() {
+ for (int trackNr = 0; trackNr < _trackCount; trackNr++) {
+ if (_tracks[trackNr].digitalChannelNr != -1)
+ return &_tracks[trackNr];
+ }
+ return NULL;
+}
+
+// Gets the filter mask for SCI0 sound resources
+int SoundResource::getChannelFilterMask(int hardwareMask, bool wantsRhythm) {
+ byte *data = _innerResource->data;
+ int channelMask = 0;
+
+ if (_soundVersion > SCI_VERSION_0_LATE)
+ return 0;
+
+ data++; // Skip over digital sample flag
+
+ for (int channelNr = 0; channelNr < 16; channelNr++) {
+ channelMask = channelMask >> 1;
+
+ byte flags;
+
+ if (_soundVersion == SCI_VERSION_0_EARLY) {
+ // Each channel is specified by a single byte
+ // Upper 4 bits of the byte is a voices count
+ // Lower 4 bits -> bit 0 set: use for AdLib
+ // bit 1 set: use for PCjr
+ // bit 2 set: use for PC speaker
+ // bit 3 set and bit 0 clear: control channel (15)
+ // bit 3 set and bit 0 set: rhythm channel (9)
+ // Note: control channel is dynamically assigned inside the drivers,
+ // but seems to be fixed at 15 in the song data.
+ flags = *data++;
+
+ // Get device bits
+ flags &= 0x7;
+ } else {
+ // Each channel is specified by 2 bytes
+ // 1st byte is voices count
+ // 2nd byte is play mask, which specifies if the channel is supposed to be played
+ // by the corresponding hardware
+
+ // Skip voice count
+ data++;
+
+ flags = *data++;
+ }
+
+ bool play;
+ switch (channelNr) {
+ case 15:
+ // Always play control channel
+ play = true;
+ break;
+ case 9:
+ // Play rhythm channel when requested
+ play = wantsRhythm;
+ break;
+ default:
+ // Otherwise check for flag
+ play = flags & hardwareMask;
+ }
+
+ if (play) {
+ // This Channel is supposed to be played by the hardware
+ channelMask |= 0x8000;
+ }
+ }
+
+ return channelMask;
+}
+
+byte SoundResource::getInitialVoiceCount(byte channel) {
+ byte *data = _innerResource->data;
+
+ if (_soundVersion > SCI_VERSION_0_LATE)
+ return 0; // TODO
+
+ data++; // Skip over digital sample flag
+
+ if (_soundVersion == SCI_VERSION_0_EARLY)
+ return data[channel] >> 4;
+ else
+ return data[channel * 2];
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h
new file mode 100644
index 0000000000..14f872b46e
--- /dev/null
+++ b/engines/sci/resource_intern.h
@@ -0,0 +1,219 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 SCI_RESOURCE_INTERN_H
+#define SCI_RESOURCE_INTERN_H
+
+#include "sci/resource.h"
+
+namespace Common {
+ class MacResManager;
+}
+
+namespace Sci {
+
+enum ResSourceType {
+ kSourceDirectory = 0,
+ kSourcePatch,
+ kSourceVolume,
+ kSourceExtMap,
+ kSourceIntMap,
+ kSourceAudioVolume,
+ kSourceExtAudioMap,
+ kSourceWave,
+ kSourceMacResourceFork,
+ kSourceChunk
+};
+
+
+class ResourceSource {
+protected:
+ const ResSourceType _sourceType;
+ const Common::String _name;
+
+public:
+ bool _scanned;
+ const Common::FSNode * const _resourceFile;
+ const int _volumeNumber;
+
+protected:
+ ResourceSource(ResSourceType type, const Common::String &name, int volNum = 0, const Common::FSNode *resFile = 0);
+public:
+ virtual ~ResourceSource();
+
+ ResSourceType getSourceType() const { return _sourceType; }
+ const Common::String &getLocationName() const { return _name; }
+
+ // Auxiliary method, used by loadResource implementations.
+ Common::SeekableReadStream *getVolumeFile(ResourceManager *resMan, Resource *res);
+
+ /**
+ * TODO: Document this
+ */
+ virtual ResourceSource *findVolume(ResourceSource *map, int volNum) {
+ return NULL;
+ }
+
+ /**
+ * Scan this source for TODO.
+ */
+ virtual void scanSource(ResourceManager *resMan) {}
+
+ /**
+ * Load a resource.
+ */
+ virtual void loadResource(ResourceManager *resMan, Resource *res);
+
+ // FIXME: This audio specific method is a hack. After all, why should a
+ // ResourceSource or a Resource (which uses this method) have audio
+ // specific methods? But for now we keep this, as it eases transition.
+ virtual uint32 getAudioCompressionType() const { return 0; }
+};
+
+class DirectoryResourceSource : public ResourceSource {
+public:
+ DirectoryResourceSource(const Common::String &name) : ResourceSource(kSourceDirectory, name) {}
+
+ virtual void scanSource(ResourceManager *resMan);
+};
+
+class PatchResourceSource : public ResourceSource {
+public:
+ PatchResourceSource(const Common::String &name) : ResourceSource(kSourcePatch, name) {}
+
+ virtual void loadResource(ResourceManager *resMan, Resource *res);
+};
+
+class VolumeResourceSource : public ResourceSource {
+protected:
+ ResourceSource * const _associatedMap;
+
+public:
+ VolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum, ResSourceType type = kSourceVolume)
+ : ResourceSource(type, name, volNum), _associatedMap(map) {
+ }
+
+ VolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum, const Common::FSNode *resFile)
+ : ResourceSource(kSourceVolume, name, volNum, resFile), _associatedMap(map) {
+ }
+
+ virtual ResourceSource *findVolume(ResourceSource *map, int volNum) {
+ if (_associatedMap == map && _volumeNumber == volNum)
+ return this;
+ return NULL;
+ }
+};
+
+class ExtMapResourceSource : public ResourceSource {
+public:
+ ExtMapResourceSource(const Common::String &name, int volNum, const Common::FSNode *resFile = 0)
+ : ResourceSource(kSourceExtMap, name, volNum, resFile) {
+ }
+
+ virtual void scanSource(ResourceManager *resMan);
+};
+
+class IntMapResourceSource : public ResourceSource {
+public:
+ IntMapResourceSource(const Common::String &name, int volNum)
+ : ResourceSource(kSourceIntMap, name, volNum) {
+ }
+
+ virtual void scanSource(ResourceManager *resMan);
+};
+
+class AudioVolumeResourceSource : public VolumeResourceSource {
+protected:
+ uint32 _audioCompressionType;
+ int32 *_audioCompressionOffsetMapping;
+
+public:
+ AudioVolumeResourceSource(ResourceManager *resMan, const Common::String &name, ResourceSource *map, int volNum);
+
+ virtual void loadResource(ResourceManager *resMan, Resource *res);
+
+ virtual uint32 getAudioCompressionType() const;
+};
+
+class ExtAudioMapResourceSource : public ResourceSource {
+public:
+ ExtAudioMapResourceSource(const Common::String &name, int volNum)
+ : ResourceSource(kSourceExtAudioMap, name, volNum) {
+ }
+
+ virtual void scanSource(ResourceManager *resMan);
+};
+
+class WaveResourceSource : public ResourceSource {
+public:
+ WaveResourceSource(const Common::String &name) : ResourceSource(kSourceWave, name) {}
+
+ virtual void loadResource(ResourceManager *resMan, Resource *res);
+};
+
+/**
+ * Reads SCI1.1+ resources from a Mac resource fork.
+ */
+class MacResourceForkResourceSource : public ResourceSource {
+protected:
+ Common::MacResManager *_macResMan;
+
+public:
+ MacResourceForkResourceSource(const Common::String &name, int volNum);
+ ~MacResourceForkResourceSource();
+
+ virtual void scanSource(ResourceManager *resMan);
+
+ virtual void loadResource(ResourceManager *resMan, Resource *res);
+};
+
+#ifdef ENABLE_SCI32
+
+/**
+ * Reads resources from SCI2.1+ chunk resources
+ */
+class ChunkResourceSource : public ResourceSource {
+public:
+ ChunkResourceSource(const Common::String &name, uint16 number);
+
+ virtual void scanSource(ResourceManager *resMan);
+ virtual void loadResource(ResourceManager *resMan, Resource *res);
+
+protected:
+ uint16 _number;
+
+ struct ResourceEntry {
+ uint32 offset;
+ uint32 length;
+ };
+
+ Common::HashMap<ResourceId, ResourceEntry, ResourceIdHash> _resMap;
+};
+
+#endif
+
+} // End of namespace Sci
+
+#endif // SCI_RESOURCE_INTERN_H
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 4862d0579a..7a9a786121 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -26,6 +26,8 @@
#include "common/system.h"
#include "common/config-manager.h"
#include "common/debug-channels.h"
+#include "common/EventRecorder.h"
+#include "common/file.h" // for Common::File::exists()
#include "engines/advancedDetector.h"
#include "engines/util.h"
@@ -36,39 +38,59 @@
#include "sci/event.h"
#include "sci/engine/features.h"
+#include "sci/engine/message.h"
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
#include "sci/engine/script.h" // for script_adjust_opcode_formats
+#include "sci/engine/selector.h" // for SELECTOR
#include "sci/sound/audio.h"
#include "sci/sound/soundcmd.h"
-#include "sci/graphics/gui.h"
+#include "sci/graphics/animate.h"
+#include "sci/graphics/cache.h"
+#include "sci/graphics/compare.h"
+#include "sci/graphics/controls.h"
+#include "sci/graphics/coordadjuster.h"
+#include "sci/graphics/cursor.h"
+#include "sci/graphics/maciconbar.h"
+#include "sci/graphics/menu.h"
+#include "sci/graphics/paint16.h"
+#include "sci/graphics/paint32.h"
+#include "sci/graphics/picture.h"
#include "sci/graphics/ports.h"
#include "sci/graphics/palette.h"
-#include "sci/graphics/cursor.h"
#include "sci/graphics/screen.h"
-#include "sci/graphics/cache.h"
+#include "sci/graphics/text16.h"
+#include "sci/graphics/transitions.h"
#ifdef ENABLE_SCI32
-#include "sci/graphics/gui32.h"
+#include "sci/graphics/frameout.h"
#endif
namespace Sci {
-extern int g_loadFromLauncher;
-
SciEngine *g_sci = 0;
class GfxDriver;
-SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc)
- : Engine(syst), _gameDescription(desc), _system(syst) {
- _console = NULL;
+SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gameId)
+ : Engine(syst), _gameDescription(desc), _gameId(gameId) {
assert(g_sci == 0);
g_sci = this;
+
+ _gfxMacIconBar = 0;
+
+ _audio = 0;
_features = 0;
+ _resMan = 0;
+ _gamestate = 0;
+ _kernel = 0;
+ _vocabulary = 0;
+ _vocabularyLanguage = 1; // we load english vocabulary on startup
+ _eventMan = 0;
+ _console = 0;
// Set up the engine specific debug levels
DebugMan.addDebugChannel(kDebugLevelError, "Error", "Script error debugging");
@@ -79,10 +101,8 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc)
DebugMan.addDebugChannel(kDebugLevelFuncCheck, "Func", "Function parameter debugging");
DebugMan.addDebugChannel(kDebugLevelBresen, "Bresenham", "Bresenham algorithms debugging");
DebugMan.addDebugChannel(kDebugLevelSound, "Sound", "Sound debugging");
- DebugMan.addDebugChannel(kDebugLevelGfxDriver, "Gfxdriver", "Gfx driver debugging");
DebugMan.addDebugChannel(kDebugLevelBaseSetter, "Base", "Base Setter debugging");
DebugMan.addDebugChannel(kDebugLevelParser, "Parser", "Parser debugging");
- DebugMan.addDebugChannel(kDebugLevelMenu, "Menu", "Menu handling debugging");
DebugMan.addDebugChannel(kDebugLevelSaid, "Said", "Said specs debugging");
DebugMan.addDebugChannel(kDebugLevelFile, "File", "File I/O debugging");
DebugMan.addDebugChannel(kDebugLevelTime, "Time", "Time debugging");
@@ -92,25 +112,28 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc)
DebugMan.addDebugChannel(kDebugLevelVM, "VM", "VM debugging");
DebugMan.addDebugChannel(kDebugLevelScripts, "Scripts", "Notifies when scripts are unloaded");
DebugMan.addDebugChannel(kDebugLevelGC, "GC", "Garbage Collector debugging");
- DebugMan.addDebugChannel(kDebugLevelSci0Pic, "Sci0Pic", "SCI0 pic drawing debugging");
DebugMan.addDebugChannel(kDebugLevelResMan, "ResMan", "Resource manager debugging");
DebugMan.addDebugChannel(kDebugLevelOnStartup, "OnStartup", "Enter debugger at start of game");
- _gamestate = 0;
-
const Common::FSNode gameDataDir(ConfMan.get("path"));
SearchMan.addSubDirectoryMatching(gameDataDir, "actors"); // KQ6 hi-res portraits
SearchMan.addSubDirectoryMatching(gameDataDir, "aud"); // resource.aud and audio files
- SearchMan.addSubDirectoryMatching(gameDataDir, "avi"); // AVI movie files for Windows versions
- SearchMan.addSubDirectoryMatching(gameDataDir, "seq"); // SEQ movie files for DOS versions
+ SearchMan.addSubDirectoryMatching(gameDataDir, "audio");// resource.aud and audio files
+ SearchMan.addSubDirectoryMatching(gameDataDir, "audiosfx");// resource.aud and audio files
SearchMan.addSubDirectoryMatching(gameDataDir, "wav"); // speech files in WAV format
SearchMan.addSubDirectoryMatching(gameDataDir, "sfx"); // music/sound files in WAV format
- SearchMan.addSubDirectoryMatching(gameDataDir, "robot"); // robot files
+ SearchMan.addSubDirectoryMatching(gameDataDir, "avi"); // AVI movie files for Windows versions
+ SearchMan.addSubDirectoryMatching(gameDataDir, "seq"); // SEQ movie files for DOS versions
+ SearchMan.addSubDirectoryMatching(gameDataDir, "robot"); // robot movie files
+ SearchMan.addSubDirectoryMatching(gameDataDir, "robots"); // robot movie files
+ SearchMan.addSubDirectoryMatching(gameDataDir, "movie"); // vmd movie files
+ SearchMan.addSubDirectoryMatching(gameDataDir, "movies"); // vmd movie files
+ SearchMan.addSubDirectoryMatching(gameDataDir, "vmd"); // vmd movie files
// Add the patches directory, except for KQ6CD; The patches folder in some versions of KQ6CD
// is for the demo of Phantasmagoria, included in the disk
- if (strcmp(getGameID(), "kq6"))
+ if (_gameId != GID_KQ6)
SearchMan.addSubDirectoryMatching(gameDataDir, "patches"); // resource patches
}
@@ -118,184 +141,352 @@ SciEngine::~SciEngine() {
// Remove all of our debug levels here
DebugMan.clearAllDebugChannels();
+#ifdef ENABLE_SCI32
+ delete _gfxFrameout;
+#endif
+ delete _gfxMenu;
+ delete _gfxControls;
+ delete _gfxText16;
+ delete _gfxAnimate;
+ delete _gfxPaint;
+ delete _gfxTransitions;
+ delete _gfxCompare;
+ delete _gfxCoordAdjuster;
+ delete _gfxPorts;
+ delete _gfxCache;
+ delete _gfxPalette;
+ delete _gfxCursor;
+ delete _gfxScreen;
+
delete _audio;
+ delete _soundCmd;
delete _kernel;
delete _vocabulary;
delete _console;
- delete _resMan;
delete _features;
+ delete _gfxMacIconBar;
+ delete _eventMan;
+ delete _gamestate->_segMan;
+ delete _gamestate;
+ delete _resMan; // should be deleted last
g_sci = 0;
}
Common::Error SciEngine::run() {
+ g_eventRec.registerRandomSource(_rng, "sci");
+
// Assign default values to the config manager, in case settings are missing
ConfMan.registerDefault("undither", "true");
ConfMan.registerDefault("enable_fb01", "false");
_resMan = new ResourceManager();
+ assert(_resMan);
+ _resMan->addAppropriateSources();
+ _resMan->init();
+ // TODO: Add error handling. Check return values of addAppropriateSources
+ // and init. We first have to *add* sensible return values, though ;).
+/*
if (!_resMan) {
warning("No resources found, aborting");
return Common::kNoGameDataFoundError;
}
+*/
+
+ // Reset, so that error()s before SoundCommandParser is initialized wont cause a crash
+ _soundCmd = NULL;
+
+ // Add the after market GM patches for the specified game, if they exist
+ _resMan->addNewGMPatch(_gameId);
+ _gameObj = _resMan->findGameObject();
SegManager *segMan = new SegManager(_resMan);
- // Scale the screen, if needed
- int upscaledHires = GFX_SCREEN_UPSCALED_DISABLED;
+ // Initialize the game screen
+ _gfxScreen = new GfxScreen(_resMan);
+ _gfxScreen->debugUnditherSetState(ConfMan.getBool("undither"));
- // King's Quest 6 and Gabriel Knight 1 have hires content, gk1/cd was able to provide that under DOS as well, but as
- // gk1/floppy does support upscaled hires scriptswise, but doesn't actually have the hires content we need to limit
- // it to platform windows.
- if (getPlatform() == Common::kPlatformWindows) {
- if (!strcmp(getGameID(), "kq6"))
- upscaledHires = GFX_SCREEN_UPSCALED_640x440;
-#ifdef ENABLE_SCI32
- if (!strcmp(getGameID(), "gk1"))
- upscaledHires = GFX_SCREEN_UPSCALED_640x480;
-#endif
+ // Create debugger console. It requires GFX to be initialized
+ _console = new Console(this);
+ _kernel = new Kernel(_resMan, segMan);
+ _features = new GameFeatures(segMan, _kernel);
+ // Only SCI0, SCI01 and SCI1 EGA games used a parser
+ _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan, false) : NULL;
+ // Also, XMAS1990 apparently had a parser too. Refer to http://forums.scummvm.org/viewtopic.php?t=9135
+ if (getGameId() == GID_CHRISTMAS1990)
+ _vocabulary = new Vocabulary(_resMan, false);
+ _audio = new AudioPlayer(_resMan);
+ _gamestate = new EngineState(segMan);
+ _eventMan = new EventManager(_resMan->detectFontExtended());
+
+ // The game needs to be initialized before the graphics system is initialized, as
+ // the graphics code checks parts of the seg manager upon initialization (e.g. for
+ // the presence of the fastCast object)
+ if (!initGame()) { /* Initialize */
+ warning("Game initialization failed: Aborting...");
+ // TODO: Add an "init failed" error?
+ return Common::kUnknownError;
}
- // Japanese versions of games use hi-res font on upscaled version of the game
- if ((getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1))
- upscaledHires = GFX_SCREEN_UPSCALED_640x400;
+ script_adjust_opcode_formats();
- // Initialize graphics-related parts
- GfxScreen *screen = 0;
+ // Must be called after game_init(), as they use _features
+ _kernel->loadKernelNames(_features);
+ _soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, _features->detectDoSoundType());
- // invokes initGraphics()
- if (_resMan->detectHires())
- screen = new GfxScreen(_resMan, 640, 480);
- else
- screen = new GfxScreen(_resMan, 320, 200, upscaledHires);
+ syncSoundSettings();
- GfxPalette *palette = new GfxPalette(_resMan, screen);
- GfxCache *cache = new GfxCache(_resMan, screen, palette);
- GfxCursor *cursor = new GfxCursor(_resMan, palette, screen);
+ // Initialize all graphics related subsystems
+ initGraphics();
- // Create debugger console. It requires GFX to be initialized
- _console = new Console(this);
+ debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()));
- _kernel = new Kernel(_resMan, segMan);
- // Only SCI0 and SCI01 games used a parser
- _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan) : NULL;
- _audio = new AudioPlayer(_resMan);
+ if (_gameDescription->flags & ADGF_ADDENGLISH) {
+ // if game is multilingual
+ Common::Language selectedLanguage = Common::parseLanguage(ConfMan.get("language"));
+ if (selectedLanguage == Common::EN_ANY) {
+ // and english was selected as language
+ if (SELECTOR(printLang) != -1) // set text language to english
+ writeSelectorValue(segMan, _gameObj, SELECTOR(printLang), 1);
+ if (SELECTOR(parseLang) != -1) // and set parser language to english as well
+ writeSelectorValue(segMan, _gameObj, SELECTOR(parseLang), 1);
+ }
+ }
- _features = new GameFeatures(segMan, _kernel);
+ // Check whether loading a savestate was requested
+ int saveSlot = ConfMan.getInt("save_slot");
+ if (saveSlot >= 0) {
+ reg_t restoreArgv[2] = { NULL_REG, make_reg(0, saveSlot) }; // special call (argv[0] is NULL)
+ kRestoreGame(_gamestate, 2, restoreArgv);
+
+ // TODO: The best way to do the following would be to invoke Game::init
+ // here and stop when the room is about to be changed, otherwise some
+ // game initialization won't take place
+
+ // Set audio language for KQ5CD (bug #3039477)
+ if (g_sci->getGameId() == GID_KQ5 && Common::File::exists("AUDIO001.002")) {
+ reg_t doAudioArgv[2] = { make_reg(0, 9), make_reg(0, 1) };
+ kDoAudio(_gamestate, 2, doAudioArgv);
+ }
+
+ // Initialize the game menu, if there is one.
+ // This is not done when loading, so we must do it manually.
+ reg_t menuBarObj = _gamestate->_segMan->findObjectByName("MenuBar");
+ if (menuBarObj.isNull())
+ menuBarObj = _gamestate->_segMan->findObjectByName("TheMenuBar"); // LSL2
+ if (menuBarObj.isNull())
+ menuBarObj = _gamestate->_segMan->findObjectByName("menuBar"); // LSL6
+ if (!menuBarObj.isNull()) {
+ // Reset abortScriptProcessing before initializing the game menu, so that the
+ // VM call performed by invokeSelector will actually run.
+ _gamestate->abortScriptProcessing = kAbortNone;
+ Object *menuBar = _gamestate->_segMan->getObject(menuBarObj);
+ // Invoke the first method (init) of the menuBar object
+ invokeSelector(_gamestate, menuBarObj, menuBar->getFuncSelector(0), 0, _gamestate->stack_base);
+ _gamestate->abortScriptProcessing = kAbortLoadGame;
+ }
+ }
- _gamestate = new EngineState(_vocabulary, segMan);
+ runGame();
- _gamestate->_event = new SciEvent(_resMan);
+ ConfMan.flushToDisk();
- if (script_init_engine(_gamestate))
- return Common::kUnknownError;
+ return Common::kNoError;
+}
-#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2) {
- _gfxAnimate = 0;
- _gfxControls = 0;
- _gfxMenu = 0;
- _gfxPaint16 = 0;
- _gfxPorts = 0;
- _gui = 0;
- _gui32 = new SciGui32(_gamestate->_segMan, _gamestate->_event, screen, palette, cache, cursor);
- } else {
-#endif
- _gfxPorts = new GfxPorts(segMan, screen);
- _gui = new SciGui(_gamestate, screen, palette, cache, cursor, _gfxPorts, _audio);
-#ifdef ENABLE_SCI32
- _gui32 = 0;
- _gfxFrameout = 0;
- }
-#endif
+bool SciEngine::initGame() {
+ // Script 0 needs to be allocated here before anything else!
+ int script0Segment = _gamestate->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK);
+ DataStack *stack = _gamestate->_segMan->allocateStack(VM_STACK_SIZE, NULL);
- _gfxPalette = palette;
- _gfxScreen = screen;
- _gfxCache = cache;
- _gfxCursor = cursor;
+ _gamestate->_msgState = new MessageState(_gamestate->_segMan);
+ _gamestate->gcCountDown = GC_INTERVAL - 1;
- if (game_init(_gamestate)) { /* Initialize */
- warning("Game initialization failed: Aborting...");
- // TODO: Add an "init failed" error?
- return Common::kUnknownError;
+ // Script 0 should always be at segment 1
+ if (script0Segment != 1) {
+ debug(2, "Failed to instantiate script.000");
+ return false;
}
- // Add the after market GM patches for the specified game, if they exist
- _resMan->addNewGMPatch(_gamestate->_gameId);
+ _gamestate->initGlobals();
+ _gamestate->_segMan->initSysStrings();
- script_adjust_opcode_formats(_gamestate);
- _kernel->loadKernelNames(getGameID());
+ _gamestate->r_acc = _gamestate->r_prev = NULL_REG;
- // Set the savegame dir (actually, we set it to a fake value,
- // since we cannot let the game control where saves are stored)
- assert(_gamestate->sys_strings->_strings[SYS_STRING_SAVEDIR]._value != 0);
- strcpy(_gamestate->sys_strings->_strings[SYS_STRING_SAVEDIR]._value, "");
+ _gamestate->_executionStack.clear(); // Start without any execution stack
+ _gamestate->executionStackBase = -1; // No vm is running yet
+ _gamestate->_executionStackPosChanged = false;
- SciVersion soundVersion = _features->detectDoSoundType();
+ _gamestate->abortScriptProcessing = kAbortNone;
+ _gamestate->gameIsRestarting = GAMEISRESTARTING_NONE;
- _gamestate->_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, soundVersion);
+ _gamestate->stack_base = stack->_entries;
+ _gamestate->stack_top = stack->_entries + stack->_capacity;
- screen->debugUnditherSetState(ConfMan.getBool("undither"));
+ if (!_gamestate->_segMan->instantiateScript(0)) {
+ error("initGame(): Could not instantiate script 0");
+ return false;
+ }
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- if (game_init_sound(_gamestate, 0, soundVersion)) {
- warning("Game initialization failed: Error in sound subsystem. Aborting...");
- return Common::kUnknownError;
+ // Reset parser
+ if (_vocabulary) {
+ _vocabulary->reset();
}
-#endif
- syncSoundSettings();
+ _gamestate->gameStartTime = _gamestate->lastWaitTime = _gamestate->_screenUpdateTime = g_system->getMillis();
+
+ // Load game language into printLang property of game object
+ setSciLanguage();
+
+ return true;
+}
+void SciEngine::initGraphics() {
+
+ // Reset all graphics objects
+ _gfxAnimate = 0;
+ _gfxCache = 0;
+ _gfxCompare = 0;
+ _gfxControls = 0;
+ _gfxCoordAdjuster = 0;
+ _gfxCursor = 0;
+ _gfxMacIconBar = 0;
+ _gfxMenu = 0;
+ _gfxPaint = 0;
+ _gfxPaint16 = 0;
+ _gfxPalette = 0;
+ _gfxPorts = 0;
+ _gfxText16 = 0;
+ _gfxTransitions = 0;
#ifdef ENABLE_SCI32
- if (_gui32)
- _gui32->init();
- else
+ _gfxFrameout = 0;
+ _gfxPaint32 = 0;
#endif
- _gui->init(_features->usesOldGfxFunctions());
- debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()));
+ if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1)
+ _gfxMacIconBar = new GfxMacIconBar();
- // Check whether loading a savestate was requested
- if (ConfMan.hasKey("save_slot")) {
- g_loadFromLauncher = ConfMan.getInt("save_slot");
+ bool paletteMerging = true;
+ if (getSciVersion() >= SCI_VERSION_1_1) {
+ // there are some games that use inbetween SCI1.1 interpreter, so we have to detect if it's merging or copying
+ if (getSciVersion() == SCI_VERSION_1_1)
+ paletteMerging = _resMan->detectForPaletteMergingForSci11();
+ else
+ paletteMerging = false;
+ }
+
+ _gfxPalette = new GfxPalette(_resMan, _gfxScreen, paletteMerging);
+ _gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette);
+ _gfxCursor = new GfxCursor(_resMan, _gfxPalette, _gfxScreen);
+
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2) {
+ // SCI32 graphic objects creation
+ _gfxCoordAdjuster = new GfxCoordAdjuster32(_gamestate->_segMan);
+ _gfxCursor->init(_gfxCoordAdjuster, _eventMan);
+ _gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster);
+ _gfxPaint32 = new GfxPaint32(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette);
+ _gfxPaint = _gfxPaint32;
+ _gfxFrameout = new GfxFrameout(_gamestate->_segMan, g_sci->getResMan(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32);
} else {
- g_loadFromLauncher = -1;
+#endif
+ // SCI0-SCI1.1 graphic objects creation
+ _gfxPorts = new GfxPorts(_gamestate->_segMan, _gfxScreen);
+ _gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts);
+ _gfxCursor->init(_gfxCoordAdjuster, g_sci->getEventManager());
+ _gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster);
+ _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, g_sci->getResMan()->isVGA());
+ _gfxPaint16 = new GfxPaint16(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio);
+ _gfxPaint = _gfxPaint16;
+ _gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions);
+ _gfxText16 = new GfxText16(g_sci->getResMan(), _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen);
+ _gfxControls = new GfxControls(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen);
+ _gfxMenu = new GfxMenu(g_sci->getEventManager(), _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor);
+
+ _gfxMenu->reset();
+#ifdef ENABLE_SCI32
}
+#endif
- game_run(&_gamestate); // Run the game
+ if (_gfxPorts) {
+ _gfxPorts->init(_features->usesOldGfxFunctions(), _gfxPaint16, _gfxText16);
+ _gfxPaint16->init(_gfxAnimate, _gfxText16);
+ }
+ // Set default (EGA, amiga or resource 999) palette
+ _gfxPalette->setDefault();
+}
- game_exit(_gamestate);
+void SciEngine::initStackBaseWithSelector(Selector selector) {
+ _gamestate->stack_base[0] = make_reg(0, (uint16)selector);
+ _gamestate->stack_base[1] = NULL_REG;
- ConfMan.flushToDisk();
+ // Register the first element on the execution stack
+ if (!send_selector(_gamestate, _gameObj, _gameObj, _gamestate->stack_base, 2, _gamestate->stack_base)) {
+ _console->printObject(_gameObj);
+ error("initStackBaseWithSelector: error while registering the first selector in the call stack");
+ }
- delete _gamestate->_soundCmd;
- delete _gui;
-#ifdef ENABLE_SCI32
- delete _gui32;
-#endif
- delete _gfxPorts;
- delete _gfxCache;
- delete _gfxPalette;
- delete cursor;
- delete _gfxScreen;
- delete _gamestate->_event;
- delete segMan;
- delete _gamestate;
+}
- return Common::kNoError;
+void SciEngine::runGame() {
+ initStackBaseWithSelector(SELECTOR(play)); // Call the play selector
+
+ // Attach the debug console on game startup, if requested
+ if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup))
+ _console->attach();
+
+ do {
+ _gamestate->_executionStackPosChanged = false;
+ run_vm(_gamestate);
+ exitGame();
+
+ if (_gamestate->abortScriptProcessing == kAbortRestartGame) {
+ _gamestate->_segMan->resetSegMan();
+ initGame();
+ initStackBaseWithSelector(SELECTOR(play));
+ _gamestate->gameIsRestarting = GAMEISRESTARTING_RESTART;
+ if (_gfxMenu)
+ _gfxMenu->reset();
+ _gamestate->abortScriptProcessing = kAbortNone;
+ } else if (_gamestate->abortScriptProcessing == kAbortLoadGame) {
+ _gamestate->abortScriptProcessing = kAbortNone;
+ _gamestate->_executionStack.clear();
+ initStackBaseWithSelector(SELECTOR(replay));
+ _gamestate->shrinkStackToBase();
+ _gamestate->abortScriptProcessing = kAbortNone;
+ } else {
+ break; // exit loop
+ }
+ } while (true);
+}
+
+void SciEngine::exitGame() {
+ if (_gamestate->abortScriptProcessing != kAbortLoadGame) {
+ _gamestate->_executionStack.clear();
+ _audio->stopAllAudio();
+ g_sci->_soundCmd->clearPlayList();
+ }
+
+ // TODO Free parser segment here
+
+ // TODO Free scripts here
+
+ // Close all opened file handles
+ _gamestate->_fileHandles.clear();
+ _gamestate->_fileHandles.resize(5);
}
// Invoked by error() when a severe error occurs
GUI::Debugger *SciEngine::getDebugger() {
if (_gamestate) {
ExecStack *xs = &(_gamestate->_executionStack.back());
- xs->addr.pc.offset = g_debugState.old_pc_offset;
- xs->sp = g_debugState.old_sp;
+ xs->addr.pc.offset = _debugState.old_pc_offset;
+ xs->sp = _debugState.old_sp;
}
- g_debugState.runningStep = 0; // Stop multiple execution
- g_debugState.seeking = kDebugSeekNothing; // Stop special seeks
+ _debugState.runningStep = 0; // Stop multiple execution
+ _debugState.seeking = kDebugSeekNothing; // Stop special seeks
return _console;
}
@@ -305,7 +496,7 @@ Console *SciEngine::getSciDebugger() {
return _console;
}
-const char* SciEngine::getGameID() const {
+const char *SciEngine::getGameIdStr() const {
return _gameDescription->gameid;
}
@@ -317,12 +508,8 @@ Common::Platform SciEngine::getPlatform() const {
return _gameDescription->platform;
}
-uint32 SciEngine::getFlags() const {
- return _gameDescription->flags;
-}
-
bool SciEngine::isDemo() const {
- return getFlags() & ADGF_DEMO;
+ return _gameDescription->flags & ADGF_DEMO;
}
Common::String SciEngine::getSavegameName(int nr) const {
@@ -334,19 +521,20 @@ Common::String SciEngine::getSavegamePattern() const {
}
Common::String SciEngine::getFilePrefix() const {
- const char* gameID = getGameID();
- if (!strcmp(gameID, "qfg2")) {
+ if (_gameId == GID_QFG2) {
// Quest for Glory 2 wants to read files from Quest for Glory 1 (EGA/VGA) to import character data
if (_gamestate->currentRoomNumber() == 805)
return "qfg1";
// TODO: Include import-room for qfg1vga
- }
- if (!strcmp(gameID, "qfg3")) {
+ } else if (_gameId == GID_QFG3) {
// Quest for Glory 3 wants to read files from Quest for Glory 2 to import character data
if (_gamestate->currentRoomNumber() == 54)
return "qfg2";
+ } else if (_gameId == GID_QFG4) {
+ // Quest for Glory 4 wants to read files from Quest for Glory 3 to import character data
+ if (_gamestate->currentRoomNumber() == 54)
+ return "qfg3";
}
- // TODO: Implement the same for qfg4, when sci32 is good enough
return _targetName;
}
@@ -362,27 +550,22 @@ Common::String SciEngine::unwrapFilename(const Common::String &name) const {
}
void SciEngine::pauseEngineIntern(bool pause) {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- _gamestate->_sound.sfx_suspend(pause);
-#endif
_mixer->pauseAll(pause);
}
void SciEngine::syncSoundSettings() {
Engine::syncSoundSettings();
-#ifndef USE_OLD_MUSIC_FUNCTIONS
bool mute = false;
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
int soundVolumeMusic = (mute ? 0 : ConfMan.getInt("music_volume"));
- if (_gamestate && _gamestate->_soundCmd) {
+ if (_gamestate && g_sci->_soundCmd) {
int vol = (soundVolumeMusic + 1) * SoundCommandParser::kMaxSciVolume / Audio::Mixer::kMaxMixerVolume;
- _gamestate->_soundCmd->setMasterVolume(vol);
+ g_sci->_soundCmd->setMasterVolume(vol);
}
-#endif
}
} // End of namespace Sci
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index fdd10bcd04..72d6e7e0cb 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -28,6 +28,9 @@
#include "engines/engine.h"
#include "common/util.h"
+#include "common/random.h"
+#include "sci/engine/vm_types.h" // for Selector
+#include "sci/debug.h" // for DebugState
struct ADGameDescription;
@@ -41,9 +44,6 @@ struct ADGameDescription;
*/
namespace Sci {
-// Uncomment this to use old music functions
-//#define USE_OLD_MUSIC_FUNCTIONS
-
struct EngineState;
class Vocabulary;
class ResourceManager;
@@ -51,6 +51,8 @@ class Kernel;
class GameFeatures;
class Console;
class AudioPlayer;
+class SoundCommandParser;
+class EventManager;
class GfxAnimate;
class GfxCache;
@@ -58,14 +60,16 @@ class GfxCompare;
class GfxControls;
class GfxCoordAdjuster;
class GfxCursor;
+class GfxMacIconBar;
class GfxMenu;
class GfxPaint;
class GfxPaint16;
+class GfxPaint32;
class GfxPalette;
class GfxPorts;
class GfxScreen;
-class SciGui;
-
+class GfxText16;
+class GfxTransitions;
#ifdef ENABLE_SCI32
class SciGui32;
@@ -82,22 +86,91 @@ enum kDebugLevels {
kDebugLevelFuncCheck = 1 << 5,
kDebugLevelBresen = 1 << 6,
kDebugLevelSound = 1 << 7,
- kDebugLevelGfxDriver = 1 << 8,
- kDebugLevelBaseSetter = 1 << 9,
- kDebugLevelParser = 1 << 10,
- kDebugLevelMenu = 1 << 11,
- kDebugLevelSaid = 1 << 12,
- kDebugLevelFile = 1 << 13,
- kDebugLevelTime = 1 << 14,
- kDebugLevelRoom = 1 << 15,
- kDebugLevelAvoidPath = 1 << 16,
- kDebugLevelDclInflate = 1 << 17,
- kDebugLevelVM = 1 << 18,
- kDebugLevelScripts = 1 << 19,
- kDebugLevelGC = 1 << 20,
- kDebugLevelSci0Pic = 1 << 21,
- kDebugLevelResMan = 1 << 22,
- kDebugLevelOnStartup = 1 << 23
+ kDebugLevelBaseSetter = 1 << 8,
+ kDebugLevelParser = 1 << 9,
+ kDebugLevelSaid = 1 << 10,
+ kDebugLevelFile = 1 << 11,
+ kDebugLevelTime = 1 << 12,
+ kDebugLevelRoom = 1 << 13,
+ kDebugLevelAvoidPath = 1 << 14,
+ kDebugLevelDclInflate = 1 << 15,
+ kDebugLevelVM = 1 << 16,
+ kDebugLevelScripts = 1 << 17,
+ kDebugLevelGC = 1 << 18,
+ kDebugLevelResMan = 1 << 19,
+ kDebugLevelOnStartup = 1 << 20
+};
+
+enum SciGameId {
+ GID_ASTROCHICKEN,
+ GID_CAMELOT,
+ GID_CASTLEBRAIN,
+ GID_CHRISTMAS1988,
+ GID_CHRISTMAS1990,
+ GID_CHRISTMAS1992,
+ GID_CNICK_KQ,
+ GID_CNICK_LAURABOW,
+ GID_CNICK_LONGBOW,
+ GID_CNICK_LSL,
+ GID_CNICK_SQ,
+ GID_ECOQUEST,
+ GID_ECOQUEST2,
+ GID_FAIRYTALES,
+ GID_FREDDYPHARKAS,
+ GID_FUNSEEKER,
+ GID_GK1,
+ GID_GK2,
+ GID_HOYLE1,
+ GID_HOYLE2,
+ GID_HOYLE3,
+ GID_HOYLE4,
+ GID_ICEMAN,
+ GID_ISLANDBRAIN,
+ GID_JONES,
+ GID_KQ1,
+ GID_KQ4,
+ GID_KQ5,
+ GID_KQ6,
+ GID_KQ7,
+ GID_LAURABOW,
+ GID_LAURABOW2,
+ GID_LIGHTHOUSE,
+ GID_LONGBOW,
+ GID_LSL1,
+ GID_LSL2,
+ GID_LSL3,
+ GID_LSL5,
+ GID_LSL6,
+ GID_LSL6HIRES, // We have a separate ID for LSL6 SCI32, because it's actually a completely different game
+ GID_LSL7,
+ GID_MOTHERGOOSE,
+ GID_MOTHERGOOSEHIRES, // We have a separate ID for Mother Goose SCI32, because it's actually a completely different game
+ GID_MSASTROCHICKEN,
+ GID_PEPPER,
+ GID_PHANTASMAGORIA,
+ GID_PHANTASMAGORIA2,
+ GID_PQ1,
+ GID_PQ2,
+ GID_PQ3,
+ GID_PQ4,
+ GID_PQSWAT,
+ GID_QFG1,
+ GID_QFG1VGA,
+ GID_QFG2,
+ GID_QFG3,
+ GID_QFG4,
+ GID_RAMA,
+ GID_SHIVERS,
+ GID_SHIVERS2,
+ GID_SLATER,
+ GID_SQ1,
+ GID_SQ3,
+ GID_SQ4,
+ GID_SQ5,
+ GID_SQ6,
+ GID_TORIN,
+
+ GID_FANMADE // FIXME: Do we really need/want this?
};
/** SCI versions */
@@ -116,12 +189,6 @@ enum SciVersion {
SCI_VERSION_3 // LSL7, RAMA, Lighthouse
};
-enum MoveCountType {
- kMoveCountUninitialized,
- kIgnoreMoveCount,
- kIncrementMoveCount
-};
-
/** Supported languages */
enum kLanguage {
K_LANG_NONE = 0,
@@ -138,7 +205,7 @@ enum kLanguage {
class SciEngine : public Engine {
friend class Console;
public:
- SciEngine(OSystem *syst, const ADGameDescription *desc);
+ SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gameId);
~SciEngine();
// Engine APIs
@@ -153,17 +220,21 @@ public:
bool canSaveGameStateCurrently();
void syncSoundSettings();
- const char* getGameID() const;
+ const SciGameId &getGameId() const { return _gameId; }
+ const char *getGameIdStr() const;
int getResourceVersion() const;
Common::Language getLanguage() const;
Common::Platform getPlatform() const;
- uint32 getFlags() const;
bool isDemo() const;
inline ResourceManager *getResMan() const { return _resMan; }
inline Kernel *getKernel() const { return _kernel; }
inline EngineState *getEngineState() const { return _gamestate; }
inline Vocabulary *getVocabulary() const { return _vocabulary; }
+ inline EventManager *getEventManager() const { return _eventMan; }
+ inline reg_t getGameObject() const { return _gameObj; }
+
+ Common::RandomSource &getRNG() { return _rng; }
Common::String getSavegameName(int nr) const;
Common::String getSavegamePattern() const;
@@ -176,6 +247,12 @@ public:
/** Remove the 'TARGET-' prefix of the given filename, if present. */
Common::String unwrapFilename(const Common::String &name) const;
+ void sleep(uint32 msecs);
+
+ void scriptDebug();
+ bool checkExportBreakpoint(uint16 script, uint16 pubfunct);
+ bool checkSelectorBreakpoint(reg_t send_obj, int selector);
+
public:
/**
@@ -189,9 +266,17 @@ public:
Common::String strSplit(const char *str, const char *sep = "\r----------\r");
kLanguage getSciLanguage();
+ void setSciLanguage(kLanguage lang);
+ void setSciLanguage();
Common::String getSciLanguageString(const char *str, kLanguage lang, kLanguage *lang2 = NULL) const;
+ // Check if vocabulary needs to get switched (in multilingual parser games)
+ void checkVocabularySwitch();
+
+ // Initializes ports and paint16 for non-sci32 games, also sets default palette
+ void initGraphics();
+
public:
GfxAnimate *_gfxAnimate; // Animate for 16-bit gfx
GfxCache *_gfxCache;
@@ -203,26 +288,62 @@ public:
GfxPalette *_gfxPalette;
GfxPaint *_gfxPaint;
GfxPaint16 *_gfxPaint16; // Painting in 16-bit gfx
+ GfxPaint32 *_gfxPaint32; // Painting in 32-bit gfx
GfxPorts *_gfxPorts; // Port managment for 16-bit gfx
GfxScreen *_gfxScreen;
- SciGui *_gui; /* Currently active Gui */
+ GfxText16 *_gfxText16;
+ GfxTransitions *_gfxTransitions; // transitions between screens for 16-bit gfx
+ GfxMacIconBar *_gfxMacIconBar; // Mac Icon Bar manager
#ifdef ENABLE_SCI32
- SciGui32 *_gui32; // GUI for SCI32 games
GfxFrameout *_gfxFrameout; // kFrameout and the like for 32-bit gfx
#endif
AudioPlayer *_audio;
+ SoundCommandParser *_soundCmd;
GameFeatures *_features;
+ DebugState _debugState;
+
private:
+ /**
+ * Initializes a SCI game
+ * This function must be run before script_run() is executed. Graphics data
+ * is initialized iff s->gfx_state != NULL.
+ * @param[in] s The state to operate on
+ * @return true on success, false if an error occurred.
+ */
+ bool initGame();
+
+ /**
+ * Runs a SCI game
+ * This is the main function for SCI games. It takes a valid state, loads
+ * script 0 to it, finds the game object, allocates a stack, and runs the
+ * init method of the game object. In layman's terms, this runs a SCI game.
+ * @param[in] s Pointer to the pointer of the state to operate on
+ */
+ void runGame();
+
+ /**
+ * Uninitializes an initialized SCI game
+ * This function should be run after each script_run() call.
+ * @param[in] s The state to operate on
+ */
+ void exitGame();
+
+ void initStackBaseWithSelector(Selector selector);
+
const ADGameDescription *_gameDescription;
+ const SciGameId _gameId;
ResourceManager *_resMan; /**< The resource manager */
EngineState *_gamestate;
Kernel *_kernel;
Vocabulary *_vocabulary;
+ int16 _vocabularyLanguage;
+ EventManager *_eventMan;
+ reg_t _gameObj; /**< Pointer to the game object */
Console *_console;
- OSystem *_system;
+ Common::RandomSource _rng;
};
diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp
index 331561eea4..4a2a8e65d7 100644
--- a/engines/sci/sound/audio.cpp
+++ b/engines/sci/sound/audio.cpp
@@ -24,21 +24,23 @@
*/
#include "sci/resource.h"
-#include "sci/engine/selector.h"
#include "sci/engine/kernel.h"
+#include "sci/engine/selector.h"
#include "sci/engine/seg_manager.h"
#include "sci/sound/audio.h"
-#include "common/system.h"
#include "common/file.h"
+#include "common/system.h"
-#include "sound/audiostream.h"
#include "sound/audiocd.h"
-#include "sound/decoders/raw.h"
-#include "sound/decoders/wave.h"
+#include "sound/audiostream.h"
+#include "sound/decoders/aiff.h"
#include "sound/decoders/flac.h"
+#include "sound/decoders/mac_snd.h"
#include "sound/decoders/mp3.h"
+#include "sound/decoders/raw.h"
#include "sound/decoders/vorbis.h"
+#include "sound/decoders/wave.h"
namespace Sci {
@@ -46,6 +48,7 @@ AudioPlayer::AudioPlayer(ResourceManager *resMan) : _resMan(resMan), _audioRate(
_syncResource(NULL), _syncOffset(0), _audioCdStart(0) {
_mixer = g_system->getMixer();
+ _wPlayFlag = false;
}
AudioPlayer::~AudioPlayer() {
@@ -64,11 +67,30 @@ int AudioPlayer::startAudio(uint16 module, uint32 number) {
Audio::AudioStream *audioStream = getAudioStream(number, module, &sampleLen);
if (audioStream) {
+ _wPlayFlag = false;
_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream);
return sampleLen;
+ } else {
+ // Don't throw a warning in this case. getAudioStream() already has. Some games
+ // do miss audio entries (perhaps because of a typo, or because they were simply
+ // forgotten).
+ return 0;
}
+}
- return 0;
+int AudioPlayer::wPlayAudio(uint16 module, uint32 tuple) {
+ // Get the audio sample length and set the wPlay flag so we return 0 on
+ // position. SSCI pre-loads the audio here, but it's much easier for us to
+ // just get the sample length and return that. wPlayAudio should *not*
+ // actually start the sample.
+
+ int sampleLen = 0;
+ Audio::AudioStream *audioStream = getAudioStream(tuple, module, &sampleLen);
+ if (!audioStream)
+ warning("wPlayAudio: unable to create stream for audio tuple %d, module %d", tuple, module);
+ delete audioStream;
+ _wPlayFlag = true;
+ return sampleLen;
}
void AudioPlayer::stopAudio() {
@@ -86,6 +108,8 @@ void AudioPlayer::resumeAudio() {
int AudioPlayer::getAudioPosition() {
if (_mixer->isSoundHandleActive(_audioHandle))
return _mixer->getSoundElapsedTime(_audioHandle) * 6 / 100; // return elapsed time in ticks
+ else if (_wPlayFlag)
+ return 0; // Sound has "loaded" so return that it hasn't started
else
return -1; // Sound finished
}
@@ -161,17 +185,28 @@ static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uin
// Sierra SOL audio file reader
// Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio
-static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags) {
- if (headerSize != 11 && headerSize != 12) {
+static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags, uint32 resSize) {
+ if (headerSize != 7 && headerSize != 11 && headerSize != 12) {
warning("SOL audio header of size %i not supported", headerSize);
return false;
}
- audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes)
+ uint32 tag = audioStream->readUint32BE();
+
+ if (tag != MKID_BE('SOL\0')) {
+ warning("No 'SOL' FourCC found");
+ return false;
+ }
+
audioRate = audioStream->readUint16LE();
audioFlags = audioStream->readByte();
- size = audioStream->readUint32LE();
+ // For the QFG3 demo format, just use the resource size
+ // Otherwise, load it from the header
+ if (headerSize == 7)
+ size = resSize;
+ else
+ size = audioStream->readUint32LE();
return true;
}
@@ -235,12 +270,15 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
uint32 audioCompressionType = audioRes->getAudioCompressionType();
if (audioCompressionType) {
+#if (defined(USE_MAD) || defined(USE_VORBIS) || defined(USE_FLAC))
// Compressed audio made by our tool
byte *compressedData = (byte *)malloc(audioRes->size);
assert(compressedData);
- // We copy over the compressed data in our own buffer. If we don't do this resourcemanager may free the data
- // later. All other compression-types already decompress completely into an additional buffer here.
- // MP3/OGG/FLAC decompression works on-the-fly instead.
+ // We copy over the compressed data in our own buffer. We have to do
+ // this, because ResourceManager may free the original data late. All
+ // other compression types already decompress completely into an
+ // additional buffer here. MP3/OGG/FLAC decompression works on-the-fly
+ // instead.
memcpy(compressedData, audioRes->data, audioRes->size);
Common::MemoryReadStream *compressedStream = new Common::MemoryReadStream(compressedData, audioRes->size, DisposeAfterUse::YES);
@@ -261,13 +299,16 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
#endif
break;
}
+#else
+ error("Compressed audio file encountered, but no appropriate decoder is compiled in");
+#endif
} else {
// Original source file
if (audioRes->_headerSize > 0) {
// SCI1.1
Common::MemoryReadStream headerStream(audioRes->_header, audioRes->_headerSize, DisposeAfterUse::NO);
- if (readSOLHeader(&headerStream, audioRes->_headerSize, size, _audioRate, audioFlags)) {
+ if (readSOLHeader(&headerStream, audioRes->_headerSize, size, _audioRate, audioFlags, audioRes->size)) {
Common::MemoryReadStream dataStream(audioRes->data, audioRes->size, DisposeAfterUse::NO);
data = readSOLAudio(&dataStream, size, audioFlags, flags);
}
@@ -283,22 +324,24 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
waveStream->seek(0, SEEK_SET);
audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES);
+ } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKID_BE('FORM')) {
+ // AIFF detected
+ Common::MemoryReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO);
+
+ // Calculate samplelen from AIFF header
+ int waveSize = 0, waveRate = 0;
+ byte waveFlags = 0;
+ Audio::loadAIFFFromStream(*waveStream, waveSize, waveRate, waveFlags);
+ *sampleLen = (waveFlags & Audio::FLAG_16BITS ? waveSize >> 1 : waveSize) * 60 / waveRate;
+
+ waveStream->seek(0, SEEK_SET);
+ audioStream = Audio::makeAIFFStream(waveStream, DisposeAfterUse::YES);
} else if (audioRes->size > 14 && READ_BE_UINT16(audioRes->data) == 1 && READ_BE_UINT16(audioRes->data + 2) == 1
&& READ_BE_UINT16(audioRes->data + 4) == 5 && READ_BE_UINT32(audioRes->data + 10) == 0x00018051) {
// Mac snd detected
- // See http://developer.apple.com/legacy/mac/library/documentation/mac/Sound/Sound-60.html#HEADING60-15 for more details
-
- uint32 soundHeaderOffset = READ_BE_UINT32(audioRes->data + 16);
- assert(READ_BE_UINT32(audioRes->data + soundHeaderOffset) == 0);
- size = READ_BE_UINT32(audioRes->data + soundHeaderOffset + 4);
- _audioRate = READ_BE_UINT16(audioRes->data + soundHeaderOffset + 8); // Really floating point, but we're just truncating
+ Common::MemoryReadStream *sndStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO);
- if (*(audioRes->data + soundHeaderOffset + 20) != 0)
- error("Unhandled Mac snd extended/compressed header");
-
- data = (byte *)malloc(size);
- memcpy(data, audioRes->data + soundHeaderOffset + 22, size);
- flags = Audio::FLAG_UNSIGNED;
+ audioSeekStream = Audio::makeMacSndStream(sndStream, DisposeAfterUse::YES);
} else {
// SCI1 raw audio
size = audioRes->size;
@@ -314,13 +357,12 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
}
if (audioSeekStream) {
- *sampleLen = (audioSeekStream->getLength().msecs() * 10000) / 166666; // we translate msecs to ticks
- // Original code
- //*sampleLen = (flags & Audio::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate;
+ *sampleLen = (audioSeekStream->getLength().msecs() * 60) / 1000; // we translate msecs to ticks
audioStream = audioSeekStream;
}
- // We have to make sure that we don't depend on resource manager pointers after this point, because the actual
- // audio resource may get unloaded by resource manager at any time
+ // We have to make sure that we don't depend on resource manager pointers
+ // after this point, because the actual audio resource may get unloaded by
+ // resource manager at any time.
if (audioStream)
return audioStream;
@@ -332,11 +374,11 @@ void AudioPlayer::setSoundSync(ResourceId id, reg_t syncObjAddr, SegManager *seg
_syncOffset = 0;
if (_syncResource) {
- PUT_SEL32V(segMan, syncObjAddr, SELECTOR(syncCue), 0);
+ writeSelectorValue(segMan, syncObjAddr, SELECTOR(syncCue), 0);
} else {
warning("setSoundSync: failed to find resource %s", id.toString().c_str());
// Notify the scripts to stop sound sync
- PUT_SEL32V(segMan, syncObjAddr, SELECTOR(syncCue), SIGNAL_OFFSET);
+ writeSelectorValue(segMan, syncObjAddr, SELECTOR(syncCue), SIGNAL_OFFSET);
}
}
@@ -352,8 +394,8 @@ void AudioPlayer::doSoundSync(reg_t syncObjAddr, SegManager *segMan) {
_syncOffset += 2;
}
- PUT_SEL32V(segMan, syncObjAddr, SELECTOR(syncTime), syncTime);
- PUT_SEL32V(segMan, syncObjAddr, SELECTOR(syncCue), syncCue);
+ writeSelectorValue(segMan, syncObjAddr, SELECTOR(syncTime), syncTime);
+ writeSelectorValue(segMan, syncObjAddr, SELECTOR(syncCue), syncCue);
}
}
diff --git a/engines/sci/sound/audio.h b/engines/sci/sound/audio.h
index 9fc3cbac51..7c1221fc4c 100644
--- a/engines/sci/sound/audio.h
+++ b/engines/sci/sound/audio.h
@@ -33,8 +33,7 @@
namespace Sci {
enum AudioCommands {
- // TODO: find the difference between kSci1AudioWPlay and kSci1AudioPlay
- kSciAudioWPlay = 1, /* Plays an audio stream */
+ kSciAudioWPlay = 1, /* Loads an audio stream */
kSciAudioPlay = 2, /* Plays an audio stream */
kSciAudioStop = 3, /* Stops an audio stream */
kSciAudioPause = 4, /* Pauses an audio stream */
@@ -69,6 +68,7 @@ public:
Audio::RewindableAudioStream *getAudioStream(uint32 number, uint32 volume, int *sampleLen);
int getAudioPosition();
int startAudio(uint16 module, uint32 tuple);
+ int wPlayAudio(uint16 module, uint32 tuple);
void stopAudio();
void pauseAudio();
void resumeAudio();
@@ -92,6 +92,7 @@ private:
Resource *_syncResource; /**< Used by kDoSync for speech syncing in CD talkie games */
uint _syncOffset;
uint32 _audioCdStart;
+ bool _wPlayFlag;
};
} // End of namespace Sci
diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp
index a743e4b5d9..55c3640c9d 100644
--- a/engines/sci/sound/drivers/adlib.cpp
+++ b/engines/sci/sound/drivers/adlib.cpp
@@ -704,6 +704,7 @@ void MidiDriver_AdLib::setVelocityReg(int regOffset, int velocity, int kbScaleLe
void MidiDriver_AdLib::setPatch(int voice, int patch) {
if ((patch < 0) || ((uint)patch >= _patches.size())) {
warning("ADLIB: Invalid patch %i requested", patch);
+ // Substitute instrument 0
patch = 0;
}
@@ -749,17 +750,24 @@ void MidiDriver_AdLib::playSwitch(bool play) {
bool MidiDriver_AdLib::loadResource(const byte *data, uint size) {
if ((size != 1344) && (size != 2690) && (size != 5382)) {
- warning("ADLIB: Unsupported patch format (%i bytes)", size);
+ error("ADLIB: Unsupported patch format (%i bytes)", size);
return false;
}
for (int i = 0; i < 48; i++)
loadInstrument(data + (28 * i));
- if (size == 2690) {
+ if (size == 1344) {
+ byte dummy[28] = {0};
+
+ // Only 48 instruments, add dummies
+ for (int i = 0; i < 48; i++)
+ loadInstrument(dummy);
+ } else if (size == 2690) {
for (int i = 48; i < 96; i++)
loadInstrument(data + 2 + (28 * i));
- } else if (size == 5382) {
+ } else {
+ // SCI1.1 and later
for (int i = 48; i < 190; i++)
loadInstrument(data + (28 * i));
_rhythmKeyMap = new byte[kRhythmKeys];
diff --git a/engines/sci/sound/drivers/amiga.cpp b/engines/sci/sound/drivers/amigamac.cpp
index 0413dbb79e..4fb9146b53 100644
--- a/engines/sci/sound/drivers/amiga.cpp
+++ b/engines/sci/sound/drivers/amigamac.cpp
@@ -25,6 +25,7 @@
#include "sound/softsynth/emumidi.h"
#include "sci/sound/drivers/mididriver.h"
+#include "sci/resource.h"
#include "common/file.h"
#include "common/frac.h"
@@ -34,35 +35,14 @@ namespace Sci {
/* #define DEBUG */
-// Frequencies for every note
-// FIXME Store only one octave
-static const int freq_table[] = {
- 58, 62, 65, 69, 73, 78, 82, 87,
- 92, 98, 104, 110, 117, 124, 131, 139,
- 147, 156, 165, 175, 185, 196, 208, 220,
- 234, 248, 262, 278, 294, 312, 331, 350,
- 371, 393, 417, 441, 468, 496, 525, 556,
- 589, 625, 662, 701, 743, 787, 834, 883,
- 936, 992, 1051, 1113, 1179, 1250, 1324, 1403,
- 1486, 1574, 1668, 1767, 1872, 1984, 2102, 2227,
- 2359, 2500, 2648, 2806, 2973, 3149, 3337, 3535,
- 3745, 3968, 4204, 4454, 4719, 5000, 5297, 5612,
- 5946, 6299, 6674, 7071, 7491, 7937, 8408, 8908,
- 9438, 10000, 10594, 11224, 11892, 12599, 13348, 14142,
- 14983, 15874, 16817, 17817, 18877, 20000, 21189, 22449,
- 23784, 25198, 26696, 28284, 29966, 31748, 33635, 35635,
- 37754, 40000, 42378, 44898, 47568, 50396, 53393, 56568,
- 59932, 63496, 67271, 71271, 75509, 80000, 84757, 89796
-};
-
-class MidiDriver_Amiga : public MidiDriver_Emulated {
+class MidiDriver_AmigaMac : public MidiDriver_Emulated {
public:
enum {
kVoices = 4
};
- MidiDriver_Amiga(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15) { }
- virtual ~MidiDriver_Amiga() { }
+ MidiDriver_AmigaMac(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15) { }
+ virtual ~MidiDriver_AmigaMac() { }
// MidiDriver
int open();
@@ -99,6 +79,7 @@ private:
int instrument;
int volume;
int pan;
+ uint16 pitch;
};
struct Envelope {
@@ -121,7 +102,7 @@ private:
frac_t rate;
};
- struct Instrument {
+ struct InstrumentSample {
char name[30];
int mode;
int size; // Size of non-looping part in bytes
@@ -130,35 +111,55 @@ private:
Envelope envelope[4]; // Envelope
int8 *samples;
int8 *loop;
+ int16 startNote;
+ int16 endNote;
+ bool isUnsigned;
+ uint16 baseFreq;
+ uint16 baseNote;
+ int16 fixedNote;
+ };
+
+ class Instrument : public Common::Array<InstrumentSample *> {
+ public:
+ char name[30];
};
struct Bank {
char name[30];
uint size;
- Instrument *instruments[256];
+ Common::Array<Instrument> instruments;
};
+ bool _isSci1;
bool _playSwitch;
int _masterVolume;
int _frequency;
Envelope _envDecay;
Bank _bank; // Instrument bank
+ double _freqTable[48];
Channel _channels[MIDI_CHANNELS];
/* Internal channels */
Voice _voices[kChannels];
void setEnvelope(Voice *channel, Envelope *envelope, int phase);
- int interpolate(int8 *samples, frac_t offset);
+ void setOutputFrac(int voice);
+ int interpolate(int8 *samples, frac_t offset, bool isUnsigned);
void playInstrument(int16 *dest, Voice *channel, int count);
void changeInstrument(int channel, int instrument);
void stopChannel(int ch);
void stopNote(int ch, int note);
void startNote(int ch, int note, int velocity);
- Instrument *readInstrument(Common::File &file, int *id);
+ InstrumentSample *findInstrument(int instrument, int note);
+ void pitchWheel(int ch, uint16 pitch);
+
+ bool loadInstrumentsSCI0(Common::File &file);
+ bool loadInstrumentsSCI0Mac(Common::SeekableReadStream &file);
+ InstrumentSample *readInstrumentSCI0(Common::SeekableReadStream &file, int *id);
+ bool loadInstrumentsSCI1(Common::SeekableReadStream &file);
};
-void MidiDriver_Amiga::setEnvelope(Voice *channel, Envelope *envelope, int phase) {
+void MidiDriver_AmigaMac::setEnvelope(Voice *channel, Envelope *envelope, int phase) {
channel->envelope = phase;
channel->envelope_samples = envelope[phase].length;
@@ -168,25 +169,32 @@ void MidiDriver_Amiga::setEnvelope(Voice *channel, Envelope *envelope, int phase
channel->velocity = envelope[phase - 1].target;
}
-int MidiDriver_Amiga::interpolate(int8 *samples, frac_t offset) {
+int MidiDriver_AmigaMac::interpolate(int8 *samples, frac_t offset, bool isUnsigned) {
int x = fracToInt(offset);
- int diff = (samples[x + 1] - samples[x]) << 8;
+ if (isUnsigned) {
+ int s1 = (byte)samples[x] - 0x80;
+ int s2 = (byte)samples[x + 1] - 0x80;
+ int diff = (s2 - s1) << 8;
+ return (s1 << 8) + fracToInt(diff * (offset & FRAC_LO_MASK));
+ }
+
+ int diff = (samples[x + 1] - samples[x]) << 8;
return (samples[x] << 8) + fracToInt(diff * (offset & FRAC_LO_MASK));
}
-void MidiDriver_Amiga::playInstrument(int16 *dest, Voice *channel, int count) {
+void MidiDriver_AmigaMac::playInstrument(int16 *dest, Voice *channel, int count) {
int index = 0;
int vol = _channels[channel->hw_channel].volume;
- Instrument *instrument = _bank.instruments[channel->instrument];
+ InstrumentSample *instrument = findInstrument(channel->instrument, channel->note);
while (1) {
/* Available source samples until end of segment */
frac_t lin_avail;
- int seg_end, rem, i, amount;
+ uint32 seg_end, rem, i, amount;
int8 *samples;
- if (channel->looping) {
+ if (channel->looping && instrument->loop) {
samples = instrument->loop;
seg_end = instrument->loop_size;
} else {
@@ -208,11 +216,11 @@ void MidiDriver_Amiga::playInstrument(int16 *dest, Voice *channel, int count) {
amount = rem;
/* Stop at next envelope event */
- if ((channel->envelope_samples != -1) && (amount > channel->envelope_samples))
+ if ((channel->envelope_samples != -1) && (amount > (uint32)channel->envelope_samples))
amount = channel->envelope_samples;
for (i = 0; i < amount; i++) {
- dest[index++] = interpolate(samples, channel->offset) * channel->velocity / 64 * channel->note_velocity * vol / (127 * 127);
+ dest[index++] = interpolate(samples, channel->offset, instrument->isUnsigned) * channel->velocity / 64 * channel->note_velocity * vol / (127 * 127);
channel->offset += channel->rate;
}
@@ -263,7 +271,7 @@ void MidiDriver_Amiga::playInstrument(int16 *dest, Voice *channel, int count) {
if (index == count)
break;
- if (fracToInt(channel->offset) >= seg_end) {
+ if ((uint32)fracToInt(channel->offset) >= seg_end) {
if (instrument->mode & kModeLoop) {
/* Loop the samples */
channel->offset -= intToFrac(seg_end);
@@ -277,9 +285,9 @@ void MidiDriver_Amiga::playInstrument(int16 *dest, Voice *channel, int count) {
}
}
-void MidiDriver_Amiga::changeInstrument(int channel, int instrument) {
+void MidiDriver_AmigaMac::changeInstrument(int channel, int instrument) {
#ifdef DEBUG
- if (_bank.instruments[instrument])
+ if (_bank.instruments[instrument][0])
printf("[sfx:seq:amiga] Setting channel %i to \"%s\" (%i)\n", channel, _bank.instruments[instrument]->name, instrument);
else
warning("[sfx:seq:amiga] instrument %i does not exist (channel %i)", instrument, channel);
@@ -287,7 +295,7 @@ void MidiDriver_Amiga::changeInstrument(int channel, int instrument) {
_channels[channel].instrument = instrument;
}
-void MidiDriver_Amiga::stopChannel(int ch) {
+void MidiDriver_AmigaMac::stopChannel(int ch) {
int i;
/* Start decay phase for note on this hw channel, if any */
@@ -300,9 +308,16 @@ void MidiDriver_Amiga::stopChannel(int ch) {
}
}
-void MidiDriver_Amiga::stopNote(int ch, int note) {
+void MidiDriver_AmigaMac::pitchWheel(int ch, uint16 pitch) {
+ _channels[ch].pitch = pitch;
+
+ for (int i = 0; i < kChannels; i++)
+ if (_voices[i].note != -1 && _voices[i].hw_channel == ch)
+ setOutputFrac(i);
+}
+
+void MidiDriver_AmigaMac::stopNote(int ch, int note) {
int channel;
- Instrument *instrument;
for (channel = 0; channel < kChannels; channel++)
if (_voices[channel].note == note && _voices[channel].hw_channel == ch && !_voices[channel].decay)
@@ -315,15 +330,75 @@ void MidiDriver_Amiga::stopNote(int ch, int note) {
return;
}
- instrument = _bank.instruments[_voices[channel].instrument];
+ InstrumentSample *instrument = findInstrument(_voices[channel].instrument, note);
+
+ // FIXME: SCI1 envelope support is not perfect yet
/* Start the envelope phases for note-off if looping is on and envelope is enabled */
if ((instrument->mode & kModeLoop) && (instrument->envelope[0].length != 0))
setEnvelope(&_voices[channel], instrument->envelope, 2);
}
-void MidiDriver_Amiga::startNote(int ch, int note, int velocity) {
- Instrument *instrument;
+MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::findInstrument(int instrument, int note) {
+ if ((uint)instrument >= _bank.instruments.size())
+ return 0;
+
+ for (uint32 i = 0; i < _bank.instruments[instrument].size(); i++) {
+ InstrumentSample *sample = _bank.instruments[instrument][i];
+ if (note >= sample->startNote && note <= sample->endNote)
+ return sample;
+ }
+
+ return 0;
+}
+
+void MidiDriver_AmigaMac::setOutputFrac(int voice) {
+ InstrumentSample *instrument = findInstrument(_voices[voice].instrument, _voices[voice].note);
+
+ int fnote = 0;
+
+ if (instrument->fixedNote == -1) {
+ fnote = _voices[voice].note;
+
+ // Handle SCI0-style transposing here
+ if (!_isSci1)
+ fnote += instrument->transpose;
+
+ if (fnote < 0 || fnote > 127) {
+ warning("[sfx:seq:amiga] illegal note %i", fnote);
+ return;
+ }
+ } else
+ fnote = instrument->fixedNote;
+
+ // Compute rate for note
+ int mulFact = 1, divFact = 1;
+
+ fnote -= instrument->baseNote;
+ fnote *= 4;
+ // FIXME: check how SSCI maps this
+ fnote += (_channels[_voices[voice].hw_channel].pitch - 0x2000) / 169;
+
+ while (fnote < 0) {
+ divFact *= 2;
+ fnote += 12 * 4;
+ }
+
+ while (fnote >= 12 * 4) {
+ mulFact *= 2;
+ fnote -= 12 * 4;
+ }
+
+ double freq = _freqTable[fnote] * instrument->baseFreq * mulFact / divFact;
+
+ // Handle SCI1-style transposing here
+ if (instrument->transpose && _isSci1)
+ freq = freq + ((_freqTable[4] - 1.0) * freq * (double)instrument->transpose / (double)16);
+
+ _voices[voice].rate = doubleToFrac(freq / _frequency);
+}
+
+void MidiDriver_AmigaMac::startNote(int ch, int note, int velocity) {
int channel;
if (_channels[ch].instrument < 0 || _channels[ch].instrument > 255) {
@@ -331,7 +406,7 @@ void MidiDriver_Amiga::startNote(int ch, int note, int velocity) {
return;
}
- instrument = _bank.instruments[_channels[ch].instrument];
+ InstrumentSample *instrument = findInstrument(_channels[ch].instrument, note);
if (!instrument) {
warning("[sfx:seq:amiga] instrument %i does not exist", _channels[ch].instrument);
@@ -349,19 +424,6 @@ void MidiDriver_Amiga::startNote(int ch, int note, int velocity) {
stopChannel(ch);
- if (instrument->mode & kModePitch) {
- int fnote = note + instrument->transpose;
-
- if (fnote < 0 || fnote > 127) {
- warning("[sfx:seq:amiga] illegal note %i\n", fnote);
- return;
- }
-
- /* Compute rate for note */
- _voices[channel].rate = doubleToFrac(freq_table[fnote] / (double) _frequency);
- } else
- _voices[channel].rate = doubleToFrac(kBaseFreq / (double) _frequency);
-
_voices[channel].instrument = _channels[ch].instrument;
_voices[channel].note = note;
_voices[channel].note_velocity = velocity;
@@ -377,30 +439,34 @@ void MidiDriver_Amiga::startNote(int ch, int note, int velocity) {
_voices[channel].hw_channel = ch;
_voices[channel].decay = 0;
_voices[channel].looping = 0;
+ setOutputFrac(channel);
}
-MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &file, int *id) {
- Instrument *instrument;
+MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(Common::SeekableReadStream &file, int *id) {
byte header[61];
- int size;
- int seg_size[3];
- int loop_offset;
- int i;
if (file.read(header, 61) < 61) {
warning("[sfx:seq:amiga] failed to read instrument header");
return NULL;
}
- instrument = new Instrument;
-
+ int seg_size[3];
seg_size[0] = READ_BE_UINT16(header + 35) * 2;
seg_size[1] = READ_BE_UINT16(header + 41) * 2;
seg_size[2] = READ_BE_UINT16(header + 47) * 2;
+ InstrumentSample *instrument = new InstrumentSample;
+
+ instrument->startNote = 0;
+ instrument->endNote = 127;
+ instrument->isUnsigned = false;
+ instrument->baseFreq = kBaseFreq;
+ instrument->baseNote = 101;
+ instrument->fixedNote = 101;
+
instrument->mode = header[33];
instrument->transpose = (int8) header[34];
- for (i = 0; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
int length = (int8) header[49 + i];
if (length == 0 && i > 0)
@@ -413,13 +479,14 @@ MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &fil
/* Final target must be 0 */
instrument->envelope[3].target = 0;
- loop_offset = READ_BE_UINT32(header + 37) & ~1;
- size = seg_size[0] + seg_size[1] + seg_size[2];
+ int loop_offset = READ_BE_UINT32(header + 37) & ~1;
+ int size = seg_size[0] + seg_size[1] + seg_size[2];
*id = READ_BE_UINT16(header);
strncpy(instrument->name, (char *) header + 2, 29);
instrument->name[29] = 0;
+
#ifdef DEBUG
printf("[sfx:seq:amiga] Reading instrument %i: \"%s\" (%i bytes)\n",
*id, instrument->name, size);
@@ -429,6 +496,7 @@ MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &fil
printf(" Segment sizes: %i %i %i\n", seg_size[0], seg_size[1], seg_size[2]);
printf(" Segment offsets: 0 %i %i\n", loop_offset, read_int32(header + 43));
#endif
+
instrument->samples = (int8 *) malloc(size + 1);
if (file.read(instrument->samples, size) < (unsigned int)size) {
warning("[sfx:seq:amiga] failed to read instrument samples");
@@ -437,6 +505,9 @@ MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &fil
return NULL;
}
+ if (instrument->mode & kModePitch)
+ instrument->fixedNote = -1;
+
if (instrument->mode & kModeLoop) {
if (loop_offset + seg_size[1] > size) {
#ifdef DEBUG
@@ -463,6 +534,7 @@ MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &fil
instrument->loop[instrument->loop_size] = instrument->loop[0];
} else {
instrument->loop = NULL;
+ instrument->loop_size = 0;
instrument->size = size;
instrument->samples[instrument->size] = 0;
}
@@ -470,7 +542,7 @@ MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &fil
return instrument;
}
-uint32 MidiDriver_Amiga::property(int prop, uint32 param) {
+uint32 MidiDriver_AmigaMac::property(int prop, uint32 param) {
switch(prop) {
case MIDI_PROP_MASTER_VOLUME:
if (param != 0xffff)
@@ -482,28 +554,17 @@ uint32 MidiDriver_Amiga::property(int prop, uint32 param) {
return 0;
}
-int MidiDriver_Amiga::open() {
+int MidiDriver_AmigaMac::open() {
+ _isSci1 = false;
+
+ for (int i = 0; i < 48; i++)
+ _freqTable[i] = pow(2, i / (double)48);
+
_frequency = _mixer->getOutputRate();
_envDecay.length = _frequency / (32 * 64);
_envDecay.delta = 1;
_envDecay.target = 0;
- Common::File file;
- byte header[40];
-
- if (!file.open("bank.001")) {
- warning("[sfx:seq:amiga] file bank.001 not found");
- return Common::kUnknownError;
- }
-
- if (file.read(header, 40) < 40) {
- warning("[sfx:seq:amiga] failed to read header of file bank.001");
- return Common::kUnknownError;
- }
-
- for (uint i = 0; i < 256; i++)
- _bank.instruments[i] = NULL;
-
for (uint i = 0; i < kChannels; i++) {
_voices[i].note = -1;
_voices[i].hw_channel = 0;
@@ -513,32 +574,46 @@ int MidiDriver_Amiga::open() {
_channels[i].instrument = -1;
_channels[i].volume = 127;
_channels[i].pan = (i % 4 == 0 || i % 4 == 3 ? kPanLeft : kPanRight);
+ _channels[i].pitch = 0x2000;
}
- _bank.size = READ_BE_UINT16(header + 38);
- strncpy(_bank.name, (char *) header + 8, 29);
- _bank.name[29] = 0;
-#ifdef DEBUG
- printf("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
-#endif
-
- for (uint i = 0; i < _bank.size; i++) {
- int id;
- Instrument *instrument = readInstrument(file, &id);
+ Common::File file;
- if (!instrument) {
- warning("[sfx:seq:amiga] failed to read bank.001");
+ if (file.open("bank.001")) {
+ if (!loadInstrumentsSCI0(file)) {
+ file.close();
return Common::kUnknownError;
}
+ file.close();
+ } else {
+ ResourceManager *resMan = g_sci->getResMan();
- if (id < 0 || id > 255) {
- warning("[sfx:seq:amiga] Error: instrument ID out of bounds");
+ Resource *resource = resMan->findResource(ResourceId(kResourceTypePatch, 7), false);
+ if (!resource)
+ resource = resMan->findResource(ResourceId(kResourceTypePatch, 9), false);
+
+ // If we have a patch by this point, it's SCI1
+ if (resource)
+ _isSci1 = true;
+
+ // Check for the SCI0 Mac patch
+ if (!resource)
+ resource = resMan->findResource(ResourceId(kResourceTypePatch, 200), false);
+
+ if (!resource) {
+ warning("Could not open patch for Amiga sound driver");
return Common::kUnknownError;
}
- _bank.instruments[id] = instrument;
- }
+ Common::MemoryReadStream stream(resource->data, resource->size);
+ if (_isSci1) {
+ if (!loadInstrumentsSCI1(stream))
+ return Common::kUnknownError;
+ } else if (!loadInstrumentsSCI0Mac(stream))
+ return Common::kUnknownError;
+ }
+
MidiDriver_Emulated::open();
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO);
@@ -546,28 +621,30 @@ int MidiDriver_Amiga::open() {
return Common::kNoError;
}
-void MidiDriver_Amiga::close() {
+void MidiDriver_AmigaMac::close() {
_mixer->stopHandle(_mixerSoundHandle);
for (uint i = 0; i < _bank.size; i++) {
- if (_bank.instruments[i]) {
- if (_bank.instruments[i]->loop)
- free(_bank.instruments[i]->loop);
- free(_bank.instruments[i]->samples);
- delete _bank.instruments[i];
+ for (uint32 j = 0; j < _bank.instruments[i].size(); j++) {
+ if (_bank.instruments[i][j]) {
+ if (_bank.instruments[i][j]->loop)
+ free(_bank.instruments[i][j]->loop);
+ free(_bank.instruments[i][j]->samples);
+ delete _bank.instruments[i][j];
+ }
}
}
}
-void MidiDriver_Amiga::playSwitch(bool play) {
+void MidiDriver_AmigaMac::playSwitch(bool play) {
_playSwitch = play;
}
-void MidiDriver_Amiga::setVolume(byte volume_) {
+void MidiDriver_AmigaMac::setVolume(byte volume_) {
_masterVolume = volume_;
}
-void MidiDriver_Amiga::send(uint32 b) {
+void MidiDriver_AmigaMac::send(uint32 b) {
byte command = b & 0xf0;
byte channel = b & 0xf;
byte op1 = (b >> 8) & 0xff;
@@ -603,12 +680,15 @@ void MidiDriver_Amiga::send(uint32 b) {
case 0xc0:
changeInstrument(channel, op1);
break;
+ case 0xe0:
+ pitchWheel(channel, (op2 << 7) | op1);
+ break;
default:
warning("[sfx:seq:amiga] unknown event %02x", command);
}
}
-void MidiDriver_Amiga::generateSamples(int16 *data, int len) {
+void MidiDriver_AmigaMac::generateSamples(int16 *data, int len) {
if (len == 0)
return;
@@ -651,24 +731,256 @@ void MidiDriver_Amiga::generateSamples(int16 *data, int len) {
free(buffers);
}
-class MidiPlayer_Amiga : public MidiPlayer {
+bool MidiDriver_AmigaMac::loadInstrumentsSCI0(Common::File &file) {
+ _isSci1 = false;
+
+ byte header[40];
+
+ if (file.read(header, 40) < 40) {
+ warning("[sfx:seq:amiga] failed to read header of file bank.001");
+ return false;
+ }
+
+ _bank.size = READ_BE_UINT16(header + 38);
+ strncpy(_bank.name, (char *) header + 8, 29);
+ _bank.name[29] = 0;
+#ifdef DEBUG
+ printf("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
+#endif
+
+ for (uint i = 0; i < _bank.size; i++) {
+ int id;
+ InstrumentSample *instrument = readInstrumentSCI0(file, &id);
+
+ if (!instrument) {
+ warning("[sfx:seq:amiga] failed to read bank.001");
+ return false;
+ }
+
+ if (id < 0 || id > 255) {
+ warning("[sfx:seq:amiga] Error: instrument ID out of bounds");
+ return false;
+ }
+
+ if ((uint)id >= _bank.instruments.size())
+ _bank.instruments.resize(id + 1);
+
+ _bank.instruments[id].push_back(instrument);
+ memcpy(_bank.instruments[id].name, instrument->name, sizeof(instrument->name));
+ }
+
+ return true;
+}
+
+bool MidiDriver_AmigaMac::loadInstrumentsSCI0Mac(Common::SeekableReadStream &file) {
+ byte header[40];
+
+ if (file.read(header, 40) < 40) {
+ warning("[sfx:seq:amiga] failed to read header of file patch.200");
+ return false;
+ }
+
+ _bank.size = 128;
+ strncpy(_bank.name, (char *) header + 8, 29);
+ _bank.name[29] = 0;
+#ifdef DEBUG
+ printf("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
+#endif
+
+ Common::Array<uint32> instrumentOffsets;
+ instrumentOffsets.resize(_bank.size);
+ _bank.instruments.resize(_bank.size);
+
+ for (uint32 i = 0; i < _bank.size; i++)
+ instrumentOffsets[i] = file.readUint32BE();
+
+ for (uint i = 0; i < _bank.size; i++) {
+ // 0 signifies it doesn't exist
+ if (instrumentOffsets[i] == 0)
+ continue;
+
+ file.seek(instrumentOffsets[i]);
+
+ uint16 id = file.readUint16BE();
+ if (id != i)
+ error("Instrument number mismatch");
+
+ InstrumentSample *instrument = new InstrumentSample;
+
+ instrument->startNote = 0;
+ instrument->endNote = 127;
+ instrument->isUnsigned = true;
+ instrument->baseFreq = kBaseFreq;
+ instrument->baseNote = 101;
+ instrument->fixedNote = 101;
+ instrument->mode = file.readUint16BE();
+
+ // Read in the offsets
+ int32 seg_size[3];
+ seg_size[0] = file.readUint32BE();
+ seg_size[1] = file.readUint32BE();
+ seg_size[2] = file.readUint32BE();
+
+ instrument->transpose = file.readUint16BE();
+
+ for (byte j = 0; j < 4; j++) {
+ int length = (int8)file.readByte();
+
+ if (length == 0 && j > 0)
+ length = 256;
+
+ instrument->envelope[j].length = length * _frequency / 60;
+ instrument->envelope[j].delta = (int8)file.readByte();
+ instrument->envelope[j].target = file.readByte();
+ }
+
+ // Final target must be 0
+ instrument->envelope[3].target = 0;
+
+ file.read(instrument->name, 30);
+
+ if (instrument->mode & kModePitch)
+ instrument->fixedNote = -1;
+
+ uint32 size = seg_size[2];
+ uint32 loop_offset = seg_size[0];
+
+ instrument->samples = (int8 *)malloc(size + 1);
+ if (file.read(instrument->samples, size) < size) {
+ warning("[sfx:seq:amiga] failed to read instrument sample");
+ free(instrument->samples);
+ delete instrument;
+ continue;
+ }
+
+ if (instrument->mode & kModeLoop) {
+ instrument->size = seg_size[0];
+ instrument->loop_size = seg_size[1] - seg_size[0];
+
+ instrument->loop = (int8*)malloc(instrument->loop_size + 1);
+ memcpy(instrument->loop, instrument->samples + loop_offset, instrument->loop_size);
+
+ instrument->samples[instrument->size] = instrument->loop[0];
+ instrument->loop[instrument->loop_size] = instrument->loop[0];
+ } else {
+ instrument->loop = NULL;
+ instrument->loop_size = 0;
+ instrument->size = size;
+ instrument->samples[instrument->size] = (int8)0x80;
+ }
+
+ _bank.instruments[id].push_back(instrument);
+ memcpy(_bank.instruments[id].name, instrument->name, sizeof(instrument->name));
+ }
+
+ return true;
+}
+
+bool MidiDriver_AmigaMac::loadInstrumentsSCI1(Common::SeekableReadStream &file) {
+ _bank.size = 128;
+
+ Common::Array<uint32> instrumentOffsets;
+ instrumentOffsets.resize(_bank.size);
+ _bank.instruments.resize(_bank.size);
+
+ for (uint32 i = 0; i < _bank.size; i++)
+ instrumentOffsets[i] = file.readUint32BE();
+
+ for (uint32 i = 0; i < _bank.size; i++) {
+ // 0 signifies it doesn't exist
+ if (instrumentOffsets[i] == 0)
+ continue;
+
+ file.seek(instrumentOffsets[i]);
+
+ // Read in the instrument name
+ file.read(_bank.instruments[i].name, 10); // last two bytes are always 0
+
+ for (uint32 j = 0; ; j++) {
+ InstrumentSample *sample = new InstrumentSample;
+ memset(sample, 0, sizeof(InstrumentSample));
+
+ sample->startNote = file.readSint16BE();
+
+ // startNote being -1 signifies we're done with this instrument
+ if (sample->startNote == -1) {
+ delete sample;
+ break;
+ }
+
+ sample->endNote = file.readSint16BE();
+ uint32 samplePtr = file.readUint32BE();
+ sample->transpose = file.readSint16BE();
+ for (int env = 0; env < 3; env++) {
+ sample->envelope[env].length = file.readByte() * _frequency / 60;
+ sample->envelope[env].delta = (env == 0 ? 10 : -10);
+ sample->envelope[env].target = file.readByte();
+ }
+
+ sample->envelope[3].length = 0;
+ sample->fixedNote = file.readSint16BE();
+ int16 loop = file.readSint16BE();
+ uint32 nextSamplePos = file.pos();
+
+ file.seek(samplePtr);
+ file.read(sample->name, 8);
+
+ sample->isUnsigned = file.readUint16BE() == 0;
+ uint16 phase1Offset = file.readUint16BE();
+ uint16 phase1End = file.readUint16BE();
+ uint16 phase2Offset = file.readUint16BE();
+ uint16 phase2End = file.readUint16BE();
+ sample->baseNote = file.readUint16BE();
+ uint32 periodTableOffset = file.readUint32BE();
+ uint32 sampleDataPos = file.pos();
+
+ sample->size = phase1End - phase1Offset + 1;
+ sample->loop_size = phase2End - phase2Offset + 1;
+
+ sample->samples = (int8 *)malloc(sample->size + 1);
+ file.seek(phase1Offset + sampleDataPos);
+ file.read(sample->samples, sample->size);
+ sample->samples[sample->size] = (sample->isUnsigned ? (int8)0x80 : 0);
+
+ if (loop == 0 && sample->loop_size > 1) {
+ sample->loop = (int8 *)malloc(sample->loop_size + 1);
+ file.seek(phase2Offset + sampleDataPos);
+ file.read(sample->loop, sample->loop_size);
+ sample->mode |= kModeLoop;
+ sample->samples[sample->size] = sample->loop[0];
+ sample->loop[sample->loop_size] = sample->loop[0];
+ }
+
+ _bank.instruments[i].push_back(sample);
+
+ file.seek(periodTableOffset + 0xe0);
+ sample->baseFreq = file.readUint16BE();
+
+ file.seek(nextSamplePos);
+ }
+ }
+
+ return true;
+}
+
+class MidiPlayer_AmigaMac : public MidiPlayer {
public:
- MidiPlayer_Amiga(SciVersion version) : MidiPlayer(version) { _driver = new MidiDriver_Amiga(g_system->getMixer()); }
+ MidiPlayer_AmigaMac(SciVersion version) : MidiPlayer(version) { _driver = new MidiDriver_AmigaMac(g_system->getMixer()); }
byte getPlayId();
- int getPolyphony() const { return MidiDriver_Amiga::kVoices; }
+ int getPolyphony() const { return MidiDriver_AmigaMac::kVoices; }
bool hasRhythmChannel() const { return false; }
- void setVolume(byte volume) { static_cast<MidiDriver_Amiga *>(_driver)->setVolume(volume); }
- void playSwitch(bool play) { static_cast<MidiDriver_Amiga *>(_driver)->playSwitch(play); }
+ void setVolume(byte volume) { static_cast<MidiDriver_AmigaMac *>(_driver)->setVolume(volume); }
+ void playSwitch(bool play) { static_cast<MidiDriver_AmigaMac *>(_driver)->playSwitch(play); }
void loadInstrument(int idx, byte *data);
};
-MidiPlayer *MidiPlayer_Amiga_create(SciVersion version) {
- return new MidiPlayer_Amiga(version);
+MidiPlayer *MidiPlayer_AmigaMac_create(SciVersion version) {
+ return new MidiPlayer_AmigaMac(version);
}
-byte MidiPlayer_Amiga::getPlayId() {
- if (_version != SCI_VERSION_0_LATE)
- error("Amiga sound support not available for this SCI version");
+byte MidiPlayer_AmigaMac::getPlayId() {
+ if (_version > SCI_VERSION_0_LATE)
+ return 0x06;
return 0x40;
}
diff --git a/engines/sci/sound/drivers/fb01.cpp b/engines/sci/sound/drivers/fb01.cpp
index 7e9fbd51a1..ab9b2e3df5 100644
--- a/engines/sci/sound/drivers/fb01.cpp
+++ b/engines/sci/sound/drivers/fb01.cpp
@@ -128,8 +128,8 @@ private:
};
MidiPlayer_Fb01::MidiPlayer_Fb01(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _timerParam(NULL), _timerProc(NULL) {
- MidiDriverType midiType = MidiDriver::detectMusicDriver(MDT_MIDI);
- _driver = createMidi(midiType);
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI);
+ _driver = createMidi(dev);
_sysExBuf[0] = 0x43;
_sysExBuf[1] = 0x75;
diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp
index 2432a8fab0..1ef0781906 100644
--- a/engines/sci/sound/drivers/midi.cpp
+++ b/engines/sci/sound/drivers/midi.cpp
@@ -55,6 +55,7 @@ public:
bool hasRhythmChannel() const { return true; }
byte getPlayId();
int getPolyphony() const { return kVoices; }
+ int getFirstChannel();
void setVolume(byte volume);
int getVolume();
void setReverb(byte reverb);
@@ -119,10 +120,10 @@ private:
};
MidiPlayer_Midi::MidiPlayer_Midi(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _isMt32(false), _hasReverb(false), _isOldPatchFormat(true) {
- MidiDriverType midiType = MidiDriver::detectMusicDriver(MDT_MIDI);
- _driver = createMidi(midiType);
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI);
+ _driver = createMidi(dev);
- if (midiType == MD_MT32 || ConfMan.getBool("native_mt32"))
+ if (MidiDriver::getMusicType(dev) == MT_MT32 || ConfMan.getBool("native_mt32"))
_isMt32 = true;
_sysExBuf[0] = 0x41;
@@ -271,6 +272,17 @@ void MidiPlayer_Midi::setPatch(int channel, int patch) {
_driver->setPitchBendRange(channel, bendRange);
_driver->send(0xc0 | channel, _patchMap[patch], 0);
+
+ // Send a pointless command to work around a firmware bug in common
+ // USB-MIDI cables. If the first MIDI command in a USB packet is a
+ // Cx or Dx command, the second command in the packet is dropped
+ // somewhere.
+ // FIXME: consider putting a workaround in the MIDI backend drivers
+ // instead.
+ // Known to be affected: alsa, coremidi
+ // Known *not* to be affected: windows (only seems to send one MIDI
+ // command per USB packet even if the device allows larger packets).
+ _driver->send(0xb0 | channel, 0x0a, _channels[channel].pan);
}
void MidiPlayer_Midi::send(uint32 b) {
@@ -306,6 +318,13 @@ void MidiPlayer_Midi::send(uint32 b) {
}
}
+// We return 1 for mt32, because if we remap channels to 0 for mt32, those won't get played at all
+int MidiPlayer_Midi::getFirstChannel() {
+ if (_isMt32)
+ return 1;
+ return 0;
+}
+
void MidiPlayer_Midi::setVolume(byte volume) {
_masterVolume = volume;
diff --git a/engines/sci/sound/drivers/mididriver.h b/engines/sci/sound/drivers/mididriver.h
index 12d3e57f5d..2db6f25c70 100644
--- a/engines/sci/sound/drivers/mididriver.h
+++ b/engines/sci/sound/drivers/mididriver.h
@@ -86,6 +86,7 @@ public:
virtual byte getPlayId() = 0;
virtual int getPolyphony() const = 0;
+ virtual int getFirstChannel() { return 0; }
virtual void setVolume(byte volume) {
if(_driver)
@@ -112,7 +113,7 @@ protected:
};
extern MidiPlayer *MidiPlayer_AdLib_create(SciVersion version);
-extern MidiPlayer *MidiPlayer_Amiga_create(SciVersion version);
+extern MidiPlayer *MidiPlayer_AmigaMac_create(SciVersion version);
extern MidiPlayer *MidiPlayer_PCJr_create(SciVersion version);
extern MidiPlayer *MidiPlayer_PCSpeaker_create(SciVersion version);
extern MidiPlayer *MidiPlayer_Midi_create(SciVersion version);
diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp
index 2068ea9a33..6ec28a8b02 100644
--- a/engines/sci/sound/midiparser_sci.cpp
+++ b/engines/sci/sound/midiparser_sci.cpp
@@ -43,27 +43,39 @@ enum SciMidiCommands {
// MidiParser_SCI
//
-MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion) :
+MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) :
MidiParser() {
_soundVersion = soundVersion;
+ _music = music;
_mixedData = NULL;
// mididata contains delta in 1/60th second
// values of ppqn and tempo are found experimentally and may be wrong
_ppqn = 1;
setTempo(16667);
- _volume = 0;
+ _volume = 127;
_signalSet = false;
_signalToSet = 0;
_dataincAdd = false;
_dataincToAdd = 0;
_resetOnPause = false;
- _channelsUsed = 0;
+ _pSnd = 0;
}
MidiParser_SCI::~MidiParser_SCI() {
unloadMusic();
+ // we do this, so that MidiParser won't be able to call his own ::allNotesOff()
+ // this one would affect all channels and we can't let that happen
+ _driver = 0;
+}
+
+void MidiParser_SCI::mainThreadBegin() {
+ _mainThreadCalled = true;
+}
+
+void MidiParser_SCI::mainThreadEnd() {
+ _mainThreadCalled = false;
}
bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion) {
@@ -72,7 +84,14 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in
_pSnd = psnd;
_soundVersion = soundVersion;
- setVolume(psnd->volume);
+ for (int i = 0; i < 16; i++) {
+ _channelUsed[i] = false;
+ _channelRemap[i] = -1;
+ _channelMuted[i] = false;
+ _channelVolume[i] = 127;
+ }
+ _channelRemap[9] = 9; // never map channel 9, because that's used for percussion
+ _channelRemap[15] = 15; // never map channel 15, because thats used by sierra internally
if (channelFilterMask) {
// SCI0 only has 1 data stream, but we need to filter out channels depending on music hardware selection
@@ -83,31 +102,272 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in
_num_tracks = 1;
_tracks[0] = _mixedData;
- setTrack(0);
+ if (_pSnd)
+ setTrack(0);
_loopTick = 0;
- _channelsUsed = 0;
-
- if (_soundVersion <= SCI_VERSION_0_LATE) {
- // Set initial voice count
- for (int i = 0; i < 16; ++i) {
- byte voiceCount = 0;
- if (channelFilterMask & (1 << i))
- voiceCount = psnd->soundRes->getInitialVoiceCount(i);
- _driver->send(0xB0 | i, 0x4B, voiceCount);
+
+ return true;
+}
+
+byte MidiParser_SCI::midiGetNextChannel(long ticker) {
+ byte curr = 0xFF;
+ long closest = ticker + 1000000, next = 0;
+
+ for (int i = 0; i < _track->channelCount; i++) {
+ if (_track->channels[i].time == -1) // channel ended
+ continue;
+ SoundResource::Channel *curChannel = &_track->channels[i];
+ if (curChannel->curPos >= curChannel->size)
+ continue;
+ next = curChannel->data[curChannel->curPos]; // when the next event should occur
+ if (next == 0xF8) // 0xF8 means 240 ticks delay
+ next = 240;
+ next += _track->channels[i].time;
+ if (next < closest) {
+ curr = i;
+ closest = next;
+ }
+ }
+
+ return curr;
+}
+
+byte *MidiParser_SCI::midiMixChannels() {
+ int totalSize = 0;
+
+ for (int i = 0; i < _track->channelCount; i++) {
+ _track->channels[i].time = 0;
+ _track->channels[i].prev = 0;
+ _track->channels[i].curPos = 0;
+ totalSize += _track->channels[i].size;
+ }
+
+ byte *outData = new byte[totalSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data
+ _mixedData = outData;
+ long ticker = 0;
+ byte channelNr, curDelta;
+ byte midiCommand = 0, midiParam, global_prev = 0;
+ long newDelta;
+ SoundResource::Channel *channel;
+
+ while ((channelNr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel
+ channel = &_track->channels[channelNr];
+ curDelta = channel->data[channel->curPos++];
+ channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the command is supposed to occur
+ if (curDelta == 0xF8)
+ continue;
+ newDelta = channel->time - ticker;
+ ticker += newDelta;
+
+ midiCommand = channel->data[channel->curPos++];
+ if (midiCommand != kEndOfTrack) {
+ // Write delta
+ while (newDelta > 240) {
+ *outData++ = 0xF8;
+ newDelta -= 240;
+ }
+ *outData++ = (byte)newDelta;
+ }
+ // Write command
+ switch (midiCommand) {
+ case 0xF0: // sysEx
+ *outData++ = midiCommand;
+ do {
+ midiParam = channel->data[channel->curPos++];
+ *outData++ = midiParam;
+ } while (midiParam != 0xF7);
+ break;
+ case kEndOfTrack: // end of channel
+ channel->time = -1;
+ break;
+ default: // MIDI command
+ if (midiCommand & 0x80) {
+ midiParam = channel->data[channel->curPos++];
+ } else {// running status
+ midiParam = midiCommand;
+ midiCommand = channel->prev;
+ }
+
+ // remember which channel got used for channel remapping
+ byte midiChannel = midiCommand & 0xF;
+ _channelUsed[midiChannel] = true;
+
+ if (midiCommand != global_prev)
+ *outData++ = midiCommand;
+ *outData++ = midiParam;
+ if (nMidiParams[(midiCommand >> 4) - 8] == 2)
+ *outData++ = channel->data[channel->curPos++];
+ channel->prev = midiCommand;
+ global_prev = midiCommand;
+ }
+ }
+
+ // Insert stop event
+ *outData++ = 0; // Delta
+ *outData++ = 0xFF; // Meta event
+ *outData++ = 0x2F; // End of track (EOT)
+ *outData++ = 0x00;
+ *outData++ = 0x00;
+ return _mixedData;
+}
+
+// This is used for SCI0 sound-data. SCI0 only has one stream that may
+// contain several channels and according to output device we remove
+// certain channels from that data.
+byte *MidiParser_SCI::midiFilterChannels(int channelMask) {
+ SoundResource::Channel *channel = &_track->channels[0];
+ byte *channelData = channel->data;
+ byte *channelDataEnd = channel->data + channel->size;
+ byte *outData = new byte[channel->size + 5];
+ byte curChannel = 15, curByte, curDelta;
+ byte command = 0, lastCommand = 0;
+ int delta = 0;
+ int midiParamCount = 0;
+
+ _mixedData = outData;
+
+ while (channelData < channelDataEnd) {
+ curDelta = *channelData++;
+ if (curDelta == 0xF8) {
+ delta += 240;
+ continue;
+ }
+ delta += curDelta;
+ curByte = *channelData++;
+
+ switch (curByte) {
+ case 0xF0: // sysEx
+ case kEndOfTrack: // end of channel
+ command = curByte;
+ curChannel = 15;
+ break;
+ default:
+ if (curByte & 0x80) {
+ command = curByte;
+ curChannel = command & 0x0F;
+ midiParamCount = nMidiParams[(command >> 4) - 8];
+ }
+ }
+ if ((1 << curChannel) & channelMask) {
+ if (command != kEndOfTrack) {
+ // Write delta
+ while (delta > 240) {
+ *outData++ = 0xF8;
+ delta -= 240;
+ }
+ *outData++ = (byte)delta;
+ delta = 0;
+ }
+ // Write command
+ switch (command) {
+ case 0xF0: // sysEx
+ *outData++ = command;
+ do {
+ curByte = *channelData++;
+ *outData++ = curByte; // out
+ } while (curByte != 0xF7);
+ lastCommand = command;
+ break;
+
+ case kEndOfTrack: // end of channel
+ break;
+
+ default: // MIDI command
+ // remember which channel got used for channel remapping
+ byte midiChannel = command & 0xF;
+ _channelUsed[midiChannel] = true;
+
+ if (lastCommand != command) {
+ *outData++ = command;
+ lastCommand = command;
+ }
+ if (midiParamCount > 0) {
+ if (curByte & 0x80)
+ *outData++ = *channelData++;
+ else
+ *outData++ = curByte;
+ }
+ if (midiParamCount > 1) {
+ *outData++ = *channelData++;
+ }
+ }
+ } else {
+ if (curByte & 0x80)
+ channelData += midiParamCount;
+ else
+ channelData += midiParamCount - 1;
+ }
+ }
+
+ // Insert stop event
+ *outData++ = 0; // Delta
+ *outData++ = 0xFF; // Meta event
+ *outData++ = 0x2F; // End of track (EOT)
+ *outData++ = 0x00;
+ *outData++ = 0x00;
+
+ return _mixedData;
+}
+
+// This will get called right before actual playing and will try to own the used channels
+void MidiParser_SCI::tryToOwnChannels() {
+ // We don't have SciMusic in case debug command show_instruments is used
+ if (!_music)
+ return;
+ for (int curChannel = 0; curChannel < 15; curChannel++) {
+ if (_channelUsed[curChannel]) {
+ if (_channelRemap[curChannel] == -1) {
+ _channelRemap[curChannel] = _music->tryToOwnChannel(_pSnd, curChannel);
+ }
+ }
+ }
+}
+
+void MidiParser_SCI::lostChannels() {
+ for (int curChannel = 0; curChannel < 15; curChannel++)
+ if ((_channelUsed[curChannel]) && (curChannel != 9))
+ _channelRemap[curChannel] = -1;
+}
+
+void MidiParser_SCI::sendInitCommands() {
+ // reset our "global" volume and channel volumes
+ _volume = 127;
+ for (int i = 0; i < 16; i++)
+ _channelVolume[i] = 127;
+
+ // Set initial voice count
+ if (_pSnd) {
+ if (_soundVersion <= SCI_VERSION_0_LATE) {
+ for (int i = 0; i < 15; ++i) {
+ byte voiceCount = 0;
+ if (_channelUsed[i]) {
+ voiceCount = _pSnd->soundRes->getInitialVoiceCount(i);
+ sendToDriver(0xB0 | i, 0x4B, voiceCount);
+ }
+ }
}
}
// Send a velocity off signal to all channels
- for (int i = 0; i < 16; ++i) {
- _driver->send(0xB0 | i, 0x4E, 0); // Reset velocity
+ for (int i = 0; i < 15; ++i) {
+ if (_channelUsed[i])
+ sendToDriver(0xB0 | i, 0x4E, 0); // Reset velocity
}
- return true;
+ // Center the pitch wheels and hold pedal in preparation for the next piece of music
+ for (int i = 0; i < 16; ++i) {
+ if (_channelUsed[i]) {
+ sendToDriver(0xE0 | i, 0, 0x40); // Reset pitch wheel
+ sendToDriver(0xB0 | i, 0x40, 0); // Reset hold pedal
+ }
+ }
}
void MidiParser_SCI::unloadMusic() {
- resetTracking();
- allNotesOff();
+ if (_pSnd) {
+ resetTracking();
+ allNotesOff();
+ }
_num_tracks = 0;
_active_track = 255;
_resetOnPause = false;
@@ -116,33 +376,77 @@ void MidiParser_SCI::unloadMusic() {
delete[] _mixedData;
_mixedData = NULL;
}
+}
- // Center the pitch wheels and hold pedal in preparation for the next piece of music
- if (_driver) {
- for (int i = 0; i < 16; ++i) {
- if (_channelsUsed & (1 << i)) {
- _driver->send(0xE0 | i, 0, 0x40); // Reset pitch wheel
- _driver->send(0xB0 | i, 0x40, 0); // Reset hold pedal
- }
+// this is used for scripts sending midi commands to us. we verify in that case that the channel is actually
+// used, so that channel remapping will work as well and then send them on
+void MidiParser_SCI::sendFromScriptToDriver(uint32 midi) {
+ byte midiChannel = midi & 0xf;
+
+ if (!_channelUsed[midiChannel]) {
+ // trying to send to an unused channel
+ // this happens for cmdSendMidi at least in sq1vga right at the start, it's a script issue
+ return;
+ }
+ if (_channelRemap[midiChannel] == -1) {
+ // trying to send to an unmapped channel
+ // this happens for cmdSendMidi at least in sq1vga right at the start, scripts are pausing the sound
+ // and then sending manually. it's a script issue
+ return;
+ }
+ sendToDriver(midi);
+}
+
+void MidiParser_SCI::sendToDriver(uint32 midi) {
+ byte midiChannel = midi & 0xf;
+
+ if ((midi & 0xFFF0) == 0x4EB0) {
+ // this is channel mute only for sci1
+ // it's velocity control for sci0
+ if (_soundVersion >= SCI_VERSION_1_EARLY) {
+ _channelMuted[midiChannel] = midi & 0xFF0000 ? true : false;
+ return; // don't send this to driver at all
}
}
+
+ // Is channel muted? if so, don't send command
+ if (_channelMuted[midiChannel])
+ return;
+
+ if ((midi & 0xFFF0) == 0x07B0) {
+ // someone trying to set channel volume?
+ int channelVolume = (midi >> 16) & 0xFF;
+ // Remember, if we need to set it ourselves
+ _channelVolume[midiChannel] = channelVolume;
+ // Adjust volume accordingly to current "global" volume
+ channelVolume = channelVolume * _volume / 127;
+ midi = (midi & 0xFFF0) | ((channelVolume & 0xFF) << 16);
+ }
+
+ // Channel remapping
+ int16 realChannel = _channelRemap[midiChannel];
+ if (realChannel == -1)
+ return;
+
+ midi = (midi & 0xFFFFFFF0) | realChannel;
+ if (_mainThreadCalled)
+ _music->putMidiCommandInQueue(midi);
+ else
+ _driver->send(midi);
}
void MidiParser_SCI::parseNextEvent(EventInfo &info) {
- // Monitor which channels are used by this song
- _channelsUsed |= (1 << info.channel());
-
// Set signal AFTER waiting for delta, otherwise we would set signal too soon resulting in all sorts of bugs
if (_dataincAdd) {
_dataincAdd = false;
_pSnd->dataInc += _dataincToAdd;
_pSnd->signal = 0x7f + _pSnd->dataInc;
- debugC(2, kDebugLevelSound, "datainc %04x", _dataincToAdd);
+ debugC(4, kDebugLevelSound, "datainc %04x", _dataincToAdd);
}
if (_signalSet) {
_signalSet = false;
_pSnd->signal = _signalToSet;
- debugC(2, kDebugLevelSound, "signal %04x", _signalToSet);
+ debugC(4, kDebugLevelSound, "signal %04x", _signalToSet);
}
info.start = _position._play_pos;
@@ -168,10 +472,16 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
info.basic.param2 = 0;
if (info.channel() == 0xF) {// SCI special case
if (info.basic.param1 != kSetSignalLoop) {
- _signalSet = true;
- _signalToSet = info.basic.param1;
+ // at least in kq5/french&mac the first scene in the intro has a song that sets signal to 4 immediately
+ // on tick 0. Signal isn't set at that point by sierra sci and it would cause the castle daventry text to
+ // get immediately removed, so we currently filter it.
+ // Sierra SCI ignores them as well at that time
+ if ((_position._play_tick) || (info.delta)) {
+ _signalSet = true;
+ _signalToSet = info.basic.param1;
+ }
} else {
- _loopTick = _position._play_tick;
+ _loopTick = _position._play_tick + info.delta;
}
}
break;
@@ -207,10 +517,11 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
break;
case SCI_VERSION_1_EARLY:
case SCI_VERSION_1_LATE:
+ case SCI_VERSION_2_1:
_dataincToAdd = 1;
break;
default:
- break;
+ error("unsupported _soundVersion");
}
break;
case kResetOnPause:
@@ -230,7 +541,6 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
case 0x0A: // pan
case 0x0B: // expression
case 0x40: // sustain
- case 0x4E: // velocity control
case 0x79: // reset all
case 0x7B: // notes off
// These are all handled by the music driver, so ignore them
@@ -244,8 +554,6 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
break;
}
}
- if (info.basic.param1 == 7) // channel volume change -scale it
- info.basic.param2 = info.basic.param2 * _volume / MUSIC_VOLUME_MAX;
info.length = 0;
break;
@@ -302,7 +610,7 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
_pSnd->status = kSoundStopped;
_pSnd->signal = SIGNAL_OFFSET;
- debugC(2, kDebugLevelSound, "signal EOT");
+ debugC(4, kDebugLevelSound, "signal EOT");
}
}
break;
@@ -314,245 +622,67 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
}// switch (info.command())
}
+void MidiParser_SCI::allNotesOff() {
+ if (!_driver)
+ return;
-byte MidiParser_SCI::midiGetNextChannel(long ticker) {
- byte curr = 0xFF;
- long closest = ticker + 1000000, next = 0;
-
- for (int i = 0; i < _track->channelCount; i++) {
- if (_track->channels[i].time == -1) // channel ended
- continue;
- next = *_track->channels[i].data; // when the next event shoudl occur
- if (next == 0xF8) // 0xF8 means 240 ticks delay
- next = 240;
- next += _track->channels[i].time;
- if (next < closest) {
- curr = i;
- closest = next;
- }
- }
-
- return curr;
-}
-
-byte *MidiParser_SCI::midiMixChannels() {
- int totalSize = 0;
- byte **dataPtr = new byte *[_track->channelCount];
-
- for (int i = 0; i < _track->channelCount; i++) {
- dataPtr[i] = _track->channels[i].data;
- _track->channels[i].time = 0;
- _track->channels[i].prev = 0;
- totalSize += _track->channels[i].size;
- }
-
- byte *outData = new byte[totalSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data
- _mixedData = outData;
- long ticker = 0;
- byte curr, curDelta;
- byte command = 0, par1, global_prev = 0;
- long new_delta;
- SoundResource::Channel *channel;
-
- while ((curr = midiGetNextChannel(ticker)) != 0xFF) { // there is still active channel
- channel = &_track->channels[curr];
- curDelta = *channel->data++;
- channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the comamnd is supposed to occur
- if (curDelta == 0xF8)
- continue;
- new_delta = channel->time - ticker;
- ticker += new_delta;
+ int i, j;
- command = *channel->data++;
- if (command != kEndOfTrack) {
- debugC(2, kDebugLevelSound, "\nDELTA ");
- // Write delta
- while (new_delta > 240) {
- *outData++ = 0xF8;
- debugC(2, kDebugLevelSound, "F8 ");
- new_delta -= 240;
- }
- *outData++ = (byte)new_delta;
- debugC(2, kDebugLevelSound, "%02X ", (uint32)new_delta);
- }
- // Write command
- switch (command) {
- case 0xF0: // sysEx
- *outData++ = command;
- debugC(2, kDebugLevelSound, "%02X ", command);
- do {
- par1 = *channel->data++;
- *outData++ = par1; // out
- } while (par1 != 0xF7);
- break;
- case kEndOfTrack: // end of channel
- channel->time = -1; // FIXME
- break;
- default: // MIDI command
- if (command & 0x80)
- par1 = *channel->data++;
- else {// running status
- par1 = command;
- command = channel->prev;
+ // Turn off all active notes
+ for (i = 0; i < 128; ++i) {
+ for (j = 0; j < 16; ++j) {
+ if ((_active_notes[i] & (1 << j)) && (_channelRemap[j] != -1)){
+ sendToDriver(0x80 | j, i, 0);
}
- if (command != global_prev)
- *outData++ = command; // out command
- *outData++ = par1;// pout par1
- if (nMidiParams[(command >> 4) - 8] == 2)
- *outData++ = *channel->data++; // out par2
- channel->prev = command;
- global_prev = command;
- }// switch(command)
- }// while (curr)
-
- // Insert stop event
- *outData++ = 0; // Delta
- *outData++ = 0xFF; // Meta event
- *outData++ = 0x2F; // End of track (EOT)
- *outData++ = 0x00;
- *outData++ = 0x00;
-
- for (int channelNr = 0; channelNr < _track->channelCount; channelNr++)
- _track->channels[channelNr].data = dataPtr[channelNr];
-
- delete[] dataPtr;
- return _mixedData;
-}
-
-// This is used for SCI0 sound-data. SCI0 only has one stream that may
-// contain several channels and according to output device we remove
-// certain channels from that data.
-byte *MidiParser_SCI::midiFilterChannels(int channelMask) {
- SoundResource::Channel *channel = &_track->channels[0];
- byte *channelData = channel->data;
- byte *channelDataEnd = channel->data + channel->size;
- byte *outData = new byte[channel->size + 5];
- byte curChannel = 15, curByte, curDelta;
- byte command = 0, lastCommand = 0;
- int delta = 0;
- int midiParamCount = 0;
-
- _mixedData = outData;
-
- while (channelData < channelDataEnd) {
- curDelta = *channelData++;
- if (curDelta == 0xF8) {
- delta += 240;
- continue;
}
- delta += curDelta;
- curByte = *channelData++;
+ }
- switch (curByte) {
- case 0xF0: // sysEx
- case kEndOfTrack: // end of channel
- command = curByte;
- curChannel = 15;
- break;
- default:
- if (curByte & 0x80) {
- command = curByte;
- curChannel = command & 0x0F;
- midiParamCount = nMidiParams[(command >> 4) - 8];
- }
+ // Turn off all hanging notes
+ for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) {
+ byte midiChannel = _hanging_notes[i].channel;
+ if ((_hanging_notes[i].time_left) && (_channelRemap[midiChannel] != -1)) {
+ sendToDriver(0x80 | midiChannel, _hanging_notes[i].note, 0);
+ _hanging_notes[i].time_left = 0;
}
- if ((1 << curChannel) & channelMask) {
- if (command != kEndOfTrack) {
- debugC(2, kDebugLevelSound, "\nDELTA ");
- // Write delta
- while (delta > 240) {
- *outData++ = 0xF8;
- debugC(2, kDebugLevelSound, "F8 ");
- delta -= 240;
- }
- *outData++ = (byte)delta;
- debugC(2, kDebugLevelSound, "%02X ", delta);
- delta = 0;
- }
- // Write command
- switch (command) {
- case 0xF0: // sysEx
- *outData++ = command;
- debugC(2, kDebugLevelSound, "%02X ", command);
- do {
- curByte = *channelData++;
- *outData++ = curByte; // out
- } while (curByte != 0xF7);
- lastCommand = command;
- break;
+ }
+ _hanging_notes_count = 0;
- case kEndOfTrack: // end of channel
- break;
+ // To be sure, send an "All Note Off" event (but not all MIDI devices
+ // support this...).
- default: // MIDI command
- if (lastCommand != command) {
- *outData++ = command;
- debugC(2, kDebugLevelSound, "%02X ", command);
- lastCommand = command;
- }
- if (midiParamCount > 0) {
- if (curByte & 0x80) {
- debugC(2, kDebugLevelSound, "%02X ", *channelData);
- *outData++ = *channelData++;
- } else {
- debugC(2, kDebugLevelSound, "%02X ", curByte);
- *outData++ = curByte;
- }
- }
- if (midiParamCount > 1) {
- debugC(2, kDebugLevelSound, "%02X ", *channelData);
- *outData++ = *channelData++;
- }
- }
- } else {
- if (curByte & 0x80) {
- channelData += midiParamCount;
- } else {
- channelData += midiParamCount - 1;
- }
- }
+ for (i = 0; i < 16; ++i) {
+ if (_channelRemap[i] != -1)
+ sendToDriver(0xB0 | i, 0x7b, 0); // All notes off
}
- // Insert stop event
- *outData++ = 0; // Delta
- *outData++ = 0xFF; // Meta event
- *outData++ = 0x2F; // End of track (EOT)
- *outData++ = 0x00;
- *outData++ = 0x00;
-
- return _mixedData;
+ memset(_active_notes, 0, sizeof(_active_notes));
}
void MidiParser_SCI::setVolume(byte volume) {
- // FIXME: This receives values > 127... throw a warning for now and clip the variable
- if (volume > MUSIC_VOLUME_MAX) {
- warning("attempted to set an invalid volume(%d)", volume);
- volume = MUSIC_VOLUME_MAX; // reset
- }
-
assert(volume <= MUSIC_VOLUME_MAX);
- if (_volume != volume) {
- _volume = volume;
-
- switch (_soundVersion) {
- case SCI_VERSION_0_EARLY:
- case SCI_VERSION_0_LATE: {
- int16 globalVolume = _volume * 15 / 127;
- ((MidiPlayer *)_driver)->setVolume(globalVolume);
- break;
- }
+ _volume = volume;
+
+ switch (_soundVersion) {
+ case SCI_VERSION_0_EARLY:
+ case SCI_VERSION_0_LATE: {
+ // SCI0 adlib driver doesn't support channel volumes, so we need to go this way
+ // TODO: this should take the actual master volume into account
+ int16 globalVolume = _volume * 15 / 127;
+ ((MidiPlayer *)_driver)->setVolume(globalVolume);
+ break;
+ }
- case SCI_VERSION_1_EARLY:
- case SCI_VERSION_1_LATE:
- // sending volume change to all active channels
- for (int i = 0; i < _track->channelCount; i++)
- if (_track->channels[i].number <= 0xF)
- _driver->send(0xB0 + _track->channels[i].number, 7, _volume);
- break;
+ case SCI_VERSION_1_EARLY:
+ case SCI_VERSION_1_LATE:
+ case SCI_VERSION_2_1:
+ // Send previous channel volumes again to actually update the volume
+ for (int i = 0; i < 15; i++)
+ if (_channelRemap[i] != -1)
+ sendToDriver(0xB0 + i, 7, _channelVolume[i]);
+ break;
- default:
- error("MidiParser_SCI::setVolume: Unsupported soundVersion");
- }
+ default:
+ error("MidiParser_SCI::setVolume: Unsupported soundVersion");
}
}
diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h
index f95c71ce2f..90db06e539 100644
--- a/engines/sci/sound/midiparser_sci.h
+++ b/engines/sci/sound/midiparser_sci.h
@@ -53,12 +53,17 @@ namespace Sci {
*/
class MidiParser_SCI : public MidiParser {
public:
- MidiParser_SCI(SciVersion soundVersion);
+ MidiParser_SCI(SciVersion soundVersion, SciMusic *music);
~MidiParser_SCI();
+
+ void mainThreadBegin();
+ void mainThreadEnd();
+
bool loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion);
bool loadMusic(byte *, uint32) {
return false;
}
+ void sendInitCommands();
void unloadMusic();
void setVolume(byte volume);
void stop() {
@@ -71,12 +76,29 @@ public:
jumpToTick(0);
}
+ void allNotesOff();
+
+ const byte *getMixedData() const { return _mixedData; }
+
+ void tryToOwnChannels();
+ void lostChannels();
+ void sendFromScriptToDriver(uint32 midi);
+ void sendToDriver(uint32 midi);
+ void sendToDriver(byte status, byte firstOp, byte secondOp) {
+ sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
+ }
+
protected:
void parseNextEvent(EventInfo &info);
byte *midiMixChannels();
byte *midiFilterChannels(int channelMask);
byte midiGetNextChannel(long ticker);
+ SciMusic *_music;
+
+ // this is set, when main thread calls us -> we send commands to queue instead to driver
+ bool _mainThreadCalled;
+
SciVersion _soundVersion;
byte *_mixedData;
SoundResource::Track *_track;
@@ -90,9 +112,10 @@ protected:
int16 _dataincToAdd;
bool _resetOnPause;
- // A 16-bit mask, containing the channels used
- // by the currently parsed song
- uint16 _channelsUsed;
+ bool _channelUsed[16];
+ int16 _channelRemap[16];
+ bool _channelMuted[16];
+ byte _channelVolume[16];
};
} // End of namespace Sci
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index 66f5ce9710..061f380ebc 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -37,15 +37,17 @@
namespace Sci {
-// When defined, volume fading immediately sets the final sound volume
-#define DISABLE_VOLUME_FADING
-
SciMusic::SciMusic(SciVersion soundVersion)
: _soundVersion(soundVersion), _soundOn(true), _masterVolume(0) {
// Reserve some space in the playlist, to avoid expensive insertion
// operations
_playList.reserve(10);
+
+ for (int i = 0; i < 16; i++)
+ _usedChannel[i] = 0;
+
+ _queuedCommands.reserve(1000);
}
SciMusic::~SciMusic() {
@@ -61,31 +63,22 @@ void SciMusic::init() {
// SCI sound init
_dwTempo = 0;
- MidiDriverType midiType;
-
- // Default to MIDI in SCI32 games, as many don't have AdLib support.
- // WORKAROUND: Default to MIDI in Amiga SCI1_EGA+ games as we don't support those patches yet.
- // We also don't yet support the 7.pat file of SCI1+ Mac games or SCI0 Mac patches, so we
- // default to MIDI in those games to let them run.
+ // Default to MIDI in SCI2.1+ games, as many don't have AdLib support.
Common::Platform platform = g_sci->getPlatform();
+ uint32 dev = MidiDriver::detectDevice((getSciVersion() >= SCI_VERSION_2_1) ? (MDT_PCSPK | MDT_PCJR | MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM) : (MDT_PCSPK | MDT_PCJR | MDT_ADLIB | MDT_MIDI));
- if (getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA))
- midiType = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI);
- else
- midiType = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB | MDT_MIDI);
-
- switch (midiType) {
- case MD_ADLIB:
+ switch (MidiDriver::getMusicType(dev)) {
+ case MT_ADLIB:
// FIXME: There's no Amiga sound option, so we hook it up to AdLib
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
- _pMidiDrv = MidiPlayer_Amiga_create(_soundVersion);
+ if (g_sci->getPlatform() == Common::kPlatformAmiga || platform == Common::kPlatformMacintosh)
+ _pMidiDrv = MidiPlayer_AmigaMac_create(_soundVersion);
else
_pMidiDrv = MidiPlayer_AdLib_create(_soundVersion);
break;
- case MD_PCJR:
+ case MT_PCJR:
_pMidiDrv = MidiPlayer_PCJr_create(_soundVersion);
break;
- case MD_PCSPK:
+ case MT_PCSPK:
_pMidiDrv = MidiPlayer_PCSpeaker_create(_soundVersion);
break;
default:
@@ -103,6 +96,49 @@ void SciMusic::init() {
}
_bMultiMidi = ConfMan.getBool("multi_midi");
+
+ // Find out what the first possible channel is (used, when doing channel
+ // remapping).
+ _driverFirstChannel = _pMidiDrv->getFirstChannel();
+}
+
+void SciMusic::miditimerCallback(void *p) {
+ SciMusic *sciMusic = (SciMusic *)p;
+
+ Common::StackLock lock(sciMusic->_mutex);
+ sciMusic->onTimer();
+}
+
+void SciMusic::onTimer() {
+ const MusicList::iterator end = _playList.end();
+ // sending out queued commands that were "sent" via main thread
+ sendMidiCommandsFromQueue();
+
+ for (MusicList::iterator i = _playList.begin(); i != end; ++i)
+ (*i)->onTimer();
+}
+
+void SciMusic::putMidiCommandInQueue(byte status, byte firstOp, byte secondOp) {
+ putMidiCommandInQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
+}
+
+void SciMusic::putMidiCommandInQueue(uint32 midi) {
+ _queuedCommands.push_back(midi);
+}
+
+// This sends the stored commands from queue to driver (is supposed to get
+// called only during onTimer()). At least mt32 emulation doesn't like getting
+// note-on commands from main thread (if we directly send, we would get a crash
+// during piano scene in lsl5).
+void SciMusic::sendMidiCommandsFromQueue() {
+ uint curCommand = 0;
+ uint commandCount = _queuedCommands.size();
+
+ while (curCommand < commandCount) {
+ _pMidiDrv->send(_queuedCommands[curCommand]);
+ curCommand++;
+ }
+ _queuedCommands.clear();
}
void SciMusic::clearPlayList() {
@@ -115,8 +151,6 @@ void SciMusic::clearPlayList() {
}
void SciMusic::pauseAll(bool pause) {
- Common::StackLock lock(_mutex);
-
const MusicList::iterator end = _playList.end();
for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
soundToggle(*i, pause);
@@ -124,22 +158,12 @@ void SciMusic::pauseAll(bool pause) {
}
void SciMusic::stopAll() {
- Common::StackLock lock(_mutex);
-
const MusicList::iterator end = _playList.end();
for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
soundStop(*i);
}
}
-
-void SciMusic::miditimerCallback(void *p) {
- SciMusic *aud = (SciMusic *)p;
-
- Common::StackLock lock(aud->_mutex);
- aud->onTimer();
-}
-
void SciMusic::soundSetSoundOn(bool soundOnFlag) {
Common::StackLock lock(_mutex);
@@ -165,27 +189,46 @@ MusicEntry *SciMusic::getSlot(reg_t obj) {
return NULL;
}
+// We return the currently active music slot for SCI0
+MusicEntry *SciMusic::getActiveSci0MusicSlot() {
+ const MusicList::iterator end = _playList.end();
+ MusicEntry *highestPrioritySlot = NULL;
+ for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
+ MusicEntry *playSlot = *i;
+ if (playSlot->pMidiParser) {
+ if (playSlot->status == kSoundPlaying)
+ return playSlot;
+ if (playSlot->status == kSoundPaused) {
+ if ((!highestPrioritySlot) || (highestPrioritySlot->priority < playSlot->priority))
+ highestPrioritySlot = playSlot;
+ }
+ }
+ }
+ return highestPrioritySlot;
+}
+
void SciMusic::setReverb(byte reverb) {
Common::StackLock lock(_mutex);
_pMidiDrv->setReverb(reverb);
}
-static int f_compare(const void *arg1, const void *arg2) {
- return ((const MusicEntry *)arg2)->priority - ((const MusicEntry *)arg1)->priority;
+static bool musicEntryCompare(const MusicEntry *l, const MusicEntry *r) {
+ return (l->priority > r->priority);
}
void SciMusic::sortPlayList() {
- MusicEntry ** pData = _playList.begin();
- qsort(pData, _playList.size(), sizeof(MusicEntry *), &f_compare);
+ // Sort the play list in descending priority order
+ Common::sort(_playList.begin(), _playList.end(), musicEntryCompare);
}
+
void SciMusic::soundInitSnd(MusicEntry *pSnd) {
int channelFilterMask = 0;
SoundResource::Track *track = pSnd->soundRes->getTrackByType(_pMidiDrv->getPlayId());
- // If MIDI device is selected but there is no digital track in sound resource
- // try to use adlib's digital sample if possible
- // Also, if the track couldn't be found, load the digital track, as some games
- // depend on this (e.g. the Longbow demo)
+ // If MIDI device is selected but there is no digital track in sound
+ // resource try to use adlib's digital sample if possible. Also, if the
+ // track couldn't be found, load the digital track, as some games depend on
+ // this (e.g. the Longbow demo).
if (!track || (_bMultiMidi && track->digitalChannelNr == -1)) {
SoundResource::Track *digital = pSnd->soundRes->getDigitalTrack();
if (digital)
@@ -214,7 +257,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
_mutex.lock();
pSnd->soundType = Audio::Mixer::kMusicSoundType;
if (pSnd->pMidiParser == NULL) {
- pSnd->pMidiParser = new MidiParser_SCI(_soundVersion);
+ pSnd->pMidiParser = new MidiParser_SCI(_soundVersion, this);
pSnd->pMidiParser->setMidiDriver(_pMidiDrv);
pSnd->pMidiParser->setTimerRate(_dwTempo);
}
@@ -223,19 +266,47 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
// Find out what channels to filter for SCI0
channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel());
- pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion);
- // Fast forward to the last position and perform associated events when loading
- pSnd->pMidiParser->jumpToTick(pSnd->ticker, true);
+ pSnd->pMidiParser->mainThreadBegin();
+ pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion);
+ pSnd->pMidiParser->mainThreadEnd();
_mutex.unlock();
}
}
}
-void SciMusic::onTimer() {
- const MusicList::iterator end = _playList.end();
- for (MusicList::iterator i = _playList.begin(); i != end; ++i)
- (*i)->onTimer();
+// This one checks, if requested channel is available -> in that case give
+// caller that channel. Otherwise look for an unused one
+int16 SciMusic::tryToOwnChannel(MusicEntry *caller, int16 bestChannel) {
+ // Don't even try this for SCI0
+ if (_soundVersion <= SCI_VERSION_0_LATE)
+ return bestChannel;
+ if (!_usedChannel[bestChannel]) {
+ // currently unused, so give it to caller directly
+ _usedChannel[bestChannel] = caller;
+ return bestChannel;
+ }
+ // otherwise look for unused channel
+ for (int channelNr = _driverFirstChannel; channelNr < 15; channelNr++) {
+ if (!_usedChannel[channelNr]) {
+ _usedChannel[channelNr] = caller;
+ return channelNr;
+ }
+ }
+ // nothing found, don't map channel at all
+ // sierra did this as well, although i'm not sure if we act exactly the same way
+ // maybe they removed channels from previous playing music
+ return -1;
+}
+
+void SciMusic::freeChannels(MusicEntry *caller) {
+ // Remove used channels
+ for (int i = 0; i < 15; i++) {
+ if (_usedChannel[i] == caller)
+ _usedChannel[i] = 0;
+ }
+ // Also tell midiparser, that he lost ownership
+ caller->pMidiParser->lostChannels();
}
void SciMusic::soundPlay(MusicEntry *pSnd) {
@@ -243,14 +314,14 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
uint playListCount = _playList.size();
uint playListNo = playListCount;
- bool alreadyPlaying = false;
+ MusicEntry *alreadyPlaying = NULL;
// searching if sound is already in _playList
for (uint i = 0; i < playListCount; i++) {
if (_playList[i] == pSnd)
playListNo = i;
if ((_playList[i]->status == kSoundPlaying) && (_playList[i]->pMidiParser))
- alreadyPlaying = true;
+ alreadyPlaying = _playList[i];
}
if (playListNo == playListCount) { // not found
_playList.push_back(pSnd);
@@ -261,13 +332,20 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
if (pSnd->pMidiParser) {
if ((_soundVersion <= SCI_VERSION_0_LATE) && (alreadyPlaying)) {
- // if any music is already playing, SCI0 queues music and plays it after the current music has finished
- // done by SoundCommandParser::updateSci0Cues()
- // Example of such case: iceman room 14
- // FIXME: this code is supposed to also take a look at priority and pause currently playing sound accordingly
- pSnd->isQueued = true;
- pSnd->status = kSoundPaused;
- return;
+ // Music already playing in SCI0?
+ if (pSnd->priority > alreadyPlaying->priority) {
+ // And new priority higher? pause previous music and play new one immediately.
+ // Example of such case: lsl3, when getting points (jingle is played then)
+ soundPause(alreadyPlaying);
+ alreadyPlaying->isQueued = true;
+ } else {
+ // And new priority equal or lower? queue up music and play it afterwards done by
+ // SoundCommandParser::updateSci0Cues()
+ // Example of such case: iceman room 14
+ pSnd->isQueued = true;
+ pSnd->status = kSoundPaused;
+ return;
+ }
}
}
@@ -279,32 +357,56 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
pSnd->pLoopStream, -1, pSnd->volume, 0,
DisposeAfterUse::NO);
} else {
+ // Rewind in case we play the same sample multiple times
+ // (non-looped) like in pharkas right at the start
+ pSnd->pStreamAud->rewind();
_pMixer->playStream(pSnd->soundType, &pSnd->hCurrentAud,
pSnd->pStreamAud, -1, pSnd->volume, 0,
DisposeAfterUse::NO);
}
} else {
- _mutex.lock();
if (pSnd->pMidiParser) {
- pSnd->pMidiParser->setVolume(pSnd->volume);
+ _mutex.lock();
+ pSnd->pMidiParser->mainThreadBegin();
+ pSnd->pMidiParser->tryToOwnChannels();
if (pSnd->status == kSoundStopped)
+ pSnd->pMidiParser->sendInitCommands();
+ pSnd->pMidiParser->setVolume(pSnd->volume);
+ if (pSnd->status == kSoundStopped) {
pSnd->pMidiParser->jumpToTick(0);
+ } else {
+ // Fast forward to the last position and perform associated events when loading
+ pSnd->pMidiParser->jumpToTick(pSnd->ticker, true);
+ }
+ pSnd->pMidiParser->mainThreadEnd();
+ _mutex.unlock();
}
- _mutex.unlock();
}
pSnd->status = kSoundPlaying;
}
void SciMusic::soundStop(MusicEntry *pSnd) {
+ SoundStatus previousStatus = pSnd->status;
pSnd->status = kSoundStopped;
+ if (_soundVersion <= SCI_VERSION_0_LATE)
+ pSnd->isQueued = false;
if (pSnd->pStreamAud)
_pMixer->stopHandle(pSnd->hCurrentAud);
- _mutex.lock();
- if (pSnd->pMidiParser)
- pSnd->pMidiParser->stop();
- _mutex.unlock();
+ if (pSnd->pMidiParser) {
+ _mutex.lock();
+ pSnd->pMidiParser->mainThreadBegin();
+ // We shouldn't call stop in case it's paused, otherwise we would send
+ // allNotesOff() again
+ if (previousStatus == kSoundPlaying)
+ pSnd->pMidiParser->stop();
+ freeChannels(pSnd);
+ pSnd->pMidiParser->mainThreadEnd();
+ _mutex.unlock();
+ }
+
+ pSnd->fadeStep = 0; // end fading, if fading was in progress
}
void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) {
@@ -313,7 +415,9 @@ void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) {
_pMixer->setChannelVolume(pSnd->hCurrentAud, volume * 2); // Mixer is 0-255, SCI is 0-127
} else if (pSnd->pMidiParser) {
_mutex.lock();
+ pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->setVolume(volume);
+ pSnd->pMidiParser->mainThreadEnd();
_mutex.unlock();
}
}
@@ -328,13 +432,15 @@ void SciMusic::soundSetPriority(MusicEntry *pSnd, byte prio) {
void SciMusic::soundKill(MusicEntry *pSnd) {
pSnd->status = kSoundStopped;
- _mutex.lock();
if (pSnd->pMidiParser) {
+ _mutex.lock();
+ pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->unloadMusic();
+ pSnd->pMidiParser->mainThreadEnd();
delete pSnd->pMidiParser;
pSnd->pMidiParser = NULL;
+ _mutex.unlock();
}
- _mutex.unlock();
if (pSnd->pStreamAud) {
_pMixer->stopHandle(pSnd->hCurrentAud);
@@ -366,10 +472,14 @@ void SciMusic::soundPause(MusicEntry *pSnd) {
if (pSnd->pStreamAud) {
_pMixer->pauseHandle(pSnd->hCurrentAud, true);
} else {
- _mutex.lock();
- if (pSnd->pMidiParser)
+ if (pSnd->pMidiParser) {
+ _mutex.lock();
+ pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->pause();
- _mutex.unlock();
+ freeChannels(pSnd);
+ pSnd->pMidiParser->mainThreadEnd();
+ _mutex.unlock();
+ }
}
}
@@ -380,7 +490,12 @@ void SciMusic::soundResume(MusicEntry *pSnd) {
return;
if (pSnd->status != kSoundPaused)
return;
- soundPlay(pSnd);
+ if (pSnd->pStreamAud) {
+ _pMixer->pauseHandle(pSnd->hCurrentAud, false);
+ pSnd->status = kSoundPlaying;
+ } else {
+ soundPlay(pSnd);
+ }
}
void SciMusic::soundToggle(MusicEntry *pSnd, bool pause) {
@@ -403,6 +518,21 @@ void SciMusic::soundSetMasterVolume(uint16 vol) {
_pMidiDrv->setVolume(vol);
}
+void SciMusic::sendMidiCommand(uint32 cmd) {
+ Common::StackLock lock(_mutex);
+ _pMidiDrv->send(cmd);
+}
+
+void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) {
+ Common::StackLock lock(_mutex);
+ if (!pSnd->pMidiParser)
+ error("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj));
+
+ pSnd->pMidiParser->mainThreadBegin();
+ pSnd->pMidiParser->sendFromScriptToDriver(cmd);
+ pSnd->pMidiParser->mainThreadEnd();
+}
+
void SciMusic::printPlayList(Console *con) {
Common::StackLock lock(_mutex);
@@ -471,7 +601,7 @@ MusicEntry::MusicEntry() {
priority = 0;
loop = 0;
volume = MUSIC_VOLUME_DEFAULT;
- hold = 0;
+ hold = -1;
pauseCounter = 0;
sampleLoopCounter = 0;
@@ -525,12 +655,6 @@ void MusicEntry::doFade() {
// Only process MIDI streams in this thread, not digital sound effects
if (pMidiParser) {
-#ifdef DISABLE_VOLUME_FADING
- // Signal fading to stop...
- volume = fadeTo;
- fadeStep = 0;
- fadeCompleted = true;
-#endif
pMidiParser->setVolume(volume);
}
diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h
index 8f08065b99..37e3c30030 100644
--- a/engines/sci/sound/music.h
+++ b/engines/sci/sound/music.h
@@ -26,15 +26,11 @@
#ifndef SCI_MUSIC_H
#define SCI_MUSIC_H
-#ifndef USE_OLD_MUSIC_FUNCTIONS
#include "common/serializer.h"
-#endif
#include "common/mutex.h"
#include "sound/mixer.h"
#include "sound/audiostream.h"
-//#include "sound/mididrv.h"
-//#include "sound/midiparser.h"
#include "sci/sci.h"
#include "sci/resource.h"
@@ -55,11 +51,7 @@ enum SoundStatus {
class MidiParser_SCI;
class SegManager;
-class MusicEntry
-#ifndef USE_OLD_MUSIC_FUNCTIONS
- : public Common::Serializable
-#endif
-{
+class MusicEntry : public Common::Serializable {
public:
// Do not get these directly for the sound objects!
// It's a bad idea, as the sound code (i.e. the SciMusic
@@ -79,7 +71,7 @@ public:
byte priority;
uint16 loop;
int16 volume;
- byte hold;
+ int16 hold;
int16 pauseCounter;
uint sampleLoopCounter;
@@ -96,9 +88,6 @@ public:
Audio::Mixer::SoundType soundType;
-#ifndef USE_OLD_MUSIC_FUNCTIONS
-//protected:
-#endif
MidiParser_SCI *pMidiParser;
// TODO: We need to revise how we store the different
@@ -114,25 +103,28 @@ public:
void doFade();
void onTimer();
-#ifndef USE_OLD_MUSIC_FUNCTIONS
virtual void saveLoadWithSerializer(Common::Serializer &ser);
-#endif
};
typedef Common::Array<MusicEntry *> MusicList;
+typedef Common::Array<uint32> MidiCommandQueue;
-class SciMusic
-#ifndef USE_OLD_MUSIC_FUNCTIONS
- : public Common::Serializable
-#endif
-{
+class SciMusic : public Common::Serializable {
public:
SciMusic(SciVersion soundVersion);
~SciMusic();
void init();
+
void onTimer();
+ void putMidiCommandInQueue(byte status, byte firstOp, byte secondOp);
+ void putMidiCommandInQueue(uint32 midi);
+private:
+ static void miditimerCallback(void *p);
+ void sendMidiCommandsFromQueue();
+
+public:
void clearPlayList();
void pauseAll(bool pause);
void stopAll();
@@ -165,6 +157,7 @@ public:
}
MusicEntry *getSlot(reg_t obj);
+ MusicEntry *getActiveSci0MusicSlot();
void pushBackSlot(MusicEntry *slotEntry) {
Common::StackLock lock(_mutex);
@@ -179,16 +172,12 @@ public:
MusicList::iterator getPlayListStart() { return _playList.begin(); }
MusicList::iterator getPlayListEnd() { return _playList.end(); }
- void sendMidiCommand(uint32 cmd) {
- Common::StackLock lock(_mutex);
- _pMidiDrv->send(cmd);
- }
+ void sendMidiCommand(uint32 cmd);
+ void sendMidiCommand(MusicEntry *pSnd, uint32 cmd);
void setReverb(byte reverb);
-#ifndef USE_OLD_MUSIC_FUNCTIONS
virtual void saveLoadWithSerializer(Common::Serializer &ser);
-#endif
// Mutex for music code. Used to guard access to the song playlist, to the
// MIDI parser and to the MIDI driver/player. Note that guarded code must NOT
@@ -196,8 +185,10 @@ public:
// where a deadlock can occur
Common::Mutex _mutex;
+ int16 tryToOwnChannel(MusicEntry *caller, int16 bestChannel);
+ void freeChannels(MusicEntry *caller);
+
protected:
- byte findAudEntry(uint16 nAud, byte&oVolume, uint32& oOffset, uint32&oSize);
void sortPlayList();
SciVersion _soundVersion;
@@ -209,12 +200,16 @@ protected:
// Mixed AdLib/MIDI mode: when enabled from the ScummVM sound options screen,
// and a sound has a digital track, the sound from the AdLib track is played
bool _bMultiMidi;
-private:
- static void miditimerCallback(void *p);
+private:
MusicList _playList;
bool _soundOn;
byte _masterVolume;
+ MusicEntry *_usedChannel[16];
+
+ MidiCommandQueue _queuedCommands;
+
+ int _driverFirstChannel;
};
} // End of namespace Sci
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index 925f3b2e1a..567a1605f3 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -23,276 +23,40 @@
*
*/
-#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-#include "sci/sound/iterator/iterator.h" // for SongIteratorStatus
-#endif
-
#include "common/config-manager.h"
#include "sci/sound/audio.h"
#include "sci/sound/music.h"
#include "sci/sound/soundcmd.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/selector.h"
namespace Sci {
-#define SCI1_SOUND_FLAG_MAY_PAUSE 1 /* Only here for completeness; The interpreter doesn't touch this bit */
-#define SCI1_SOUND_FLAG_SCRIPTED_PRI 2 /* but does touch this */
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-#define FROBNICATE_HANDLE(reg) ((reg).segment << 16 | (reg).offset)
-#define DEFROBNICATE_HANDLE(handle) (make_reg((handle >> 16) & 0xffff, handle & 0xffff))
-#endif
-
-#define SOUNDCOMMAND(x) _soundCommands.push_back(new MusicEntryCommand(#x, &SoundCommandParser::x))
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-static void script_set_priority(ResourceManager *resMan, SegManager *segMan, SfxState *state, reg_t obj, int priority) {
- int song_nr = GET_SEL32V(segMan, obj, SELECTOR(number));
- Resource *song = resMan->findResource(ResourceId(kResourceTypeSound, song_nr), 0);
- int flags = GET_SEL32V(segMan, obj, SELECTOR(flags));
-
- if (priority == -1) {
- if (song->data[0] == 0xf0)
- priority = song->data[1];
- else
- warning("Attempt to unset song priority when there is no built-in value");
-
- flags &= ~SCI1_SOUND_FLAG_SCRIPTED_PRI;
- } else flags |= SCI1_SOUND_FLAG_SCRIPTED_PRI;
-
- state->sfx_song_renice(FROBNICATE_HANDLE(obj), priority);
- PUT_SEL32V(segMan, obj, SELECTOR(flags), flags);
-}
-
-SongIterator *build_iterator(ResourceManager *resMan, int song_nr, SongIteratorType type, songit_id_t id) {
- Resource *song = resMan->findResource(ResourceId(kResourceTypeSound, song_nr), 0);
-
- if (!song)
- return NULL;
-
- return songit_new(song->data, song->size, type, id);
-}
-
-void process_sound_events(EngineState *s) { /* Get all sound events, apply their changes to the heap */
- int result;
- SongHandle handle;
- int cue;
- SegManager *segMan = s->_segMan;
-
- if (getSciVersion() > SCI_VERSION_01)
- return;
- // SCI1 and later explicitly poll for everything
-
- while ((result = s->_sound.sfx_poll(&handle, &cue))) {
- reg_t obj = DEFROBNICATE_HANDLE(handle);
- if (!s->_segMan->isObject(obj)) {
- warning("Non-object %04x:%04x received sound signal (%d/%d)", PRINT_REG(obj), result, cue);
- return;
- }
-
- switch (result) {
-
- case SI_LOOP:
- debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x looped (to %d)",
- PRINT_REG(obj), cue);
- /* PUT_SEL32V(segMan, obj, SELECTOR(loops), GET_SEL32V(segMan, obj, SELECTOR(loop));; - 1);*/
- PUT_SEL32V(segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
- break;
-
- case SI_RELATIVE_CUE:
- debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received relative cue %d",
- PRINT_REG(obj), cue);
- PUT_SEL32V(segMan, obj, SELECTOR(signal), cue + 0x7f);
- break;
-
- case SI_ABSOLUTE_CUE:
- debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received absolute cue %d",
- PRINT_REG(obj), cue);
- PUT_SEL32V(segMan, obj, SELECTOR(signal), cue);
- break;
-
- case SI_FINISHED:
- debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x finished",
- PRINT_REG(obj));
- PUT_SEL32V(segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
- PUT_SEL32V(segMan, obj, SELECTOR(state), kSoundStopped);
- break;
-
- default:
- warning("Unexpected result from sfx_poll: %d", result);
- break;
- }
- }
-}
-
-#endif
SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, AudioPlayer *audio, SciVersion soundVersion) :
_resMan(resMan), _segMan(segMan), _kernel(kernel), _audio(audio), _soundVersion(soundVersion) {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- // The following hack is needed to ease the change from old to new sound code (because the new sound code does not use SfxState)
- _state = &g_sci->getEngineState()->_sound; // HACK
-#endif
-
- #ifndef USE_OLD_MUSIC_FUNCTIONS
- _music = new SciMusic(_soundVersion);
- _music->init();
- #endif
-
- switch (_soundVersion) {
- case SCI_VERSION_0_EARLY:
- case SCI_VERSION_0_LATE:
- SOUNDCOMMAND(cmdInitSound);
- SOUNDCOMMAND(cmdPlaySound);
- SOUNDCOMMAND(cmdDummy);
- SOUNDCOMMAND(cmdDisposeSound);
- SOUNDCOMMAND(cmdMuteSound);
- SOUNDCOMMAND(cmdStopSound);
- SOUNDCOMMAND(cmdPauseSound);
- SOUNDCOMMAND(cmdResumeSound);
- SOUNDCOMMAND(cmdMasterVolume);
- SOUNDCOMMAND(cmdUpdateSound);
- SOUNDCOMMAND(cmdFadeSound);
- SOUNDCOMMAND(cmdGetPolyphony);
- SOUNDCOMMAND(cmdStopAllSounds);
- _cmdUpdateCuesIndex = -1;
- break;
- case SCI_VERSION_1_EARLY:
- SOUNDCOMMAND(cmdMasterVolume);
- SOUNDCOMMAND(cmdMuteSound);
- SOUNDCOMMAND(cmdDummy);
- SOUNDCOMMAND(cmdGetPolyphony);
- SOUNDCOMMAND(cmdUpdateSound);
- SOUNDCOMMAND(cmdInitSound);
- SOUNDCOMMAND(cmdDisposeSound);
- SOUNDCOMMAND(cmdPlaySound);
- SOUNDCOMMAND(cmdStopSound);
- SOUNDCOMMAND(cmdPauseSound);
- SOUNDCOMMAND(cmdFadeSound);
- SOUNDCOMMAND(cmdUpdateCues);
- SOUNDCOMMAND(cmdSendMidi);
- SOUNDCOMMAND(cmdReverb);
- SOUNDCOMMAND(cmdSetSoundHold);
- _cmdUpdateCuesIndex = 11;
- break;
- case SCI_VERSION_1_LATE:
- SOUNDCOMMAND(cmdMasterVolume);
- SOUNDCOMMAND(cmdMuteSound);
- SOUNDCOMMAND(cmdDummy);
- SOUNDCOMMAND(cmdGetPolyphony);
- SOUNDCOMMAND(cmdGetAudioCapability);
- SOUNDCOMMAND(cmdSuspendSound);
- SOUNDCOMMAND(cmdInitSound);
- SOUNDCOMMAND(cmdDisposeSound);
- SOUNDCOMMAND(cmdPlaySound);
- SOUNDCOMMAND(cmdStopSound);
- SOUNDCOMMAND(cmdPauseSound);
- SOUNDCOMMAND(cmdFadeSound);
- SOUNDCOMMAND(cmdSetSoundHold);
- SOUNDCOMMAND(cmdDummy);
- SOUNDCOMMAND(cmdSetSoundVolume);
- SOUNDCOMMAND(cmdSetSoundPriority);
- SOUNDCOMMAND(cmdSetSoundLoop);
- SOUNDCOMMAND(cmdUpdateCues);
- SOUNDCOMMAND(cmdSendMidi);
- SOUNDCOMMAND(cmdReverb);
- SOUNDCOMMAND(cmdUpdateSound);
- _cmdUpdateCuesIndex = 17;
- break;
- default:
- warning("Sound command parser: unknown sound version %d", _soundVersion);
- break;
- }
+ _music = new SciMusic(_soundVersion);
+ _music->init();
}
SoundCommandParser::~SoundCommandParser() {
- for (SoundCommandContainer::iterator i = _soundCommands.begin(); i != _soundCommands.end(); ++i)
- delete *i;
-
-#ifndef USE_OLD_MUSIC_FUNCTIONS
delete _music;
-#endif
}
-reg_t SoundCommandParser::parseCommand(int argc, reg_t *argv, reg_t acc) {
- uint16 command = argv[0].toUint16();
- reg_t obj = (argc > 1) ? argv[1] : NULL_REG;
- int16 value = (argc > 2) ? argv[2].toSint16() : 0;
- _acc = acc;
- _argc = argc;
- _argv = argv;
-
- if (argc == 6) { // cmdSendMidi
- byte channel = argv[2].toUint16() & 0xf;
- byte midiCmd = argv[3].toUint16() & 0xff;
-
- uint16 controller = argv[4].toUint16();
- uint16 param = argv[5].toUint16();
-
- _midiCommand = (channel | midiCmd) | ((uint32)controller << 8) | ((uint32)param << 16);
- }
-
- if (command < _soundCommands.size()) {
- if (command != _cmdUpdateCuesIndex) {
- //printf("%s, object %04x:%04x\n", _soundCommands[command]->desc, PRINT_REG(obj)); // debug
- debugC(2, kDebugLevelSound, "%s, object %04x:%04x", _soundCommands[command]->desc, PRINT_REG(obj));
- }
-
- (this->*(_soundCommands[command]->sndCmd))(obj, value);
- } else {
- warning("Invalid sound command requested (%d), valid range is 0-%d", command, _soundCommands.size() - 1);
- }
-
- return _acc;
+reg_t SoundCommandParser::kDoSoundInit(int argc, reg_t *argv, reg_t acc) {
+ debugC(2, kDebugLevelSound, "kDoSound(init): %04x:%04x", PRINT_REG(argv[0]));
+ processInitSound(argv[0]);
+ return acc;
}
-void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) {
- if (!obj.segment)
- return;
-
- int resourceId = GET_SEL32V(_segMan, obj, SELECTOR(number));
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-
- SongHandle handle = FROBNICATE_HANDLE(obj);
-
- if (_soundVersion != SCI_VERSION_1_LATE) {
- if (!obj.segment)
- return;
- }
-
- SongIteratorType type = (_soundVersion <= SCI_VERSION_0_LATE) ? SCI_SONG_ITERATOR_TYPE_SCI0 : SCI_SONG_ITERATOR_TYPE_SCI1;
-
- if (_soundVersion <= SCI_VERSION_0_LATE) {
- if (GET_SEL32V(_segMan, obj, SELECTOR(nodePtr))) {
- _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
- _state->sfx_remove_song(handle);
- }
- }
-
- if (!obj.segment || !_resMan->testResource(ResourceId(kResourceTypeSound, resourceId)))
- return;
-
- _state->sfx_add_song(build_iterator(_resMan, resourceId, type, handle), 0, handle, resourceId);
-
-
- // Notify the engine
- if (_soundVersion <= SCI_VERSION_0_LATE)
- PUT_SEL32V(_segMan, obj, SELECTOR(state), kSoundInitialized);
- else
- PUT_SEL32(_segMan, obj, SELECTOR(nodePtr), obj);
-
- PUT_SEL32(_segMan, obj, SELECTOR(handle), obj);
-
-#else
+void SoundCommandParser::processInitSound(reg_t obj) {
+ int resourceId = readSelectorValue(_segMan, obj, SELECTOR(number));
// Check if a track with the same sound object is already playing
MusicEntry *oldSound = _music->getSlot(obj);
if (oldSound)
- cmdDisposeSound(obj, value);
+ processDisposeSound(obj);
MusicEntry *newSound = new MusicEntry();
newSound->resourceId = resourceId;
@@ -302,10 +66,13 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) {
newSound->soundRes = 0;
newSound->soundObj = obj;
- newSound->loop = GET_SEL32V(_segMan, obj, SELECTOR(loop));
- newSound->priority = GET_SEL32V(_segMan, obj, SELECTOR(pri)) & 0xFF;
- if (_soundVersion >= SCI_VERSION_1_LATE)
- newSound->volume = CLIP<int>(GET_SEL32V(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX);
+ newSound->loop = readSelectorValue(_segMan, obj, SELECTOR(loop));
+ newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(pri)) & 0xFF;
+ if (_soundVersion >= SCI_VERSION_1_EARLY)
+ newSound->volume = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX);
+
+ debugC(2, kDebugLevelSound, "kDoSound(init): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj),
+ resourceId, newSound->loop, newSound->priority, newSound->volume);
// In SCI1.1 games, sound effects are started from here. If we can find
// a relevant audio resource, play it, otherwise switch to synthesized
@@ -327,492 +94,288 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) {
if (newSound->soundRes || newSound->pStreamAud) {
// Notify the engine
if (_soundVersion <= SCI_VERSION_0_LATE)
- PUT_SEL32V(_segMan, obj, SELECTOR(state), kSoundInitialized);
+ writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundInitialized);
else
- PUT_SEL32(_segMan, obj, SELECTOR(nodePtr), obj);
+ writeSelector(_segMan, obj, SELECTOR(nodePtr), obj);
- PUT_SEL32(_segMan, obj, SELECTOR(handle), obj);
+ writeSelector(_segMan, obj, SELECTOR(handle), obj);
}
-#endif
-
}
-void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) {
- if (!obj.segment)
- return;
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- SongHandle handle = FROBNICATE_HANDLE(obj);
-
- if (_soundVersion <= SCI_VERSION_0_LATE) {
- _state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING);
- _state->sfx_song_set_loops(handle, GET_SEL32V(_segMan, obj, SELECTOR(loop)));
- PUT_SEL32V(_segMan, obj, SELECTOR(state), kSoundPlaying);
- } else if (_soundVersion == SCI_VERSION_1_EARLY) {
- _state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING);
- _state->sfx_song_set_loops(handle, GET_SEL32V(_segMan, obj, SELECTOR(loop)));
- _state->sfx_song_renice(handle, GET_SEL32V(_segMan, obj, SELECTOR(pri)));
- RESTORE_BEHAVIOR rb = (RESTORE_BEHAVIOR) value; /* Too lazy to look up a default value for this */
- _state->_songlib.setSongRestoreBehavior(handle, rb);
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), 0);
- } else if (_soundVersion == SCI_VERSION_1_LATE) {
- int looping = GET_SEL32V(_segMan, obj, SELECTOR(loop));
- //int vol = GET_SEL32V(_segMan, obj, SELECTOR(vol));
- int pri = GET_SEL32V(_segMan, obj, SELECTOR(pri));
- int sampleLen = 0;
- Song *song = _state->_songlib.findSong(handle);
- int songNumber = GET_SEL32V(_segMan, obj, SELECTOR(number));
-
- if (GET_SEL32V(_segMan, obj, SELECTOR(nodePtr)) && (song && songNumber != song->_resourceNum)) {
- _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
- _state->sfx_remove_song(handle);
- PUT_SEL32(_segMan, obj, SELECTOR(nodePtr), NULL_REG);
- }
-
- if (!GET_SEL32V(_segMan, obj, SELECTOR(nodePtr)) && obj.segment) {
- // In SCI1.1 games, sound effects are started from here. If we can find
- // a relevant audio resource, play it, otherwise switch to synthesized
- // effects. If the resource exists, play it using map 65535 (sound
- // effects map)
- if (_resMan->testResource(ResourceId(kResourceTypeAudio, songNumber)) &&
- getSciVersion() >= SCI_VERSION_1_1) {
- // Found a relevant audio resource, play it
- _audio->stopAudio();
- warning("Initializing audio resource instead of requested sound resource %d", songNumber);
- sampleLen = _audio->startAudio(65535, songNumber);
- // Also create iterator, that will fire SI_FINISHED event, when the sound is done playing
- _state->sfx_add_song(new_timer_iterator(sampleLen), 0, handle, songNumber);
- } else {
- if (!_resMan->testResource(ResourceId(kResourceTypeSound, songNumber))) {
- warning("Could not open song number %d", songNumber);
- // Send a "stop handle" event so that the engine won't wait forever here
- _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
- return;
- }
- debugC(2, kDebugLevelSound, "Initializing song number %d", songNumber);
- _state->sfx_add_song(build_iterator(_resMan, songNumber, SCI_SONG_ITERATOR_TYPE_SCI1,
- handle), 0, handle, songNumber);
- }
-
- PUT_SEL32(_segMan, obj, SELECTOR(nodePtr), obj);
- PUT_SEL32(_segMan, obj, SELECTOR(handle), obj);
- }
-
- if (obj.segment) {
- _state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING);
- _state->sfx_song_set_loops(handle, looping);
- _state->sfx_song_renice(handle, pri);
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), 0);
- }
- }
-
-#else
+reg_t SoundCommandParser::kDoSoundPlay(int argc, reg_t *argv, reg_t acc) {
+ debugC(2, kDebugLevelSound, "kDoSound(play): %04x:%04x", PRINT_REG(argv[0]));
+ processPlaySound(argv[0]);
+ return acc;
+}
+void SoundCommandParser::processPlaySound(reg_t obj) {
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
- warning("cmdPlaySound: Slot not found (%04x:%04x)", PRINT_REG(obj));
+ warning("kDoSound(play): Slot not found (%04x:%04x)", PRINT_REG(obj));
return;
}
- int resourceId = obj.segment ? GET_SEL32V(_segMan, obj, SELECTOR(number)) : -1;
+ int resourceId = obj.segment ? readSelectorValue(_segMan, obj, SELECTOR(number)) : -1;
if (musicSlot->resourceId != resourceId) { // another sound loaded into struct
- cmdDisposeSound(obj, value);
- cmdInitSound(obj, value);
+ processDisposeSound(obj);
+ processInitSound(obj);
// Find slot again :)
musicSlot = _music->getSlot(obj);
}
- int16 loop = GET_SEL32V(_segMan, obj, SELECTOR(loop));
- debugC(2, kDebugLevelSound, "cmdPlaySound: resource number %d, loop %d", resourceId, loop);
- PUT_SEL32(_segMan, obj, SELECTOR(handle), obj);
+ writeSelector(_segMan, obj, SELECTOR(handle), obj);
if (_soundVersion >= SCI_VERSION_1_EARLY) {
- PUT_SEL32(_segMan, obj, SELECTOR(nodePtr), obj);
- PUT_SEL32V(_segMan, obj, SELECTOR(min), 0);
- PUT_SEL32V(_segMan, obj, SELECTOR(sec), 0);
- PUT_SEL32V(_segMan, obj, SELECTOR(frame), 0);
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), 0);
+ writeSelector(_segMan, obj, SELECTOR(nodePtr), obj);
+ writeSelectorValue(_segMan, obj, SELECTOR(min), 0);
+ writeSelectorValue(_segMan, obj, SELECTOR(sec), 0);
+ writeSelectorValue(_segMan, obj, SELECTOR(frame), 0);
+ writeSelectorValue(_segMan, obj, SELECTOR(signal), 0);
} else {
- PUT_SEL32V(_segMan, obj, SELECTOR(state), kSoundPlaying);
+ writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundPlaying);
}
- musicSlot->loop = GET_SEL32V(_segMan, obj, SELECTOR(loop));
- musicSlot->priority = GET_SEL32V(_segMan, obj, SELECTOR(priority));
- if (_soundVersion >= SCI_VERSION_1_LATE)
- musicSlot->volume = GET_SEL32V(_segMan, obj, SELECTOR(vol));
- _music->soundPlay(musicSlot);
+ musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop));
+ musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority));
+ if (_soundVersion >= SCI_VERSION_1_EARLY)
+ musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol));
-#endif
+ debugC(2, kDebugLevelSound, "kDoSound(play): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj),
+ resourceId, musicSlot->loop, musicSlot->priority, musicSlot->volume);
+ _music->soundPlay(musicSlot);
}
-void SoundCommandParser::cmdDummy(reg_t obj, int16 value) {
- warning("cmdDummy invoked"); // not supposed to occur
+reg_t SoundCommandParser::kDoSoundRestore(int argc, reg_t *argv, reg_t acc) {
+ // Called after loading, to restore the playlist
+ // We don't really use or need this
+ return acc;
}
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-void SoundCommandParser::changeSoundStatus(reg_t obj, int newStatus) {
- SongHandle handle = FROBNICATE_HANDLE(obj);
- if (obj.segment) {
- _state->sfx_song_set_status(handle, newStatus);
- if (_soundVersion <= SCI_VERSION_0_LATE)
- PUT_SEL32V(_segMan, obj, SELECTOR(state), newStatus);
- }
+reg_t SoundCommandParser::kDoSoundDummy(int argc, reg_t *argv, reg_t acc) {
+ warning("cmdDummy invoked"); // not supposed to occur
+ return acc;
}
-#endif
-void SoundCommandParser::cmdDisposeSound(reg_t obj, int16 value) {
- if (!obj.segment)
- return;
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- SongHandle handle = FROBNICATE_HANDLE(obj);
- changeSoundStatus(obj, SOUND_STATUS_STOPPED);
-
- if (obj.segment) {
- _state->sfx_remove_song(handle);
-
- if (_soundVersion <= SCI_VERSION_0_LATE)
- PUT_SEL32V(_segMan, obj, SELECTOR(handle), 0x0000);
- }
-
-#else
+reg_t SoundCommandParser::kDoSoundDispose(int argc, reg_t *argv, reg_t acc) {
+ debugC(2, kDebugLevelSound, "kDoSound(dispose): %04x:%04x", PRINT_REG(argv[0]));
+ processDisposeSound(argv[0]);
+ return acc;
+}
+void SoundCommandParser::processDisposeSound(reg_t obj) {
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
- warning("cmdDisposeSound: Slot not found (%04x:%04x)", PRINT_REG(obj));
+ warning("kDoSound(dispose): Slot not found (%04x:%04x)", PRINT_REG(obj));
return;
}
- cmdStopSound(obj, value);
+ processStopSound(obj, false);
_music->soundKill(musicSlot);
- PUT_SEL32V(_segMan, obj, SELECTOR(handle), 0);
+ writeSelectorValue(_segMan, obj, SELECTOR(handle), 0);
if (_soundVersion >= SCI_VERSION_1_EARLY)
- PUT_SEL32(_segMan, obj, SELECTOR(nodePtr), NULL_REG);
+ writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG);
else
- PUT_SEL32V(_segMan, obj, SELECTOR(state), kSoundStopped);
-#endif
+ writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped);
}
-void SoundCommandParser::cmdStopSound(reg_t obj, int16 value) {
- processStopSound(obj, value, false);
+reg_t SoundCommandParser::kDoSoundStop(int argc, reg_t *argv, reg_t acc) {
+ debugC(2, kDebugLevelSound, "kDoSound(stop): %04x:%04x", PRINT_REG(argv[0]));
+ processStopSound(argv[0], false);
+ return acc;
}
-void SoundCommandParser::processStopSound(reg_t obj, int16 value, bool sampleFinishedPlaying) {
- if (!obj.segment)
- return;
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- changeSoundStatus(obj, SOUND_STATUS_STOPPED);
-
- if (_soundVersion >= SCI_VERSION_1_EARLY)
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
-#else
+void SoundCommandParser::processStopSound(reg_t obj, bool sampleFinishedPlaying) {
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
- warning("cmdStopSound: Slot not found (%04x:%04x)", PRINT_REG(obj));
+ warning("kDoSound(stop): Slot not found (%04x:%04x)", PRINT_REG(obj));
return;
}
if (_soundVersion <= SCI_VERSION_0_LATE) {
- PUT_SEL32V(_segMan, obj, SELECTOR(state), kSoundStopped);
+ writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped);
} else {
- PUT_SEL32V(_segMan, obj, SELECTOR(handle), 0);
+ writeSelectorValue(_segMan, obj, SELECTOR(handle), 0);
}
- // Set signal selector in sound SCI0 games only, when the sample has finished playing
- // If we don't set it at all, we get a problem when using vaporizer on the 2 guys
- // If we set it all the time, we get no music in sq3new and kq1
- // FIXME: this *may* be wrong, it's impossible to find out in sierra DOS sci, because SCI0 under DOS didn't have
- // sfx drivers included
- // We need to set signal in sound SCI1+ games all the time
+ // Set signal selector in sound SCI0 games only, when the sample has
+ // finished playing. If we don't set it at all, we get a problem when using
+ // vaporizer on the 2 guys. If we set it all the time, we get no music in
+ // sq3new and kq1.
+ // FIXME: This *may* be wrong, it's impossible to find out in Sierra DOS
+ // SCI, because SCI0 under DOS didn't have sfx drivers included.
+ // We need to set signal in sound SCI1+ games all the time.
if ((_soundVersion > SCI_VERSION_0_LATE) || sampleFinishedPlaying)
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
+ writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
musicSlot->dataInc = 0;
musicSlot->signal = 0;
_music->soundStop(musicSlot);
-#endif
}
-void SoundCommandParser::cmdPauseSound(reg_t obj, int16 value) {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- if (!obj.segment)
- return;
-
- if (_soundVersion <= SCI_VERSION_0_LATE)
- changeSoundStatus(obj, SOUND_STATUS_SUSPENDED);
+reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) {
+ if (argc == 1)
+ debugC(2, kDebugLevelSound, "kDoSound(pause): %04x:%04x", PRINT_REG(argv[0]));
else
- changeSoundStatus(obj, value ? SOUND_STATUS_SUSPENDED : SOUND_STATUS_PLAYING);
-#else
+ debugC(2, kDebugLevelSound, "kDoSound(pause): %04x:%04x, %04x:%04x", PRINT_REG(argv[0]), PRINT_REG(argv[1]));
- if (!obj.segment) { // pause the whole playlist
- // Pausing/Resuming the whole playlist was introduced
- // in the SCI1 late sound scheme
- if (_soundVersion <= SCI_VERSION_1_EARLY)
- return;
+ if (_soundVersion <= SCI_VERSION_0_LATE) {
+ // SCI0 games give us 0/1 for either resuming or pausing the current music
+ // this one doesn't count, so pausing 2 times and resuming once means here that we are supposed to resume
+ uint16 value = argv[0].toUint16();
+ MusicEntry *musicSlot = _music->getActiveSci0MusicSlot();
+ switch (value) {
+ case 1:
+ if ((musicSlot) && (musicSlot->status == kSoundPlaying)) {
+ _music->soundPause(musicSlot);
+ writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPaused);
+ }
+ return make_reg(0, 0);
+ case 0:
+ if ((musicSlot) && (musicSlot->status == kSoundPaused)) {
+ _music->soundResume(musicSlot);
+ writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying);
+ return make_reg(0, 1);
+ }
+ return make_reg(0, 0);
+ default:
+ error("kDoSound(pause): parameter 0 is invalid for sound-sci0");
+ }
+ }
+ reg_t obj = argv[0];
+ uint16 value = argc > 1 ? argv[1].toUint16() : 0;
+ if (!obj.segment) { // pause the whole playlist
_music->pauseAll(value);
} else { // pause a playlist slot
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
- warning("cmdPauseSound: Slot not found (%04x:%04x)", PRINT_REG(obj));
- return;
+ // This happens quite frequently
+ debugC(2, kDebugLevelSound, "kDoSound(pause): Slot not found (%04x:%04x)", PRINT_REG(obj));
+ return acc;
}
- if (_soundVersion <= SCI_VERSION_0_LATE) {
- // Always pause the sound in SCI0 games. It's resumed in cmdResumeSound()
- PUT_SEL32V(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPaused);
- _music->soundPause(musicSlot);
- } else {
- _music->soundToggle(musicSlot, value);
- }
+ _music->soundToggle(musicSlot, value);
}
-
-#endif
+ return acc;
}
-void SoundCommandParser::cmdResumeSound(reg_t obj, int16 value) {
- // SCI0 only command
-
- if (!obj.segment)
- return;
+// SCI0 only command
+// It's called right after restoring a game - it's responsible to kick off playing music again
+// we don't need this at all, so we don't do anything here
+reg_t SoundCommandParser::kDoSoundResumeAfterRestore(int argc, reg_t *argv, reg_t acc) {
+ return acc;
+}
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- changeSoundStatus(obj, SOUND_STATUS_PLAYING);
-#else
- MusicEntry *musicSlot = _music->getSlot(obj);
- if (!musicSlot) {
- warning("cmdResumeSound: Slot not found (%04x:%04x)", PRINT_REG(obj));
- return;
+reg_t SoundCommandParser::kDoSoundMute(int argc, reg_t *argv, reg_t acc) {
+ uint16 previousState = _music->soundGetSoundOn();
+ if (argc > 0) {
+ debugC(2, kDebugLevelSound, "kDoSound(mute): %d", argv[0].toUint16());
+ _music->soundSetSoundOn(argv[0].toUint16());
}
- PUT_SEL32V(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying);
- _music->soundResume(musicSlot);
-#endif
+ return make_reg(0, previousState);
}
-void SoundCommandParser::cmdMuteSound(reg_t obj, int16 value) {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
- if (_argc > 1) // the first parameter is the sound command
- _music->soundSetSoundOn(obj.toUint16());
- _acc = make_reg(0, _music->soundGetSoundOn());
-#endif
-}
-
-void SoundCommandParser::cmdMasterVolume(reg_t obj, int16 value) {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- _acc = make_reg(0, _state->sfx_getVolume());
-
- if (obj != SIGNAL_REG)
- _state->sfx_setVolume(obj.toSint16());
-#else
- debugC(2, kDebugLevelSound, "cmdMasterVolume: %d", value);
- _acc = make_reg(0, _music->soundGetMasterVolume());
+reg_t SoundCommandParser::kDoSoundMasterVolume(int argc, reg_t *argv, reg_t acc) {
+ acc = make_reg(0, _music->soundGetMasterVolume());
- if (_argc > 1) { // the first parameter is the sound command
- int vol = CLIP<int16>(obj.toSint16(), 0, kMaxSciVolume);
+ if (argc > 0) {
+ debugC(2, kDebugLevelSound, "kDoSound(masterVolume): %d", argv[0].toSint16());
+ int vol = CLIP<int16>(argv[0].toSint16(), 0, kMaxSciVolume);
vol = vol * Audio::Mixer::kMaxMixerVolume / kMaxSciVolume;
ConfMan.setInt("music_volume", vol);
ConfMan.setInt("sfx_volume", vol);
g_engine->syncSoundSettings();
}
-#endif
+ return acc;
}
-void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) {
- if (!obj.segment)
- return;
+reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) {
+ reg_t obj = argv[0];
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- SongHandle handle = FROBNICATE_HANDLE(obj);
- if (_soundVersion != SCI_VERSION_1_LATE) {
- /*s->sound_server->command(s, SOUND_COMMAND_FADE_HANDLE, obj, 120);*/ /* Fade out in 2 secs */
- /* FIXME: The next couple of lines actually STOP the handle, rather
- ** than fading it! */
- _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
- if (_soundVersion <= SCI_VERSION_0_LATE)
- PUT_SEL32V(_segMan, obj, SELECTOR(state), SOUND_STATUS_STOPPED);
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
- } else {
- fade_params_t fade;
- fade.final_volume = _argv[2].toUint16();
- fade.ticks_per_step = _argv[3].toUint16();
- fade.step_size = _argv[4].toUint16();
- fade.action = _argv[5].toUint16() ?
- FADE_ACTION_FADE_AND_STOP :
- FADE_ACTION_FADE_AND_CONT;
-
- _state->sfx_song_set_fade(handle, &fade);
-
- /* FIXME: The next couple of lines actually STOP the handle, rather
- ** than fading it! */
- if (_argv[5].toUint16()) {
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
- _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
- } else {
- // FIXME: Support fade-and-continue. For now, send signal right away.
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
- }
- }
-#else
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
- warning("cmdFadeSound: Slot not found (%04x:%04x)", PRINT_REG(obj));
- return;
+ warning("kDoSound(fade): Slot not found (%04x:%04x)", PRINT_REG(obj));
+ return acc;
}
int volume = musicSlot->volume;
- switch (_argc) {
- case 2: // SCI0
- // SCI0 fades out all the time and when fadeout is done it will also stop the music from playing
+ // If sound is not playing currently, set signal directly
+ if (musicSlot->status != kSoundPlaying) {
+ debugC(2, kDebugLevelSound, "kDoSound(fade): %04x:%04x fading requested, but sound is currently not playing", PRINT_REG(obj));
+ writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
+ return acc;
+ }
+
+ switch (argc) {
+ case 1: // SCI0
+ // SCI0 fades out all the time and when fadeout is done it will also
+ // stop the music from playing
musicSlot->fadeTo = 0;
musicSlot->fadeStep = -5;
musicSlot->fadeTickerStep = 10 * 16667 / _music->soundGetTempo();
musicSlot->fadeTicker = 0;
break;
- case 5: // SCI01+
- case 6: // SCI1+ (SCI1 late sound scheme), with fade and continue
- musicSlot->fadeTo = CLIP<uint16>(_argv[2].toUint16(), 0, MUSIC_VOLUME_MAX);
- musicSlot->fadeStep = volume > _argv[2].toUint16() ? -_argv[4].toUint16() : _argv[4].toUint16();
- musicSlot->fadeTickerStep = _argv[3].toUint16() * 16667 / _music->soundGetTempo();
+ case 4: // SCI01+
+ case 5: // SCI1+ (SCI1 late sound scheme), with fade and continue
+ musicSlot->fadeTo = CLIP<uint16>(argv[1].toUint16(), 0, MUSIC_VOLUME_MAX);
+ // sometimes we get objects in that position, fix it up (ffs. workarounds)
+ if (!argv[1].segment)
+ musicSlot->fadeStep = volume > musicSlot->fadeTo ? -argv[3].toUint16() : argv[3].toUint16();
+ else
+ musicSlot->fadeStep = volume > musicSlot->fadeTo ? -5 : 5;
+ musicSlot->fadeTickerStep = argv[2].toUint16() * 16667 / _music->soundGetTempo();
musicSlot->fadeTicker = 0;
- musicSlot->stopAfterFading = (_argc == 6) ? (_argv[5].toUint16() != 0) : false;
+ musicSlot->stopAfterFading = (argc == 5) ? (argv[4].toUint16() != 0) : false;
break;
default:
- error("cmdFadeSound: unsupported argc %d", _argc);
- }
-
- // If sound is not playing currently, set signal directly
- if (musicSlot->status != kSoundPlaying) {
- warning("cmdFadeSound: fading requested, but sound is currently not playing");
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
+ error("kDoSound(fade): unsupported argc %d", argc);
}
- debugC(2, kDebugLevelSound, "cmdFadeSound: to %d, step %d, ticker %d", musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep);
-#endif
+ debugC(2, kDebugLevelSound, "kDoSound(fade): %04x:%04x to %d, step %d, ticker %d", PRINT_REG(obj), musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep);
+ return acc;
}
-void SoundCommandParser::cmdGetPolyphony(reg_t obj, int16 value) {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- _acc = make_reg(0, _state->sfx_get_player_polyphony());
-#else
- _acc = make_reg(0, _music->soundGetVoices()); // Get the number of voices
-#endif
+reg_t SoundCommandParser::kDoSoundGetPolyphony(int argc, reg_t *argv, reg_t acc) {
+ return make_reg(0, _music->soundGetVoices()); // Get the number of voices
}
-void SoundCommandParser::cmdUpdateSound(reg_t obj, int16 value) {
- if (!obj.segment)
- return;
+reg_t SoundCommandParser::kDoSoundUpdate(int argc, reg_t *argv, reg_t acc) {
+ reg_t obj = argv[0];
+
+ debugC(2, kDebugLevelSound, "kDoSound(update): %04x:%04x", PRINT_REG(argv[0]));
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- SongHandle handle = FROBNICATE_HANDLE(obj);
- if (_soundVersion <= SCI_VERSION_0_LATE && obj.segment) {
- _state->sfx_song_set_loops(handle, GET_SEL32V(_segMan, obj, SELECTOR(loop)));
- script_set_priority(_resMan, _segMan, _state, obj, GET_SEL32V(_segMan, obj, SELECTOR(pri)));
- }
-#else
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
- warning("cmdUpdateSound: Slot not found (%04x:%04x)", PRINT_REG(obj));
- return;
+ warning("kDoSound(update): Slot not found (%04x:%04x)", PRINT_REG(obj));
+ return acc;
}
- musicSlot->loop = GET_SEL32V(_segMan, obj, SELECTOR(loop));
- int16 objVol = CLIP<int>(GET_SEL32V(_segMan, obj, SELECTOR(vol)), 0, 255);
+ musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop));
+ int16 objVol = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, 255);
if (objVol != musicSlot->volume)
_music->soundSetVolume(musicSlot, objVol);
- uint32 objPrio = GET_SEL32V(_segMan, obj, SELECTOR(pri));
+ uint32 objPrio = readSelectorValue(_segMan, obj, SELECTOR(pri));
if (objPrio != musicSlot->priority)
_music->soundSetPriority(musicSlot, objPrio);
-
-#endif
+ return acc;
}
-void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) {
- if (!obj.segment)
- return;
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- int signal = 0;
- int min = 0;
- int sec = 0;
- int frame = 0;
- int result = SI_LOOP; // small hack
- SongHandle handle = FROBNICATE_HANDLE(obj);
-
- while (result == SI_LOOP)
- result = _state->sfx_poll_specific(handle, &signal);
-
- switch (result) {
- case SI_ABSOLUTE_CUE:
- debugC(2, kDebugLevelSound, "--- [CUE] %04x:%04x Absolute Cue: %d",
- PRINT_REG(obj), signal);
- debugC(2, kDebugLevelSound, "abs-signal %04X", signal);
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), signal);
- break;
-
- case SI_RELATIVE_CUE:
- debugC(2, kDebugLevelSound, "--- [CUE] %04x:%04x Relative Cue: %d",
- PRINT_REG(obj), signal);
-
- /* FIXME to match commented-out semantics
- * below, with proper storage of dataInc and
- * signal in the iterator code. */
- PUT_SEL32V(_segMan, obj, SELECTOR(dataInc), signal);
- debugC(2, kDebugLevelSound, "rel-signal %04X", signal);
- if (_soundVersion == SCI_VERSION_1_EARLY)
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), signal);
- else
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), signal + 127);
- break;
-
- case SI_FINISHED:
- debugC(2, kDebugLevelSound, "--- [FINISHED] %04x:%04x", PRINT_REG(obj));
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
- break;
-
- case SI_LOOP:
- break; // Doesn't happen
- }
+reg_t SoundCommandParser::kDoSoundUpdateCues(int argc, reg_t *argv, reg_t acc) {
+ processUpdateCues(argv[0]);
+ return acc;
+}
- //switch (signal) {
- //case 0x00:
- // if (dataInc != GET_SEL32V(segMan, obj, SELECTOR(dataInc))) {
- // PUT_SEL32V(segMan, obj, SELECTOR(dataInc), dataInc);
- // PUT_SEL32V(segMan, obj, SELECTOR(signal), dataInc+0x7f);
- // } else {
- // PUT_SEL32V(segMan, obj, SELECTOR(signal), signal);
- // }
- // break;
- //case 0xFF: // May be unnecessary
- // s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
- // break;
- //default :
- // if (dataInc != GET_SEL32V(segMan, obj, SELECTOR(dataInc))) {
- // PUT_SEL32V(segMan, obj, SELECTOR(dataInc), dataInc);
- // PUT_SEL32V(segMan, obj, SELECTOR(signal), dataInc + 0x7f);
- // } else {
- // PUT_SEL32V(segMan, obj, SELECTOR(signal), signal);
- // }
- // break;
- //}
-
- if (_soundVersion == SCI_VERSION_1_EARLY) {
- PUT_SEL32V(_segMan, obj, SELECTOR(min), min);
- PUT_SEL32V(_segMan, obj, SELECTOR(sec), sec);
- PUT_SEL32V(_segMan, obj, SELECTOR(frame), frame);
- }
-#else
+void SoundCommandParser::processUpdateCues(reg_t obj) {
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
- warning("cmdUpdateCues: Slot not found (%04x:%04x)", PRINT_REG(obj));
+ warning("kDoSound(updateCues): Slot not found (%04x:%04x)", PRINT_REG(obj));
return;
}
@@ -828,9 +391,13 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) {
musicSlot->loop -= currentLoopCounter - musicSlot->sampleLoopCounter;
musicSlot->sampleLoopCounter = currentLoopCounter;
}
- if (!_music->soundIsActive(musicSlot)) {
- processStopSound(obj, 0, true);
- } else {
+ if (musicSlot->status == kSoundPlaying) {
+ if (!_music->soundIsActive(musicSlot)) {
+ processStopSound(obj, true);
+ } else {
+ _music->updateAudioStreamTicker(musicSlot);
+ }
+ } else if (musicSlot->status == kSoundPaused) {
_music->updateAudioStreamTicker(musicSlot);
}
// We get a flag from MusicEntry::doFade() here to set volume for the stream
@@ -841,150 +408,169 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) {
} else if (musicSlot->pMidiParser) {
// Update MIDI slots
if (musicSlot->signal == 0) {
- if (musicSlot->dataInc != GET_SEL32V(_segMan, obj, SELECTOR(dataInc))) {
- if (_kernel->_selectorCache.dataInc > -1)
- PUT_SEL32V(_segMan, obj, SELECTOR(dataInc), musicSlot->dataInc);
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), musicSlot->dataInc + 127);
+ if (musicSlot->dataInc != readSelectorValue(_segMan, obj, SELECTOR(dataInc))) {
+ if (SELECTOR(dataInc) > -1)
+ writeSelectorValue(_segMan, obj, SELECTOR(dataInc), musicSlot->dataInc);
+ writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->dataInc + 127);
}
} else {
// Sync the signal of the sound object
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), musicSlot->signal);
+ writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->signal);
// We need to do this especially because state selector needs to get updated
if (musicSlot->signal == SIGNAL_OFFSET)
- cmdStopSound(obj, 0);
+ processStopSound(obj, false);
}
} else {
- // Slot actually has no data (which would mean that a sound-resource w/ unsupported data is used
+ // Slot actually has no data (which would mean that a sound-resource w/
+ // unsupported data is used.
// (example lsl5 - sound resource 744 - it's roland exclusive
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
- // If we don't set signal here, at least the switch to the mud wrestling room in lsl5 will not work
+ writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
+ // If we don't set signal here, at least the switch to the mud wrestling
+ // room in lsl5 will not work.
}
if (musicSlot->fadeCompleted) {
musicSlot->fadeCompleted = false;
// We need signal for sci0 at least in iceman as well (room 14, fireworks)
- PUT_SEL32V(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
+ writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
if (_soundVersion <= SCI_VERSION_0_LATE) {
- cmdStopSound(obj, 0);
+ processStopSound(obj, false);
} else {
if (musicSlot->stopAfterFading)
- cmdStopSound(obj, 0);
+ processStopSound(obj, false);
}
}
// Sync loop selector for SCI0
if (_soundVersion <= SCI_VERSION_0_LATE)
- PUT_SEL32V(_segMan, obj, SELECTOR(loop), musicSlot->loop);
+ writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop);
musicSlot->signal = 0;
if (_soundVersion >= SCI_VERSION_1_EARLY) {
- PUT_SEL32V(_segMan, obj, SELECTOR(min), musicSlot->ticker / 3600);
- PUT_SEL32V(_segMan, obj, SELECTOR(sec), musicSlot->ticker % 3600 / 60);
- PUT_SEL32V(_segMan, obj, SELECTOR(frame), musicSlot->ticker);
+ writeSelectorValue(_segMan, obj, SELECTOR(min), musicSlot->ticker / 3600);
+ writeSelectorValue(_segMan, obj, SELECTOR(sec), musicSlot->ticker % 3600 / 60);
+ writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker);
}
-
-#endif
}
-void SoundCommandParser::cmdSendMidi(reg_t obj, int16 value) {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- //SongHandle handle = FROBNICATE_HANDLE(obj);
- //_state->sfx_send_midi(handle, value, _midiCmd, _controller, _param);
-#else
- _music->sendMidiCommand(_midiCommand);
-#endif
+reg_t SoundCommandParser::kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc) {
+ reg_t obj = argv[0];
+ byte channel = argv[1].toUint16() & 0xf;
+ byte midiCmd = argv[2].toUint16() & 0xff;
+
+ // TODO: first there is a 4-parameter variant of this call which needs to get reversed
+ // second the current code isn't 100% accurate, sierra sci does checks on the 4th parameter
+ if (argc == 4)
+ return acc;
+
+ uint16 controller = argv[3].toUint16();
+ uint16 param = argv[4].toUint16();
+
+ debugC(2, kDebugLevelSound, "kDoSound(sendMidi): %04x:%04x, %d, %d, %d, %d", PRINT_REG(obj), channel, midiCmd, controller, param);
+ if (channel)
+ channel--; // channel is given 1-based, we are using 0-based
+
+ uint32 midiCommand = (channel | midiCmd) | ((uint32)controller << 8) | ((uint32)param << 16);
+
+ MusicEntry *musicSlot = _music->getSlot(obj);
+ if (!musicSlot) {
+ // TODO: maybe it's possible to call this with obj == 0:0 and send directly?!
+ // if so, allow it
+ //_music->sendMidiCommand(_midiCommand);
+ warning("kDoSound(sendMidi): Slot not found (%04x:%04x)", PRINT_REG(obj));
+ return acc;
+ }
+ _music->sendMidiCommand(musicSlot, midiCommand);
+ return acc;
}
-void SoundCommandParser::cmdReverb(reg_t obj, int16 value) {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
- _music->setReverb(obj.toUint16() & 0xF);
-#endif
+reg_t SoundCommandParser::kDoSoundReverb(int argc, reg_t *argv, reg_t acc) {
+ debugC(2, kDebugLevelSound, "doSoundReverb: %d", argv[0].toUint16() & 0xF);
+ _music->setReverb(argv[0].toUint16() & 0xF);
+ return acc;
}
-void SoundCommandParser::cmdSetSoundHold(reg_t obj, int16 value) {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- SongHandle handle = FROBNICATE_HANDLE(obj);
- _state->sfx_song_set_hold(handle, value);
-#else
+reg_t SoundCommandParser::kDoSoundSetHold(int argc, reg_t *argv, reg_t acc) {
+ reg_t obj = argv[0];
+
+ debugC(2, kDebugLevelSound, "doSoundSetHold: %04x:%04x, %d", PRINT_REG(argv[0]), argv[1].toUint16());
+
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
- warning("cmdSetSoundHold: Slot not found (%04x:%04x)", PRINT_REG(obj));
- return;
+ warning("kDoSound(setHold): Slot not found (%04x:%04x)", PRINT_REG(obj));
+ return acc;
}
// Set the special hold marker ID where the song should be looped at.
- musicSlot->hold = value;
-#endif
+ musicSlot->hold = argv[1].toSint16();
+ return acc;
}
-void SoundCommandParser::cmdGetAudioCapability(reg_t obj, int16 value) {
+reg_t SoundCommandParser::kDoSoundGetAudioCapability(int argc, reg_t *argv, reg_t acc) {
// Tests for digital audio support
- _acc = make_reg(0, 1);
+ return make_reg(0, 1);
}
-void SoundCommandParser::cmdStopAllSounds(reg_t obj, int16 value) {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
- Common::StackLock(_music->_mutex);
+reg_t SoundCommandParser::kDoSoundStopAll(int argc, reg_t *argv, reg_t acc) {
+ // TODO: this can't be right, this gets called in kq1 - e.g. being in witch house, getting the note
+ // now the point jingle plays and after a messagebox they call this - and would stop the background effects with it
+ // this doesn't make sense, so i disable it for now
+ return acc;
- // FIXME: this can't be right, it's called in iceman (room 14) when the door sound has done playing
- // stopping sounds can't be right, because music is starting afterwards in ssci. can't be resume queued
- // song(s), because music is playing even when this call is nuked inside ssci.
- return;
+ Common::StackLock(_music->_mutex);
const MusicList::iterator end = _music->getPlayListEnd();
for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) {
if (_soundVersion <= SCI_VERSION_0_LATE) {
- PUT_SEL32V(_segMan, (*i)->soundObj, SELECTOR(state), kSoundStopped);
+ writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(state), kSoundStopped);
} else {
- PUT_SEL32V(_segMan, obj, SELECTOR(handle), 0);
- PUT_SEL32V(_segMan, (*i)->soundObj, SELECTOR(signal), SIGNAL_OFFSET);
+ writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(handle), 0);
+ writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(signal), SIGNAL_OFFSET);
}
(*i)->dataInc = 0;
_music->soundStop(*i);
}
-#endif
+ return acc;
}
-void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) {
- if (!obj.segment)
- return;
+reg_t SoundCommandParser::kDoSoundSetVolume(int argc, reg_t *argv, reg_t acc) {
+ reg_t obj = argv[0];
+ int16 value = argv[1].toSint16();
-#ifndef USE_OLD_MUSIC_FUNCTIONS
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
// Do not throw a warning if the sound can't be found, as in some games
- // this is called before the actual sound is loaded (e.g. SQ4CD, with the
- // drum sounds of the energizer bunny at the beginning), so this is normal
- // behavior
+ // this is called before the actual sound is loaded (e.g. SQ4CD, with
+ // the drum sounds of the energizer bunny at the beginning), so this is
+ // normal behavior.
//warning("cmdSetSoundVolume: Slot not found (%04x:%04x)", PRINT_REG(obj));
- return;
+ return acc;
}
- debugC(2, kDebugLevelSound, "cmdSetSoundVolume: %d", value);
+ debugC(2, kDebugLevelSound, "kDoSound(setVolume): %d", value);
value = CLIP<int>(value, 0, MUSIC_VOLUME_MAX);
if (musicSlot->volume != value) {
musicSlot->volume = value;
_music->soundSetVolume(musicSlot, value);
- PUT_SEL32V(_segMan, obj, SELECTOR(vol), value);
+ writeSelectorValue(_segMan, obj, SELECTOR(vol), value);
}
-#endif
+ return acc;
}
-void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) {
- if (!obj.segment)
- return;
+reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) {
+ reg_t obj = argv[0];
+ int16 value = argv[1].toSint16();
+
+ debugC(2, kDebugLevelSound, "kDoSound(setPriority): %04x:%04x, %d", PRINT_REG(obj), value);
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- script_set_priority(_resMan, _segMan, _state, obj, value);
-#else
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
- warning("cmdSetSoundPriority: Slot not found (%04x:%04x)", PRINT_REG(obj));
- return;
+ debugC(2, kDebugLevelSound, "kDoSound(setPriority): Slot not found (%04x:%04x)", PRINT_REG(obj));
+ return acc;
}
if (value == -1) {
@@ -993,43 +579,39 @@ void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) {
if (song->data[0] == 0xf0)
_music->soundSetPriority(musicSlot, song->data[1]);
else
- warning("cmdSetSoundPriority: Attempt to unset song priority when there is no built-in value");
+ warning("kDoSound(setPriority): Attempt to unset song priority when there is no built-in value");
//pSnd->prio=0;field_15B=0
- PUT_SEL32V(_segMan, obj, SELECTOR(flags), GET_SEL32V(_segMan, obj, SELECTOR(flags)) & 0xFD);
+ writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) & 0xFD);
} else {
// Scripted priority
//pSnd->field_15B=1;
- PUT_SEL32V(_segMan, obj, SELECTOR(flags), GET_SEL32V(_segMan, obj, SELECTOR(flags)) | 2);
+ writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) | 2);
//DoSOund(0xF,hobj,w)
}
-#endif
+ return acc;
}
-void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) {
- if (!obj.segment)
- return;
+reg_t SoundCommandParser::kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc) {
+ reg_t obj = argv[0];
+ int16 value = argv[1].toSint16();
+
+ debugC(2, kDebugLevelSound, "kDoSound(setLoop): %04x:%04x, %d", PRINT_REG(obj), value);
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- if (!GET_SEL32(_segMan, obj, SELECTOR(nodePtr)).isNull()) {
- SongHandle handle = FROBNICATE_HANDLE(obj);
- _state->sfx_song_set_loops(handle, value);
- }
-#else
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
// Apparently, it's perfectly normal for a game to call cmdSetSoundLoop
// before actually initializing the sound and adding it to the playlist
// with cmdInitSound. Usually, it doesn't matter if the game doesn't
// request to loop the sound, so in this case, don't throw any warning,
- // otherwise do, because the sound won't be looped
+ // otherwise do, because the sound won't be looped.
if (value == -1) {
- warning("cmdSetSoundLoop: Slot not found (%04x:%04x) and the song was requested to be looped", PRINT_REG(obj));
+ warning("kDoSound(setLoop): Slot not found (%04x:%04x) and the song was requested to be looped", PRINT_REG(obj));
} else {
// Doesn't really matter
}
- return;
+ return acc;
}
if (value == -1) {
musicSlot->loop = 0xFFFF;
@@ -1037,38 +619,38 @@ void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) {
musicSlot->loop = 1; // actually plays the music once
}
- PUT_SEL32V(_segMan, obj, SELECTOR(loop), musicSlot->loop);
-#endif
+ writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop);
+ return acc;
}
-void SoundCommandParser::cmdSuspendSound(reg_t obj, int16 value) {
+reg_t SoundCommandParser::kDoSoundSuspend(int argc, reg_t *argv, reg_t acc) {
// TODO
- warning("STUB: cmdSuspendSound");
+ warning("kDoSound(suspend): STUB");
+ return acc;
}
-#ifndef USE_OLD_MUSIC_FUNCTIONS
-
void SoundCommandParser::updateSci0Cues() {
bool noOnePlaying = true;
MusicEntry *pWaitingForPlay = NULL;
- _music->_mutex.lock();
-
const MusicList::iterator end = _music->getPlayListEnd();
for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) {
// Is the sound stopped, and the sound object updated too? If yes, skip
- // this sound, as SCI0 only allows one active song
- if (((*i)->isQueued) && (!pWaitingForPlay)) {
+ // this sound, as SCI0 only allows one active song.
+ if ((*i)->isQueued) {
pWaitingForPlay = (*i);
+ // FIXME(?): In iceman 2 songs are queued when playing the door
+ // sound - if we use the first song for resuming then it's the wrong
+ // one. Both songs have same priority. Maybe the new sound function
+ // in sci0 is somehow responsible.
continue;
}
if ((*i)->signal == 0 && (*i)->status != kSoundPlaying)
continue;
- cmdUpdateCues((*i)->soundObj, 0);
+ processUpdateCues((*i)->soundObj);
noOnePlaying = false;
}
- _music->_mutex.unlock();
if (noOnePlaying && pWaitingForPlay) {
// If there is a queued entry, play it now ffs: SciMusic::soundPlay()
@@ -1077,90 +659,40 @@ void SoundCommandParser::updateSci0Cues() {
}
}
-#endif
-
void SoundCommandParser::clearPlayList() {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->clearPlayList();
-#endif
-}
-
-void SoundCommandParser::syncPlayList(Common::Serializer &s) {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
- _music->saveLoadWithSerializer(s);
-#endif
-}
-
-void SoundCommandParser::reconstructPlayList(int savegame_version) {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
- Common::StackLock lock(_music->_mutex);
-
- const MusicList::iterator end = _music->getPlayListEnd();
- for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) {
- if ((*i)->resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, (*i)->resourceId))) {
- (*i)->soundRes = new SoundResource((*i)->resourceId, _resMan, _soundVersion);
- _music->soundInitSnd(*i);
- } else {
- (*i)->soundRes = 0;
- }
- if ((*i)->status == kSoundPlaying) {
- if (savegame_version < 14) {
- (*i)->dataInc = GET_SEL32V(_segMan, (*i)->soundObj, SELECTOR(dataInc));
- (*i)->signal = GET_SEL32V(_segMan, (*i)->soundObj, SELECTOR(signal));
-
- if (_soundVersion >= SCI_VERSION_1_LATE)
- (*i)->volume = GET_SEL32V(_segMan, (*i)->soundObj, SELECTOR(vol));
- }
-
- cmdPlaySound((*i)->soundObj, 0);
- }
- }
-
-#endif
}
void SoundCommandParser::printPlayList(Console *con) {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->printPlayList(con);
-#endif
}
void SoundCommandParser::printSongInfo(reg_t obj, Console *con) {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->printSongInfo(obj, con);
-#endif
}
void SoundCommandParser::stopAllSounds() {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->stopAll();
-#endif
}
void SoundCommandParser::startNewSound(int number) {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
Common::StackLock lock(_music->_mutex);
// Overwrite the first sound in the playlist
MusicEntry *song = *_music->getPlayListStart();
reg_t soundObj = song->soundObj;
- cmdDisposeSound(soundObj, 0);
- PUT_SEL32V(_segMan, soundObj, SELECTOR(number), number);
- cmdInitSound(soundObj, 0);
- cmdPlaySound(soundObj, 0);
-#endif
+ processDisposeSound(soundObj);
+ writeSelectorValue(_segMan, soundObj, SELECTOR(number), number);
+ processInitSound(soundObj);
+ processPlaySound(soundObj);
}
void SoundCommandParser::setMasterVolume(int vol) {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->soundSetMasterVolume(vol);
-#endif
}
void SoundCommandParser::pauseAll(bool pause) {
-#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->pauseAll(pause);
-#endif
}
} // End of namespace Sci
diff --git a/engines/sci/sound/soundcmd.h b/engines/sci/sound/soundcmd.h
index 09cca23450..8e6fb81762 100644
--- a/engines/sci/sound/soundcmd.h
+++ b/engines/sci/sound/soundcmd.h
@@ -26,8 +26,6 @@
#ifndef SCI_SOUNDCMD_H
#define SCI_SOUNDCMD_H
-#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
-
#include "common/list.h"
#include "sci/engine/state.h"
@@ -36,13 +34,13 @@ namespace Sci {
class Console;
class SciMusic;
class SoundCommandParser;
-typedef void (SoundCommandParser::*SoundCommand)(reg_t obj, int16 value);
+//typedef void (SoundCommandParser::*SoundCommand)(reg_t obj, int16 value);
-struct MusicEntryCommand {
- MusicEntryCommand(const char *d, SoundCommand c) : sndCmd(c), desc(d) {}
- SoundCommand sndCmd;
- const char *desc;
-};
+//struct MusicEntryCommand {
+// MusicEntryCommand(const char *d, SoundCommand c) : sndCmd(c), desc(d) {}
+// SoundCommand sndCmd;
+// const char *desc;
+//};
class SoundCommandParser {
public:
@@ -53,11 +51,7 @@ public:
kMaxSciVolume = 15
};
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- void updateSfxState(SfxState *newState) { _state = newState; }
-#endif
-
- reg_t parseCommand(int argc, reg_t *argv, reg_t acc);
+ //reg_t parseCommand(int argc, reg_t *argv, reg_t acc);
// Functions used for game state loading
void clearPlayList();
@@ -69,14 +63,14 @@ public:
void pauseAll(bool pause);
// Debug console functions
- void playSound(reg_t obj) { cmdPlaySound(obj, 0); }
- void stopSound(reg_t obj) { cmdStopSound(obj, 0); }
void startNewSound(int number);
void stopAllSounds();
void printPlayList(Console *con);
void printSongInfo(reg_t obj, Console *con);
-#ifndef USE_OLD_MUSIC_FUNCTIONS
+ void processPlaySound(reg_t obj);
+ void processStopSound(reg_t obj, bool sampleFinishedPlaying);
+
/**
* Synchronizes the current state of the music list to the rest of the engine, so that
* the changes that the sound thread makes to the music are registered with the engine
@@ -85,56 +79,44 @@ public:
* by the engine scripts themselves, so the engine itself polls for changes to the music
*/
void updateSci0Cues();
-#endif
+
+ reg_t kDoSoundInit(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundPlay(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundRestore(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundMute(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundPause(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundResumeAfterRestore(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundStop(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundStopAll(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundDispose(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundMasterVolume(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundFade(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundGetPolyphony(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundUpdate(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundUpdateCues(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundReverb(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundSetHold(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundDummy(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundGetAudioCapability(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundSetVolume(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc);
+ reg_t kDoSoundSuspend(int argc, reg_t *argv, reg_t acc);
private:
- typedef Common::Array<MusicEntryCommand *> SoundCommandContainer;
- SoundCommandContainer _soundCommands;
+ //typedef Common::Array<MusicEntryCommand *> SoundCommandContainer;
+ //SoundCommandContainer _soundCommands;
ResourceManager *_resMan;
SegManager *_segMan;
Kernel *_kernel;
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- SfxState *_state;
- int _midiCmd, _controller, _param;
-#else
SciMusic *_music;
-#endif
AudioPlayer *_audio;
SciVersion _soundVersion;
- int _argc;
- reg_t *_argv; // for cmdFadeSound
- uint32 _midiCommand; // for cmdSendMidi
- reg_t _acc;
- int _cmdUpdateCuesIndex;
-
- void cmdInitSound(reg_t obj, int16 value);
- void cmdPlaySound(reg_t obj, int16 value);
- void cmdDummy(reg_t obj, int16 value);
- void cmdMuteSound(reg_t obj, int16 value);
- void cmdPauseSound(reg_t obj, int16 value);
- void cmdResumeSound(reg_t obj, int16 value);
- void cmdStopSound(reg_t obj, int16 value);
- void cmdDisposeSound(reg_t obj, int16 value);
- void cmdMasterVolume(reg_t obj, int16 value);
- void cmdFadeSound(reg_t obj, int16 value);
- void cmdGetPolyphony(reg_t obj, int16 value);
- void cmdStopAllSounds(reg_t obj, int16 value);
- void cmdUpdateSound(reg_t obj, int16 value);
- void cmdUpdateCues(reg_t obj, int16 value);
- void cmdSendMidi(reg_t obj, int16 value);
- void cmdReverb(reg_t obj, int16 value);
- void cmdSetSoundHold(reg_t obj, int16 value);
- void cmdGetAudioCapability(reg_t obj, int16 value);
- void cmdSetSoundVolume(reg_t obj, int16 value);
- void cmdSetSoundPriority(reg_t obj, int16 value);
- void cmdSetSoundLoop(reg_t obj, int16 value);
- void cmdSuspendSound(reg_t obj, int16 value);
-
- void processStopSound(reg_t obj, int16 value, bool sampleFinishedPlaying);
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- void changeSoundStatus(reg_t obj, int newStatus);
-#endif
+
+ void processInitSound(reg_t obj);
+ void processDisposeSound(reg_t obj);
+ void processUpdateCues(reg_t obj);
};
} // End of namespace Sci
diff --git a/engines/sci/video/seq_decoder.cpp b/engines/sci/video/seq_decoder.cpp
index 2c117ae329..58fd60621d 100644
--- a/engines/sci/video/seq_decoder.cpp
+++ b/engines/sci/video/seq_decoder.cpp
@@ -55,10 +55,10 @@ SeqDecoder::~SeqDecoder() {
close();
}
-bool SeqDecoder::load(Common::SeekableReadStream &stream) {
+bool SeqDecoder::load(Common::SeekableReadStream *stream) {
close();
- _fileStream = &stream;
+ _fileStream = stream;
_surface = new Graphics::Surface();
_surface->create(SEQ_SCREEN_WIDTH, SEQ_SCREEN_HEIGHT, 1);
@@ -76,6 +76,7 @@ bool SeqDecoder::load(Common::SeekableReadStream &stream) {
uint16 palColorCount = READ_LE_UINT16(paletteData + 29);
int palOffset = 37;
+ memset(_palette, 0, 256 * 3);
for (uint16 colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) {
if (palFormat == kSeqPalVariable)
diff --git a/engines/sci/video/seq_decoder.h b/engines/sci/video/seq_decoder.h
index 416abb78fa..1714477083 100644
--- a/engines/sci/video/seq_decoder.h
+++ b/engines/sci/video/seq_decoder.h
@@ -38,7 +38,7 @@ public:
SeqDecoder();
virtual ~SeqDecoder();
- bool load(Common::SeekableReadStream &stream);
+ bool load(Common::SeekableReadStream *stream);
void close();
void setFrameDelay(int frameDelay) { _frameDelay = frameDelay; }
diff --git a/engines/sci/video/vmd_decoder.cpp b/engines/sci/video/vmd_decoder.cpp
deleted file mode 100644
index 93132bc5d6..0000000000
--- a/engines/sci/video/vmd_decoder.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifdef ENABLE_SCI32
-
-#include "sci/video/vmd_decoder.h"
-
-#include "common/endian.h"
-#include "common/util.h"
-#include "common/stream.h"
-#include "common/system.h"
-
-#include "graphics/dither.h"
-
-#include "sound/mixer.h"
-#include "sound/audiostream.h"
-
-namespace Sci {
-
-VMDDecoder::VMDDecoder(Audio::Mixer *mixer) : _mixer(mixer) {
- _vmdDecoder = new Graphics::Vmd(new Graphics::PaletteLUT(5, Graphics::PaletteLUT::kPaletteYUV));
- _surface = 0;
- _dirtyPalette = false;
- _fileStream = 0;
-}
-
-VMDDecoder::~VMDDecoder() {
- close();
-}
-
-bool VMDDecoder::load(Common::SeekableReadStream &stream) {
- close();
-
- if (!_vmdDecoder->load(stream))
- return false;
-
- _fileStream = &stream;
-
- if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesPalette)
- loadPaletteFromVMD();
-
- if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesSound)
- _vmdDecoder->enableSound(*_mixer);
-
- if (_vmdDecoder->hasExtraData())
- warning("This VMD video has extra embedded data, which is currently not handled");
-
- _surface = new Graphics::Surface();
- _surface->create(_vmdDecoder->getWidth(), _vmdDecoder->getHeight(), 1);
- _vmdDecoder->setVideoMemory((byte *)_surface->pixels, _surface->w, _surface->h);
- return true;
-}
-
-void VMDDecoder::close() {
- if (!_fileStream)
- return;
-
- _vmdDecoder->unload();
-
- delete _fileStream;
- _fileStream = 0;
-
- _surface->free();
- delete _surface;
- _surface = 0;
-
- reset();
-}
-
-Graphics::Surface *VMDDecoder::decodeNextFrame() {
- Graphics::CoktelVideo::State state = _vmdDecoder->nextFrame();
-
- if (state.flags & Graphics::CoktelVideo::kStatePalette)
- loadPaletteFromVMD();
-
- if (_curFrame == -1)
- _startTime = g_system->getMillis();
-
- _curFrame++;
- return _surface;
-}
-
-void VMDDecoder::loadPaletteFromVMD() {
- const byte *pal = _vmdDecoder->getPalette();
-
- for (int i = 0; i < 256; i++) {
- _palette[i * 3 + 0] = pal[i * 3 + 0] << 2;
- _palette[i * 3 + 1] = pal[i * 3 + 1] << 2;
- _palette[i * 3 + 2] = pal[i * 3 + 2] << 2;
- }
-
- _dirtyPalette = true;
-}
-
-} // End of namespace Graphics
-
-#endif
diff --git a/engines/sci/video/vmd_decoder.h b/engines/sci/video/vmd_decoder.h
deleted file mode 100644
index 231da9202e..0000000000
--- a/engines/sci/video/vmd_decoder.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifdef ENABLE_SCI32
-
-#ifndef GRAPHICS_VIDEO_VMD_DECODER_H
-#define GRAPHICS_VIDEO_VMD_DECODER_H
-
-#include "graphics/video/coktelvideo/coktelvideo.h"
-#include "graphics/video/video_decoder.h"
-#include "sound/mixer.h"
-
-namespace Sci {
-
-/**
- * Wrapper for the Coktel Vision VMD video decoder
- * for videos by Coktel Vision/Sierra.
- *
- * VMD videos were used in the following SCI21/SCI3
- * adventure games, developed by Sierra:
- * - Gabriel Knight 2: The Beast Within
- * - Leisure Suit Larry 7
- * - Lighthouse
- * - Phantasmagoria 1
- * - RAMA
- * - Shivers
- * - Shivers 2: Harvest of Souls
- * - Torin's Passage
- */
-class VMDDecoder : public Graphics::FixedRateVideoDecoder {
-public:
- VMDDecoder(Audio::Mixer *mixer);
- virtual ~VMDDecoder();
-
- uint32 getFrameWaitTime();
-
- bool load(Common::SeekableReadStream &stream);
- void close();
-
- bool isVideoLoaded() const { return _fileStream != 0; }
- uint16 getWidth() const { return _surface->w; }
- uint16 getHeight() const { return _surface->h; }
- uint32 getFrameCount() const { return _vmdDecoder->getFramesCount(); }
- Graphics::Surface *decodeNextFrame();
- Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); }
- byte *getPalette() { _dirtyPalette = false; return _palette; }
- bool hasDirtyPalette() const { return _dirtyPalette; }
-
-protected:
- Common::Rational getFrameRate() const { return _vmdDecoder->getFrameRate(); }
-
-private:
- Graphics::Vmd *_vmdDecoder;
- Audio::Mixer *_mixer;
- Graphics::Surface *_surface;
- Common::SeekableReadStream *_fileStream;
- byte _palette[256 * 3];
- bool _dirtyPalette;
-
- void loadPaletteFromVMD();
-};
-
-} // End of namespace Graphics
-
-#endif
-
-#endif
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 757171b24c..053bf597f8 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -109,10 +109,9 @@ void ScummEngine::loadCJKFont() {
numChar = 8192;
break;
case Common::ZH_TWN:
- if (_game.id == GID_CMI) {
- fontFile = "chinese.fnt";
- numChar = 13630;
- }
+ // Both The DIG and COMI use same font
+ fontFile = "chinese.fnt";
+ numChar = 13630;
break;
case Common::ZH_CNA:
if (_game.id == GID_FT || _game.id == GID_LOOM || _game.id == GID_INDY3 ||
diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp
index a0975839d6..e0582f79ef 100644
--- a/engines/scumm/debugger.cpp
+++ b/engines/scumm/debugger.cpp
@@ -62,8 +62,6 @@ ScummDebugger::ScummDebugger(ScummEngine *s)
_vm = s;
// Register variables
- DVar_Register("debug_countdown", &_frame_countdown, DVAR_INT, 0);
-
DVar_Register("scumm_speed", &_vm->_fastMode, DVAR_BYTE, 0);
DVar_Register("scumm_room", &_vm->_currentRoom, DVAR_BYTE, 0);
DVar_Register("scumm_roomresource", &_vm->_roomResource, DVAR_INT, 0);
@@ -128,7 +126,7 @@ void ScummDebugger::postEnter() {
bool ScummDebugger::Cmd_Restart(int argc, const char **argv) {
_vm->restart();
- _detach_now = true;
+ detach();
return false;
}
@@ -202,7 +200,7 @@ bool ScummDebugger::Cmd_LoadGame(int argc, const char **argv) {
_vm->requestLoad(slot);
- _detach_now = true;
+ detach();
return false;
}
@@ -867,7 +865,7 @@ bool ScummDebugger::Cmd_Passcode(int argc, const char **argv) {
}
_vm->_bootParam = 0;
- _detach_now = true;
+ detach();
} else {
DebugPrintf("Use 'passcode <SEGA CD Passcode>'\n");
@@ -878,9 +876,7 @@ bool ScummDebugger::Cmd_Passcode(int argc, const char **argv) {
bool ScummDebugger::Cmd_ResetCursors(int argc, const char **argv) {
_vm->resetCursors();
-
- _detach_now = true;
-
+ detach();
return false;
}
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 7275caaa1e..9721c75677 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -314,7 +314,7 @@ static Common::Language detectLanguage(const Common::FSList &fslist, byte id) {
case 449787: // 64f3fe479d45b52902cf88145c41d172
return Common::ES_ESP;
}
- } else {
+ } else { // The DIG
switch (size) {
case 248627: // 1fd585ac849d57305878c77b2f6c74ff
return Common::DE_DEU;
@@ -328,6 +328,8 @@ static Common::Language detectLanguage(const Common::FSList &fslist, byte id) {
return Common::ES_ESP;
case 223107: // 64f3fe479d45b52902cf88145c41d172
return Common::JA_JPN;
+ case 180730: // 424fdd60822722cdc75356d921dad9bf
+ return Common::ZH_TWN;
}
}
}
@@ -381,10 +383,12 @@ static void computeGameSettingsFromMD5(const Common::FSList &fslist, const GameF
}
}
-static void detectGames(const Common::FSList &fslist, Common::List<DetectorResult> &results, const char *gameid) {
- DescMap fileMD5Map;
- DetectorResult dr;
- char md5str[32+1];
+static void composeFileHashMap(const Common::FSList &fslist, DescMap &fileMD5Map, int depth, const char **globs) {
+ if (depth <= 0)
+ return;
+
+ if (fslist.empty())
+ return;
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (!file->isDirectory()) {
@@ -392,8 +396,36 @@ static void detectGames(const Common::FSList &fslist, Common::List<DetectorResul
d.node = *file;
d.md5Entry = 0;
fileMD5Map[file->getName()] = d;
+ } else {
+ if (!globs)
+ continue;
+
+ bool matched = false;
+ for (const char *glob = *globs; *glob; glob++)
+ if (file->getName().matchString(glob, true)) {
+ matched = true;
+ break;
+ }
+
+ if (!matched)
+ continue;
+
+ Common::FSList files;
+
+ if (file->getChildren(files, Common::FSNode::kListAll)) {
+ composeFileHashMap(files, fileMD5Map, depth - 1, globs);
+ }
}
}
+}
+
+static void detectGames(const Common::FSList &fslist, Common::List<DetectorResult> &results, const char *gameid) {
+ DescMap fileMD5Map;
+ DetectorResult dr;
+ char md5str[32+1];
+
+ // Dive one level down since mac indy3/loom has its files split into directories. See Bug #1438631
+ composeFileHashMap(fslist, fileMD5Map, 2, directoryGlobs);
// Iterate over all filename patterns.
for (const GameFilenamePattern *gfp = gameFilenamesTable; gfp->gameid; ++gfp) {
@@ -458,6 +490,12 @@ static void detectGames(const Common::FSList &fslist, Common::List<DetectorResul
// Exact match found. Compute the precise game settings.
computeGameSettingsFromMD5(fslist, gfp, d.md5Entry, dr);
+ // Print some debug info
+ int filesize = tmp->size();
+ if (d.md5Entry->filesize != filesize)
+ debug(1, "SCUMM detector found matching file '%s' with MD5 %s, size %d\n",
+ file.c_str(), md5str, filesize);
+
// Sanity check: We *should* have found a matching gameid / variant at this point.
// If not, then there's a bug in our data tables...
assert(dr.game.gameid != 0);
@@ -866,7 +904,8 @@ GameList ScummMetaEngine::detectGames(const Common::FSList &fslist) const {
}
}
- dg.setGUIOptions(x->game.guioptions);
+ dg.setGUIOptions(x->game.guioptions | MidiDriver::musicType2GUIO(x->game.midi));
+ dg.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language));
detectedGames.push_back(dg);
}
@@ -966,6 +1005,10 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co
debug(1, "Using MD5 '%s'", res.md5.c_str());
}
+ // If the GUI options were updated, we catch this here and update them in the users config
+ // file transparently.
+ Common::updateGameGUIOptions(res.game.guioptions, getGameGUIOptionsDescriptionLanguage(res.language));
+
// Check for a user override of the platform. We allow the user to override
// the platform, to make it possible to add games which are not yet in
// our MD5 database but require a specific platform setting.
@@ -982,11 +1025,6 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co
// TODO: Maybe allow the null driver, too?
if (res.game.platform == Common::kPlatformFMTowns && res.game.version == 3)
res.game.midi = MDT_TOWNS;
-
- // If the GUI options were updated, we catch this here and update them in the users config
- // file transparently.
- Common::updateGameGUIOptions(res.game.guioptions);
-
// Finally, we have massaged the GameDescriptor to our satisfaction, and can
// instantiate the appropriate game engine. Hooray!
switch (res.game.version) {
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index 0b90af4ec4..d8987c816f 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -48,6 +48,15 @@ namespace Scumm {
#pragma mark --- Tables ---
#pragma mark -
+/**
+ * This table contains list of directories which could contain game data
+ * and which should be looked into during detection.
+ */
+static const char *directoryGlobs[] = {
+ "rooms *", // Mac version of indy3/loom
+ 0
+};
+
/**
* This table contains all game IDs supported by the SCUMM engine, and maps
@@ -215,7 +224,7 @@ static const GameSettings gameVariantsTable[] = {
{"indy3", "VGA", "vga", GID_INDY3, 3, 0, MDT_PCSPK | MDT_ADLIB, GF_OLD256 | GF_FEW_LOCALS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
{"indy3", "FM-TOWNS", 0, GID_INDY3, 3, 0, MDT_TOWNS, GF_OLD256 | GF_FEW_LOCALS | GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI},
- {"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH},
+ {"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH},
{"loom", "No AdLib", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI},
#ifdef USE_RGB_COLOR
{"loom", "PC-Engine", 0, GID_LOOM, 3, 0, MDT_NONE, GF_AUDIOTRACKS | GF_OLD256 | GF_16BIT_COLOR, Common::kPlatformPCEngine, GUIO_NOSPEECH | GUIO_NOMIDI},
@@ -225,24 +234,24 @@ static const GameSettings gameVariantsTable[] = {
{"pass", 0, 0, GID_PASS, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
- {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH},
- {"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH},
+ {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH},
+ {"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH},
{"monkey", "No AdLib", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK, GF_16COLOR, Common::kPlatformAtariST, GUIO_NOSPEECH | GUIO_NOMIDI},
{"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
{"monkey", "CD", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, UNK, GUIO_NOSPEECH | GUIO_NOMIDI},
{"monkey", "FM-TOWNS", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI},
{"monkey", "SEGA", 0, GID_MONKEY, 5, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformSegaCD, GUIO_NOSPEECH | GUIO_NOMIDI},
- {"monkey2", 0, 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH},
+ {"monkey2", 0, 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH},
- {"atlantis", "" , 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NONE},
- {"atlantis", "Floppy", 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH},
+ {"atlantis", "" , 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NONE},
+ {"atlantis", "Floppy", 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH},
- {"tentacle", "", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE},
- {"tentacle", "Floppy", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH},
+ {"tentacle", "", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NONE},
+ {"tentacle", "Floppy", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NOSPEECH},
- {"samnmax", "", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE},
- {"samnmax", "Floppy", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH},
+ {"samnmax", "", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NONE},
+ {"samnmax", "Floppy", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NOSPEECH},
#ifdef ENABLE_SCUMM_7_8
{"ft", 0, 0, GID_FT, 7, 0, MDT_NONE, 0, UNK, GUIO_NOMIDI},
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index 1f153094c1..b160dac6f2 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -26,6 +26,7 @@
#include "common/savefile.h"
#include "common/system.h"
#include "common/events.h"
+#include "common/translation.h"
#include "graphics/scaler.h"
@@ -488,9 +489,9 @@ HelpDialog::HelpDialog(const GameSettings &game)
_numPages = ScummHelp::numPages(_game.id);
- _prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", "Previous", kPrevCmd, 'P');
- _nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", "Next", kNextCmd, 'N');
- new GUI::ButtonWidget(this, "ScummHelp.Close", "Close", GUI::kCloseCmd, 'C');
+ _prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", _("~P~revious"), 0, kPrevCmd);
+ _nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", _("~N~ext"), 0, kNextCmd);
+ new GUI::ButtonWidget(this, "ScummHelp.Close", _("~C~lose"), 0, GUI::kCloseCmd);
_prevButton->clearFlags(WIDGET_ENABLED);
_numLines = HELP_NUM_LINES;
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index 298917477f..7b0d4909d6 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -1482,7 +1482,7 @@ void GdiV2::prepareDrawBitmap(const byte *ptr, VirtScreen *vs,
// Since V3, all graphics data was encoded in strips, which is very efficient
// for redrawing only parts of the screen. However, V2 is different: here
// the whole graphics are encoded as one big chunk. That makes it rather
- // dificult to draw only parts of a room/object. We handle the V2 graphics
+ // difficult to draw only parts of a room/object. We handle the V2 graphics
// differently from all other (newer) graphic formats for this reason.
//
StripTable *table = (_objectMode ? 0 : _roomStrips);
@@ -2823,7 +2823,7 @@ void GdiPCEngine::decodePCEngineObject(const byte *ptr, int xpos, int ypos, int
free(stripOffsets);
}
-void setTileData(byte *tile, int index, byte byte0, byte byte1) {
+void GdiPCEngine::setTileData(byte *tile, int index, byte byte0, byte byte1) {
int row = index % 8;
int plane = (index / 8) * 2;
int plane02Bit, plane13Bit;
diff --git a/engines/scumm/gfx.h b/engines/scumm/gfx.h
index 108fd4555d..cdb473a67c 100644
--- a/engines/scumm/gfx.h
+++ b/engines/scumm/gfx.h
@@ -322,6 +322,7 @@ protected:
protected:
void decodePCEngineGfx(const byte *room);
void decodeStrip(const byte *ptr, uint16 *tiles, byte *colors, uint16 *masks, int numRows, bool isObject);
+ void setTileData(byte *tile, int index, byte byte0, byte byte1);
void decodePCEngineTileData(const byte *ptr);
void decodePCEngineMaskData(const byte *ptr);
void decodePCEngineObject(const byte *ptr, int xpos, int ypos, int width, int height);
diff --git a/engines/scumm/imuse/instrument.cpp b/engines/scumm/imuse/instrument.cpp
index efe15f308f..57a842f297 100644
--- a/engines/scumm/imuse/instrument.cpp
+++ b/engines/scumm/imuse/instrument.cpp
@@ -421,11 +421,11 @@ Instrument_Roland::Instrument_Roland(Serializer *s) {
memset(&_instrument, 0, sizeof(_instrument));
}
-void Instrument_Roland::saveOrLoad (Serializer *s) {
+void Instrument_Roland::saveOrLoad(Serializer *s) {
if (s->isSaving()) {
- s->saveBytes (&_instrument, sizeof(_instrument));
+ s->saveBytes(&_instrument, sizeof(_instrument));
} else {
- s->loadBytes (&_instrument, sizeof(_instrument));
+ s->loadBytes(&_instrument, sizeof(_instrument));
memcpy(&_instrument_name, &_instrument.common.name, sizeof(_instrument.common.name));
_instrument_name[10] = '\0';
if (!_native_mt32 && getEquivalentGM() >= 128) {
diff --git a/engines/scumm/player_nes.cpp b/engines/scumm/player_nes.cpp
index 4618de3175..96396e7a08 100644
--- a/engines/scumm/player_nes.cpp
+++ b/engines/scumm/player_nes.cpp
@@ -23,6 +23,7 @@
*
*/
+#ifndef DISABLE_NES_APU
#include "engines/engine.h"
#include "scumm/player_nes.h"
@@ -1065,3 +1066,5 @@ byte Player_NES::APU_readStatus() {
}
} // End of namespace Scumm
+
+#endif // DISABLE_NES_APU
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 7362dcd8cf..3cc619f630 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -364,7 +364,7 @@ bool ScummEngine::loadState(int slot, bool compat) {
}
}
- Graphics::skipThumbnailHeader(*in);
+ Graphics::skipThumbnail(*in);
}
// Since version 56 we save additional information about the creation of
@@ -577,6 +577,10 @@ bool ScummEngine::loadState(int slot, bool compat) {
// Fixes bug #1766072: MANIACNES: Music Doesn't Start On Load Game
if (_game.platform == Common::kPlatformNES) {
runScript(5, 0, 0, 0);
+
+ if (VAR(224)) {
+ _sound->addSoundToQueue(VAR(224));
+ }
}
return true;
@@ -717,7 +721,7 @@ bool ScummEngine::loadInfosFromSlot(const char *target, int slot, InfoStuff *stu
return false;
}
- if (!Graphics::skipThumbnailHeader(*in)) {
+ if (!Graphics::skipThumbnail(*in)) {
delete in;
return false;
}
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index b1545db0f3..5c20e0dfd3 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -2594,6 +2594,17 @@ void ScummEngine_v5::decodeParseString() {
else
strcpy((char *)tmpBuf+16, "^19^");
printString(textSlot, tmpBuf);
+ } else if (_game.id == GID_MONKEY_EGA && _roomResource == 30 && vm.slot[_currentScript].number == 411 &&
+ strstr((const char *)_scriptPointer, "NCREDIT-NOTE-AMOUNT")) {
+ // WORKAROUND for bug #3003643 (MI1EGA German: Credit text incorrect)
+ // The script contains buggy text.
+ const char *tmp = strstr((const char *)_scriptPointer, "NCREDIT-NOTE-AMOUNT");
+ char tmpBuf[256];
+ const int diff = tmp - (const char *)_scriptPointer;
+ memcpy(tmpBuf, _scriptPointer, diff);
+ strcpy(tmpBuf + diff, "5000");
+ strcpy(tmpBuf + diff + 4, tmp + sizeof("NCREDIT-NOTE-AMOUNT") - 1);
+ printString(textSlot, (byte *)tmpBuf);
} else {
printString(textSlot, _scriptPointer);
}
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index 9b7e0798eb..a25fac1a88 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Sun May 9 20:53:55 2010
+ This file was generated by the md5table tool on Sun Jun 27 05:23:26 2010
DO NOT EDIT MANUALLY!
*/
@@ -40,14 +40,14 @@ static const MD5Table md5table[] = {
{ "0a295b80f9a9edf818e8e161a0e83830", "freddi2", "HE 80", "", -1, Common::FR_FRA, Common::kPlatformUnknown },
{ "0a41311d462b6639fc45297b9044bf16", "monkey", "No AdLib", "EGA", -1, Common::ES_ESP, Common::kPlatformAtariST },
{ "0a6d7b81b850ed4a77811c60c9b5c555", "PuttTime", "HE 99", "Mini Game", -1, Common::EN_USA, Common::kPlatformWindows },
- { "0aa050f4ad79402fbe9c4f78fb8ac494", "loom", "PC-Engine", "", -1, Common::EN_ANY, Common::kPlatformPCEngine },
+ { "0aa050f4ad79402fbe9c4f78fb8ac494", "loom", "PC-Engine", "", 6532, Common::EN_ANY, Common::kPlatformPCEngine },
{ "0ab19be9e2a3f6938226638b2a3744fe", "PuttTime", "HE 100", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "0ac41e2e3d2174e5a042a6b565328dba", "puttrace", "HE 98", "Demo", 13110, Common::EN_USA, Common::kPlatformUnknown },
{ "0b3222aaa7efcf283eb621e0cefd26cc", "puttputt", "HE 60", "", -1, Common::RU_RUS, Common::kPlatformPC },
{ "0be88565f734b1e9e77ccaaf3bb14b29", "loom", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformPC },
{ "0bf1a3eb198ca1bd2ebe104825cec770", "puttrace", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "0c331637580950aea2346e012ef2a868", "maniac", "V2", "V2", 1988, Common::EN_ANY, Common::kPlatformAtariST },
- { "0c45eb4baff0c12c3d9dfa889c8070ab", "pajama3", "", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown },
+ { "0c45eb4baff0c12c3d9dfa889c8070ab", "pajama3", "", "Demo", 13884, Common::DE_DEU, Common::kPlatformUnknown },
{ "0cccfa5223099a60e76cfcca57a1a141", "freddi3", "", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "0d1b69471605201ef2fa9cec1f5f02d2", "maniac", "V2", "V2", -1, Common::ES_ESP, Common::kPlatformPC },
{ "0e4c5d54a0ad4b26132e78b5ea76642a", "samnmax", "Floppy", "Demo", 6485, Common::EN_ANY, Common::kPlatformPC },
@@ -75,11 +75,11 @@ static const MD5Table md5table[] = {
{ "15e03ffbfeddb9c2aebc13dcb2a4a8f4", "monkey", "VGA", "VGA", 8357, Common::EN_ANY, Common::kPlatformPC },
{ "15f588e887e857e8c56fe6ade4956168", "atlantis", "Floppy", "Floppy", -1, Common::ES_ESP, Common::kPlatformAmiga },
{ "16542a7342a918bfe4ba512007d36c47", "FreddisFunShop", "HE 99L", "", -1, Common::EN_USA, Common::kPlatformUnknown },
- { "166553538ff320c69edafeee29525419", "samnmax", "", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh },
+ { "166553538ff320c69edafeee29525419", "samnmax", "", "CD", 199195304, Common::EN_ANY, Common::kPlatformMacintosh },
{ "16effd200aa6b8abe9c569c3e578814d", "freddi4", "HE 99", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "179879b6e35c1ead0d93aab26db0951b", "fbear", "HE 70", "", 13381, Common::EN_ANY, Common::kPlatformWindows },
{ "17b5d5e6af4ae89d62631641d66d5a05", "indy3", "VGA", "VGA", -1, Common::IT_ITA, Common::kPlatformPC },
- { "17f7296f63c78642724f057fd8e736a7", "maniac", "NES", "", -1, Common::EN_GRB, Common::kPlatformNES },
+ { "17f7296f63c78642724f057fd8e736a7", "maniac", "NES", "", 2082, Common::EN_GRB, Common::kPlatformNES },
{ "17fa250eb72dae2dad511ba79c0b6b0a", "tentacle", "", "Demo", -1, Common::FR_FRA, Common::kPlatformPC },
{ "182344899c2e2998fca0bebcd82aa81a", "atlantis", "", "CD", 12035, Common::EN_ANY, Common::kPlatformPC },
{ "183d7464902d40d00800e8ee1f04117c", "maniac", "V2", "V2", 1988, Common::DE_DEU, Common::kPlatformPC },
@@ -130,13 +130,14 @@ static const MD5Table md5table[] = {
{ "2d388339d6050d8ccaa757b64633954e", "zak", "FM-TOWNS", "Demo", 7520, Common::EN_ANY, Common::kPlatformFMTowns },
{ "2d4536a56e01da4b02eb021e7770afa2", "zak", "FM-TOWNS", "", 7520, Common::EN_ANY, Common::kPlatformFMTowns },
{ "2d4acbdcfd8e374c9da8c2e7303a5cd0", "BluesBirthday", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
- { "2d624d1b214f7faf0094daea65c6d1a6", "maniac", "Apple II", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
+ { "2d624d1b214f7faf0094daea65c6d1a6", "maniac", "Apple II", "", -1, Common::EN_ANY, Common::kPlatformApple2GS },
{ "2d9d46f23cb07bbc90b8ad464d3e4ff8", "atlantis", "", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "2e85f7aa054930c692a5b1bed1dfc295", "football2002", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "2e8a1f76ea33bc5e04347646feee173d", "pajama3", "", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "2fe369ad70f52a8cf7ad6077ee64f81a", "loom", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformAmiga },
{ "305d3dd57c96c65b017bc70c8c7cfb5e", "monkey", "CD", "CD", 8955, Common::DE_DEU, Common::kPlatformPC },
{ "30ba1e825d4ad2b448143ae8df18482a", "pajama2", "HE 98.5", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
+ { "30d1903b0715759af064be2127381cd0", "freddi", "HE 100", "", 34837, Common::DE_DEU, Common::kPlatformWii },
{ "319a4dde52c7960b5aae8a1ec348d918", "monkey", "VGA", "VGA", -1, Common::DE_DEU, Common::kPlatformAmiga },
{ "31aa57f460a3d12429f0552a46a90b39", "puttputt", "Demo", "Demo", 6150, Common::EN_ANY, Common::kPlatformPC },
{ "31b8fda4c8c7413fa6b39997e776eba4", "loom", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns },
@@ -145,7 +146,7 @@ static const MD5Table md5table[] = {
{ "330f631502e381a4e199a3f7cb483c20", "indy3", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformAmiga },
{ "33e989f85da700e2014d00f345cab3d7", "puttrace", "HE 98.5", "", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "3433be9866ca4261b2d5d25374e3f243", "monkey", "VGA", "VGA", -1, Common::FR_FRA, Common::kPlatformAmiga },
- { "3486ede0f904789267d4bcc5537a46d4", "puttzoo", "", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh },
+ { "3486ede0f904789267d4bcc5537a46d4", "puttzoo", "", "Demo", 14337, Common::EN_ANY, Common::kPlatformMacintosh },
{ "356fb5f680b68251333016175935d126", "BluesABCTime", "HE CUP", "Preview", 4133436, Common::UNK_LANG, Common::kPlatformUnknown },
{ "35a2d3040fa512f8232d9e443319d84d", "dig", "", "", 659335495, Common::EN_ANY, Common::kPlatformMacintosh },
{ "362c1d281fb9899254cda66ad246c66a", "dig", "Demo", "Demo", 3472, Common::EN_ANY, Common::kPlatformUnknown },
@@ -167,21 +168,24 @@ static const MD5Table md5table[] = {
{ "3a3e592b074f595489f7f11e150c398d", "puttzoo", "HE 99", "Updated", -1, Common::EN_USA, Common::kPlatformWindows },
{ "3a5d13675e9a23aedac0bac7730f0ac1", "samnmax", "", "CD", -1, Common::FR_FRA, Common::kPlatformMacintosh },
{ "3a5ec90d556d4920976c5578bfbfaf79", "maniac", "NES", "", -1, Common::DE_DEU, Common::kPlatformNES },
+ { "3ae7f002d9256b8bdf76aaf8a3a069f8", "freddi", "HE 100", "", 34837, Common::EN_GRB, Common::kPlatformWii },
{ "3af61c5edf8e15b43dbafd285b2e9777", "puttcircus", "", "Demo", -1, Common::HE_ISR, Common::kPlatformWindows },
{ "3b301b7892f883ce42ab4be6a274fea6", "samnmax", "Floppy", "Floppy", -1, Common::EN_ANY, Common::kPlatformPC },
{ "3b832f4a90740bf22e9b8ed42ca0128c", "freddi4", "HE 99", "", -1, Common::EN_GRB, Common::kPlatformWindows },
+ { "3c4c471342bd95505a42334367d8f127", "puttmoon", "HE 70", "", 12161, Common::RU_RUS, Common::kPlatformWindows },
{ "3cce1913a3bc586b51a75c3892ff18dd", "indy3", "VGA", "VGA", -1, Common::RU_RUS, Common::kPlatformPC },
{ "3d219e7546039543307b55a91282bf18", "funpack", "", "", -1, Common::EN_ANY, Common::kPlatformPC },
{ "3de99ef0523f8ca7958faa3afccd035a", "spyfox", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "3df6ead57930488bc61e6e41901d0e97", "fbear", "HE 62", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "3e48298920fab9b7aec5a971e1bd1fab", "pajama3", "", "Demo", -1, Common::EN_GRB, Common::kPlatformWindows },
+ { "3e861421f494711bc6f619d4aba60285", "airport", "", "", 93231, Common::RU_RUS, Common::kPlatformWindows },
{ "40564ec47da48a67787d1f9bd043902a", "maniac", "V2 Demo", "V2 Demo", 1988, Common::EN_ANY, Common::kPlatformPC },
{ "4167a92a1d46baa4f4127d918d561f88", "tentacle", "", "CD", 7932, Common::EN_ANY, Common::kPlatformUnknown },
{ "41958e24d03181ff9a381a66d048a581", "ft", "", "", -1, Common::PT_BRA, Common::kPlatformUnknown },
{ "425205754fa749f4f0b0dd9d09fa45fd", "football", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "430bc518017b6fac046f58bab6baad5d", "monkey2", "", "", -1, Common::JA_JPN, Common::kPlatformFMTowns },
{ "439a7f4adf510489981ac52308e7d7a2", "maniac", "C64", "", -1, Common::DE_DEU, Common::kPlatformC64 },
- { "45082a5c9f42ba14dacfe1fdeeba819d", "freddicove", "HE 100", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
+ { "45082a5c9f42ba14dacfe1fdeeba819d", "freddicove", "HE 100", "Demo", 18422, Common::EN_ANY, Common::kPlatformUnknown },
{ "45152f7cf2ba8f43cf8a8ea2e740ae09", "monkey", "VGA", "VGA", 8357, Common::ES_ESP, Common::kPlatformPC },
{ "4521138d15d1fd7649c31fb981746231", "pajama2", "HE 98.5", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "46b53fd430adcfbed791b48a0d4b079f", "funpack", "", "", -1, Common::EN_ANY, Common::kPlatformPC },
@@ -194,6 +198,7 @@ static const MD5Table md5table[] = {
{ "49a1739981a89066b1121fac04b710f4", "spyfox2", "HE CUP", "Preview", 5756234, Common::UNK_LANG, Common::kPlatformUnknown },
{ "4aa93cb30e485b728504ba3a693f12bf", "pajama", "HE 100", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "4af4a6b248103c1fe9edef619677f540", "puttmoon", "", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh },
+ { "4afb734df8315ee412669c812d4cf0a1", "freddi", "HE 100", "", 34837, Common::FR_FRA, Common::kPlatformWii },
{ "4ba37f835be11a59d969f90f272f575b", "water", "HE 80", "", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "4ba7fb331296c283e73d8f5b2096e551", "samnmax", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown },
{ "4bedb49943df95a9c900a5a82ccbe9de", "ft", "", "", -1, Common::FR_FRA, Common::kPlatformUnknown },
@@ -223,11 +228,12 @@ static const MD5Table md5table[] = {
{ "5262a27afcaee04e5c4900220bd463e7", "PuttsFunShop", "", "", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "52a4bae0746a11d7b1e8554e91a6645c", "zak", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformPC },
{ "53e94115b55dd51d4b8ff0871aa1df1e", "spyfox", "", "Demo", 20103, Common::EN_ANY, Common::kPlatformUnknown },
- { "54a936ad06161ff7bfefcb96200f7bff", "monkey", "VGA", "VGA Demo", -1, Common::EN_ANY, Common::kPlatformAmiga },
+ { "54a936ad06161ff7bfefcb96200f7bff", "monkey", "VGA", "VGA Demo", 7617, Common::EN_ANY, Common::kPlatformAmiga },
{ "55518cd73cf9c6d23ea29c51ee06bdfe", "ft", "", "", -1, Common::IT_ITA, Common::kPlatformUnknown },
{ "55e4cc866ff9046824e1c638ba2b8c7f", "ft", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown },
{ "55f4e9402bec2bded383843123f37c5c", "pajama2", "HE 98.5", "", -1, Common::DE_DEU, Common::kPlatformWindows },
{ "566165a7338fa11029e7c14d94fa70d0", "freddi", "HE 73", "Demo", 9800, Common::EN_ANY, Common::kPlatformWindows },
+ { "56b5922751be7ffd771b38dda56b028b", "freddi", "HE 100", "", 34837, Common::NL_NLD, Common::kPlatformWii },
{ "5719fc8a13b4638b78d9d8d12f091f94", "puttrace", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "5798972220cd458be2626d54c80f71d7", "atlantis", "Floppy", "Floppy", -1, Common::IT_ITA, Common::kPlatformAmiga },
{ "57a17febe2183f521250e55d55b83e60", "PuttTime", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformWindows },
@@ -240,9 +246,10 @@ static const MD5Table md5table[] = {
{ "59d5cfcc5e672a6e07baae01328b918b", "PuttTime", "HE 90", "Demo", -1, Common::FR_FRA, Common::kPlatformUnknown },
{ "5a35e36fd777e9c37a49c5b2faca52f9", "loom", "EGA", "EGA Demo", 6108, Common::EN_ANY, Common::kPlatformPC },
{ "5b08000a9c47b2887df6506ac767ca68", "fbear", "HE 62", "", -1, Common::EN_ANY, Common::kPlatform3DO },
- { "5bd335265a61caa3d78956ad9f88ba23", "football", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
+ { "5bd335265a61caa3d78956ad9f88ba23", "football", "", "Demo", 23135, Common::EN_ANY, Common::kPlatformUnknown },
{ "5c21fc49aee8f46e58fef21579e614a1", "thinker1", "", "", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "5d88b9d6a88e6f8e90cded9d01b7f082", "loom", "VGA", "VGA", 8307, Common::EN_ANY, Common::kPlatformPC },
+ { "5dda73606533d66a4c3f4f9ea6e842af", "farm", "", "", 87061, Common::RU_RUS, Common::kPlatformWindows },
{ "5e8fb66971a60e523e5afbc4c129c0e8", "socks", "HE 85", "", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "5ebb57234b2fe5c5dff641e00184ad81", "freddi", "HE 73", "", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "5fbe557049892eb4b709d90916ec97ca", "indy3", "EGA", "EGA", 5361, Common::EN_ANY, Common::kPlatformPC },
@@ -354,6 +361,7 @@ static const MD5Table md5table[] = {
{ "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 },
+ { "880c5ca5b944648b3f8b03feb41705a8", "freddi", "HE 100", "", 34837, Common::SE_SWE, Common::kPlatformWii },
{ "883af4b0af4f77a92f1dcf1d0a283140", "tentacle", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown },
{ "898ce8eb1234a955ef75e87141902bb3", "freddi3", "", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "898eaa21f79cf8d4f08db856244689ff", "pajama", "HE 99", "Updated", 66505, Common::EN_ANY, Common::kPlatformWindows },
@@ -363,13 +371,13 @@ static const MD5Table md5table[] = {
{ "8aed489aba45d2b9fb8a04079c9c6e6a", "baseball", "HE CUP", "Preview", 12876596, Common::UNK_LANG, Common::kPlatformUnknown },
{ "8afb3cf9f95abf208358e984f0c9e738", "funpack", "", "", -1, Common::EN_ANY, Common::kPlatform3DO },
{ "8bdb0bf87b5e303dd35693afb9351215", "ft", "", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
- { "8d479e36f35e80257dfc102cf4b8a912", "farm", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "8d479e36f35e80257dfc102cf4b8a912", "farm", "HE 72", "Demo", 34333, Common::EN_ANY, Common::kPlatformWindows },
{ "8de13897f0121c79d29a2377159f9ad0", "socks", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "8e3241ddd6c8dadf64305e8740d45e13", "balloon", "HE 100", "Updated", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "8e4ee4db46954bfe2912e259a16fad82", "monkey2", "", "", -1, Common::FR_FRA, Common::kPlatformPC },
{ "8e9417564f33790815445b2136efa667", "atlantis", "", "CD", 11915, Common::JA_JPN, Common::kPlatformMacintosh },
{ "8e9830a6f2702be5b22c8fa0a6aaf977", "freddi2", "HE 80", "", -1, Common::NL_NLD, Common::kPlatformMacintosh },
- { "8eb84cee9b429314c7f0bdcf560723eb", "monkey", "FM-TOWNS", "", -1, Common::EN_ANY, Common::kPlatformFMTowns },
+ { "8eb84cee9b429314c7f0bdcf560723eb", "monkey", "FM-TOWNS", "", 9925, Common::EN_ANY, Common::kPlatformFMTowns },
{ "8ee63cafb1fe9d62aa0d5a23117e70e7", "freddi2", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "8f3758ff98c9c5d78e5d635222cad026", "atlantis", "Floppy", "Floppy", -1, Common::IT_ITA, Common::kPlatformPC },
{ "8fec68383202d38c0d25e9e3b757c5df", "comi", "Demo", "Demo", 18041, Common::UNK_LANG, Common::kPlatformWindows },
@@ -410,7 +418,7 @@ static const MD5Table md5table[] = {
{ "9d7b67be003fea60be4dcbd193611936", "ft", "Demo", "Demo", 11164, Common::EN_ANY, Common::kPlatformMacintosh },
{ "9dc02577bf50d4cfaf3de3fbac06fbe2", "puttmoon", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "9e5e0fb43bd22f4628719b7501adb717", "monkey", "No AdLib", "EGA", -1, Common::FR_FRA, Common::kPlatformAtariST },
- { "9fd66fb3b04703bd50da4356e4202558", "spyfox2", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
+ { "9fd66fb3b04703bd50da4356e4202558", "spyfox2", "", "", 51295, Common::EN_ANY, Common::kPlatformMacintosh },
{ "a00554c31d623fdb9fcb0f924b89b42b", "loom", "EGA", "EGA Demo", -1, Common::EN_ANY, Common::kPlatformPC },
{ "a01fab4a64d47b96e2e58e6b0f825cc7", "monkey", "VGA", "VGA", 8347, Common::FR_FRA, Common::kPlatformPC },
{ "a095616d2d23ccf43b8e257711202cba", "football2002", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
@@ -427,6 +435,7 @@ static const MD5Table md5table[] = {
{ "a561d2e2413cc1c71d5a1bf87bf493ea", "lost", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "a56e8d9d4281c53c3f63c9bd22a59e21", "catalog", "HE CUP", "Preview", 10978342, Common::EN_ANY, Common::kPlatformUnknown },
{ "a570381b028972d891052ee1e51dc011", "maniac", "V2", "V2", 1988, Common::EN_ANY, Common::kPlatformAtariST },
+ { "a59a438cb182124c30c4447d8ed469e9", "freddi", "HE 100", "", 34837, Common::NB_NOR, Common::kPlatformWii },
{ "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 },
@@ -486,13 +495,13 @@ static const MD5Table md5table[] = {
{ "c4787c3e8b5e2dfda90850ee800af00f", "zak", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformPC },
{ "c4ffae9fac495475d6bc3343ccc8faf9", "Soccer2004", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "c5cc7cba02a2fbd539c4439e775b0536", "puttzoo", "HE 99", "Updated", 43470, Common::DE_DEU, Common::kPlatformWindows },
- { "c5d10e190d4b4d59114b824f2fdbd00e", "loom", "FM-TOWNS", "", -1, Common::EN_ANY, Common::kPlatformFMTowns },
+ { "c5d10e190d4b4d59114b824f2fdbd00e", "loom", "FM-TOWNS", "", 7540, Common::EN_ANY, Common::kPlatformFMTowns },
{ "c63ee46143ba65f9ce14cf539ca51bd7", "atlantis", "Floppy", "Floppy", -1, Common::EN_ANY, Common::kPlatformPC },
{ "c666a998af90d81db447eccba9f72c8d", "monkey", "No AdLib", "EGA", -1, Common::EN_ANY, Common::kPlatformAtariST },
{ "c6907d44f1166941d982864cd42cdc89", "pajama2", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "c782fbbe74a987c3df8ac73cd3e289ed", "freddi", "HE 73", "", -1, Common::SE_SWE, Common::kPlatformMacintosh },
{ "c7890e038806df2bb5c0c8c6f1986ea2", "monkey", "VGA", "VGA", -1, Common::EN_ANY, Common::kPlatformPC },
- { "c7be10f775404fd9785a8b92a06d240c", "atlantis", "", "", -1, Common::EN_ANY, Common::kPlatformFMTowns },
+ { "c7be10f775404fd9785a8b92a06d240c", "atlantis", "", "", 12030, Common::EN_ANY, Common::kPlatformFMTowns },
{ "c7c492a107ec520d7a7943037d0ca54a", "freddi", "HE 71", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "c83079157ec765a28de445aec9768d60", "tentacle", "", "Demo", 7477, Common::EN_ANY, Common::kPlatformUnknown },
{ "c8575e0b973ff1723aba6cd92c642db2", "puttrace", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },
@@ -516,7 +525,7 @@ static const MD5Table md5table[] = {
{ "cf4ef315214c7d8cdab6302cdb7e50db", "freddi", "HE 73", "Demo", -1, Common::DE_DEU, Common::kPlatformWindows },
{ "cf8d13446ec6cb6222287a925fd47c1d", "baseball", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "cf8ef3a1fb483c5c4b1c584d1167b2c4", "freddi", "HE 73", "", -1, Common::DE_DEU, Common::kPlatformWindows },
- { "cf90b4db5486ef798db78fe6fbf897e5", "pajama3", "", "Demo", -1, Common::EN_USA, Common::kPlatformWindows },
+ { "cf90b4db5486ef798db78fe6fbf897e5", "pajama3", "", "Demo", 13902, Common::EN_USA, Common::kPlatformWindows },
{ "d00ffc8c32d17e575fd985d435d2eb88", "arttime", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "d0549508a06bbb9f99ed19c9e97891f3", "football2002", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "d06fbe28818fef7bfc45c2cdf0c0849d", "zak", "V2", "V2", -1, Common::DE_DEU, Common::kPlatformPC },
@@ -551,14 +560,14 @@ static const MD5Table md5table[] = {
{ "dbf4d59d70b826733f379f998354d350", "BluesBirthday", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "dcf0119a90451a7d6e0f1920931ba130", "freddi4", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "dd30a53035393baa5a5e222e716559af", "maniac", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformAtariST },
- { "de4efb910210736813c9a1185384bace", "puttzoo", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "de4efb910210736813c9a1185384bace", "puttzoo", "HE 72", "Demo", 14337, Common::EN_ANY, Common::kPlatformWindows },
{ "debe337f73d660e951ece7c1f1c81add", "zak", "V2", "V2", -1, Common::EN_ANY, Common::kPlatformPC },
{ "defb8cb9ec4b0f91acfb6b61c6129ad9", "PuttTime", "HE 99", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "df03ee021aa9b81d90cab9c26da07614", "indy3", "EGA", "EGA", -1, Common::IT_ITA, Common::kPlatformAmiga },
{ "df047cc4792150f601290357566d36a6", "freddi", "HE 90", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "e01acc8c12ef44e8f778fe87e5f90f4e", "fbpack", "", "", -1, Common::EN_ANY, Common::kPlatform3DO },
{ "e03ed1474ec14de78359970e0457a820", "freddi4", "HE 99", "Demo", -1, Common::EN_GRB, Common::kPlatformWindows },
- { "e144f5f49d9241d2a9dee2576b3d09cb", "airport", "", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "e144f5f49d9241d2a9dee2576b3d09cb", "airport", "", "Demo", 51152, Common::EN_ANY, Common::kPlatformWindows },
{ "e17db1ddf91b39ca6bbc8ad3ed19e883", "monkey", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns },
{ "e246e02db9630533a40d99c9f54a8e01", "monkey2", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "e361a7058ed8e8ebb462663c0a3ae8d6", "puttputt", "HE 62", "", -1, Common::HE_ISR, Common::kPlatformPC },
@@ -573,12 +582,13 @@ static const MD5Table md5table[] = {
{ "e6cd81b25ab1453a8a6d3482118c391e", "pass", "", "", 7857, Common::EN_ANY, Common::kPlatformPC },
{ "e72bb4c2b613db2cf50f89ff6350e70a", "ft", "", "", -1, Common::ES_ESP, Common::kPlatformUnknown },
{ "e781230da44a44e2f0770edb2b3b3633", "maniac", "V2", "V2", -1, Common::EN_ANY, Common::kPlatformAmiga },
+ { "e8d0697906e53fee8b7e9f5652696da8", "atlantis", "", "CD", 11915, Common::JA_JPN, Common::kPlatformPC },
{ "e94c7cc3686fce406d3c91b5eae5a72d", "zak", "V2", "V2", -1, Common::EN_ANY, Common::kPlatformAmiga },
{ "e95cf980719c0be078fb68a67af97b4a", "funpack", "", "", -1, Common::JA_JPN, Common::kPlatform3DO },
{ "e98b982ceaf9d253d730bde8903233d6", "monkey", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformPC },
{ "eae95b2b3546d8ba86ae1d397c383253", "dog", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "eb700bb73ca1cc44a1ad5e4b1a4bdeaf", "indy3", "EGA", "EGA", 5361, Common::DE_DEU, Common::kPlatformPC },
- { "ebd0b2c8a387f18887282afe6cad894a", "spyozon", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
+ { "ebd0b2c8a387f18887282afe6cad894a", "spyozon", "", "Demo", 15317, Common::EN_ANY, Common::kPlatformUnknown },
{ "ebd324dcf06a4c49e1ba5c231eee1060", "freddi4", "HE 99", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "ecc4340c2b801f5af8da4e00c0e432d9", "puttcircus", "", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "ed2b074bc3166087a747acb2a3c6abb0", "freddi3", "HE 98.5", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown },
@@ -614,7 +624,7 @@ static const MD5Table md5table[] = {
{ "fbbbb38a81fc9d6a61d509278390a290", "farm", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "fbdd947d21e8f5bac6d6f7a316af1c5a", "spyfox", "", "Demo", 15693, Common::EN_ANY, Common::kPlatformUnknown },
{ "fc53ce0e5f6562b1c1e1b4b8203acafb", "samnmax", "Floppy", "Floppy", -1, Common::ES_ESP, Common::kPlatformPC },
- { "fc6b6148e80d67939d9a18697c0f626a", "monkey", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformPC },
+ { "fc6b6148e80d67939d9a18697c0f626a", "monkey", "EGA", "EGA", 8367, Common::DE_DEU, Common::kPlatformPC },
{ "fc8d197a22146e74766e9cb0cfcaf1da", "freddi2", "HE 80", "Demo", 27298, Common::EN_ANY, Common::kPlatformUnknown },
{ "fcb78ebecab2757264c590890c319cc5", "PuttTime", "HE 85", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "fce4b8010704b103acfeea9413788f32", "freddi2", "HE 80", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 2359d4a04f..dcbe4e6c0a 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1631,28 +1631,28 @@ void ScummEngine_v100he::resetScumm() {
#endif
void ScummEngine::setupMusic(int midi) {
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(midi);
- _native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(midi);
+ _native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
- switch (midiDriver) {
- case MD_NULL:
+ switch (MidiDriver::getMusicType(dev)) {
+ case MT_NULL:
_musicType = MDT_NONE;
break;
- case MD_PCSPK:
- case MD_PCJR:
+ case MT_PCSPK:
+ case MT_PCJR:
_musicType = MDT_PCSPK;
break;
- case MD_CMS:
+ //case MT_CMS:
#if 1
_musicType = MDT_ADLIB;
#else
_musicType = MDT_CMS; // Still has number of bugs, disable by default
#endif
break;
- case MD_TOWNS:
+ case MT_TOWNS:
_musicType = MDT_TOWNS;
break;
- case MD_ADLIB:
+ case MT_ADLIB:
_musicType = MDT_ADLIB;
break;
default:
@@ -1704,7 +1704,7 @@ void ScummEngine::setupMusic(int midi) {
if (!_mixer->isReady()) {
warning("Sound mixer initialization failed");
if (_musicType == MDT_ADLIB || _musicType == MDT_PCSPK || _musicType == MDT_CMS) {
- midiDriver = MD_NULL;
+ dev = 0;
_musicType = MDT_NONE;
warning("MIDI driver depends on sound mixer, switching to null MIDI driver");
}
@@ -1720,7 +1720,9 @@ void ScummEngine::setupMusic(int midi) {
_musicEngine = new Player_SID(this, _mixer);
#endif
} else if (_game.platform == Common::kPlatformNES && _game.version == 1) {
+#ifndef DISABLE_NES_APU
_musicEngine = new Player_NES(this, _mixer);
+#endif
} else if (_game.platform == Common::kPlatformAmiga && _game.version == 2) {
_musicEngine = new Player_V2A(this, _mixer);
} else if (_game.platform == Common::kPlatformAmiga && _game.version == 3) {
@@ -1732,11 +1734,11 @@ void ScummEngine::setupMusic(int midi) {
} else if (_game.platform == Common::kPlatformAmiga && _game.version <= 4) {
_musicEngine = new Player_V4A(this, _mixer);
} else if (_game.id == GID_MANIAC && _game.version == 1) {
- _musicEngine = new Player_V1(this, _mixer, midiDriver != MD_PCSPK);
+ _musicEngine = new Player_V1(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK);
} else if (_game.version <= 2) {
- _musicEngine = new Player_V2(this, _mixer, midiDriver != MD_PCSPK);
+ _musicEngine = new Player_V2(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK);
} else if ((_musicType == MDT_PCSPK) && (_game.version > 2 && _game.version <= 4)) {
- _musicEngine = new Player_V2(this, _mixer, midiDriver != MD_PCSPK);
+ _musicEngine = new Player_V2(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK);
} else if (_musicType == MDT_CMS) {
_musicEngine = new Player_V2CMS(this, _mixer);
} else if (_game.platform == Common::kPlatform3DO && _game.heversion <= 62) {
@@ -1746,12 +1748,12 @@ void ScummEngine::setupMusic(int midi) {
MidiDriver *adlibMidiDriver = 0;
if (_musicType != MDT_ADLIB)
- nativeMidiDriver = MidiDriver::createMidi(midiDriver);
+ nativeMidiDriver = MidiDriver::createMidi(dev);
if (nativeMidiDriver != NULL && _native_mt32)
nativeMidiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
bool multi_midi = ConfMan.getBool("multi_midi") && _musicType != MDT_NONE && (midi & MDT_ADLIB);
if (_musicType == MDT_ADLIB || multi_midi) {
- adlibMidiDriver = MidiDriver_ADLIB_create();
+ adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_ADLIB));
adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0);
}
@@ -1766,7 +1768,7 @@ void ScummEngine::setupMusic(int midi) {
// YM2162 driver can't handle midi->getPercussionChannel(), NULL shouldn't init MT-32/GM/GS
if ((midi != MDT_TOWNS) && (midi != MDT_NONE)) {
_imuse->property(IMuse::PROP_NATIVE_MT32, _native_mt32);
- if (midiDriver != MD_MT32) // MT-32 Emulation shouldn't be GM/GS initialized
+ if (MidiDriver::getMusicType(dev) != MT_MT32) // MT-32 Emulation shouldn't be GM/GS initialized
_imuse->property(IMuse::PROP_GS, _enable_gs);
}
if (_game.heversion >= 60 || midi == MDT_TOWNS) {
@@ -1837,8 +1839,7 @@ Common::Error ScummEngine::go() {
while (!shouldQuit()) {
- if (_debugger->isAttached())
- _debugger->onFrame();
+ _debugger->onFrame();
// Randomize the PRNG by calling it at regular intervals. This ensures
// that it will be in a different state each time you run the program.
@@ -2078,6 +2079,12 @@ void ScummEngine::scummLoop_updateScummVars() {
if (_game.version >= 7) {
VAR(VAR_CAMERA_POS_X) = camera._cur.x;
VAR(VAR_CAMERA_POS_Y) = camera._cur.y;
+ } else if (_game.platform == Common::kPlatformNES) {
+ // WORKAROUND:
+ // Since there are 2 2-stripes wide borders in MM NES screen,
+ // we have to compensate for it here. This fixes paning effects.
+ // Fixes bug #1328120: "MANIACNES: Screen width incorrect, camera halts sometimes"
+ VAR(VAR_CAMERA_POS_X) = (camera._cur.x >> V12_X_SHIFT) + 2;
} else if (_game.version <= 2) {
VAR(VAR_CAMERA_POS_X) = camera._cur.x >> V12_X_SHIFT;
} else {
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 65c50aff14..a845f623c2 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -1789,7 +1789,7 @@ static void convertADResource(ResourceManager *res, const GameSettings& game, in
// There is a constant delay of ppqn/3 before the music starts.
if (ppqn / 3 >= 128)
- *ptr++ = (ppqn / 3 >> 7) | 0x80;
+ *ptr++ = ((ppqn / 3) >> 7) | 0x80;
*ptr++ = ppqn / 3 & 0x7f;
// Now copy the actual music data
diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp
index 480e18e514..30281cb565 100644
--- a/engines/scumm/string.cpp
+++ b/engines/scumm/string.cpp
@@ -1110,6 +1110,8 @@ int ScummEngine::convertMessageToString(const byte *msg, byte *dst, int dstSize)
}
num += (_game.version == 8) ? 4 : 2;
}
+ } else if (_game.id == GID_DIG && (chr == 1 || chr == 2 || chr == 3 || chr == 8)) {
+ // Skip these characters
} else {
if (!(chr == '@') || (_game.id == GID_CMI && _language == Common::ZH_TWN) ||
(_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine && _language == Common::JA_JPN))
@@ -1351,6 +1353,8 @@ void ScummEngine_v7::loadLanguageBundle() {
// File contains Korean text (Hangul). just ignore it
} else if (*ptr == 'j') {
// File contains Japanese text. just ignore it
+ } else if (*ptr == 'c') {
+ // File contains Chinese text. just ignore it
} else if (*ptr == 'e') {
// File is encoded!
enc = 0x13;
diff --git a/engines/scumm/verbs.h b/engines/scumm/verbs.h
index 96a49a7ced..83e924edac 100644
--- a/engines/scumm/verbs.h
+++ b/engines/scumm/verbs.h
@@ -31,7 +31,7 @@
namespace Scumm {
/**
- * The area in which some click (or key press) occured and which is passed
+ * The area in which some click (or key press) occurred and which is passed
* to the input script.
*/
enum ClickArea {
diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp
index 9ea20aafc6..edf96f8e8c 100644
--- a/engines/sky/sky.cpp
+++ b/engines/sky/sky.cpp
@@ -185,8 +185,7 @@ Common::Error SkyEngine::go() {
uint32 delayCount = _system->getMillis();
while (!shouldQuit()) {
- if (_debugger->isAttached())
- _debugger->onFrame();
+ _debugger->onFrame();
if (shouldPerformAutoSave(_lastSaveTime)) {
if (_skyControl->loadSaveAllowed()) {
@@ -259,16 +258,16 @@ Common::Error SkyEngine::init() {
_systemVars.gameVersion = _skyDisk->determineGameVersion();
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI);
- if (midiDriver == MD_ADLIB) {
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32);
+ if (MidiDriver::getMusicType(dev) == MT_ADLIB) {
_systemVars.systemFlags |= SF_SBLASTER;
_skyMusic = new AdLibMusic(_mixer, _skyDisk);
} else {
_systemVars.systemFlags |= SF_ROLAND;
- if ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"))
- _skyMusic = new MT32Music(MidiDriver::createMidi(midiDriver), _skyDisk);
+ if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"))
+ _skyMusic = new MT32Music(MidiDriver::createMidi(dev), _skyDisk);
else
- _skyMusic = new GmMusic(MidiDriver::createMidi(midiDriver), _skyDisk);
+ _skyMusic = new GmMusic(MidiDriver::createMidi(dev), _skyDisk);
}
if (isCDVersion()) {
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index d6a04513a8..8d9ca85829 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -1175,8 +1175,7 @@ bool Control::restoreGameFromFile(uint8 slot) {
if (saveVersion < 2) // These older version of the savegames used a flag to signal presence of thumbnail
inf->skip(1);
- if (Graphics::checkThumbnailHeader(*inf))
- Graphics::skipThumbnailHeader(*inf);
+ Graphics::skipThumbnail(*inf);
inf->readUint32BE(); // save date
inf->readUint16BE(); // save time
diff --git a/engines/sword1/memman.h b/engines/sword1/memman.h
index 845a8638a2..b489eae2f9 100644
--- a/engines/sword1/memman.h
+++ b/engines/sword1/memman.h
@@ -42,11 +42,7 @@ struct MemHandle {
#define MEM_CAN_FREE 1
#define MEM_DONT_FREE 2
-#ifdef PALMOS_MODE
-#define MAX_ALLOC (3*1024*1024) // max amount of mem we want to alloc().
-#else
#define MAX_ALLOC (6*1024*1024) // max amount of mem we want to alloc().
-#endif
class MemMan {
public:
diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp
index 91c943472c..23cc30e4b1 100644
--- a/engines/sword1/music.cpp
+++ b/engines/sword1/music.cpp
@@ -107,7 +107,7 @@ bool MusicHandle::play(const char *fileBase, bool loop) {
if (!_audioSource) {
sprintf(fileName, "%s.aif", fileBase);
if (_file.open(fileName))
- _audioSource = Audio::makeLoopingAudioStream(Audio::makeAIFFStream(_file), loop ? 0 : 1);
+ _audioSource = Audio::makeLoopingAudioStream(Audio::makeAIFFStream(&_file, DisposeAfterUse::NO), loop ? 0 : 1);
}
if (!_audioSource)
diff --git a/engines/sword2/anims.cpp b/engines/sword2/anims.cpp
index 1bf3967047..7fd36fcc86 100644
--- a/engines/sword2/anims.cpp
+++ b/engines/sword2/anims.cpp
@@ -56,8 +56,6 @@ int Router::doAnimate(byte *ob_logic, byte *ob_graph, int32 animRes, bool revers
ObjectGraphic obGraph(ob_graph);
if (obLogic.getLooping() == 0) {
- byte *ptr;
-
// This is the start of the anim - set up the first frame
// For testing all anims!
@@ -75,12 +73,8 @@ int Router::doAnimate(byte *ob_logic, byte *ob_graph, int32 animRes, bool revers
return IR_STOP;
}
- ptr = _vm->_resman->openResource(animRes);
-
// if it's not an animation file
if (_vm->_resman->fetchType(animRes) != ANIMATION_FILE) {
- _vm->_resman->closeResource(animRes);
-
// switch off the sprite
// don't animate - just continue
// script next cycle
@@ -88,8 +82,6 @@ int Router::doAnimate(byte *ob_logic, byte *ob_graph, int32 animRes, bool revers
return IR_STOP;
}
- _vm->_resman->closeResource(animRes);
-
// switch on the sprite
setSpriteStatus(ob_graph, SORT_SPRITE);
}
diff --git a/engines/sword2/music.cpp b/engines/sword2/music.cpp
index a68baed097..c052aa6b46 100644
--- a/engines/sword2/music.cpp
+++ b/engines/sword2/music.cpp
@@ -136,10 +136,8 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base,
return NULL;
}
if (fh->fileSize != fh->file.size()) {
- if (fh->idxTab) {
- free(fh->idxTab);
- fh->idxTab = NULL;
- }
+ free(fh->idxTab);
+ fh->idxTab = NULL;
}
} else
alreadyOpen = true;
diff --git a/engines/sword2/resman.h b/engines/sword2/resman.h
index 72bdf73b98..dcc79927ea 100644
--- a/engines/sword2/resman.h
+++ b/engines/sword2/resman.h
@@ -32,11 +32,7 @@ namespace Common {
class File;
}
-#ifdef PALMOS_MODE
-#define MAX_MEM_CACHE (4 * 1024 * 1024) // 4 seems to be enough, 8 = out of memory
-#else
#define MAX_MEM_CACHE (8 * 1024 * 1024) // we keep up to 8 megs of resource data files in memory
-#endif
#define MAX_res_files 20
namespace Sword2 {
diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp
index 29f567d7ef..3cdab2bd2b 100644
--- a/engines/sword2/sword2.cpp
+++ b/engines/sword2/sword2.cpp
@@ -326,12 +326,20 @@ void Sword2Engine::registerDefaultSettings() {
}
void Sword2Engine::syncSoundSettings() {
- // Sound settings. At the time of writing, not all of these can be set
- // by the global options dialog, but it seems silly to split them up.
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
setSubtitles(ConfMan.getBool("subtitles"));
+
+ // Our own settings dialog can mute the music, speech and sound effects
+ // individually. ScummVM's settings dialog has one master mute setting.
+
+ if (ConfMan.getBool("mute")) {
+ ConfMan.setBool("music_mute", true);
+ ConfMan.setBool("speech_mute", true);
+ ConfMan.setBool("sfx_mute", true);
+ }
+
_sound->muteMusic(ConfMan.getBool("music_mute"));
_sound->muteSpeech(ConfMan.getBool("speech_mute"));
_sound->muteFx(ConfMan.getBool("sfx_mute"));
@@ -356,6 +364,13 @@ void Sword2Engine::writeSettings() {
ConfMan.setBool("object_labels", _mouse->getObjectLabels());
ConfMan.setInt("reverse_stereo", _sound->isReverseStereo());
+ // If even one sound type is unmuted, we can't say that all sound is
+ // muted.
+
+ if (!_sound->isMusicMute() || !_sound->isSpeechMute() || !_sound->isFxMute()) {
+ ConfMan.setBool("mute", false);
+ }
+
ConfMan.flushToDisk();
}
@@ -458,8 +473,7 @@ Common::Error Sword2Engine::run() {
_screen->initialiseRenderCycle();
while (1) {
- if (_debugger->isAttached())
- _debugger->onFrame();
+ _debugger->onFrame();
#ifdef SWORD2_DEBUG
if (_stepOneCycle) {
diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp
index 258bd982ed..a2dab9658d 100644
--- a/engines/teenagent/detection.cpp
+++ b/engines/teenagent/detection.cpp
@@ -91,7 +91,9 @@ static const ADParams detectionParams = {
"teenagent",
0,
0,
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ 1,
+ 0
};
#define MAX_SAVES 20
diff --git a/engines/teenagent/module.mk b/engines/teenagent/module.mk
index 2c04c99376..01ba3c79cb 100644
--- a/engines/teenagent/module.mk
+++ b/engines/teenagent/module.mk
@@ -1,23 +1,23 @@
MODULE := engines/teenagent
MODULE_OBJS := \
+ actor.o \
+ animation.o \
+ callbacks.o \
+ console.o \
detection.o \
- teenagent.o \
- resources.o \
+ dialog.o \
+ font.o \
+ inventory.o \
+ music.o \
+ objects.o \
pack.o \
- segment.o \
+ resources.o \
scene.o \
- animation.o \
- font.o \
+ segment.o \
surface.o \
surface_list.o \
- actor.o \
- callbacks.o \
- inventory.o \
- objects.o \
- music.o \
- console.o \
- dialog.o
+ teenagent.o
# This module can be built as a plugin
ifeq ($(ENABLE_TEENAGENT), DYNAMIC_PLUGIN)
diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp
index bb0e9773a2..c30809eef4 100644
--- a/engines/teenagent/teenagent.cpp
+++ b/engines/teenagent/teenagent.cpp
@@ -618,9 +618,7 @@ Common::Error TeenAgentEngine::run() {
_system->updateScreen();
- if (console->isAttached()) {
- console->onFrame();
- }
+ console->onFrame();
uint32 next_tick = MIN(game_timer, mark_timer);
if (next_tick > 0) {
diff --git a/engines/tinsel/actors.cpp b/engines/tinsel/actors.cpp
index efcefb442c..3577f4e0cc 100644
--- a/engines/tinsel/actors.cpp
+++ b/engines/tinsel/actors.cpp
@@ -197,10 +197,8 @@ void RegisterActors(int num) {
}
void FreeActors() {
- if (actorInfo) {
- free(actorInfo);
- actorInfo = NULL;
- }
+ free(actorInfo);
+ actorInfo = NULL;
}
/**
diff --git a/engines/tinsel/bmv.cpp b/engines/tinsel/bmv.cpp
index 938507c3f9..b13de103c0 100644
--- a/engines/tinsel/bmv.cpp
+++ b/engines/tinsel/bmv.cpp
@@ -730,16 +730,12 @@ void BMVPlayer::FinishBMV() {
stream.close();
// Release the data buffer
- if (bigBuffer != NULL) {
- free(bigBuffer);
- bigBuffer = NULL;
- }
+ free(bigBuffer);
+ bigBuffer = NULL;
// Release the screen buffer
- if (screenBuffer != NULL) {
- free(screenBuffer);
- screenBuffer = NULL;
- }
+ free(screenBuffer);
+ screenBuffer = NULL;
// Ditch any text objects
for (i = 0; i < 2; i++) {
diff --git a/engines/tinsel/cliprect.cpp b/engines/tinsel/cliprect.cpp
index 69a71b874f..5f287d3eab 100644
--- a/engines/tinsel/cliprect.cpp
+++ b/engines/tinsel/cliprect.cpp
@@ -28,17 +28,15 @@
#include "tinsel/graphics.h" // normal object drawing
#include "tinsel/object.h"
#include "tinsel/palette.h"
+#include "tinsel/tinsel.h" // for _vm
namespace Tinsel {
-/** list of all clip rectangles */
-static RectList s_rectList;
-
/**
* Resets the clipping rectangle allocator.
*/
void ResetClipRect() {
- s_rectList.clear();
+ _vm->_clipRects.clear();
}
/**
@@ -46,11 +44,11 @@ void ResetClipRect() {
* @param pClip clip rectangle dimensions to allocate
*/
void AddClipRect(const Common::Rect &pClip) {
- s_rectList.push_back(pClip);
+ _vm->_clipRects.push_back(pClip);
}
const RectList &GetClipRects() {
- return s_rectList;
+ return _vm->_clipRects;
}
/**
@@ -175,6 +173,8 @@ void FindMovingObjects(OBJECT *pObjList, Common::Point *pWin, Common::Rect *pCli
* the total number of clip rectangles.
*/
void MergeClipRect() {
+ RectList &s_rectList = _vm->_clipRects;
+
if (s_rectList.size() <= 1)
return;
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index 70a2f475ee..d6bdad6032 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -75,549 +75,7 @@ static const PlainGameDescriptor tinselGames[] = {
{0, 0}
};
-
-namespace Tinsel {
-
-using Common::GUIO_NONE;
-using Common::GUIO_NOSPEECH;
-using Common::GUIO_NOSFX;
-using Common::GUIO_NOMUSIC;
-
-static const TinselGameDescription gameDescriptions[] = {
-
- // Note: The following is the (hopefully) definitive list of version details:
- // TINSEL_V0: Used only by the Discworld 1 demo - this used a more primitive version
- // of the Tinsel engine and graphics compression
- // TINSEL_V1: There were two versions of the Discworld 1 game - the first used .GRA
- // files, and the second used .SCN files. The second also provided some fixes to
- // various script bugs and coding errors, but is still considered TINSEL_V1,
- // as both game versions work equally well with the newer code.
- // TINSEL_V2: The Discworld 2 game used this updated version of the Tinsel 1 engine,
- // and as far as we know there aren't any variations of this engine.
-
- { // Floppy Demo V0 from http://www.adventure-treff.de/specials/dl_demos.php
- {
- "dw",
- "Floppy Demo",
- AD_ENTRY1s("dw.gra", "ce1b57761ba705221bcf70955b827b97", 441192),
- //AD_ENTRY1s("dw.scn", "ccd72f02183d0e96b6e7d8df9492cda8", 23308),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DEMO,
- GUIO_NOSPEECH | GUIO_NOSFX | GUIO_NOMUSIC
- },
- GID_DW1,
- 0,
- GF_DEMO,
- TINSEL_V0,
- },
-
- { // CD Demo V1 version, with *.gra files
- {
- "dw",
- "CD Demo",
- {
- {"dw.gra", 0, "ef5a2518c9e205f786f5a4526396e661", 781676},
- {"english.smp", 0, NULL, -1},
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_DEMO,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD,
- TINSEL_V1,
- },
-
- { // Multilingual Floppy V1 with *.gra files.
- // Note: It contains no english subtitles.
- {
- "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,
- ADGF_DROPLANGUAGE,
- GUIO_NOSPEECH
- },
- GID_DW1,
- 0,
- GF_FLOPPY | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
- TINSEL_V1,
- },
-
- { // Floppy V1 version, with *.gra files
- {
- "dw",
- "Floppy",
- AD_ENTRY1s("dw.gra", "c8808ccd988d603dd35dff42013ae7fd", 781656),
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NOSPEECH
- },
- GID_DW1,
- 0,
- GF_FLOPPY | GF_ENHANCED_AUDIO_SUPPORT,
- TINSEL_V1,
- },
-
- { // CD V1 version, with *.gra files (same as the floppy one, with english.smp)
- {
- "dw",
- "CD",
- {
- {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656},
- {"english.smp", 0, NULL, -1},
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_ENHANCED_AUDIO_SUPPORT,
- TINSEL_V1,
- },
-
- { // Italian CD with english speech and *.gra files.
- // Note: It contains only italian subtitles, but inside english.txt
- {
- "dw",
- "CD",
- {
- {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656},
- {"english.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 237774},
- {"english.smp", 0, NULL, -1},
- {NULL, 0, NULL, 0}
- },
- Common::IT_ITA,
- Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
- 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,
- ADGF_DROPLANGUAGE,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
- 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,
- ADGF_DROPLANGUAGE,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
- 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,
- ADGF_DROPLANGUAGE,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
- 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,
- ADGF_DROPLANGUAGE,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
- TINSEL_V1,
- },
-
- { // English CD v2
- {
- "dw",
- "CD",
- {
- {"dw.scn", 0, "70955425870c7720d6eebed903b2ef41", 776188},
- {"english.smp", 0, NULL, -1},
- {NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
- TINSEL_V1,
- },
-
- { // Hebrew CD v2
- {
- "dw",
- "CD",
- {
- {"dw.scn", 0, "759d1374b4f02af6d52fc07c96679936", 770780},
- {"english.smp", 0, NULL, -1},
- {NULL, 0, NULL, 0}
- },
- Common::HE_ISR,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
- TINSEL_V1,
- },
-
- { // Discworld PSX CD
- {
- "dw",
- "CD",
- {
- {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326},
- {NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformPSX,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
- TINSEL_V1,
- },
-
- { // multilanguage PSX demo
- {
- "dw",
- "CD demo",
- {
- {"french.txt", 0, "e7020d35f58d0d187052ac406d86cc87", 273914},
- {"german.txt", 0, "52f0a01e0ff0d340b02a36fd5109d705", 263942},
- {"italian.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 239834},
- {"spanish.txt", 0, "c324170c3f1922c605c5cc09ba265aa5", 236702},
- {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326},
- {NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformPSX,
- ADGF_DEMO,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_SCNFILES,
- TINSEL_V1,
- },
-
-#if 0
- { // English Saturn CD
- {
- "dw",
- "CD",
- {
- {"dw.scn", 0, "6803f293c88758057cc685b9437f7637", 382248},
- {"english.smp", 0, NULL, -1},
- {NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
- TINSEL_V1,
- },
-#endif
-
-#if 0
- { // Mac multilanguage CD
- {
- "dw",
- "CD",
- {
- {"dw.scn", 0, "cfc40a8d5d476a1c9d3abf826fa46f8c", 1265532},
- {"english.smp", 0, NULL, -1},
- {NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
- TINSEL_V1,
- },
-
-#endif
-
- { // German CD re-release "Neon Edition"
- // Note: This release has ENGLISH.TXT (with german content) instead of GERMAN.TXT
- {
- "dw",
- "CD",
- AD_ENTRY1s("dw.scn", "6182c7986eaec893c62fb6ea13a9f225", 774556),
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
- TINSEL_V1,
- },
-
- { // Russian Discworld 1
- {
- "dw",
- "CD",
- {
- {"dw.scn", 0, "133041bde59d05c1bf084fd6f1bdce4b", 776524},
- {"english.txt", 0, "f73dcbd7b136b37c2adf7c9448ea336d", 231821},
- {"english.smp", 0, NULL, -1},
- {NULL, 0, NULL, 0}
- },
- Common::RU_RUS,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW1,
- 0,
- GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
- TINSEL_V1,
- },
-
- { // European/Australian Discworld 2 release
- {
- "dw2",
- "CD",
- {
- {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
- {"english1.smp", 0, NULL, -1},
- {NULL, 0, NULL, 0}
- },
- Common::EN_GRB,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW2,
- 0,
- GF_CD | GF_SCNFILES,
- TINSEL_V2,
- },
-
- { // US Discworld 2 release
- {
- "dw2",
- "CD",
- {
- {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
- {"us1.smp", 0, NULL, -1},
- {NULL, 0, NULL, 0}
- },
- Common::EN_USA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW2,
- 0,
- GF_CD | GF_SCNFILES,
- TINSEL_V2,
- },
-
- { // French version of Discworld 2
- {
- "dw2",
- "CD",
- {
- {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
- {"french1.smp", 0, NULL, -1},
- {NULL, 0, NULL, 0}
- },
- Common::FR_FRA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW2,
- 0,
- GF_CD | GF_SCNFILES,
- TINSEL_V2,
- },
-
- { // German Discworld 2 re-release "Neon Edition"
- {
- "dw2",
- "CD",
- {
- {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
- {"german1.smp", 0, NULL, -1},
- {NULL, 0, NULL, 0}
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW2,
- 0,
- GF_CD | GF_SCNFILES,
- TINSEL_V2,
- },
-
- { // Italian/Spanish Discworld 2
- {
- "dw2",
- "CD",
- {
- {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
- {"english1.smp", 0, NULL, -1},
- {"italian1.txt", 0, "d443249f8b55489b5888c227b9096f4e", 246495},
- {NULL, 0, NULL, 0}
- },
- Common::IT_ITA,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW2,
- 0,
- GF_CD | GF_SCNFILES,
- TINSEL_V2,
- },
- {
- {
- "dw2",
- "CD",
- {
- {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
- {"english1.smp", 0, NULL, -1},
- {"spanish1.txt", 0, "bc6e147c5f542db228ac577357e4d897", 230323},
- {NULL, 0, NULL, 0}
- },
- Common::ES_ESP,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW2,
- 0,
- GF_CD | GF_SCNFILES,
- TINSEL_V2,
- },
-
- { // Russian Discworld 2 release by Fargus
- {
- "dw2",
- "CD",
- {
- {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
- {"english1.smp", 0, NULL, -1},
- {"english1.txt", 0, "b522e19d7b2cd7b85e50e36fe48e36a9", 274444},
- {NULL, 0, NULL, 0}
- },
- Common::RU_RUS,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO_NONE
- },
- GID_DW2,
- 0,
- GF_CD | GF_SCNFILES,
- TINSEL_V2,
- },
-
- { AD_TABLE_END_MARKER, 0, 0, 0, 0 }
-};
-
-} // End of namespace Tinsel
+#include "tinsel/detection_tables.h"
static const ADParams detectionParams = {
// Pointer to ADGameDescription or its superset structure
@@ -637,7 +95,11 @@ static const ADParams detectionParams = {
// Flags
0,
// Additional GUI options (for every game}
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ // Maximum directory depth
+ 1,
+ // List of directory globs
+ 0
};
class TinselMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/tinsel/detection_tables.h b/engines/tinsel/detection_tables.h
new file mode 100644
index 0000000000..b467cc613e
--- /dev/null
+++ b/engines/tinsel/detection_tables.h
@@ -0,0 +1,567 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Tinsel {
+
+using Common::GUIO_NONE;
+using Common::GUIO_NOSPEECH;
+using Common::GUIO_NOSFX;
+using Common::GUIO_NOMUSIC;
+
+static const TinselGameDescription gameDescriptions[] = {
+
+ // Note: The following is the (hopefully) definitive list of version details:
+ // TINSEL_V0: Used only by the Discworld 1 demo - this used a more primitive version
+ // of the Tinsel engine and graphics compression
+ // TINSEL_V1: There were two versions of the Discworld 1 game - the first used .GRA
+ // files, and the second used .SCN files. The second also provided some fixes to
+ // various script bugs and coding errors, but is still considered TINSEL_V1,
+ // as both game versions work equally well with the newer code.
+ // TINSEL_V2: The Discworld 2 game used this updated version of the Tinsel 1 engine,
+ // and as far as we know there aren't any variations of this engine.
+
+ { // Floppy Demo V0 from http://www.adventure-treff.de/specials/dl_demos.php
+ {
+ "dw",
+ "Floppy Demo",
+ AD_ENTRY1s("dw.gra", "ce1b57761ba705221bcf70955b827b97", 441192),
+ //AD_ENTRY1s("dw.scn", "ccd72f02183d0e96b6e7d8df9492cda8", 23308),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSPEECH | GUIO_NOSFX | GUIO_NOMUSIC
+ },
+ GID_DW1,
+ 0,
+ GF_DEMO,
+ TINSEL_V0,
+ },
+
+ { // CD Demo V1 version, with *.gra files
+ {
+ "dw",
+ "CD Demo",
+ {
+ {"dw.gra", 0, "ef5a2518c9e205f786f5a4526396e661", 781676},
+ {"english.smp", 0, NULL, -1},
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD,
+ TINSEL_V1,
+ },
+
+ { // Multilingual Floppy V1 with *.gra files.
+ // Note: It contains no english subtitles.
+ {
+ "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,
+ ADGF_DROPLANGUAGE,
+ GUIO_NOSPEECH
+ },
+ GID_DW1,
+ 0,
+ GF_FLOPPY | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+
+ { // Floppy V1 version, with *.gra files
+ {
+ "dw",
+ "Floppy",
+ AD_ENTRY1s("dw.gra", "c8808ccd988d603dd35dff42013ae7fd", 781656),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSPEECH
+ },
+ GID_DW1,
+ 0,
+ GF_FLOPPY | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+
+ { // CD V1 version, with *.gra files (same as the floppy one, with english.smp)
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656},
+ {"english.smp", 0, NULL, -1},
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+
+ { // Italian CD with english speech and *.gra files.
+ // Note: It contains only italian subtitles, but inside english.txt
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656},
+ {"english.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 237774},
+ {"english.smp", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
+ 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,
+ ADGF_DROPLANGUAGE,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
+ 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,
+ ADGF_DROPLANGUAGE,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
+ 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,
+ ADGF_DROPLANGUAGE,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
+ 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,
+ ADGF_DROPLANGUAGE,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+
+ { // English CD v2
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.scn", 0, "70955425870c7720d6eebed903b2ef41", 776188},
+ {"english.smp", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+
+ { // Hebrew CD v2
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.scn", 0, "759d1374b4f02af6d52fc07c96679936", 770780},
+ {"english.smp", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::HE_ISR,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+
+ { // Discworld PSX CD
+ {
+ "dw",
+ "CD",
+ {
+ {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326},
+ {NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPSX,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+
+ { // multilanguage PSX demo
+ {
+ "dw",
+ "CD demo",
+ {
+ {"french.txt", 0, "e7020d35f58d0d187052ac406d86cc87", 273914},
+ {"german.txt", 0, "52f0a01e0ff0d340b02a36fd5109d705", 263942},
+ {"italian.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 239834},
+ {"spanish.txt", 0, "c324170c3f1922c605c5cc09ba265aa5", 236702},
+ {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326},
+ {NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPSX,
+ ADGF_DEMO,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_SCNFILES,
+ TINSEL_V1,
+ },
+
+#if 0
+ { // English Saturn CD
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.scn", 0, "6803f293c88758057cc685b9437f7637", 382248},
+ {"english.smp", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+#endif
+
+#if 0
+ { // Mac multilanguage CD
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.scn", 0, "cfc40a8d5d476a1c9d3abf826fa46f8c", 1265532},
+ {"english.smp", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+
+#endif
+
+ { // German CD re-release "Neon Edition"
+ // Note: This release has ENGLISH.TXT (with german content) instead of GERMAN.TXT
+ {
+ "dw",
+ "CD",
+ AD_ENTRY1s("dw.scn", "6182c7986eaec893c62fb6ea13a9f225", 774556),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+
+ { // Russian Discworld 1
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.scn", 0, "133041bde59d05c1bf084fd6f1bdce4b", 776524},
+ {"english.txt", 0, "f73dcbd7b136b37c2adf7c9448ea336d", 231821},
+ {"english.smp", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::RU_RUS,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
+ TINSEL_V1,
+ },
+
+ { // European/Australian Discworld 2 release
+ {
+ "dw2",
+ "CD",
+ {
+ {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
+ {"english1.smp", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::EN_GRB,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW2,
+ 0,
+ GF_CD | GF_SCNFILES,
+ TINSEL_V2,
+ },
+
+ { // US Discworld 2 release
+ {
+ "dw2",
+ "CD",
+ {
+ {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
+ {"us1.smp", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::EN_USA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW2,
+ 0,
+ GF_CD | GF_SCNFILES,
+ TINSEL_V2,
+ },
+
+ { // French version of Discworld 2
+ {
+ "dw2",
+ "CD",
+ {
+ {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
+ {"french1.smp", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW2,
+ 0,
+ GF_CD | GF_SCNFILES,
+ TINSEL_V2,
+ },
+
+ { // German Discworld 2 re-release "Neon Edition"
+ {
+ "dw2",
+ "CD",
+ {
+ {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
+ {"german1.smp", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW2,
+ 0,
+ GF_CD | GF_SCNFILES,
+ TINSEL_V2,
+ },
+
+ { // Italian/Spanish Discworld 2
+ {
+ "dw2",
+ "CD",
+ {
+ {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
+ {"english1.smp", 0, NULL, -1},
+ {"italian1.txt", 0, "d443249f8b55489b5888c227b9096f4e", 246495},
+ {NULL, 0, NULL, 0}
+ },
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW2,
+ 0,
+ GF_CD | GF_SCNFILES,
+ TINSEL_V2,
+ },
+ {
+ {
+ "dw2",
+ "CD",
+ {
+ {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
+ {"english1.smp", 0, NULL, -1},
+ {"spanish1.txt", 0, "bc6e147c5f542db228ac577357e4d897", 230323},
+ {NULL, 0, NULL, 0}
+ },
+ Common::ES_ESP,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW2,
+ 0,
+ GF_CD | GF_SCNFILES,
+ TINSEL_V2,
+ },
+
+ { // Russian Discworld 2 release by Fargus
+ {
+ "dw2",
+ "CD",
+ {
+ {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593},
+ {"english1.smp", 0, NULL, -1},
+ {"english1.txt", 0, "b522e19d7b2cd7b85e50e36fe48e36a9", 274444},
+ {NULL, 0, NULL, 0}
+ },
+ Common::RU_RUS,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_DW2,
+ 0,
+ GF_CD | GF_SCNFILES,
+ TINSEL_V2,
+ },
+
+ { AD_TABLE_END_MARKER, 0, 0, 0, 0 }
+};
+
+} // End of namespace Tinsel
diff --git a/engines/tinsel/graphics.cpp b/engines/tinsel/graphics.cpp
index 9700e8947f..48270d94e3 100644
--- a/engines/tinsel/graphics.cpp
+++ b/engines/tinsel/graphics.cpp
@@ -443,6 +443,12 @@ static void t2WrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool apply
int numBytes;
int clipAmount;
+ // WORKAROUND: One of the mortician frames has several corrupt bytes in the Russian version
+ if ((pObj->hBits == 2517583660UL) && (_vm->getLanguage() == Common::RU_RUS)) {
+ uint8 correctBytes[5] = {0xA3, 0x00, 0x89, 0xC0, 0xA6};
+ Common::copy(&correctBytes[0], &correctBytes[5], srcP);
+ }
+
for (int y = 0; y < pObj->height; ++y) {
// Get the position to start writing out from
uint8 *tempP = !horizFlipped ? destP :
@@ -596,6 +602,23 @@ static void PackedWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP,
int numBytes, colour;
int v;
+ if (_vm->getLanguage() == Common::RU_RUS) {
+ // WORKAROUND: One of the mortician frames has several corrupt bytes in the Russian version
+ if (pObj->hBits == 2517583393UL) {
+ uint8 correctBytes[5] = {0x00, 0x00, 0x17, 0x01, 0x00};
+ Common::copy(&correctBytes[0], &correctBytes[5], srcP + 267);
+ }
+ // WORKAROUND: One of Dibbler's frames in the end sequence has corrupt bytes in the Russian version
+ if (pObj->hBits == 33651742) {
+ uint8 correctBytes[40] = {
+ 0x06, 0xc0, 0xd6, 0xc1, 0x09, 0xce, 0x0d, 0x24, 0x02, 0x12, 0x01, 0x00, 0x00, 0x23, 0x21, 0x32,
+ 0x12, 0x00, 0x00, 0x20, 0x01, 0x11, 0x32, 0x12, 0x01, 0x00, 0x00, 0x1b, 0x02, 0x11, 0x34, 0x11,
+ 0x00, 0x00, 0x18, 0x01, 0x11, 0x35, 0x21, 0x01
+ };
+ Common::copy(&correctBytes[0], &correctBytes[40], srcP);
+ }
+ }
+
if (applyClipping) {
pObj->height -= pObj->botClip;
topClip = pObj->topClip;
diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp
index de573feee2..df686f8bee 100644
--- a/engines/tinsel/handle.cpp
+++ b/engines/tinsel/handle.cpp
@@ -175,22 +175,18 @@ void SetupHandleTable() {
}
void FreeHandleTable() {
- if (handleTable) {
- free(handleTable);
- handleTable = NULL;
- }
- if (cdGraphStream) {
- delete cdGraphStream;
- cdGraphStream = 0;
- }
+ free(handleTable);
+ handleTable = NULL;
+
+ delete cdGraphStream;
+ cdGraphStream = NULL;
}
/**
* Loads a memory block as a file.
*/
void OpenCDGraphFile() {
- if (cdGraphStream)
- delete cdGraphStream;
+ delete cdGraphStream;
// As the theory goes, the right CD will be in there!
diff --git a/engines/tinsel/object.cpp b/engines/tinsel/object.cpp
index f91e37a063..7a93a0b30a 100644
--- a/engines/tinsel/object.cpp
+++ b/engines/tinsel/object.cpp
@@ -49,10 +49,8 @@ static int maxObj = 0;
#endif
void FreeObjectList() {
- if (objectList) {
- free(objectList);
- objectList = NULL;
- }
+ free(objectList);
+ objectList = NULL;
}
/**
diff --git a/engines/tinsel/pcode.cpp b/engines/tinsel/pcode.cpp
index c472a770d2..98fb078459 100644
--- a/engines/tinsel/pcode.cpp
+++ b/engines/tinsel/pcode.cpp
@@ -148,6 +148,7 @@ static const byte fragment12[] = {OP_JMPTRUE | OPSIZE16, FRAGMENT_WORD(1491),
OP_ONE, OP_LIBCALL | OPSIZE8, 14, // Re-show the cursor
OP_IMM | OPSIZE16, FRAGMENT_WORD(322), OP_LIBCALL | OPSIZE8, 46, // Give back the whistle
OP_JUMP | OPSIZE16, FRAGMENT_WORD(1568)};
+static const byte fragment13[] = {OP_ZERO, OP_GSTORE | OPSIZE16, FRAGMENT_WORD(306)};
#undef FRAGMENT_WORD
@@ -207,6 +208,12 @@ const WorkaroundEntry workaroundList[] = {
// See bug report #2934211.
{TINSEL_V1, true, 352601285, 1569, sizeof(fragment11), fragment11},
{TINSEL_V1, false, 352602304, 1488, sizeof(fragment12), fragment12},
+
+ // DW2: Corrects a bug with global 306 not being cleared if you leave
+ // the marketplace scene whilst D'Blah is talking (even if it's not
+ // actually audible); returning to the scene and clicking on him multiple
+ // times would cause the game to crash
+ {TINSEL_V2, true, 1109294728, 0, sizeof(fragment13), fragment13},
{TINSEL_V0, false, 0, 0, 0, NULL}
};
diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp
index b90ace4613..b010ad1fcb 100644
--- a/engines/tinsel/saveload.cpp
+++ b/engines/tinsel/saveload.cpp
@@ -180,7 +180,8 @@ static void syncSavedMover(Common::Serializer &s, SAVED_MOVER &sm) {
static void syncSavedActor(Common::Serializer &s, SAVED_ACTOR &sa) {
s.syncAsUint16LE(sa.actorID);
s.syncAsUint16LE(sa.zFactor);
- s.syncAsUint32LE(sa.bAlive);
+ s.syncAsUint16LE(sa.bAlive);
+ s.syncAsUint16LE(sa.bHidden);
s.syncAsUint32LE(sa.presFilm);
s.syncAsUint16LE(sa.presRnum);
s.syncAsUint16LE(sa.presPlayX);
diff --git a/engines/tinsel/savescn.cpp b/engines/tinsel/savescn.cpp
index 50231d34bb..2b5c815d3c 100644
--- a/engines/tinsel/savescn.cpp
+++ b/engines/tinsel/savescn.cpp
@@ -162,10 +162,8 @@ void InitialiseSaveScenes() {
}
void FreeSaveScenes() {
- if (ssData) {
- free(ssData);
- ssData = NULL;
- }
+ free(ssData);
+ ssData = NULL;
}
/**
diff --git a/engines/tinsel/strres.cpp b/engines/tinsel/strres.cpp
index 8f9f72f446..2416d6a8fa 100644
--- a/engines/tinsel/strres.cpp
+++ b/engines/tinsel/strres.cpp
@@ -88,11 +88,9 @@ void ChangeLanguage(LANGUAGE newLang) {
textLanguage = newLang;
sampleLanguage = newLang;
- if (textBuffer) {
- // free the previous buffer
- free(textBuffer);
- textBuffer = NULL;
- }
+ // free the previous buffer
+ free(textBuffer);
+ textBuffer = NULL;
// Try and open the specified language file. If it fails, and the language
// isn't English, try falling back on opening 'english.txt' - some foreign
@@ -355,10 +353,8 @@ int SubStringCount(int id) {
void FreeTextBuffer() {
- if (textBuffer) {
- free(textBuffer);
- textBuffer = NULL;
- }
+ free(textBuffer);
+ textBuffer = NULL;
}
/**
diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp
index 677392a35d..766d4ed54a 100644
--- a/engines/tinsel/tinlib.cpp
+++ b/engines/tinsel/tinlib.cpp
@@ -5557,7 +5557,7 @@ int CallLibraryRoutine(CORO_PARAM, int operand, int32 *pp, const INT_CONTEXT *pi
case WALKED: {
// Common to both DW1 & DW2
pp -= 3; // 4 parameters
- bool tmp;
+ bool tmp = false;
Walked(coroParam, pp[0], pp[1], pp[2], pp[3], pic->escOn, pic->myEscape, tmp);
if (!coroParam) {
// Only write the result to the stack if walked actually completed running.
diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp
index 8d11efef3c..6c77a98dda 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -856,11 +856,11 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc)
if (cd_num >= 0)
_system->openCD(cd_num);
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
- //bool adlib = (midiDriver == MD_ADLIB);
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+ //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
- _driver = MidiDriver::createMidi(midiDriver);
+ _driver = MidiDriver::createMidi(dev);
if (native_mt32)
_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
@@ -1001,8 +1001,7 @@ Common::Error TinselEngine::run() {
uint32 timerVal = 0;
while (!shouldQuit()) {
assert(_console);
- if (_console->isAttached())
- _console->onFrame();
+ _console->onFrame();
// Check for time to do next game cycle
if ((g_system->getMillis() > timerVal + GAME_FRAME_DELAY)) {
diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h
index 0e1d705815..df27a1e0e1 100644
--- a/engines/tinsel/tinsel.h
+++ b/engines/tinsel/tinsel.h
@@ -61,6 +61,8 @@ class PCMMusicPlayer;
class Scheduler;
class SoundManager;
+typedef Common::List<Common::Rect> RectList;
+
enum TinselGameID {
GID_DW1 = 0,
GID_DW2 = 1
@@ -203,6 +205,10 @@ public:
/** Stack of pending keypresses. */
Common::List<Common::Event> _keypresses;
+
+ /** List of all clip rectangles. */
+ RectList _clipRects;
+
private:
//MidiMusicPlayer *_midiMusic;
int _musicVolume;
diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp
index 65a6a29bcc..35f03fa657 100644
--- a/engines/touche/detection.cpp
+++ b/engines/touche/detection.cpp
@@ -124,6 +124,11 @@ static const ADFileBasedFallback fileBasedFallback[] = {
} // End of namespace Touche
+static const char *directoryGlobs[] = {
+ "database",
+ 0
+};
+
static const ADParams detectionParams = {
(const byte *)Touche::gameDescriptions,
sizeof(ADGameDescription),
@@ -134,7 +139,11 @@ static const ADParams detectionParams = {
Touche::fileBasedFallback, // file-based detection data to enable not yet known versions to start
kADFlagPrintWarningOnFileBasedFallback,
// Additional GUI options (for every game}
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ // Maximum directory depth
+ 2,
+ // List of directory globs
+ directoryGlobs
};
class ToucheMetaEngine : public AdvancedMetaEngine {
diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp
index 9dbef4d76f..439d3b9ac2 100644
--- a/engines/touche/midi.cpp
+++ b/engines/touche/midi.cpp
@@ -92,9 +92,9 @@ void MidiPlayer::setVolume(int volume) {
}
int MidiPlayer::open() {
- MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
- _driver = MidiDriver::createMidi(midiDriver);
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+ _driver = MidiDriver::createMidi(dev);
int ret = _driver->open();
if (ret == 0) {
_parser = MidiParser::createParser_SMF();
diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index 187e685d06..2dc8b76b4f 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -28,6 +28,8 @@
#include "common/debug-channels.h"
#include "common/events.h"
#include "common/EventRecorder.h"
+#include "common/file.h"
+#include "common/fs.h"
#include "common/system.h"
#include "engines/util.h"
@@ -70,6 +72,10 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language)
_menuRedrawCounter = 0;
memset(_paletteBuffer, 0, sizeof(_paletteBuffer));
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+
+ SearchMan.addSubDirectoryMatching(gameDataDir, "database");
+
DebugMan.addDebugChannel(kDebugEngine, "Engine", "Engine debug level");
DebugMan.addDebugChannel(kDebugGraphics, "Graphics", "Graphics debug level");
DebugMan.addDebugChannel(kDebugResource, "Resource", "Resource debug level");
diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp
index b4f30cb7fd..0a9dec9b46 100644
--- a/engines/tucker/detection.cpp
+++ b/engines/tucker/detection.cpp
@@ -114,7 +114,9 @@ static const ADParams detectionParams = {
"tucker",
0,
0,
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ 1,
+ 0
};
static const ADGameDescription tuckerDemoGameDescription = {
diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp
index 68f5301a80..633ed2790d 100644
--- a/engines/tucker/sequences.cpp
+++ b/engines/tucker/sequences.cpp
@@ -491,7 +491,6 @@ AnimationSequencePlayer::AnimationSequencePlayer(OSystem *system, Audio::Mixer *
_offscreenBuffer = (uint8 *)malloc(kScreenWidth * kScreenHeight);
_updateScreenWidth = 0;
_updateScreenPicture = false;
- _updateScreenOffset = 0;
_picBufPtr = _pic2BufPtr = 0;
}
@@ -537,9 +536,9 @@ void AnimationSequencePlayer::mainLoop() {
}
// budttle2.flc is shorter in french version ; start the background music
// earlier and skip any sounds effects
- if (_seqNum == 19 && _flicPlayer[0].getFrameCount() == 127) {
+ if (_seqNum == 19 && _flicPlayer[0].getFrameCount() == 126) {
_soundSeqDataIndex = 6;
- _frameCounter = 79;
+ _frameCounter = 80;
}
}
(this->*(_updateFunc[_updateFuncIndex].play))();
@@ -765,10 +764,10 @@ void AnimationSequencePlayer::openAnimation(int index, const char *fileName) {
}
}
-bool AnimationSequencePlayer::decodeNextAnimationFrame(int index) {
+bool AnimationSequencePlayer::decodeNextAnimationFrame(int index, bool copyDirtyRects) {
::Graphics::Surface *surface = _flicPlayer[index].decodeNextFrame();
- if (_seqNum == 19) {
+ if (!copyDirtyRects) {
for (uint16 y = 0; (y < surface->h) && (y < kScreenHeight); y++)
memcpy(_offscreenBuffer + y * kScreenWidth, (byte *)surface->pixels + y * surface->pitch, surface->w);
} else {
@@ -807,13 +806,13 @@ void AnimationSequencePlayer::playIntroSeq19_20() {
// cogs, and is being replayed when an intro credit appears
::Graphics::Surface *surface = 0;
- if (_flicPlayer[0].getCurFrame() >= 117) {
+ if (_flicPlayer[0].getCurFrame() >= 115) {
surface = _flicPlayer[1].decodeNextFrame();
if (_flicPlayer[1].endOfVideo())
_flicPlayer[1].reset();
}
- bool framesLeft = decodeNextAnimationFrame(0);
+ bool framesLeft = decodeNextAnimationFrame(0, false);
if (surface)
for (int i = 0; i < kScreenWidth * kScreenHeight; ++i)
@@ -841,19 +840,28 @@ void AnimationSequencePlayer::displayLoadingScreen() {
void AnimationSequencePlayer::initPicPart4() {
_updateScreenWidth = 320;
_updateScreenPicture = true;
- _updateScreenOffset = 0;
+ _updateScreenCounter = 0;
+ _updateScreenIndex = -1;
}
void AnimationSequencePlayer::drawPicPart4() {
- static const uint8 offsetsTable[77] = {
- 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
- 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3,
- 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1
- };
- _updateScreenWidth = _updateScreenWidth - offsetsTable[_updateScreenOffset];
- ++_updateScreenOffset;
+ static const uint8 offsets[] = { 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1 };
+ if (_updateScreenIndex == -1) {
+ for (int i = 0; i < 256; ++i) {
+ if (memcmp(_animationPalette + i * 4, _picBufPtr + 32 + i * 3, 3) != 0) {
+ memcpy(_animationPalette + i * 4, _picBufPtr + 32 + i * 3, 3);
+ _animationPalette[i * 4 + 3] = 0;
+ }
+ }
+ }
+ if (_updateScreenCounter == 0) {
+ static const uint8 counter[] = { 1, 2, 3, 4, 5, 35, 5, 4, 3, 2, 1 };
+ ++_updateScreenIndex;
+ assert(_updateScreenIndex < ARRAYSIZE(counter));
+ _updateScreenCounter = counter[_updateScreenIndex];
+ }
+ --_updateScreenCounter;
+ _updateScreenWidth -= offsets[_updateScreenIndex];
for (int y = 0; y < 200; ++y) {
memcpy(_offscreenBuffer + y * 320, _picBufPtr + 800 + y * 640 + _updateScreenWidth, 320);
}
@@ -875,7 +883,7 @@ void AnimationSequencePlayer::loadIntroSeq3_4() {
void AnimationSequencePlayer::playIntroSeq3_4() {
if (!_updateScreenPicture) {
bool framesLeft = decodeNextAnimationFrame(0);
- if (_flicPlayer[0].getCurFrame() == 707) {
+ if (_flicPlayer[0].getCurFrame() == 705) {
initPicPart4();
}
if (!framesLeft) {
@@ -914,17 +922,10 @@ void AnimationSequencePlayer::drawPic2Part10() {
}
void AnimationSequencePlayer::drawPic1Part10() {
- ::Graphics::Surface *surface = _flicPlayer[0].decodeNextFrame();
- _flicPlayer[0].copyDirtyRectsToBuffer(_offscreenBuffer, kScreenWidth);
- ++_frameCounter;
-
- if (_flicPlayer[0].hasDirtyPalette())
- getRGBPalette(0);
-
int offset = 0;
for (int y = 0; y < kScreenHeight; ++y) {
for (int x = 0; x < kScreenWidth; ++x) {
- byte color = *((byte *)surface->pixels + offset);
+ byte color = _offscreenBuffer[offset];
if (color == 0)
color = _picBufPtr[800 + y * 640 + _updateScreenWidth + x];
@@ -943,22 +944,24 @@ void AnimationSequencePlayer::loadIntroSeq9_10() {
}
void AnimationSequencePlayer::playIntroSeq9_10() {
- if (_flicPlayer[0].getCurFrame() >= 265 && _flicPlayer[0].getCurFrame() <= 296) {
+ const int nextFrame = _flicPlayer[0].getCurFrame() + 1;
+ if (nextFrame >= 263 && nextFrame <= 294) {
+ decodeNextAnimationFrame(0, false);
drawPic1Part10();
_updateScreenWidth += 6;
- } else if (_flicPlayer[0].getCurFrame() == 985) {
+ } else if (nextFrame == 983) {
decodeNextAnimationFrame(0);
drawPic2Part10();
- } else if (_flicPlayer[0].getCurFrame() >= 989 && _flicPlayer[0].getCurFrame() <= 997) {
+ } else if (nextFrame >= 987 && nextFrame <= 995) {
+ decodeNextAnimationFrame(0, false);
drawPic1Part10();
_updateScreenWidth -= 25;
if (_updateScreenWidth < 0) {
_updateScreenWidth = 0;
}
- }
-
- if (_flicPlayer[0].endOfVideo())
+ } else if (!decodeNextAnimationFrame(0)) {
_changeToNextSequence = true;
+ }
}
void AnimationSequencePlayer::loadIntroSeq21_22() {
diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h
index d9810c7929..86f5843e77 100644
--- a/engines/tucker/tucker.h
+++ b/engines/tucker/tucker.h
@@ -934,7 +934,7 @@ private:
void unloadAnimation();
uint8 *loadPicture(const char *fileName);
void openAnimation(int index, const char *fileName);
- bool decodeNextAnimationFrame(int index);
+ bool decodeNextAnimationFrame(int index, bool copyDirtyRects = true);
void loadIntroSeq17_18();
void playIntroSeq17_18();
void loadIntroSeq19_20();
@@ -975,7 +975,8 @@ private:
uint8 *_offscreenBuffer;
int _updateScreenWidth;
int _updateScreenPicture;
- int _updateScreenOffset;
+ int _updateScreenCounter;
+ int _updateScreenIndex;
int _frameCounter;
int _frameTime;
uint32 _lastFrameTime;
diff --git a/graphics/conversion.h b/graphics/conversion.h
index 149d7204c6..b6d230612e 100644
--- a/graphics/conversion.h
+++ b/graphics/conversion.h
@@ -45,13 +45,6 @@ inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) {
v = CLIP<int>( ((r * 512) >> 10) - ((g * 429) >> 10) - ((b * 83) >> 10) + 128, 0, 255);
}
-/** Converting a color from YUV to RGB colorspace, Cinepak style. */
-inline static void CPYUV2RGB(byte y, byte u, byte v, byte &r, byte &g, byte &b) {
- r = CLIP<int>(y + 2 * (v - 128), 0, 255);
- g = CLIP<int>(y - (u - 128) / 2 - (v - 128), 0, 255);
- b = CLIP<int>(y + 2 * (u - 128), 0, 255);
-}
-
// TODO: generic YUV to RGB blit
/**
diff --git a/graphics/font.cpp b/graphics/font.cpp
index 629f2f4b82..74247d4da1 100644
--- a/graphics/font.cpp
+++ b/graphics/font.cpp
@@ -609,8 +609,8 @@ bool NewFont::cacheFontData(const NewFont &font, const Common::String &filename)
cacheFile.writeUint16BE(font.desc.height);
cacheFile.writeUint16BE(font.desc.fbbw);
cacheFile.writeUint16BE(font.desc.fbbh);
- cacheFile.writeUint16BE(font.desc.fbbx);
- cacheFile.writeUint16BE(font.desc.fbby);
+ cacheFile.writeSint16BE(font.desc.fbbx);
+ cacheFile.writeSint16BE(font.desc.fbby);
cacheFile.writeUint16BE(font.desc.ascent);
cacheFile.writeUint16BE(font.desc.firstchar);
cacheFile.writeUint16BE(font.desc.size);
@@ -667,8 +667,8 @@ NewFont *NewFont::loadFromCache(Common::SeekableReadStream &stream) {
data->height = stream.readUint16BE();
data->fbbw = stream.readUint16BE();
data->fbbh = stream.readUint16BE();
- data->fbbx = stream.readUint16BE();
- data->fbby = stream.readUint16BE();
+ data->fbbx = stream.readSint16BE();
+ data->fbby = stream.readSint16BE();
data->ascent = stream.readUint16BE();
data->firstchar = stream.readUint16BE();
data->size = stream.readUint16BE();
diff --git a/graphics/font.h b/graphics/font.h
index 6927e0e076..0e65e9418c 100644
--- a/graphics/font.h
+++ b/graphics/font.h
@@ -67,10 +67,10 @@ public:
int getStringWidth(const Common::String &str) const;
/**
- * Take a text (which may contain newlines characters) and word wrap it so thata
+ * Take a text (which may contain newline characters) and word wrap it so that
* no text line is wider than maxWidth pixels. If necessary, additional line breaks
- * are generated, preferably between words (i.e. were whitespaces are).
- * The resulting lines are appended to the string list lines.
+ * are generated, preferably between words (i.e. where whitespaces are).
+ * The resulting lines are appended to the lines string list.
* It returns the maximal width of any of the new lines (i.e. a value which is less
* or equal to maxWidth).
*
diff --git a/graphics/fontman.cpp b/graphics/fontman.cpp
index 1827cb69aa..c6972cfaab 100644
--- a/graphics/fontman.cpp
+++ b/graphics/fontman.cpp
@@ -57,7 +57,29 @@ FontManager::~FontManager() {
g_consolefont = 0;
}
+const struct {
+ const char *name;
+ FontManager::FontUsage id;
+} builtinFontNames[] = {
+ { "builtinOSD", FontManager::kOSDFont },
+ { "builtinConsole", FontManager::kConsoleFont },
+ { "fixed5x8.bdf", FontManager::kConsoleFont },
+ { "fixed5x8-iso-8859-1.bdf", FontManager::kConsoleFont },
+ { "fixed5x8-ascii.bdf", FontManager::kConsoleFont },
+ { "clR6x12.bdf", FontManager::kGUIFont },
+ { "clR6x12-iso-8859-1.bdf", FontManager::kGUIFont },
+ { "clR6x12-ascii.bdf", FontManager::kGUIFont },
+ { "helvB12.bdf", FontManager::kBigGUIFont },
+ { "helvB12-iso-8859-1.bdf", FontManager::kBigGUIFont },
+ { "helvB12-ascii.bdf", FontManager::kBigGUIFont },
+ { 0, FontManager::kOSDFont }
+};
+
const Font *FontManager::getFontByName(const Common::String &name) const {
+ for (int i = 0; builtinFontNames[i].name; i++)
+ if (!scumm_stricmp(name.c_str(), builtinFontNames[i].name))
+ return getFontByUsage(builtinFontNames[i].id);
+
if (!_fontMap.contains(name))
return 0;
return _fontMap[name];
diff --git a/graphics/fontman.h b/graphics/fontman.h
index 9896fad38c..7871f32ba9 100644
--- a/graphics/fontman.h
+++ b/graphics/fontman.h
@@ -38,10 +38,10 @@ namespace Graphics {
class FontManager : public Common::Singleton<FontManager> {
public:
enum FontUsage {
- kOSDFont,
- kConsoleFont,
- kGUIFont,
- kBigGUIFont
+ kOSDFont = 0,
+ kConsoleFont = 1,
+ kGUIFont = 2,
+ kBigGUIFont = 3
};
/**
diff --git a/graphics/module.mk b/graphics/module.mk
index ff6d7f8f60..445001ae6b 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -13,6 +13,7 @@ MODULE_OBJS := \
iff.o \
imagedec.o \
jpeg.o \
+ pict.o \
primitives.o \
scaler.o \
scaler/thumbnail_intern.o \
@@ -22,15 +23,22 @@ MODULE_OBJS := \
VectorRenderer.o \
VectorRendererSpec.o \
video/avi_decoder.o \
+ video/coktel_decoder.o \
video/dxa_decoder.o \
video/flic_decoder.o \
video/mpeg_player.o \
+ video/qt_decoder.o \
video/smk_decoder.o \
video/video_decoder.o \
+ video/codecs/cinepak.o \
+ video/codecs/mjpeg.o \
video/codecs/msrle.o \
video/codecs/msvideo1.o \
- video/coktelvideo/indeo3.o \
- video/coktelvideo/coktelvideo.o
+ video/codecs/qdm2.o \
+ video/codecs/qtrle.o \
+ video/codecs/rpza.o \
+ video/codecs/smc.o \
+ video/codecs/indeo3.o
ifdef USE_SCALERS
MODULE_OBJS += \
diff --git a/engines/mohawk/myst_pict.cpp b/graphics/pict.cpp
index 794ec9b87f..f0dd7bbc6f 100644
--- a/engines/mohawk/myst_pict.cpp
+++ b/graphics/pict.cpp
@@ -23,26 +23,38 @@
*
*/
-#include "common/system.h"
+#include "common/stream.h"
-#include "mohawk/myst_pict.h"
+#include "graphics/conversion.h"
+#include "graphics/jpeg.h"
+#include "graphics/pict.h"
+#include "graphics/surface.h"
-namespace Mohawk {
+namespace Graphics {
// The PICT code is based off of the QuickDraw specs:
-// http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-461.html
+// http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-461.html
+// http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-269.html
-MystPICT::MystPICT(JPEGDecoder *jpegDecoder) {
- _jpegDecoder = jpegDecoder;
- _pixelFormat = g_system->getScreenFormat();
+PictDecoder::PictDecoder(PixelFormat pixelFormat) {
+ _jpeg = new JPEG();
+ _pixelFormat = pixelFormat;
}
-Graphics::Surface *MystPICT::decodeImage(Common::SeekableReadStream *stream) {
- // Skip initial 512 bytes (all 0's)
- stream->seek(512, SEEK_CUR);
+PictDecoder::~PictDecoder() {
+ delete _jpeg;
+}
+
+Surface *PictDecoder::decodeImage(Common::SeekableReadStream *stream, byte *palette) {
+ assert(stream);
+
+ uint16 fileSize = stream->readUint16BE();
- // Read in the first part of the header
- /* uint16 fileSize = */ stream->readUint16BE();
+ // If we have no file size here, we probably have a PICT from a file
+ // and not a resource. The other two bytes are the fileSize which we
+ // don't actually need (and already read if from a resource).
+ if (!fileSize)
+ stream->seek(512 + 2);
_imageRect.top = stream->readUint16BE();
_imageRect.left = stream->readUint16BE();
@@ -52,11 +64,12 @@ Graphics::Surface *MystPICT::decodeImage(Common::SeekableReadStream *stream) {
Graphics::Surface *image = new Graphics::Surface();
image->create(_imageRect.width(), _imageRect.height(), _pixelFormat.bytesPerPixel);
+ _isPaletted = false;
// NOTE: This is only a subset of the full PICT format.
// - Only V2 Images Supported
- // - JPEG Chunks are Supported
- // - DirectBitsRect Chunks are Supported
+ // - CompressedQuickTime (JPEG) compressed data is supported
+ // - DirectBitsRect/PackBitsRect compressed data is supported
for (uint32 opNum = 0; !stream->eos() && !stream->err() && stream->pos() < stream->size(); opNum++) {
uint16 opcode = stream->readUint16BE();
debug(2, "Found PICT opcode %04x", opcode);
@@ -82,8 +95,11 @@ Graphics::Surface *MystPICT::decodeImage(Common::SeekableReadStream *stream) {
error ("Unknown PICT version");
} else if (opcode == 0x001E) { // DefHilite
// Ignore, Contains no Data
+ } else if (opcode == 0x0098) { // PackBitsRect
+ decodeDirectBitsRect(stream, image, true);
+ _isPaletted = true;
} else if (opcode == 0x009A) { // DirectBitsRect
- decodeDirectBitsRect(stream, image);
+ decodeDirectBitsRect(stream, image, false);
} else if (opcode == 0x00A1) { // LongComment
stream->readUint16BE();
uint16 dataSize = stream->readUint16BE();
@@ -106,59 +122,71 @@ Graphics::Surface *MystPICT::decodeImage(Common::SeekableReadStream *stream) {
decodeCompressedQuickTime(stream, image);
break;
} else {
- error ("Unknown PICT opcode %04x", opcode);
+ warning("Unknown PICT opcode %04x", opcode);
}
}
+ // If we got a palette throughout this nonsense, go and grab it
+ if (palette && _isPaletted)
+ memcpy(palette, _palette, 256 * 4);
+
return image;
}
+PictDecoder::PixMap PictDecoder::readPixMap(Common::SeekableReadStream *stream, bool hasBaseAddr) {
+ PixMap pixMap;
+ pixMap.baseAddr = hasBaseAddr ? stream->readUint32BE() : 0;
+ pixMap.rowBytes = stream->readUint16BE() & 0x3fff;
+ pixMap.bounds.top = stream->readUint16BE();
+ pixMap.bounds.left = stream->readUint16BE();
+ pixMap.bounds.bottom = stream->readUint16BE();
+ pixMap.bounds.right = stream->readUint16BE();
+ pixMap.pmVersion = stream->readUint16BE();
+ pixMap.packType = stream->readUint16BE();
+ pixMap.packSize = stream->readUint32BE();
+ pixMap.hRes = stream->readUint32BE();
+ pixMap.vRes = stream->readUint32BE();
+ pixMap.pixelType = stream->readUint16BE();
+ pixMap.pixelSize = stream->readUint16BE();
+ pixMap.cmpCount = stream->readUint16BE();
+ pixMap.cmpSize = stream->readUint16BE();
+ pixMap.planeBytes = stream->readUint32BE();
+ pixMap.pmTable = stream->readUint32BE();
+ pixMap.pmReserved = stream->readUint32BE();
+ return pixMap;
+}
+
struct DirectBitsRectData {
- // PixMap
- struct {
- uint32 baseAddr;
- uint16 rowBytes;
- Common::Rect bounds;
- uint16 pmVersion;
- uint16 packType;
- uint32 packSize;
- uint32 hRes;
- uint32 vRes;
- uint16 pixelType;
- uint16 pixelSize;
- uint16 cmpCount;
- uint16 cmpSize;
- uint32 planeBytes;
- uint32 pmTable;
- uint32 pmReserved;
- } pixMap;
+ PictDecoder::PixMap pixMap;
Common::Rect srcRect;
Common::Rect dstRect;
uint16 mode;
};
-void MystPICT::decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics::Surface *image) {
- static const Graphics::PixelFormat directBitsFormat16 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+void PictDecoder::decodeDirectBitsRect(Common::SeekableReadStream *stream, Surface *image, bool hasPalette) {
+ static const PixelFormat directBitsFormat16 = PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+
+ // Clear the palette
+ memset(_palette, 0, sizeof(_palette));
DirectBitsRectData directBitsData;
- directBitsData.pixMap.baseAddr = stream->readUint32BE();
- directBitsData.pixMap.rowBytes = stream->readUint16BE() & 0x3fff;
- directBitsData.pixMap.bounds.top = stream->readUint16BE();
- directBitsData.pixMap.bounds.left = stream->readUint16BE();
- directBitsData.pixMap.bounds.bottom = stream->readUint16BE();
- directBitsData.pixMap.bounds.right = stream->readUint16BE();
- directBitsData.pixMap.pmVersion = stream->readUint16BE();
- directBitsData.pixMap.packType = stream->readUint16BE();
- directBitsData.pixMap.packSize = stream->readUint32BE();
- directBitsData.pixMap.hRes = stream->readUint32BE();
- directBitsData.pixMap.vRes = stream->readUint32BE();
- directBitsData.pixMap.pixelType = stream->readUint16BE();
- directBitsData.pixMap.pixelSize = stream->readUint16BE();
- directBitsData.pixMap.cmpCount = stream->readUint16BE();
- directBitsData.pixMap.cmpSize = stream->readUint16BE();
- directBitsData.pixMap.planeBytes = stream->readUint32BE();
- directBitsData.pixMap.pmTable = stream->readUint32BE();
- directBitsData.pixMap.pmReserved = stream->readUint32BE();
+ directBitsData.pixMap = readPixMap(stream, !hasPalette);
+
+ // Read in the palette if there is one present
+ if (hasPalette) {
+ // See http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-267.html
+ stream->readUint32BE(); // seed
+ stream->readUint16BE(); // flags
+ uint16 colorCount = stream->readUint16BE() + 1;
+
+ for (uint32 i = 0; i < colorCount; i++) {
+ stream->readUint16BE();
+ _palette[i * 4] = stream->readUint16BE() >> 8;
+ _palette[i * 4 + 1] = stream->readUint16BE() >> 8;
+ _palette[i * 4 + 2] = stream->readUint16BE() >> 8;
+ }
+ }
+
directBitsData.srcRect.top = stream->readUint16BE();
directBitsData.srcRect.left = stream->readUint16BE();
directBitsData.srcRect.bottom = stream->readUint16BE();
@@ -169,34 +197,44 @@ void MystPICT::decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics
directBitsData.dstRect.right = stream->readUint16BE();
directBitsData.mode = stream->readUint16BE();
- if (directBitsData.pixMap.pixelSize != 16 && directBitsData.pixMap.pixelSize != 32)
- error("Unhandled directBitsRect bitsPerPixel %d", directBitsData.pixMap.pixelSize);
+ if (directBitsData.pixMap.pixelSize != 8 && directBitsData.pixMap.pixelSize != 16 && directBitsData.pixMap.pixelSize != 32)
+ error("Unhandled DirectBitsRect bitsPerPixel %d", directBitsData.pixMap.pixelSize);
- byte bytesPerPixel = (directBitsData.pixMap.pixelSize == 16) ? 2 : 3;
+ byte bytesPerPixel = (directBitsData.pixMap.pixelSize == 32) ? 3 : directBitsData.pixMap.pixelSize / 8;
byte *buffer = new byte[image->w * image->h * bytesPerPixel];
// Read in amount of data per row
for (uint16 i = 0; i < directBitsData.pixMap.bounds.height(); i++) {
- if (directBitsData.pixMap.packType == 1 || directBitsData.pixMap.rowBytes < 8) { // Unpacked, Pad-Byte
- error("Pack Type = %d, Row Bytes = %d", directBitsData.pixMap.packType, directBitsData.pixMap.rowBytes);
- // TODO
- } else if (directBitsData.pixMap.packType == 2) { // Unpacked, No Pad-Byte
- error("Pack Type = 2");
- // TODO
- } else if (directBitsData.pixMap.packType > 2) { // Packed
+ // NOTE: Compression 0 is "default". The format in SCI games is packed when 0.
+ // In the future, we may need to have something to set the "default" packing
+ // format, but this is good for now.
+
+ if (directBitsData.pixMap.packType == 1 || directBitsData.pixMap.rowBytes < 8) { // Unpacked, Pad-Byte (on 24-bit)
+ // TODO: Finish this. Hasn't been needed (yet).
+ error("Unpacked DirectBitsRect data (padded)");
+ } else if (directBitsData.pixMap.packType == 2) { // Unpacked, No Pad-Byte (on 24-bit)
+ // TODO: Finish this. Hasn't been needed (yet).
+ error("Unpacked DirectBitsRect data (not padded)");
+ } else if (directBitsData.pixMap.packType == 0 || directBitsData.pixMap.packType > 2) { // Packed
uint16 byteCount = (directBitsData.pixMap.rowBytes > 250) ? stream->readUint16BE() : stream->readByte();
decodeDirectBitsLine(buffer + i * image->w * bytesPerPixel, directBitsData.pixMap.rowBytes, stream->readStream(byteCount), bytesPerPixel);
}
}
-
- if (bytesPerPixel == 2) {
+
+ if (bytesPerPixel == 1) {
+ // Just copy to the image
+ memcpy(image->pixels, buffer, image->w * image->h);
+ } else if (bytesPerPixel == 2) {
// Convert from 16-bit to whatever surface we need
for (uint16 y = 0; y < image->h; y++) {
for (uint16 x = 0; x < image->w; x++) {
byte r = 0, g = 0, b = 0;
uint32 color = READ_BE_UINT16(buffer + (y * image->w + x) * bytesPerPixel);
directBitsFormat16.colorToRGB(color, r, g, b);
- *((uint16 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
+ if (_pixelFormat.bytesPerPixel == 2)
+ *((uint16 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
+ else
+ *((uint32 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
}
}
} else {
@@ -206,7 +244,10 @@ void MystPICT::decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics
byte r = *(buffer + y * image->w * 3 + x);
byte g = *(buffer + y * image->w * 3 + image->w + x);
byte b = *(buffer + y * image->w * 3 + image->w * 2 + x);
- *((uint16 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
+ if (_pixelFormat.bytesPerPixel == 2)
+ *((uint16 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
+ else
+ *((uint32 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
}
}
}
@@ -214,7 +255,7 @@ void MystPICT::decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics
delete[] buffer;
}
-void MystPICT::decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bytesPerPixel) {
+void PictDecoder::decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bytesPerPixel) {
uint32 dataDecoded = 0;
byte bytesPerDecode = (bytesPerPixel == 2) ? 2 : 1;
@@ -256,17 +297,37 @@ void MystPICT::decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableRe
// http://developer.apple.com/documentation/QuickTime/Rm/CompressDecompress/ImageComprMgr/F-Chapter/6WorkingwiththeImage.html
// I'm just ignoring that because Myst ME uses none of that extra stuff. The offset is always the same.
-void MystPICT::decodeCompressedQuickTime(Common::SeekableReadStream *stream, Graphics::Surface *image) {
+void PictDecoder::decodeCompressedQuickTime(Common::SeekableReadStream *stream, Graphics::Surface *image) {
uint32 dataSize = stream->readUint32BE();
uint32 startPos = stream->pos();
- Graphics::Surface *jpegImage = _jpegDecoder->decodeImage(new Common::SeekableSubReadStream(stream, stream->pos() + 156, stream->pos() + dataSize));
- stream->seek(startPos + dataSize);
+ Common::SeekableReadStream *jpegStream = new Common::SeekableSubReadStream(stream, stream->pos() + 156, stream->pos() + dataSize);
+
+ if (!_jpeg->read(jpegStream))
+ error("PictDecoder::decodeCompressedQuickTime(): Could not decode JPEG data");
- image->copyFrom(*jpegImage);
+ Surface *yComponent = _jpeg->getComponent(1);
+ Surface *uComponent = _jpeg->getComponent(2);
+ Surface *vComponent = _jpeg->getComponent(3);
- jpegImage->free();
- delete jpegImage;
+ Surface jpegImage;
+ jpegImage.create(yComponent->w, yComponent->h, _pixelFormat.bytesPerPixel);
+
+ for (uint16 i = 0; i < jpegImage.h; i++) {
+ for (uint16 j = 0; j < jpegImage.w; j++) {
+ byte r = 0, g = 0, b = 0;
+ YUV2RGB(*((byte *)yComponent->getBasePtr(j, i)), *((byte *)uComponent->getBasePtr(j, i)), *((byte *)vComponent->getBasePtr(j, i)), r, g, b);
+ if (_pixelFormat.bytesPerPixel == 2)
+ *((uint16 *)jpegImage.getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
+ else
+ *((uint32 *)jpegImage.getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
+ }
+ }
+
+ image->copyFrom(jpegImage);
+ stream->seek(startPos + dataSize);
+ jpegImage.free();
+ delete jpegStream;
}
-} // End of namespace Mohawk
+} // End of namespace Graphics
diff --git a/engines/mohawk/myst_pict.h b/graphics/pict.h
index 0684e3352a..12681f6128 100644
--- a/engines/mohawk/myst_pict.h
+++ b/graphics/pict.h
@@ -23,35 +23,61 @@
*
*/
-#ifndef MYST_PICT_H
-#define MYST_PICT_H
+#ifndef GRAPHICS_PICT_H
+#define GRAPHICS_PICT_H
#include "common/rect.h"
#include "common/scummsys.h"
-#include "common/stream.h"
+
#include "graphics/pixelformat.h"
-#include "graphics/surface.h"
-#include "mohawk/jpeg.h"
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Graphics {
-namespace Mohawk {
+class JPEG;
+struct Surface;
-class MystPICT {
+class PictDecoder {
public:
- MystPICT(JPEGDecoder *jpegDecoder);
- ~MystPICT() {}
- Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
+ PictDecoder(Graphics::PixelFormat pixelFormat);
+ ~PictDecoder();
+ Surface *decodeImage(Common::SeekableReadStream *stream, byte *palette = 0);
+
+ struct PixMap {
+ uint32 baseAddr;
+ uint16 rowBytes;
+ Common::Rect bounds;
+ uint16 pmVersion;
+ uint16 packType;
+ uint32 packSize;
+ uint32 hRes;
+ uint32 vRes;
+ uint16 pixelType;
+ uint16 pixelSize;
+ uint16 cmpCount;
+ uint16 cmpSize;
+ uint32 planeBytes;
+ uint32 pmTable;
+ uint32 pmReserved;
+ };
+
+ static PixMap readPixMap(Common::SeekableReadStream *stream, bool hasBaseAddr = true);
private:
- JPEGDecoder *_jpegDecoder;
Common::Rect _imageRect;
- Graphics::PixelFormat _pixelFormat;
+ PixelFormat _pixelFormat;
+ JPEG *_jpeg;
+ byte _palette[256 * 4];
+ bool _isPaletted;
- void decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics::Surface *image);
+ void decodeDirectBitsRect(Common::SeekableReadStream *stream, Surface *image, bool hasPalette);
void decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bytesPerPixel);
- void decodeCompressedQuickTime(Common::SeekableReadStream *stream, Graphics::Surface *image);
+ void decodeCompressedQuickTime(Common::SeekableReadStream *stream, Surface *image);
};
-} // End of namespace Mohawk
+} // End of namespace Graphics
#endif
diff --git a/graphics/scaler.h b/graphics/scaler.h
index 22bda5273a..577a91ccc1 100644
--- a/graphics/scaler.h
+++ b/graphics/scaler.h
@@ -77,7 +77,7 @@ enum {
* 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
+ * @return false if a error occurred
*/
extern bool createThumbnailFromScreen(Graphics::Surface *surf);
diff --git a/graphics/scaler/thumbnail_intern.cpp b/graphics/scaler/thumbnail_intern.cpp
index 12048249f0..f767c91bd5 100644
--- a/graphics/scaler/thumbnail_intern.cpp
+++ b/graphics/scaler/thumbnail_intern.cpp
@@ -148,8 +148,8 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
Graphics::Surface newscreen;
newscreen.create(width, in.h, in.bytesPerPixel);
- uint8 *dst = (uint8*)newscreen.getBasePtr((320 - in.w) / 2, 0);
- const uint8 *src = (uint8*)in.getBasePtr(0, 0);
+ uint8 *dst = (uint8 *)newscreen.getBasePtr((320 - in.w) / 2, 0);
+ const uint8 *src = (const uint8 *)in.getBasePtr(0, 0);
uint16 height = in.h;
while (height--) {
@@ -173,8 +173,8 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
Graphics::Surface newscreen;
newscreen.create(width, 400, in.bytesPerPixel);
- uint8 *dst = (uint8*)in.getBasePtr(0, (400 - 240) / 2);
- const uint8 *src = (uint8*)in.getBasePtr(41, 28);
+ uint8 *dst = (uint8 *)newscreen.getBasePtr(0, (400 - 240) / 2);
+ const uint8 *src = (const uint8 *)in.getBasePtr(41, 28);
for (int y = 0; y < 240; ++y) {
memcpy(dst, src, 640 * in.bytesPerPixel);
@@ -184,6 +184,18 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
in.free();
in = newscreen;
+ } else if (width == 640 && inHeight == 440) {
+ // Special case to handle KQ6 Windows: resize the screen to 640x480,
+ // adding a black band in the bottom.
+ inHeight = 480;
+
+ Graphics::Surface newscreen;
+ newscreen.create(width, 480, in.bytesPerPixel);
+
+ memcpy(newscreen.getBasePtr(0, 0), in.getBasePtr(0, 0), width * 440 * in.bytesPerPixel);
+
+ in.free();
+ in = newscreen;
}
uint16 newHeight = !(inHeight % 240) ? kThumbnailHeight2 : kThumbnailHeight1;
diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp
index 4c8ce289cf..ccde78806d 100644
--- a/graphics/thumbnail.cpp
+++ b/graphics/thumbnail.cpp
@@ -82,7 +82,7 @@ bool checkThumbnailHeader(Common::SeekableReadStream &in) {
return hasHeader;
}
-bool skipThumbnailHeader(Common::SeekableReadStream &in) {
+bool skipThumbnail(Common::SeekableReadStream &in) {
uint32 position = in.pos();
ThumbnailHeader header;
diff --git a/graphics/thumbnail.h b/graphics/thumbnail.h
index b3fdb70b95..9341582aa1 100644
--- a/graphics/thumbnail.h
+++ b/graphics/thumbnail.h
@@ -39,14 +39,14 @@ namespace Graphics {
bool checkThumbnailHeader(Common::SeekableReadStream &in);
/**
- * Skips a thumbnail header, if present.
+ * Skips a thumbnail, if present.
*
* @param in stream to process
*/
-bool skipThumbnailHeader(Common::SeekableReadStream &in);
+bool skipThumbnail(Common::SeekableReadStream &in);
/**
- * Lodas a thumbnail from the given input stream.
+ * Loads a thumbnail from the given input stream.
* The loaded thumbnail will be automatically converted to the
* current overlay pixelformat.
*/
diff --git a/graphics/video/avi_decoder.cpp b/graphics/video/avi_decoder.cpp
index 944c9700bd..4973cb3eb0 100644
--- a/graphics/video/avi_decoder.cpp
+++ b/graphics/video/avi_decoder.cpp
@@ -35,8 +35,10 @@
#include "graphics/video/avi_decoder.h"
// Codecs
+#include "graphics/video/codecs/cinepak.h"
#include "graphics/video/codecs/msvideo1.h"
#include "graphics/video/codecs/msrle.h"
+#include "graphics/video/codecs/indeo3.h"
namespace Graphics {
@@ -153,10 +155,8 @@ void AviDecoder::handleStreamHeader() {
sHeader.bufferSize = _fileStream->readUint32LE();
sHeader.quality = _fileStream->readUint32LE();
sHeader.sampleSize = _fileStream->readUint32LE();
- sHeader.frame.left = _fileStream->readSint16LE();
- sHeader.frame.top = _fileStream->readSint16LE();
- sHeader.frame.right = _fileStream->readSint16LE();
- sHeader.frame.bottom = _fileStream->readSint16LE();
+
+ _fileStream->skip(sHeader.size - 48); // Skip over the remainder of the chunk (frame)
if (_fileStream->readUint32BE() != ID_STRF)
error("Could not find STRF tag");
@@ -187,11 +187,14 @@ void AviDecoder::handleStreamHeader() {
_palette[i * 3 + 2] = _fileStream->readByte();
_palette[i * 3 + 1] = _fileStream->readByte();
_palette[i * 3] = _fileStream->readByte();
- /*_palette[i * 4 + 3] = */_fileStream->readByte();
+ _fileStream->readByte();
}
_dirtyPalette = true;
}
+
+ if (!_vidsHeader.streamHandler)
+ _vidsHeader.streamHandler = _bmInfo.compression;
} else if (sHeader.streamType == ID_AUDS) {
_audsHeader = sHeader;
@@ -201,13 +204,18 @@ void AviDecoder::handleStreamHeader() {
_wvInfo.avgBytesPerSec = _fileStream->readUint32LE();
_wvInfo.blockAlign = _fileStream->readUint16LE();
_wvInfo.size = _fileStream->readUint16LE();
+
+ // AVI seems to treat the sampleSize as including the second
+ // channel as well, so divide for our sake.
+ if (_wvInfo.channels == 2)
+ _audsHeader.sampleSize /= 2;
}
}
-bool AviDecoder::load(Common::SeekableReadStream &stream) {
+bool AviDecoder::load(Common::SeekableReadStream *stream) {
close();
- _fileStream = &stream;
+ _fileStream = stream;
_decodedHeader = false;
// Read chunks until we have decoded the header
@@ -324,6 +332,9 @@ Surface *AviDecoder::decodeNextFrame() {
else
flags |= Audio::FLAG_UNSIGNED;
+ if (_wvInfo.channels == 2)
+ flags |= Audio::FLAG_STEREO;
+
_audStream->queueBuffer(data, chunkSize, DisposeAfterUse::YES, flags);
_fileStream->skip(chunkSize & 1); // Alignment
} else if (getStreamType(nextTag) == 'dc' || getStreamType(nextTag) == 'id' ||
@@ -377,8 +388,14 @@ Codec *AviDecoder::createCodec() {
case ID_MSVC:
case ID_WHAM:
return new MSVideo1Decoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount);
- case ID_RLE :
+ case ID_RLE:
return new MSRLEDecoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount);
+ case ID_CVID:
+ return new CinepakDecoder();
+#ifdef USE_INDEO3
+ case ID_IV32:
+ return new Indeo3Decoder(_bmInfo.width, _bmInfo.height);
+#endif
default:
warning ("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler));
}
@@ -393,7 +410,7 @@ PixelFormat AviDecoder::getPixelFormat() const {
Audio::QueuingAudioStream *AviDecoder::createAudioStream() {
if (_wvInfo.tag == AVI_WAVE_FORMAT_PCM)
- return Audio::makeQueuingAudioStream(AUDIO_RATE, false);
+ return Audio::makeQueuingAudioStream(AUDIO_RATE, _wvInfo.channels == 2);
if (_wvInfo.tag != 0) // No sound
warning ("Unsupported AVI audio format %d", _wvInfo.tag);
diff --git a/graphics/video/avi_decoder.h b/graphics/video/avi_decoder.h
index 5f09992647..72cf2d7ef5 100644
--- a/graphics/video/avi_decoder.h
+++ b/graphics/video/avi_decoder.h
@@ -178,7 +178,7 @@ public:
Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
virtual ~AviDecoder();
- bool load(Common::SeekableReadStream &stream);
+ bool load(Common::SeekableReadStream *stream);
void close();
bool isVideoLoaded() const { return _fileStream != 0; }
diff --git a/graphics/video/codecs/cinepak.cpp b/graphics/video/codecs/cinepak.cpp
new file mode 100644
index 0000000000..a14eaf9acf
--- /dev/null
+++ b/graphics/video/codecs/cinepak.cpp
@@ -0,0 +1,285 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/video/codecs/cinepak.h"
+
+#include "common/system.h"
+
+// Code here partially based off of ffmpeg ;)
+
+namespace Graphics {
+
+// Convert a color from YUV to RGB colorspace, Cinepak style.
+inline static void CPYUV2RGB(byte y, byte u, byte v, byte &r, byte &g, byte &b) {
+ r = CLIP<int>(y + 2 * (v - 128), 0, 255);
+ g = CLIP<int>(y - (u - 128) / 2 - (v - 128), 0, 255);
+ b = CLIP<int>(y + 2 * (u - 128), 0, 255);
+}
+
+#define PUT_PIXEL(offset, lum, u, v) \
+ CPYUV2RGB(lum, u, v, r, g, b); \
+ if (_pixelFormat.bytesPerPixel == 2) \
+ *((uint16 *)_curFrame.surface->pixels + offset) = _pixelFormat.RGBToColor(r, g, b); \
+ else \
+ *((uint32 *)_curFrame.surface->pixels + offset) = _pixelFormat.RGBToColor(r, g, b)
+
+CinepakDecoder::CinepakDecoder() : Codec() {
+ _curFrame.surface = NULL;
+ _curFrame.strips = NULL;
+ _y = 0;
+ _pixelFormat = g_system->getScreenFormat();
+}
+
+CinepakDecoder::~CinepakDecoder() {
+ if (_curFrame.surface) {
+ _curFrame.surface->free();
+ delete _curFrame.surface;
+ }
+
+ delete[] _curFrame.strips;
+}
+
+Surface *CinepakDecoder::decodeImage(Common::SeekableReadStream *stream) {
+ _curFrame.flags = stream->readByte();
+ _curFrame.length = (stream->readByte() << 16) + stream->readUint16BE();
+ _curFrame.width = stream->readUint16BE();
+ _curFrame.height = stream->readUint16BE();
+ _curFrame.stripCount = stream->readUint16BE();
+
+ if (_curFrame.strips == NULL)
+ _curFrame.strips = new CinepakStrip[_curFrame.stripCount];
+
+ debug (4, "Cinepak Frame: Width = %d, Height = %d, Strip Count = %d", _curFrame.width, _curFrame.height, _curFrame.stripCount);
+
+ // Borrowed from FFMPEG. This should cut out the extra data Cinepak for Sega has (which is useless).
+ // The theory behind this is that this is here to confuse standard Cinepak decoders. But, we won't let that happen! ;)
+ if (_curFrame.length != (uint32)stream->size()) {
+ if (stream->readUint16BE() == 0xFE00)
+ stream->readUint32BE();
+ }
+
+ if (!_curFrame.surface) {
+ _curFrame.surface = new Surface();
+ _curFrame.surface->create(_curFrame.width, _curFrame.height, _pixelFormat.bytesPerPixel);
+ }
+
+ // Reset the y variable.
+ _y = 0;
+
+ for (uint16 i = 0; i < _curFrame.stripCount; i++) {
+ if (i > 0 && !(_curFrame.flags & 1)) { // Use codebooks from last strip
+ for (uint16 j = 0; j < 256; j++) {
+ _curFrame.strips[i].v1_codebook[j] = _curFrame.strips[i - 1].v1_codebook[j];
+ _curFrame.strips[i].v4_codebook[j] = _curFrame.strips[i - 1].v4_codebook[j];
+ }
+ }
+
+ _curFrame.strips[i].id = stream->readUint16BE();
+ _curFrame.strips[i].length = stream->readUint16BE() - 12; // Subtract the 12 byte header
+ _curFrame.strips[i].rect.top = _y; stream->readUint16BE(); // Ignore, substitute with our own.
+ _curFrame.strips[i].rect.left = 0; stream->readUint16BE(); // Ignore, substitute with our own
+ _curFrame.strips[i].rect.bottom = _y + stream->readUint16BE();
+ _curFrame.strips[i].rect.right = _curFrame.width; stream->readUint16BE(); // Ignore, substitute with our own
+
+ // Sanity check. Because Cinepak is based on 4x4 blocks, the width and height of each strip needs to be divisible by 4.
+ assert(!(_curFrame.strips[i].rect.width() % 4) && !(_curFrame.strips[i].rect.height() % 4));
+
+ uint32 pos = stream->pos();
+
+ while ((uint32)stream->pos() < (pos + _curFrame.strips[i].length) && !stream->eos()) {
+ byte chunkID = stream->readByte();
+
+ if (stream->eos())
+ break;
+
+ // Chunk Size is 24-bit, ignore the first 4 bytes
+ uint32 chunkSize = stream->readByte() << 16;
+ chunkSize += stream->readUint16BE() - 4;
+
+ int32 startPos = stream->pos();
+
+ switch (chunkID) {
+ case 0x20:
+ case 0x21:
+ case 0x24:
+ case 0x25:
+ loadCodebook(stream, i, 4, chunkID, chunkSize);
+ break;
+ case 0x22:
+ case 0x23:
+ case 0x26:
+ case 0x27:
+ loadCodebook(stream, i, 1, chunkID, chunkSize);
+ break;
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ decodeVectors(stream, i, chunkID, chunkSize);
+ break;
+ default:
+ warning("Unknown Cinepak chunk ID %02x", chunkID);
+ return _curFrame.surface;
+ }
+
+ if (stream->pos() != startPos + (int32)chunkSize)
+ stream->seek(startPos + chunkSize);
+ }
+
+ _y = _curFrame.strips[i].rect.bottom;
+ }
+
+ return _curFrame.surface;
+}
+
+void CinepakDecoder::loadCodebook(Common::SeekableReadStream *stream, uint16 strip, byte codebookType, byte chunkID, uint32 chunkSize) {
+ CinepakCodebook *codebook = (codebookType == 1) ? _curFrame.strips[strip].v1_codebook : _curFrame.strips[strip].v4_codebook;
+
+ int32 startPos = stream->pos();
+ uint32 flag = 0, mask = 0;
+
+ for (uint16 i = 0; i < 256; i++) {
+ if ((chunkID & 0x01) && !(mask >>= 1)) {
+ if ((stream->pos() - startPos + 4) > (int32)chunkSize)
+ break;
+
+ flag = stream->readUint32BE();
+ mask = 0x80000000;
+ }
+
+ if (!(chunkID & 0x01) || (flag & mask)) {
+ byte n = (chunkID & 0x04) ? 4 : 6;
+ if ((stream->pos() - startPos + n) > (int32)chunkSize)
+ break;
+
+ for (byte j = 0; j < 4; j++)
+ codebook[i].y[j] = stream->readByte();
+
+ if (n == 6) {
+ codebook[i].u = stream->readByte() + 128;
+ codebook[i].v = stream->readByte() + 128;
+ } else {
+ // This codebook type indicates either greyscale or
+ // palettized video. We don't handle palettized video
+ // currently.
+ codebook[i].u = 128;
+ codebook[i].v = 128;
+ }
+ }
+ }
+}
+
+void CinepakDecoder::decodeVectors(Common::SeekableReadStream *stream, uint16 strip, byte chunkID, uint32 chunkSize) {
+ uint32 flag = 0, mask = 0;
+ uint32 iy[4];
+ int32 startPos = stream->pos();
+ byte r = 0, g = 0, b = 0;
+
+ for (uint16 y = _curFrame.strips[strip].rect.top; y < _curFrame.strips[strip].rect.bottom; y += 4) {
+ iy[0] = _curFrame.strips[strip].rect.left + y * _curFrame.width;
+ iy[1] = iy[0] + _curFrame.width;
+ iy[2] = iy[1] + _curFrame.width;
+ iy[3] = iy[2] + _curFrame.width;
+
+ for (uint16 x = _curFrame.strips[strip].rect.left; x < _curFrame.strips[strip].rect.right; x += 4) {
+ if ((chunkID & 0x01) && !(mask >>= 1)) {
+ if ((stream->pos() - startPos + 4) > (int32)chunkSize)
+ return;
+
+ flag = stream->readUint32BE();
+ mask = 0x80000000;
+ }
+
+ if (!(chunkID & 0x01) || (flag & mask)) {
+ if (!(chunkID & 0x02) && !(mask >>= 1)) {
+ if ((stream->pos() - startPos + 4) > (int32)chunkSize)
+ return;
+
+ flag = stream->readUint32BE();
+ mask = 0x80000000;
+ }
+
+ if ((chunkID & 0x02) || (~flag & mask)) {
+ if ((stream->pos() - startPos + 1) > (int32)chunkSize)
+ return;
+
+ // Get the codebook
+ CinepakCodebook codebook = _curFrame.strips[strip].v1_codebook[stream->readByte()];
+
+ PUT_PIXEL(iy[0] + 0, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[0] + 1, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 0, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 1, codebook.y[0], codebook.u, codebook.v);
+
+ PUT_PIXEL(iy[0] + 2, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[0] + 3, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 2, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 3, codebook.y[1], codebook.u, codebook.v);
+
+ PUT_PIXEL(iy[2] + 0, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[2] + 1, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 0, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 1, codebook.y[2], codebook.u, codebook.v);
+
+ PUT_PIXEL(iy[2] + 2, codebook.y[3], codebook.u, codebook.v);
+ PUT_PIXEL(iy[2] + 3, codebook.y[3], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 2, codebook.y[3], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 3, codebook.y[3], codebook.u, codebook.v);
+ } else if (flag & mask) {
+ if ((stream->pos() - startPos + 4) > (int32)chunkSize)
+ return;
+
+ CinepakCodebook codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
+ PUT_PIXEL(iy[0] + 0, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[0] + 1, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 0, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 1, codebook.y[3], codebook.u, codebook.v);
+
+ codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
+ PUT_PIXEL(iy[0] + 2, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[0] + 3, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 2, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 3, codebook.y[3], codebook.u, codebook.v);
+
+ codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
+ PUT_PIXEL(iy[2] + 0, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[2] + 1, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 0, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 1, codebook.y[3], codebook.u, codebook.v);
+
+ codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
+ PUT_PIXEL(iy[2] + 2, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[2] + 3, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 2, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 3, codebook.y[3], codebook.u, codebook.v);
+ }
+ }
+
+ for (byte i = 0; i < 4; i++)
+ iy[i] += 4;
+ }
+ }
+}
+
+} // End of namespace Graphics
diff --git a/graphics/video/codecs/cinepak.h b/graphics/video/codecs/cinepak.h
new file mode 100644
index 0000000000..92351cdba8
--- /dev/null
+++ b/graphics/video/codecs/cinepak.h
@@ -0,0 +1,81 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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_CINEPAK_H
+#define GRAPHICS_CINEPAK_H
+
+#include "common/scummsys.h"
+#include "common/stream.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+#include "graphics/pixelformat.h"
+
+#include "graphics/video/codecs/codec.h"
+
+namespace Graphics {
+
+struct CinepakCodebook {
+ byte y[4];
+ byte u, v;
+};
+
+struct CinepakStrip {
+ uint16 id;
+ uint16 length;
+ Common::Rect rect;
+ CinepakCodebook v1_codebook[256], v4_codebook[256];
+};
+
+struct CinepakFrame {
+ byte flags;
+ uint32 length;
+ uint16 width;
+ uint16 height;
+ uint16 stripCount;
+ CinepakStrip *strips;
+
+ Surface *surface;
+};
+
+class CinepakDecoder : public Codec {
+public:
+ CinepakDecoder();
+ ~CinepakDecoder();
+
+ Surface *decodeImage(Common::SeekableReadStream *stream);
+ PixelFormat getPixelFormat() const { return _pixelFormat; }
+
+private:
+ CinepakFrame _curFrame;
+ int32 _y;
+ PixelFormat _pixelFormat;
+
+ void loadCodebook(Common::SeekableReadStream *stream, uint16 strip, byte codebookType, byte chunkID, uint32 chunkSize);
+ void decodeVectors(Common::SeekableReadStream *stream, uint16 strip, byte chunkID, uint32 chunkSize);
+};
+
+} // End of namespace Graphics
+
+#endif
diff --git a/graphics/video/codecs/indeo3.cpp b/graphics/video/codecs/indeo3.cpp
new file mode 100644
index 0000000000..f59ae81e81
--- /dev/null
+++ b/graphics/video/codecs/indeo3.cpp
@@ -0,0 +1,3431 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#ifdef USE_INDEO3
+
+/* Intel Indeo 3 decompressor, derived from ffmpeg.
+ *
+ * Original copyright note: * Intel Indeo 3 (IV31, IV32, etc.) video decoder for ffmpeg
+ * written, produced, and directed by Alan Smithee
+ */
+
+#include "common/system.h"
+#include "common/endian.h"
+#include "common/frac.h"
+#include "common/file.h"
+
+#include "graphics/conversion.h"
+
+#include "graphics/video/codecs/indeo3.h"
+
+namespace Graphics {
+
+Indeo3Decoder::Indeo3Decoder(uint16 width, uint16 height) : _ModPred(0), _corrector_type(0) {
+ _iv_frame[0].the_buf = 0;
+ _iv_frame[1].the_buf = 0;
+
+ _pixelFormat = g_system->getScreenFormat();
+
+ _surface = new Surface;
+ _surface->create(width, height, _pixelFormat.bytesPerPixel);
+
+ buildModPred();
+ allocFrames();
+}
+
+Indeo3Decoder::~Indeo3Decoder() {
+ delete _surface;
+
+ delete[] _iv_frame[0].the_buf;
+ delete[] _ModPred;
+ delete[] _corrector_type;
+}
+
+PixelFormat Indeo3Decoder::getPixelFormat() const {
+ return _pixelFormat;
+}
+
+bool Indeo3Decoder::isIndeo3(byte *data, uint32 dataLen) {
+ // No data, no Indeo 3
+ if (!data)
+ return false;
+
+ // Less than 16 bytes? This can't be right
+ if (dataLen < 16)
+ return false;
+
+ // Unknown, but according to the docs, always 0
+ if (READ_LE_UINT32(data + 4) != 0)
+ return false;
+
+ uint32 id;
+ id = READ_LE_UINT32(data ); // frame number
+ id ^= READ_LE_UINT32(data + 4); // unknown
+ id ^= READ_LE_UINT32(data + 8); // checksum
+ id ^= READ_LE_UINT32(data + 12); // frame data length
+
+ // These 4 uint32s XOR'd need to spell "FRMH"
+ if (id != MKID_BE('FRMH'))
+ return false;
+
+ return true;
+}
+
+void Indeo3Decoder::buildModPred() {
+ _ModPred = new byte[8 * 128];
+
+ for (int i = 0; i < 128; i++) {
+ _ModPred[i+0*128] = (i > 126) ? 254 : 2*((i + 1) - ((i + 1) % 2));
+ _ModPred[i+1*128] = (i == 7) ? 20 : ((i == 119 || i == 120)
+ ? 236 : 2*((i + 2) - ((i + 1) % 3)));
+ _ModPred[i+2*128] = (i > 125) ? 248 : 2*((i + 2) - ((i + 2) % 4));
+ _ModPred[i+3*128] = 2*((i + 1) - ((i - 3) % 5));
+ _ModPred[i+4*128] = (i == 8) ? 20 : 2*((i + 1) - ((i - 3) % 6));
+ _ModPred[i+5*128] = 2*((i + 4) - ((i + 3) % 7));
+ _ModPred[i+6*128] = (i > 123) ? 240 : 2*((i + 4) - ((i + 4) % 8));
+ _ModPred[i+7*128] = 2*((i + 5) - ((i + 4) % 9));
+ }
+
+ _corrector_type = new uint16[24 * 256];
+
+ for (int i = 0; i < 24; i++) {
+ for (int j = 0; j < 256; j++) {
+ _corrector_type[i*256+j] =
+ (j < _corrector_type_0[i]) ? 1 :
+ ((j < 248 || (i == 16 && j == 248)) ? 0 :
+ _corrector_type_2[j - 248]);
+ }
+ }
+}
+
+void Indeo3Decoder::allocFrames() {
+ int32 luma_width = (_surface->w + 3) & (~3);
+ int32 luma_height = (_surface->h + 3) & (~3);
+
+ int32 chroma_width = ((luma_width >> 2) + 3) & (~3);
+ int32 chroma_height = ((luma_height >> 2) + 3) & (~3);
+
+ int32 luma_pixels = luma_width * luma_height;
+ int32 chroma_pixels = chroma_width * chroma_height;
+
+ uint32 bufsize = luma_pixels * 2 + luma_width * 3 +
+ (chroma_pixels + chroma_width) * 4;
+
+ _iv_frame[0].y_w = _iv_frame[1].y_w = luma_width;
+ _iv_frame[0].y_h = _iv_frame[1].y_h = luma_height;
+ _iv_frame[0].uv_w = _iv_frame[1].uv_w = chroma_width;
+ _iv_frame[0].uv_h = _iv_frame[1].uv_h = chroma_height;
+
+ _iv_frame[0].the_buf_size = bufsize;
+ _iv_frame[1].the_buf_size = 0;
+
+ _iv_frame[0].the_buf = new byte[bufsize];
+ memset(_iv_frame[0].the_buf, 0, bufsize);
+ _iv_frame[1].the_buf = 0;
+
+ uint32 offs = 0;
+
+ _iv_frame[0].Ybuf = _iv_frame[0].the_buf + luma_width;
+ offs += luma_pixels + luma_width * 2;
+ _iv_frame[1].Ybuf = _iv_frame[0].the_buf + offs;
+ offs += (luma_pixels + luma_width);
+ _iv_frame[0].Ubuf = _iv_frame[0].the_buf + offs;
+ offs += (chroma_pixels + chroma_width);
+ _iv_frame[1].Ubuf = _iv_frame[0].the_buf + offs;
+ offs += (chroma_pixels + chroma_width);
+ _iv_frame[0].Vbuf = _iv_frame[0].the_buf + offs;
+ offs += (chroma_pixels + chroma_width);
+ _iv_frame[1].Vbuf = _iv_frame[0].the_buf + offs;
+
+ for (int i = 1; i <= luma_width; i++)
+ _iv_frame[0].Ybuf[-i] = _iv_frame[1].Ybuf[-i] =
+ _iv_frame[0].Ubuf[-i] = 0x80;
+
+ for (int i = 1; i <= chroma_width; i++) {
+ _iv_frame[1].Ubuf[-i] = 0x80;
+ _iv_frame[0].Vbuf[-i] = 0x80;
+ _iv_frame[1].Vbuf[-i] = 0x80;
+ _iv_frame[1].Vbuf[chroma_pixels+i-1] = 0x80;
+ }
+}
+
+Surface *Indeo3Decoder::decodeImage(Common::SeekableReadStream *stream) {
+ uint32 dataLen = stream->size();
+
+ byte *inData = new byte[dataLen];
+
+ if (stream->read(inData, dataLen) != dataLen)
+ return 0;
+
+ // Not Indeo 3? Fail
+ if (!isIndeo3(inData, dataLen))
+ return 0;
+
+ uint32 frameDataLen = READ_LE_UINT32(inData + 12);
+
+ // Less data than the frame should have? Fail
+ if (dataLen < (frameDataLen - 16))
+ return 0;
+
+ Common::MemoryReadStream frame(inData, dataLen);
+
+ frame.skip(16); // Header
+ frame.skip(2); // Unknown
+
+ uint16 flags1 = frame.readUint16LE();
+ uint32 flags3 = frame.readUint32LE();
+ uint8 flags2 = frame.readByte();
+
+ // Finding the reference frame
+ if (flags1 & 0x200) {
+ _cur_frame = _iv_frame + 1;
+ _ref_frame = _iv_frame;
+ } else {
+ _cur_frame = _iv_frame;
+ _ref_frame = _iv_frame + 1;
+ }
+
+ if (flags3 == 0x80)
+ return _surface;
+
+ frame.skip(3);
+
+ uint16 fHeight = frame.readUint16LE();
+ uint16 fWidth = frame.readUint16LE();
+
+ uint32 chromaHeight = ((fHeight >> 2) + 3) & 0x7FFC;
+ uint32 chromaWidth = ((fWidth >> 2) + 3) & 0x7FFC;
+
+ uint32 offs;
+ uint32 offsY = frame.readUint32LE() + 16;
+ uint32 offsU = frame.readUint32LE() + 16;
+ uint32 offsV = frame.readUint32LE() + 16;
+
+ frame.skip(4);
+
+ uint32 hPos = frame.pos();
+
+ byte *hdr_pos = inData + hPos;
+ byte *buf_pos;
+
+ // Luminance Y
+ frame.seek(offsY);
+ buf_pos = inData + offsY + 4;
+ offs = frame.readUint32LE();
+ decodeChunk(_cur_frame->Ybuf, _ref_frame->Ybuf, fWidth, fHeight,
+ buf_pos + offs * 2, flags2, hdr_pos, buf_pos, MIN<int>(fWidth, 160));
+
+ // Chrominance U
+ frame.seek(offsU);
+ buf_pos = inData + offsU + 4;
+ offs = frame.readUint32LE();
+ decodeChunk(_cur_frame->Vbuf, _ref_frame->Vbuf, chromaWidth, chromaHeight,
+ buf_pos + offs * 2, flags2, hdr_pos, buf_pos, MIN<int>(chromaWidth, 40));
+
+ // Chrominance V
+ frame.seek(offsV);
+ buf_pos = inData + offsV + 4;
+ offs = frame.readUint32LE();
+ decodeChunk(_cur_frame->Ubuf, _ref_frame->Ubuf, chromaWidth, chromaHeight,
+ buf_pos + offs * 2, flags2, hdr_pos, buf_pos, MIN<int>(chromaWidth, 40));
+
+ // Blit the frame onto the surface
+ const byte *srcY = _cur_frame->Ybuf;
+ const byte *srcU = _cur_frame->Ubuf;
+ const byte *srcV = _cur_frame->Vbuf;
+ byte *dest = (byte *)_surface->pixels;
+ for (uint32 y = 0; y < fHeight; y++) {
+ byte *rowDest = dest;
+
+ for (uint32 x = 0; x < fWidth; x++, rowDest += _surface->bytesPerPixel) {
+ const byte cY = srcY[x];
+ const byte cU = srcU[x >> 2];
+ const byte cV = srcV[x >> 2];
+
+ byte r = 0, g = 0, b = 0;
+ YUV2RGB(cY, cU, cV, r, g, b);
+
+ const uint32 color = _pixelFormat.RGBToColor(r, g, b);
+
+ if (_surface->bytesPerPixel == 1)
+ *((uint8 *)rowDest) = (uint8)color;
+ else if (_surface->bytesPerPixel == 2)
+ *((uint16 *)rowDest) = (uint16)color;
+ }
+
+ dest += _surface->pitch;
+ srcY += fWidth;
+
+ if ((y & 3) == 3) {
+ srcU += fWidth >> 2;
+ srcV += fWidth >> 2;
+ }
+ }
+
+ return _surface;
+}
+
+typedef struct {
+ int32 xpos;
+ int32 ypos;
+ int32 width;
+ int32 height;
+ int32 split_flag;
+ int32 split_direction;
+ int32 usl7;
+} ustr_t;
+
+/* ---------------------------------------------------------------------- */
+
+#define LV1_CHECK(buf1,rle_v3,lv1,lp2) \
+ if ((lv1 & 0x80) != 0) { \
+ if (rle_v3 != 0) \
+ rle_v3 = 0; \
+ else { \
+ rle_v3 = 1; \
+ buf1 -= 2; \
+ } \
+ } \
+ lp2 = 4;
+
+
+#define RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3) \
+ if (rle_v3 == 0) { \
+ rle_v2 = *buf1; \
+ rle_v1 = 1; \
+ if (rle_v2 > 32) { \
+ rle_v2 -= 32; \
+ rle_v1 = 0; \
+ } \
+ rle_v3 = 1; \
+ } \
+ buf1--;
+
+
+#define LP2_CHECK(buf1,rle_v3,lp2) \
+ if (lp2 == 0 && rle_v3 != 0) \
+ rle_v3 = 0; \
+ else { \
+ buf1--; \
+ rle_v3 = 1; \
+ }
+
+
+#define RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2) \
+ rle_v2--; \
+ if (rle_v2 == 0) { \
+ rle_v3 = 0; \
+ buf1 += 2; \
+ } \
+ lp2 = 4;
+
+void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
+ const byte *buf1, uint32 fflags2, const byte *hdr,
+ const byte *buf2, int min_width_160) {
+
+ byte bit_buf;
+ uint32 bit_pos, lv, lv1, lv2;
+ int32 *width_tbl, width_tbl_arr[10];
+ const int8 *ref_vectors;
+ byte *cur_frm_pos, *ref_frm_pos, *cp, *cp2;
+ uint32 *cur_lp, *ref_lp;
+ const uint32 *correction_lp[2], *correctionloworder_lp[2], *correctionhighorder_lp[2];
+ uint16 *correction_type_sp[2];
+ ustr_t strip_tbl[20], *strip;
+ int i, j, k, lp1, lp2, flag1, cmd;
+ int blks_width, blks_height, region_160_width;
+ int rle_v1, rle_v2, rle_v3;
+ uint16 res;
+
+ bit_buf = 0;
+ ref_vectors = NULL;
+
+ width_tbl = width_tbl_arr + 1;
+ i = (width < 0 ? width + 3 : width)/4;
+ for (j = -1; j < 8; j++)
+ width_tbl[j] = i * j;
+
+ strip = strip_tbl;
+
+ for (region_160_width = 0; region_160_width < (width - min_width_160); region_160_width += min_width_160)
+ ;
+
+ strip->ypos = strip->xpos = 0;
+ for (strip->width = min_width_160; width > strip->width; strip->width *= 2)
+ ;
+ strip->height = height;
+ strip->split_direction = 0;
+ strip->split_flag = 0;
+ strip->usl7 = 0;
+
+ bit_pos = 0;
+
+ rle_v1 = rle_v2 = rle_v3 = 0;
+
+ while (strip >= strip_tbl) {
+ if (bit_pos <= 0) {
+ bit_pos = 8;
+ bit_buf = *buf1++;
+ }
+
+ bit_pos -= 2;
+ cmd = (bit_buf >> bit_pos) & 0x03;
+
+ if (cmd == 0) {
+ strip++;
+ memcpy(strip, strip-1, sizeof(ustr_t));
+ strip->split_flag = 1;
+ strip->split_direction = 0;
+ strip->height = (strip->height > 8 ? ((strip->height+8)>>4)<<3 : 4);
+ continue;
+ } else if (cmd == 1) {
+ strip++;
+ memcpy(strip, strip-1, sizeof(ustr_t));
+ strip->split_flag = 1;
+ strip->split_direction = 1;
+ strip->width = (strip->width > 8 ? ((strip->width+8)>>4)<<3 : 4);
+ continue;
+ } else if (cmd == 2) {
+ if (strip->usl7 == 0) {
+ strip->usl7 = 1;
+ ref_vectors = NULL;
+ continue;
+ }
+ } else if (cmd == 3) {
+ if (strip->usl7 == 0) {
+ strip->usl7 = 1;
+ ref_vectors = (const signed char*)buf2 + (*buf1 * 2);
+ buf1++;
+ continue;
+ }
+ }
+
+ cur_frm_pos = cur + width * strip->ypos + strip->xpos;
+
+ if ((blks_width = strip->width) < 0)
+ blks_width += 3;
+ blks_width >>= 2;
+ blks_height = strip->height;
+
+ if (ref_vectors != NULL) {
+ ref_frm_pos = ref + (ref_vectors[0] + strip->ypos) * width +
+ ref_vectors[1] + strip->xpos;
+ } else
+ ref_frm_pos = cur_frm_pos - width_tbl[4];
+
+ if (cmd == 2) {
+ if (bit_pos <= 0) {
+ bit_pos = 8;
+ bit_buf = *buf1++;
+ }
+
+ bit_pos -= 2;
+ cmd = (bit_buf >> bit_pos) & 0x03;
+
+ if (cmd == 0 || ref_vectors != NULL) {
+ for (lp1 = 0; lp1 < blks_width; lp1++) {
+ for (i = 0, j = 0; i < blks_height; i++, j += width_tbl[1])
+ ((uint32 *)cur_frm_pos)[j] = ((uint32 *)ref_frm_pos)[j];
+ cur_frm_pos += 4;
+ ref_frm_pos += 4;
+ }
+ } else if (cmd != 1)
+ return;
+ } else {
+ k = *buf1 >> 4;
+ j = *buf1 & 0x0f;
+ buf1++;
+ lv = j + fflags2;
+
+ if ((lv - 8) <= 7 && (k == 0 || k == 3 || k == 10)) {
+ cp2 = _ModPred + ((lv - 8) << 7);
+ cp = ref_frm_pos;
+ for (i = 0; i < blks_width << 2; i++) {
+ int v = *cp >> 1;
+ *(cp++) = cp2[v];
+ }
+ }
+
+ if (k == 1 || k == 4) {
+ lv = (hdr[j] & 0xf) + fflags2;
+ correction_type_sp[0] = _corrector_type + (lv << 8);
+ correction_lp[0] = correction + (lv << 8);
+ lv = (hdr[j] >> 4) + fflags2;
+ correction_lp[1] = correction + (lv << 8);
+ correction_type_sp[1] = _corrector_type + (lv << 8);
+ } else {
+ correctionloworder_lp[0] = correctionloworder_lp[1] = correctionloworder + (lv << 8);
+ correctionhighorder_lp[0] = correctionhighorder_lp[1] = correctionhighorder + (lv << 8);
+ correction_type_sp[0] = correction_type_sp[1] = _corrector_type + (lv << 8);
+ correction_lp[0] = correction_lp[1] = correction + (lv << 8);
+ }
+
+ switch (k) {
+ case 1:
+ case 0: /********** CASE 0 **********/
+ for ( ; blks_height > 0; blks_height -= 4) {
+ for (lp1 = 0; lp1 < blks_width; lp1++) {
+ for (lp2 = 0; lp2 < 4; ) {
+ k = *buf1++;
+ cur_lp = ((uint32 *)cur_frm_pos) + width_tbl[lp2];
+ ref_lp = ((uint32 *)ref_frm_pos) + width_tbl[lp2];
+
+ switch (correction_type_sp[0][k]) {
+ case 0:
+ *cur_lp = FROM_LE_32(((FROM_LE_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ lp2++;
+ break;
+ case 1:
+ res = ((FROM_LE_16(((uint16 *)(ref_lp))[0]) >> 1) + correction_lp[lp2 & 0x01][*buf1]) << 1;
+ ((uint16 *)cur_lp)[0] = FROM_LE_16(res);
+ res = ((FROM_LE_16(((uint16 *)(ref_lp))[1]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
+ ((uint16 *)cur_lp)[1] = FROM_LE_16(res);
+ buf1++;
+ lp2++;
+ break;
+ case 2:
+ if (lp2 == 0) {
+ for (i = 0, j = 0; i < 2; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 += 2;
+ }
+ break;
+ case 3:
+ if (lp2 < 2) {
+ for (i = 0, j = 0; i < (3 - lp2); i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 = 3;
+ }
+ break;
+ case 8:
+ if (lp2 == 0) {
+ RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
+
+ if (rle_v1 == 1 || ref_vectors != NULL) {
+ for (i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ }
+
+ RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
+ break;
+ } else {
+ rle_v1 = 1;
+ rle_v2 = *buf1 - 1;
+ }
+ case 5:
+ LP2_CHECK(buf1,rle_v3,lp2)
+ case 4:
+ for (i = 0, j = 0; i < (4 - lp2); i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 = 4;
+ break;
+
+ case 7:
+ if (rle_v3 != 0)
+ rle_v3 = 0;
+ else {
+ buf1--;
+ rle_v3 = 1;
+ }
+ case 6:
+ if (ref_vectors != NULL) {
+ for (i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ }
+ lp2 = 4;
+ break;
+
+ case 9:
+ lv1 = *buf1++;
+ lv = (lv1 & 0x7F) << 1;
+ lv += (lv << 8);
+ lv += (lv << 16);
+ for (i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = lv;
+
+ LV1_CHECK(buf1,rle_v3,lv1,lp2)
+ break;
+ default:
+ return;
+ }
+ }
+
+ cur_frm_pos += 4;
+ ref_frm_pos += 4;
+ }
+
+ cur_frm_pos += ((width - blks_width) * 4);
+ ref_frm_pos += ((width - blks_width) * 4);
+ }
+ break;
+
+ case 4:
+ case 3: /********** CASE 3 **********/
+ if (ref_vectors != NULL)
+ return;
+ flag1 = 1;
+
+ for ( ; blks_height > 0; blks_height -= 8) {
+ for (lp1 = 0; lp1 < blks_width; lp1++) {
+ for (lp2 = 0; lp2 < 4; ) {
+ k = *buf1++;
+
+ cur_lp = ((uint32 *)cur_frm_pos) + width_tbl[lp2 * 2];
+ ref_lp = ((uint32 *)cur_frm_pos) + width_tbl[(lp2 * 2) - 1];
+
+ switch (correction_type_sp[lp2 & 0x01][k]) {
+ case 0:
+ cur_lp[width_tbl[1]] = FROM_LE_32(((FROM_LE_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ if (lp2 > 0 || flag1 == 0 || strip->ypos != 0)
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ else
+ cur_lp[0] = FROM_LE_32(((FROM_LE_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ lp2++;
+ break;
+
+ case 1:
+ res = ((FROM_LE_16(((uint16 *)ref_lp)[0]) >> 1) + correction_lp[lp2 & 0x01][*buf1]) << 1;
+ ((uint16 *)cur_lp)[width_tbl[2]] = FROM_LE_16(res);
+ res = ((FROM_LE_16(((uint16 *)ref_lp)[1]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
+ ((uint16 *)cur_lp)[width_tbl[2]+1] = FROM_LE_16(res);
+
+ if (lp2 > 0 || flag1 == 0 || strip->ypos != 0)
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ else
+ cur_lp[0] = cur_lp[width_tbl[1]];
+ buf1++;
+ lp2++;
+ break;
+
+ case 2:
+ if (lp2 == 0) {
+ for (i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = *ref_lp;
+ lp2 += 2;
+ }
+ break;
+
+ case 3:
+ if (lp2 < 2) {
+ for (i = 0, j = 0; i < 6 - (lp2 * 2); i++, j += width_tbl[1])
+ cur_lp[j] = *ref_lp;
+ lp2 = 3;
+ }
+ break;
+
+ case 6:
+ lp2 = 4;
+ break;
+
+ case 7:
+ if (rle_v3 != 0)
+ rle_v3 = 0;
+ else {
+ buf1--;
+ rle_v3 = 1;
+ }
+ lp2 = 4;
+ break;
+
+ case 8:
+ if (lp2 == 0) {
+ RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
+
+ if (rle_v1 == 1) {
+ for (i = 0, j = 0; i < 8; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ }
+
+ RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
+ break;
+ } else {
+ rle_v2 = (*buf1) - 1;
+ rle_v1 = 1;
+ }
+ case 5:
+ LP2_CHECK(buf1,rle_v3,lp2)
+ case 4:
+ for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1])
+ cur_lp[j] = *ref_lp;
+ lp2 = 4;
+ break;
+
+ case 9:
+ warning("Indeo3Decoder::decodeChunk: Untested (1)");
+ lv1 = *buf1++;
+ lv = (lv1 & 0x7F) << 1;
+ lv += (lv << 8);
+ lv += (lv << 16);
+
+ for (i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = lv;
+
+ LV1_CHECK(buf1,rle_v3,lv1,lp2)
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ cur_frm_pos += 4;
+ }
+
+ cur_frm_pos += (((width * 2) - blks_width) * 4);
+ flag1 = 0;
+ }
+ break;
+
+ case 10: /********** CASE 10 **********/
+ if (ref_vectors == NULL) {
+ flag1 = 1;
+
+ for ( ; blks_height > 0; blks_height -= 8) {
+ for (lp1 = 0; lp1 < blks_width; lp1 += 2) {
+ for (lp2 = 0; lp2 < 4; ) {
+ k = *buf1++;
+ cur_lp = ((uint32 *)cur_frm_pos) + width_tbl[lp2 * 2];
+ ref_lp = ((uint32 *)cur_frm_pos) + width_tbl[(lp2 * 2) - 1];
+ lv1 = ref_lp[0];
+ lv2 = ref_lp[1];
+ if (lp2 == 0 && flag1 != 0) {
+#if defined(SCUMM_BIG_ENDIAN)
+ lv1 = lv1 & 0xFF00FF00;
+ lv1 = (lv1 >> 8) | lv1;
+ lv2 = lv2 & 0xFF00FF00;
+ lv2 = (lv2 >> 8) | lv2;
+#else
+ lv1 = lv1 & 0x00FF00FF;
+ lv1 = (lv1 << 8) | lv1;
+ lv2 = lv2 & 0x00FF00FF;
+ lv2 = (lv2 << 8) | lv2;
+#endif
+ }
+
+ switch (correction_type_sp[lp2 & 0x01][k]) {
+ case 0:
+ cur_lp[width_tbl[1]] = FROM_LE_32(((FROM_LE_32(lv1) >> 1) + correctionloworder_lp[lp2 & 0x01][k]) << 1);
+ cur_lp[width_tbl[1]+1] = FROM_LE_32(((FROM_LE_32(lv2) >> 1) + correctionhighorder_lp[lp2 & 0x01][k]) << 1);
+ if (lp2 > 0 || strip->ypos != 0 || flag1 == 0) {
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ cur_lp[0] = cur_lp[width_tbl[1]];
+ cur_lp[1] = cur_lp[width_tbl[1]+1];
+ }
+ lp2++;
+ break;
+
+ case 1:
+ cur_lp[width_tbl[1]] = FROM_LE_32(((FROM_LE_32(lv1) >> 1) + correctionloworder_lp[lp2 & 0x01][*buf1]) << 1);
+ cur_lp[width_tbl[1]+1] = FROM_LE_32(((FROM_LE_32(lv2) >> 1) + correctionloworder_lp[lp2 & 0x01][k]) << 1);
+ if (lp2 > 0 || strip->ypos != 0 || flag1 == 0) {
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ cur_lp[0] = cur_lp[width_tbl[1]];
+ cur_lp[1] = cur_lp[width_tbl[1]+1];
+ }
+ buf1++;
+ lp2++;
+ break;
+
+ case 2:
+ if (lp2 == 0) {
+ if (flag1 != 0) {
+ for (i = 0, j = width_tbl[1]; i < 3; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ for (i = 0, j = 0; i < 4; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ }
+ lp2 += 2;
+ }
+ break;
+
+ case 3:
+ if (lp2 < 2) {
+ if (lp2 == 0 && flag1 != 0) {
+ for (i = 0, j = width_tbl[1]; i < 5; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ for (i = 0, j = 0; i < 6 - (lp2 * 2); i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ }
+ lp2 = 3;
+ }
+ break;
+
+ case 8:
+ if (lp2 == 0) {
+ RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
+ if (rle_v1 == 1) {
+ if (flag1 != 0) {
+ for (i = 0, j = width_tbl[1]; i < 7; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ for (i = 0, j = 0; i < 8; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ }
+ }
+ RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
+ break;
+ } else {
+ rle_v1 = 1;
+ rle_v2 = (*buf1) - 1;
+ }
+ case 5:
+ LP2_CHECK(buf1,rle_v3,lp2)
+ case 4:
+ if (lp2 == 0 && flag1 != 0) {
+ for (i = 0, j = width_tbl[1]; i < 7; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ }
+ lp2 = 4;
+ break;
+
+ case 6:
+ lp2 = 4;
+ break;
+
+ case 7:
+ if (lp2 == 0) {
+ if (rle_v3 != 0)
+ rle_v3 = 0;
+ else {
+ buf1--;
+ rle_v3 = 1;
+ }
+ lp2 = 4;
+ }
+ break;
+
+ case 9:
+ warning("Indeo3Decoder::decodeChunk: Untested (2)");
+ lv1 = *buf1;
+ lv = (lv1 & 0x7F) << 1;
+ lv += (lv << 8);
+ lv += (lv << 16);
+ for (i = 0, j = 0; i < 8; i++, j += width_tbl[1])
+ cur_lp[j] = lv;
+ LV1_CHECK(buf1,rle_v3,lv1,lp2)
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ cur_frm_pos += 8;
+ }
+
+ cur_frm_pos += (((width * 2) - blks_width) * 4);
+ flag1 = 0;
+ }
+ } else {
+ for ( ; blks_height > 0; blks_height -= 8) {
+ for (lp1 = 0; lp1 < blks_width; lp1 += 2) {
+ for (lp2 = 0; lp2 < 4; ) {
+ k = *buf1++;
+ cur_lp = ((uint32 *)cur_frm_pos) + width_tbl[lp2 * 2];
+ ref_lp = ((uint32 *)ref_frm_pos) + width_tbl[lp2 * 2];
+
+ switch (correction_type_sp[lp2 & 0x01][k]) {
+ case 0:
+ lv1 = correctionloworder_lp[lp2 & 0x01][k];
+ lv2 = correctionhighorder_lp[lp2 & 0x01][k];
+ cur_lp[0] = FROM_LE_32(((FROM_LE_32(ref_lp[0]) >> 1) + lv1) << 1);
+ cur_lp[1] = FROM_LE_32(((FROM_LE_32(ref_lp[1]) >> 1) + lv2) << 1);
+ cur_lp[width_tbl[1]] = FROM_LE_32(((FROM_LE_32(ref_lp[width_tbl[1]]) >> 1) + lv1) << 1);
+ cur_lp[width_tbl[1]+1] = FROM_LE_32(((FROM_LE_32(ref_lp[width_tbl[1]+1]) >> 1) + lv2) << 1);
+ lp2++;
+ break;
+
+ case 1:
+ lv1 = correctionloworder_lp[lp2 & 0x01][*buf1++];
+ lv2 = correctionloworder_lp[lp2 & 0x01][k];
+ cur_lp[0] = FROM_LE_32(((FROM_LE_32(ref_lp[0]) >> 1) + lv1) << 1);
+ cur_lp[1] = FROM_LE_32(((FROM_LE_32(ref_lp[1]) >> 1) + lv2) << 1);
+ cur_lp[width_tbl[1]] = FROM_LE_32(((FROM_LE_32(ref_lp[width_tbl[1]]) >> 1) + lv1) << 1);
+ cur_lp[width_tbl[1]+1] = FROM_LE_32(((FROM_LE_32(ref_lp[width_tbl[1]+1]) >> 1) + lv2) << 1);
+ lp2++;
+ break;
+
+ case 2:
+ if (lp2 == 0) {
+ for (i = 0, j = 0; i < 4; i++, j += width_tbl[1]) {
+ cur_lp[j] = ref_lp[j];
+ cur_lp[j+1] = ref_lp[j+1];
+ }
+ lp2 += 2;
+ }
+ break;
+
+ case 3:
+ if (lp2 < 2) {
+ for (i = 0, j = 0; i < 6 - (lp2 * 2); i++, j += width_tbl[1]) {
+ cur_lp[j] = ref_lp[j];
+ cur_lp[j+1] = ref_lp[j+1];
+ }
+ lp2 = 3;
+ }
+ break;
+
+ case 8:
+ if (lp2 == 0) {
+ RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
+ for (i = 0, j = 0; i < 8; i++, j += width_tbl[1]) {
+ ((uint32 *)cur_frm_pos)[j] = ((uint32 *)ref_frm_pos)[j];
+ ((uint32 *)cur_frm_pos)[j+1] = ((uint32 *)ref_frm_pos)[j+1];
+ }
+ RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
+ break;
+ } else {
+ rle_v1 = 1;
+ rle_v2 = (*buf1) - 1;
+ }
+ case 5:
+ case 7:
+ LP2_CHECK(buf1,rle_v3,lp2)
+ case 6:
+ case 4:
+ for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1]) {
+ cur_lp[j] = ref_lp[j];
+ cur_lp[j+1] = ref_lp[j+1];
+ }
+ lp2 = 4;
+ break;
+
+ case 9:
+ warning("Indeo3Decoder::decodeChunk: Untested (3)");
+ lv1 = *buf1;
+ lv = (lv1 & 0x7F) << 1;
+ lv += (lv << 8);
+ lv += (lv << 16);
+ for (i = 0, j = 0; i < 8; i++, j += width_tbl[1])
+ ((uint32 *)cur_frm_pos)[j] = ((uint32 *)cur_frm_pos)[j+1] = lv;
+ LV1_CHECK(buf1,rle_v3,lv1,lp2)
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ cur_frm_pos += 8;
+ ref_frm_pos += 8;
+ }
+
+ cur_frm_pos += (((width * 2) - blks_width) * 4);
+ ref_frm_pos += (((width * 2) - blks_width) * 4);
+ }
+ }
+ break;
+
+ case 11: /********** CASE 11 **********/
+ if (ref_vectors == NULL)
+ return;
+
+ for ( ; blks_height > 0; blks_height -= 8) {
+ for (lp1 = 0; lp1 < blks_width; lp1++) {
+ for (lp2 = 0; lp2 < 4; ) {
+ k = *buf1++;
+ cur_lp = ((uint32 *)cur_frm_pos) + width_tbl[lp2 * 2];
+ ref_lp = ((uint32 *)ref_frm_pos) + width_tbl[lp2 * 2];
+
+ switch (correction_type_sp[lp2 & 0x01][k]) {
+ case 0:
+ cur_lp[0] = FROM_LE_32(((FROM_LE_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ cur_lp[width_tbl[1]] = FROM_LE_32(((FROM_LE_32(ref_lp[width_tbl[1]]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ lp2++;
+ break;
+
+ case 1:
+ lv1 = (uint16)(correction_lp[lp2 & 0x01][*buf1++]);
+ lv2 = (uint16)(correction_lp[lp2 & 0x01][k]);
+ res = (uint16)(((FROM_LE_16(((uint16 *)ref_lp)[0]) >> 1) + lv1) << 1);
+ ((uint16 *)cur_lp)[0] = FROM_LE_16(res);
+ res = (uint16)(((FROM_LE_16(((uint16 *)ref_lp)[1]) >> 1) + lv2) << 1);
+ ((uint16 *)cur_lp)[1] = FROM_LE_16(res);
+ res = (uint16)(((FROM_LE_16(((uint16 *)ref_lp)[width_tbl[2]]) >> 1) + lv1) << 1);
+ ((uint16 *)cur_lp)[width_tbl[2]] = FROM_LE_16(res);
+ res = (uint16)(((FROM_LE_16(((uint16 *)ref_lp)[width_tbl[2]+1]) >> 1) + lv2) << 1);
+ ((uint16 *)cur_lp)[width_tbl[2]+1] = FROM_LE_16(res);
+ lp2++;
+ break;
+
+ case 2:
+ if (lp2 == 0) {
+ for (i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 += 2;
+ }
+ break;
+
+ case 3:
+ if (lp2 < 2) {
+ for (i = 0, j = 0; i < 6 - (lp2 * 2); i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 = 3;
+ }
+ break;
+
+ case 8:
+ if (lp2 == 0) {
+ RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
+
+ for (i = 0, j = 0; i < 8; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+
+ RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
+ break;
+ } else {
+ rle_v1 = 1;
+ rle_v2 = (*buf1) - 1;
+ }
+ case 5:
+ case 7:
+ LP2_CHECK(buf1,rle_v3,lp2)
+ case 4:
+ case 6:
+ for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 = 4;
+ break;
+
+ case 9:
+ warning("Indeo3Decoder::decodeChunk: Untested (4)");
+ lv1 = *buf1++;
+ lv = (lv1 & 0x7F) << 1;
+ lv += (lv << 8);
+ lv += (lv << 16);
+ for (i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = lv;
+ LV1_CHECK(buf1,rle_v3,lv1,lp2)
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ cur_frm_pos += 4;
+ ref_frm_pos += 4;
+ }
+
+ cur_frm_pos += (((width * 2) - blks_width) * 4);
+ ref_frm_pos += (((width * 2) - blks_width) * 4);
+ }
+ break;
+
+ default:
+ // FIXME: I've seen case 13 happen in Urban
+ // Runner. Perhaps it uses a more recent form of
+ // Indeo 3? There appears to have been several.
+ warning("Indeo3Decoder::decodeChunk: Unknown case %d", k);
+ return;
+ }
+ }
+
+ if (strip < strip_tbl)
+ return;
+
+ for ( ; strip >= strip_tbl; strip--) {
+ if (strip->split_flag != 0) {
+ strip->split_flag = 0;
+ strip->usl7 = (strip-1)->usl7;
+
+ if (strip->split_direction) {
+ strip->xpos += strip->width;
+ strip->width = (strip-1)->width - strip->width;
+ if (region_160_width <= strip->xpos && width < strip->width + strip->xpos)
+ strip->width = width - strip->xpos;
+ } else {
+ strip->ypos += strip->height;
+ strip->height = (strip-1)->height - strip->height;
+ }
+ break;
+ }
+ }
+ }
+}
+
+// static data
+
+const int Indeo3Decoder::_corrector_type_0[24] = {
+ 195, 159, 133, 115, 101, 93, 87, 77,
+ 195, 159, 133, 115, 101, 93, 87, 77,
+ 128, 79, 79, 79, 79, 79, 79, 79
+};
+
+const int Indeo3Decoder::_corrector_type_2[8] = { 9, 7, 6, 8, 5, 4, 3, 2 };
+
+const uint32 Indeo3Decoder::correction[] = {
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x000002ff, 0xfffffd01, 0xffffff03, 0x000000fd, 0x00000404,
+ 0xfffffbfc, 0x00000501, 0xfffffaff, 0x00000105, 0xfffffefb, 0x000003fc, 0xfffffc04, 0x000005fe,
+ 0xfffffa02, 0xfffffe06, 0x000001fa, 0x00000904, 0xfffff6fc, 0x00000409, 0xfffffbf7, 0x00000909,
+ 0xfffff6f7, 0x00000a01, 0xfffff5ff, 0x0000010a, 0xfffffef6, 0x000007fb, 0xfffff805, 0xfffffb08,
+ 0x000004f8, 0x00000f09, 0xfffff0f7, 0x0000090f, 0xfffff6f1, 0x00000bfd, 0xfffff403, 0xfffffd0c,
+ 0x000002f4, 0x00001004, 0xffffeffc, 0x00000410, 0xfffffbf0, 0x00001010, 0xffffeff0, 0x00001200,
+ 0xffffee00, 0x00000012, 0xffffffee, 0x00000bf4, 0xfffff40c, 0x00000ff7, 0xfffff009, 0xfffff710,
+ 0x000008f0, 0x00001b0b, 0xffffe4f5, 0x00000b1b, 0xfffff4e5, 0x00001c13, 0xffffe3ed, 0x0000131c,
+ 0xffffece4, 0x000015fa, 0xffffea06, 0xfffffa16, 0x000005ea, 0x00001d04, 0xffffe2fc, 0x0000041d,
+ 0xfffffbe3, 0x00001e1e, 0xffffe1e2, 0x000020fe, 0xffffdf02, 0xfffffe21, 0x000001df, 0x000016ee,
+ 0xffffe912, 0xffffee17, 0x000011e9, 0x00001df1, 0xffffe20f, 0xfffff11e, 0x00000ee2, 0x00002e16,
+ 0xffffd1ea, 0x0000162e, 0xffffe9d2, 0x00002f0d, 0xffffd0f3, 0x00000d2f, 0xfffff2d1, 0x00003123,
+ 0xffffcedd, 0x00002331, 0xffffdccf, 0x000028f5, 0xffffd70b, 0xfffff529, 0x00000ad7, 0x00003304,
+ 0xffffccfc, 0x00000433, 0xfffffbcd, 0x00003636, 0xffffc9ca, 0x000021de, 0xffffde22, 0x000029e3,
+ 0xffffd61d, 0xffffe32a, 0x00001cd6, 0x00003bfa, 0xffffc406, 0xfffffa3c, 0x000005c4, 0x00004c1b,
+ 0xffffb3e5, 0x00001b4c, 0xffffe4b4, 0x00004d2b, 0xffffb2d5, 0x00002b4d, 0xffffd4b3, 0x000036e8,
+ 0xffffc918, 0xffffe837, 0x000017c9, 0x00004f0e, 0xffffb0f2, 0x00000e4f, 0xfffff1b1, 0x0000533f,
+ 0xffffacc1, 0x00003f53, 0xffffc0ad, 0x000049ec, 0xffffb614, 0xffffec4a, 0x000013b6, 0x00005802,
+ 0xffffa7fe, 0x00000258, 0xfffffda8, 0x00005d5d, 0xffffa2a3, 0x00003ccc, 0xffffc334, 0xffffcc3d,
+ 0x000033c3, 0x00007834, 0xffff87cc, 0x00003478, 0xffffcb88, 0x00004ad3, 0xffffb52d, 0xffffd34b,
+ 0x00002cb5, 0x00007d4b, 0xffff82b5, 0x00004b7d, 0xffffb483, 0x00007a21, 0xffff85df, 0x0000217a,
+ 0xffffde86, 0x000066f3, 0xffff990d, 0xfffff367, 0x00000c99, 0x00005fd8, 0xffffa028, 0xffffd860,
+ 0x000027a0, 0x00007ede, 0xffff8122, 0xffffde7f, 0x00002181, 0x000058a7, 0xffffa759, 0x000068b2,
+ 0xffff974e, 0xffffb269, 0x00004d97, 0x00000c0c, 0xfffff3f4, 0x00001717, 0xffffe8e9, 0x00002a2a,
+ 0xffffd5d6, 0x00004949, 0xffffb6b7, 0x00000000, 0x02020000, 0xfdfe0000, 0x02ff0000, 0xfd010000,
+ 0xff030000, 0x00fd0000, 0x00000202, 0x02020202, 0xfdfe0202, 0x02ff0202, 0xfd010202, 0xff030202,
+ 0x00fd0202, 0xfffffdfe, 0x0201fdfe, 0xfdfdfdfe, 0x02fefdfe, 0xfd00fdfe, 0xff02fdfe, 0x00fcfdfe,
+ 0x000002ff, 0x020202ff, 0xfdfe02ff, 0x02ff02ff, 0xfd0102ff, 0xff0302ff, 0x00fd02ff, 0xfffffd01,
+ 0x0201fd01, 0xfdfdfd01, 0x02fefd01, 0xfd00fd01, 0xff02fd01, 0x00fcfd01, 0xffffff03, 0x0201ff03,
+ 0xfdfdff03, 0x02feff03, 0xfd00ff03, 0xff02ff03, 0x00fcff03, 0x000000fd, 0x020200fd, 0xfdfe00fd,
+ 0x02ff00fd, 0xfd0100fd, 0xff0300fd, 0x00fd00fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000303, 0xfffffcfd, 0x000003ff, 0xfffffc01, 0xffffff04, 0x000000fc, 0x00000707,
+ 0xfffff8f9, 0x00000802, 0xfffff7fe, 0x00000208, 0xfffffdf8, 0x000008fe, 0xfffff702, 0xfffffe09,
+ 0x000001f7, 0x000005fa, 0xfffffa06, 0x00000d06, 0xfffff2fa, 0x0000060d, 0xfffff9f3, 0x00000d0d,
+ 0xfffff2f3, 0x00000e01, 0xfffff1ff, 0x0000010e, 0xfffffef2, 0x00000bf8, 0xfffff408, 0xfffff80c,
+ 0x000007f4, 0x0000170e, 0xffffe8f2, 0x00000e17, 0xfffff1e9, 0x000011fb, 0xffffee05, 0xfffffb12,
+ 0x000004ee, 0x00001806, 0xffffe7fa, 0x00000618, 0xfffff9e8, 0x00001818, 0xffffe7e8, 0x00001aff,
+ 0xffffe501, 0xffffff1b, 0x000000e5, 0x000010ef, 0xffffef11, 0x000016f3, 0xffffe90d, 0xfffff317,
+ 0x00000ce9, 0x00002810, 0xffffd7f0, 0x00001028, 0xffffefd8, 0x0000291c, 0xffffd6e4, 0x00001c29,
+ 0xffffe3d7, 0x000020f7, 0xffffdf09, 0xfffff721, 0x000008df, 0x00002b06, 0xffffd4fa, 0x0000062b,
+ 0xfffff9d5, 0x00002e2e, 0xffffd1d2, 0x000031fc, 0xffffce04, 0xfffffc32, 0x000003ce, 0x000021e5,
+ 0xffffde1b, 0xffffe522, 0x00001ade, 0x00002cea, 0xffffd316, 0xffffea2d, 0x000015d3, 0x00004522,
+ 0xffffbade, 0x00002245, 0xffffddbb, 0x00004613, 0xffffb9ed, 0x00001346, 0xffffecba, 0x00004935,
+ 0xffffb6cb, 0x00003549, 0xffffcab7, 0x00003def, 0xffffc211, 0xffffef3e, 0x000010c2, 0x00004d05,
+ 0xffffb2fb, 0x0000054d, 0xfffffab3, 0x00005252, 0xffffadae, 0x000032cd, 0xffffcd33, 0x00003fd5,
+ 0xffffc02b, 0xffffd540, 0x00002ac0, 0x000059f6, 0xffffa60a, 0xfffff65a, 0x000009a6, 0x00007229,
+ 0xffff8dd7, 0x00002972, 0xffffd68e, 0x00007440, 0xffff8bc0, 0x00004074, 0xffffbf8c, 0x000051db,
+ 0xffffae25, 0xffffdb52, 0x000024ae, 0x00007716, 0xffff88ea, 0x00001677, 0xffffe989, 0x00007c5f,
+ 0xffff83a1, 0x00005f7c, 0xffffa084, 0x00006ee2, 0xffff911e, 0xffffe26f, 0x00001d91, 0x00005bb2,
+ 0xffffa44e, 0xffffb25c, 0x00004da4, 0x000070bc, 0xffff8f44, 0xffffbc71, 0x0000438f, 0x00001212,
+ 0xffffedee, 0x00002222, 0xffffddde, 0x00003f3f, 0xffffc0c1, 0x00006d6d, 0xffff9293, 0x00000000,
+ 0x03030000, 0xfcfd0000, 0x03ff0000, 0xfc010000, 0xff040000, 0x00fc0000, 0x07070000, 0xf8f90000,
+ 0x00000303, 0x03030303, 0xfcfd0303, 0x03ff0303, 0xfc010303, 0xff040303, 0x00fc0303, 0x07070303,
+ 0xf8f90303, 0xfffffcfd, 0x0302fcfd, 0xfcfcfcfd, 0x03fefcfd, 0xfc00fcfd, 0xff03fcfd, 0x00fbfcfd,
+ 0x0706fcfd, 0xf8f8fcfd, 0x000003ff, 0x030303ff, 0xfcfd03ff, 0x03ff03ff, 0xfc0103ff, 0xff0403ff,
+ 0x00fc03ff, 0x070703ff, 0xf8f903ff, 0xfffffc01, 0x0302fc01, 0xfcfcfc01, 0x03fefc01, 0xfc00fc01,
+ 0xff03fc01, 0x00fbfc01, 0x0706fc01, 0xf8f8fc01, 0xffffff04, 0x0302ff04, 0xfcfcff04, 0x03feff04,
+ 0xfc00ff04, 0xff03ff04, 0x00fbff04, 0x0706ff04, 0xf8f8ff04, 0x000000fc, 0x030300fc, 0xfcfd00fc,
+ 0x03ff00fc, 0xfc0100fc, 0xff0400fc, 0x00fc00fc, 0x070700fc, 0xf8f900fc, 0x00000707, 0x03030707,
+ 0xfcfd0707, 0x03ff0707, 0xfc010707, 0xff040707, 0x00fc0707, 0x07070707, 0xf8f90707, 0xfffff8f9,
+ 0x0302f8f9, 0xfcfcf8f9, 0x03fef8f9, 0xfc00f8f9, 0xff03f8f9, 0x00fbf8f9, 0x0706f8f9, 0xf8f8f8f9,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000404, 0xfffffbfc, 0x000004ff, 0xfffffb01, 0xffffff05, 0x000000fb, 0x00000a03,
+ 0xfffff5fd, 0x0000030a, 0xfffffcf6, 0x00000909, 0xfffff6f7, 0x000006f9, 0xfffff907, 0x00000bfd,
+ 0xfffff403, 0xfffffd0c, 0x000002f4, 0x00001108, 0xffffeef8, 0x00000811, 0xfffff7ef, 0x00001111,
+ 0xffffeeef, 0x00001301, 0xffffecff, 0x00000113, 0xfffffeed, 0x00000ff5, 0xfffff00b, 0xfffff510,
+ 0x00000af0, 0x000016fa, 0xffffe906, 0xfffffa17, 0x000005e9, 0x00001f12, 0xffffe0ee, 0x0000121f,
+ 0xffffede1, 0x00002008, 0xffffdff8, 0x00000820, 0xfffff7e0, 0x00002121, 0xffffdedf, 0x000023ff,
+ 0xffffdc01, 0xffffff24, 0x000000dc, 0x000016e9, 0xffffe917, 0x00001eef, 0xffffe111, 0xffffef1f,
+ 0x000010e1, 0x00003615, 0xffffc9eb, 0x00001536, 0xffffeaca, 0x00003725, 0xffffc8db, 0x00002537,
+ 0xffffdac9, 0x00002bf4, 0xffffd40c, 0xfffff42c, 0x00000bd4, 0x00003908, 0xffffc6f8, 0x00000839,
+ 0xfffff7c7, 0x00003d3d, 0xffffc2c3, 0x000041fb, 0xffffbe05, 0xfffffb42, 0x000004be, 0x00002cdc,
+ 0xffffd324, 0xffffdc2d, 0x000023d3, 0x00003be3, 0xffffc41d, 0xffffe33c, 0x00001cc4, 0x00005c2d,
+ 0xffffa3d3, 0x00002d5c, 0xffffd2a4, 0x00005d19, 0xffffa2e7, 0x0000195d, 0xffffe6a3, 0x00006147,
+ 0xffff9eb9, 0x00004761, 0xffffb89f, 0x000052ea, 0xffffad16, 0xffffea53, 0x000015ad, 0x00006607,
+ 0xffff99f9, 0x00000766, 0xfffff89a, 0x00006d6d, 0xffff9293, 0x000043bc, 0xffffbc44, 0x000054c7,
+ 0xffffab39, 0xffffc755, 0x000038ab, 0x000077f3, 0xffff880d, 0xfffff378, 0x00000c88, 0x00006dcf,
+ 0xffff9231, 0xffffcf6e, 0x00003092, 0x00007a98, 0xffff8568, 0xffff987b, 0x00006785, 0x00001818,
+ 0xffffe7e8, 0x00002e2e, 0xffffd1d2, 0x00005454, 0xffffabac, 0x00000000, 0x04040000, 0xfbfc0000,
+ 0x04ff0000, 0xfb010000, 0xff050000, 0x00fb0000, 0x0a030000, 0xf5fd0000, 0x030a0000, 0x00000404,
+ 0x04040404, 0xfbfc0404, 0x04ff0404, 0xfb010404, 0xff050404, 0x00fb0404, 0x0a030404, 0xf5fd0404,
+ 0x030a0404, 0xfffffbfc, 0x0403fbfc, 0xfbfbfbfc, 0x04fefbfc, 0xfb00fbfc, 0xff04fbfc, 0x00fafbfc,
+ 0x0a02fbfc, 0xf5fcfbfc, 0x0309fbfc, 0x000004ff, 0x040404ff, 0xfbfc04ff, 0x04ff04ff, 0xfb0104ff,
+ 0xff0504ff, 0x00fb04ff, 0x0a0304ff, 0xf5fd04ff, 0x030a04ff, 0xfffffb01, 0x0403fb01, 0xfbfbfb01,
+ 0x04fefb01, 0xfb00fb01, 0xff04fb01, 0x00fafb01, 0x0a02fb01, 0xf5fcfb01, 0x0309fb01, 0xffffff05,
+ 0x0403ff05, 0xfbfbff05, 0x04feff05, 0xfb00ff05, 0xff04ff05, 0x00faff05, 0x0a02ff05, 0xf5fcff05,
+ 0x0309ff05, 0x000000fb, 0x040400fb, 0xfbfc00fb, 0x04ff00fb, 0xfb0100fb, 0xff0500fb, 0x00fb00fb,
+ 0x0a0300fb, 0xf5fd00fb, 0x030a00fb, 0x00000a03, 0x04040a03, 0xfbfc0a03, 0x04ff0a03, 0xfb010a03,
+ 0xff050a03, 0x00fb0a03, 0x0a030a03, 0xf5fd0a03, 0x030a0a03, 0xfffff5fd, 0x0403f5fd, 0xfbfbf5fd,
+ 0x04fef5fd, 0xfb00f5fd, 0xff04f5fd, 0x00faf5fd, 0x0a02f5fd, 0xf5fcf5fd, 0x0309f5fd, 0x0000030a,
+ 0x0404030a, 0xfbfc030a, 0x04ff030a, 0xfb01030a, 0xff05030a, 0x00fb030a, 0x0a03030a, 0xf5fd030a,
+ 0x030a030a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000505, 0xfffffafb, 0x000006fe, 0xfffff902, 0xfffffe07, 0x000001f9, 0x00000b0b,
+ 0xfffff4f5, 0x00000d03, 0xfffff2fd, 0x0000030d, 0xfffffcf3, 0x000008f7, 0xfffff709, 0x00000efc,
+ 0xfffff104, 0xfffffc0f, 0x000003f1, 0x0000160b, 0xffffe9f5, 0x00000b16, 0xfffff4ea, 0x00001515,
+ 0xffffeaeb, 0x00001802, 0xffffe7fe, 0x00000218, 0xfffffde8, 0x000013f2, 0xffffec0e, 0xfffff214,
+ 0x00000dec, 0x00002617, 0xffffd9e9, 0x00001726, 0xffffe8da, 0x00001cf8, 0xffffe308, 0xfffff81d,
+ 0x000007e3, 0x0000270b, 0xffffd8f5, 0x00000b27, 0xfffff4d9, 0x00002929, 0xffffd6d7, 0x00002cff,
+ 0xffffd301, 0xffffff2d, 0x000000d3, 0x00001ce3, 0xffffe31d, 0x000026ea, 0xffffd916, 0xffffea27,
+ 0x000015d9, 0x0000431b, 0xffffbce5, 0x00001b43, 0xffffe4bd, 0x0000452f, 0xffffbad1, 0x00002f45,
+ 0xffffd0bb, 0x000037f1, 0xffffc80f, 0xfffff138, 0x00000ec8, 0x0000470b, 0xffffb8f5, 0x00000b47,
+ 0xfffff4b9, 0x00004c4c, 0xffffb3b4, 0x000052fa, 0xffffad06, 0xfffffa53, 0x000005ad, 0x000038d3,
+ 0xffffc72d, 0xffffd339, 0x00002cc7, 0x00004adc, 0xffffb524, 0xffffdc4b, 0x000023b5, 0x00007338,
+ 0xffff8cc8, 0x00003873, 0xffffc78d, 0x0000751f, 0xffff8ae1, 0x00001f75, 0xffffe08b, 0x00007a58,
+ 0xffff85a8, 0x0000587a, 0xffffa786, 0x000067e4, 0xffff981c, 0xffffe468, 0x00001b98, 0x000054ab,
+ 0xffffab55, 0x000069b8, 0xffff9648, 0xffffb86a, 0x00004796, 0x00001e1e, 0xffffe1e2, 0x00003a3a,
+ 0xffffc5c6, 0x00006969, 0xffff9697, 0x00000000, 0x05050000, 0xfafb0000, 0x06fe0000, 0xf9020000,
+ 0xfe070000, 0x01f90000, 0x0b0b0000, 0xf4f50000, 0x0d030000, 0xf2fd0000, 0x00000505, 0x05050505,
+ 0xfafb0505, 0x06fe0505, 0xf9020505, 0xfe070505, 0x01f90505, 0x0b0b0505, 0xf4f50505, 0x0d030505,
+ 0xf2fd0505, 0xfffffafb, 0x0504fafb, 0xfafafafb, 0x06fdfafb, 0xf901fafb, 0xfe06fafb, 0x01f8fafb,
+ 0x0b0afafb, 0xf4f4fafb, 0x0d02fafb, 0xf2fcfafb, 0x000006fe, 0x050506fe, 0xfafb06fe, 0x06fe06fe,
+ 0xf90206fe, 0xfe0706fe, 0x01f906fe, 0x0b0b06fe, 0xf4f506fe, 0x0d0306fe, 0xf2fd06fe, 0xfffff902,
+ 0x0504f902, 0xfafaf902, 0x06fdf902, 0xf901f902, 0xfe06f902, 0x01f8f902, 0x0b0af902, 0xf4f4f902,
+ 0x0d02f902, 0xf2fcf902, 0xfffffe07, 0x0504fe07, 0xfafafe07, 0x06fdfe07, 0xf901fe07, 0xfe06fe07,
+ 0x01f8fe07, 0x0b0afe07, 0xf4f4fe07, 0x0d02fe07, 0xf2fcfe07, 0x000001f9, 0x050501f9, 0xfafb01f9,
+ 0x06fe01f9, 0xf90201f9, 0xfe0701f9, 0x01f901f9, 0x0b0b01f9, 0xf4f501f9, 0x0d0301f9, 0xf2fd01f9,
+ 0x00000b0b, 0x05050b0b, 0xfafb0b0b, 0x06fe0b0b, 0xf9020b0b, 0xfe070b0b, 0x01f90b0b, 0x0b0b0b0b,
+ 0xf4f50b0b, 0x0d030b0b, 0xf2fd0b0b, 0xfffff4f5, 0x0504f4f5, 0xfafaf4f5, 0x06fdf4f5, 0xf901f4f5,
+ 0xfe06f4f5, 0x01f8f4f5, 0x0b0af4f5, 0xf4f4f4f5, 0x0d02f4f5, 0xf2fcf4f5, 0x00000d03, 0x05050d03,
+ 0xfafb0d03, 0x06fe0d03, 0xf9020d03, 0xfe070d03, 0x01f90d03, 0x0b0b0d03, 0xf4f50d03, 0x0d030d03,
+ 0xf2fd0d03, 0xfffff2fd, 0x0504f2fd, 0xfafaf2fd, 0x06fdf2fd, 0xf901f2fd, 0xfe06f2fd, 0x01f8f2fd,
+ 0x0b0af2fd, 0xf4f4f2fd, 0x0d02f2fd, 0xf2fcf2fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000606, 0xfffff9fa, 0x000007fe, 0xfffff802, 0xfffffe08, 0x000001f8, 0x00000d0d,
+ 0xfffff2f3, 0x00000f04, 0xfffff0fc, 0x0000040f, 0xfffffbf1, 0x00000af5, 0xfffff50b, 0x000011fb,
+ 0xffffee05, 0xfffffb12, 0x000004ee, 0x00001a0d, 0xffffe5f3, 0x00000d1a, 0xfffff2e6, 0x00001a1a,
+ 0xffffe5e6, 0x00001d02, 0xffffe2fe, 0x0000021d, 0xfffffde3, 0x000017f0, 0xffffe810, 0xfffff018,
+ 0x00000fe8, 0x00002e1c, 0xffffd1e4, 0x00001c2e, 0xffffe3d2, 0x000022f7, 0xffffdd09, 0xfffff723,
+ 0x000008dd, 0x00002f0d, 0xffffd0f3, 0x00000d2f, 0xfffff2d1, 0x00003131, 0xffffcecf, 0x000035ff,
+ 0xffffca01, 0xffffff36, 0x000000ca, 0x000022dd, 0xffffdd23, 0x00002ee6, 0xffffd11a, 0xffffe62f,
+ 0x000019d1, 0x00005120, 0xffffaee0, 0x00002051, 0xffffdfaf, 0x00005338, 0xffffacc8, 0x00003853,
+ 0xffffc7ad, 0x000042ee, 0xffffbd12, 0xffffee43, 0x000011bd, 0x0000560d, 0xffffa9f3, 0x00000d56,
+ 0xfffff2aa, 0x00005b5b, 0xffffa4a5, 0x000062f9, 0xffff9d07, 0xfffff963, 0x0000069d, 0x000043ca,
+ 0xffffbc36, 0xffffca44, 0x000035bc, 0x000059d4, 0xffffa62c, 0xffffd45a, 0x00002ba6, 0x00007bdf,
+ 0xffff8421, 0xffffdf7c, 0x00002084, 0x00006699, 0xffff9967, 0x00007eaa, 0xffff8156, 0xffffaa7f,
+ 0x00005581, 0x00002525, 0xffffdadb, 0x00004545, 0xffffbabb, 0x00000000, 0x06060000, 0xf9fa0000,
+ 0x07fe0000, 0xf8020000, 0xfe080000, 0x01f80000, 0x0d0d0000, 0xf2f30000, 0x0f040000, 0xf0fc0000,
+ 0x040f0000, 0x00000606, 0x06060606, 0xf9fa0606, 0x07fe0606, 0xf8020606, 0xfe080606, 0x01f80606,
+ 0x0d0d0606, 0xf2f30606, 0x0f040606, 0xf0fc0606, 0x040f0606, 0xfffff9fa, 0x0605f9fa, 0xf9f9f9fa,
+ 0x07fdf9fa, 0xf801f9fa, 0xfe07f9fa, 0x01f7f9fa, 0x0d0cf9fa, 0xf2f2f9fa, 0x0f03f9fa, 0xf0fbf9fa,
+ 0x040ef9fa, 0x000007fe, 0x060607fe, 0xf9fa07fe, 0x07fe07fe, 0xf80207fe, 0xfe0807fe, 0x01f807fe,
+ 0x0d0d07fe, 0xf2f307fe, 0x0f0407fe, 0xf0fc07fe, 0x040f07fe, 0xfffff802, 0x0605f802, 0xf9f9f802,
+ 0x07fdf802, 0xf801f802, 0xfe07f802, 0x01f7f802, 0x0d0cf802, 0xf2f2f802, 0x0f03f802, 0xf0fbf802,
+ 0x040ef802, 0xfffffe08, 0x0605fe08, 0xf9f9fe08, 0x07fdfe08, 0xf801fe08, 0xfe07fe08, 0x01f7fe08,
+ 0x0d0cfe08, 0xf2f2fe08, 0x0f03fe08, 0xf0fbfe08, 0x040efe08, 0x000001f8, 0x060601f8, 0xf9fa01f8,
+ 0x07fe01f8, 0xf80201f8, 0xfe0801f8, 0x01f801f8, 0x0d0d01f8, 0xf2f301f8, 0x0f0401f8, 0xf0fc01f8,
+ 0x040f01f8, 0x00000d0d, 0x06060d0d, 0xf9fa0d0d, 0x07fe0d0d, 0xf8020d0d, 0xfe080d0d, 0x01f80d0d,
+ 0x0d0d0d0d, 0xf2f30d0d, 0x0f040d0d, 0xf0fc0d0d, 0x040f0d0d, 0xfffff2f3, 0x0605f2f3, 0xf9f9f2f3,
+ 0x07fdf2f3, 0xf801f2f3, 0xfe07f2f3, 0x01f7f2f3, 0x0d0cf2f3, 0xf2f2f2f3, 0x0f03f2f3, 0xf0fbf2f3,
+ 0x040ef2f3, 0x00000f04, 0x06060f04, 0xf9fa0f04, 0x07fe0f04, 0xf8020f04, 0xfe080f04, 0x01f80f04,
+ 0x0d0d0f04, 0xf2f30f04, 0x0f040f04, 0xf0fc0f04, 0x040f0f04, 0xfffff0fc, 0x0605f0fc, 0xf9f9f0fc,
+ 0x07fdf0fc, 0xf801f0fc, 0xfe07f0fc, 0x01f7f0fc, 0x0d0cf0fc, 0xf2f2f0fc, 0x0f03f0fc, 0xf0fbf0fc,
+ 0x040ef0fc, 0x0000040f, 0x0606040f, 0xf9fa040f, 0x07fe040f, 0xf802040f, 0xfe08040f, 0x01f8040f,
+ 0x0d0d040f, 0xf2f3040f, 0x0f04040f, 0xf0fc040f, 0x040f040f, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000707, 0xfffff8f9, 0x000009fd, 0xfffff603, 0xfffffd0a, 0x000002f6, 0x00001010,
+ 0xffffeff0, 0x00001205, 0xffffedfb, 0x00000512, 0xfffffaee, 0x00000cf3, 0xfffff30d, 0x000014fa,
+ 0xffffeb06, 0xfffffa15, 0x000005eb, 0x00001e0f, 0xffffe1f1, 0x00000f1e, 0xfffff0e2, 0x00001e1e,
+ 0xffffe1e2, 0x00002202, 0xffffddfe, 0x00000222, 0xfffffdde, 0x00001bed, 0xffffe413, 0xffffed1c,
+ 0x000012e4, 0x00003620, 0xffffc9e0, 0x00002036, 0xffffdfca, 0x000028f5, 0xffffd70b, 0xfffff529,
+ 0x00000ad7, 0x0000370f, 0xffffc8f1, 0x00000f37, 0xfffff0c9, 0x00003939, 0xffffc6c7, 0x00003eff,
+ 0xffffc101, 0xffffff3f, 0x000000c1, 0x000027d8, 0xffffd828, 0x000036e2, 0xffffc91e, 0xffffe237,
+ 0x00001dc9, 0x00005e25, 0xffffa1db, 0x0000255e, 0xffffdaa2, 0x00006041, 0xffff9fbf, 0x00004160,
+ 0xffffbea0, 0x00004deb, 0xffffb215, 0xffffeb4e, 0x000014b2, 0x0000640f, 0xffff9bf1, 0x00000f64,
+ 0xfffff09c, 0x00006a6a, 0xffff9596, 0x000073f8, 0xffff8c08, 0xfffff874, 0x0000078c, 0x00004ec1,
+ 0xffffb13f, 0xffffc14f, 0x00003eb1, 0x000068cd, 0xffff9733, 0xffffcd69, 0x00003297, 0x00007788,
+ 0xffff8878, 0x00002b2b, 0xffffd4d5, 0x00005050, 0xffffafb0, 0x00000000, 0x07070000, 0xf8f90000,
+ 0x09fd0000, 0xf6030000, 0xfd0a0000, 0x02f60000, 0x10100000, 0xeff00000, 0x12050000, 0xedfb0000,
+ 0x05120000, 0x00000707, 0x07070707, 0xf8f90707, 0x09fd0707, 0xf6030707, 0xfd0a0707, 0x02f60707,
+ 0x10100707, 0xeff00707, 0x12050707, 0xedfb0707, 0x05120707, 0xfffff8f9, 0x0706f8f9, 0xf8f8f8f9,
+ 0x09fcf8f9, 0xf602f8f9, 0xfd09f8f9, 0x02f5f8f9, 0x100ff8f9, 0xefeff8f9, 0x1204f8f9, 0xedfaf8f9,
+ 0x0511f8f9, 0x000009fd, 0x070709fd, 0xf8f909fd, 0x09fd09fd, 0xf60309fd, 0xfd0a09fd, 0x02f609fd,
+ 0x101009fd, 0xeff009fd, 0x120509fd, 0xedfb09fd, 0x051209fd, 0xfffff603, 0x0706f603, 0xf8f8f603,
+ 0x09fcf603, 0xf602f603, 0xfd09f603, 0x02f5f603, 0x100ff603, 0xefeff603, 0x1204f603, 0xedfaf603,
+ 0x0511f603, 0xfffffd0a, 0x0706fd0a, 0xf8f8fd0a, 0x09fcfd0a, 0xf602fd0a, 0xfd09fd0a, 0x02f5fd0a,
+ 0x100ffd0a, 0xefeffd0a, 0x1204fd0a, 0xedfafd0a, 0x0511fd0a, 0x000002f6, 0x070702f6, 0xf8f902f6,
+ 0x09fd02f6, 0xf60302f6, 0xfd0a02f6, 0x02f602f6, 0x101002f6, 0xeff002f6, 0x120502f6, 0xedfb02f6,
+ 0x051202f6, 0x00001010, 0x07071010, 0xf8f91010, 0x09fd1010, 0xf6031010, 0xfd0a1010, 0x02f61010,
+ 0x10101010, 0xeff01010, 0x12051010, 0xedfb1010, 0x05121010, 0xffffeff0, 0x0706eff0, 0xf8f8eff0,
+ 0x09fceff0, 0xf602eff0, 0xfd09eff0, 0x02f5eff0, 0x100feff0, 0xefefeff0, 0x1204eff0, 0xedfaeff0,
+ 0x0511eff0, 0x00001205, 0x07071205, 0xf8f91205, 0x09fd1205, 0xf6031205, 0xfd0a1205, 0x02f61205,
+ 0x10101205, 0xeff01205, 0x12051205, 0xedfb1205, 0x05121205, 0xffffedfb, 0x0706edfb, 0xf8f8edfb,
+ 0x09fcedfb, 0xf602edfb, 0xfd09edfb, 0x02f5edfb, 0x100fedfb, 0xefefedfb, 0x1204edfb, 0xedfaedfb,
+ 0x0511edfb, 0x00000512, 0x07070512, 0xf8f90512, 0x09fd0512, 0xf6030512, 0xfd0a0512, 0x02f60512,
+ 0x10100512, 0xeff00512, 0x12050512, 0xedfb0512, 0x05120512, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000808, 0xfffff7f8, 0x00000afd, 0xfffff503, 0xfffffd0b, 0x000002f5, 0x00001212,
+ 0xffffedee, 0x00001405, 0xffffebfb, 0x00000514, 0xfffffaec, 0x00000ef1, 0xfffff10f, 0x000017f9,
+ 0xffffe807, 0xfffff918, 0x000006e8, 0x00002311, 0xffffdcef, 0x00001123, 0xffffeedd, 0x00002222,
+ 0xffffddde, 0x00002603, 0xffffd9fd, 0x00000326, 0xfffffcda, 0x00001fea, 0xffffe016, 0xffffea20,
+ 0x000015e0, 0x00003d25, 0xffffc2db, 0x0000253d, 0xffffdac3, 0x00002ef3, 0xffffd10d, 0xfffff32f,
+ 0x00000cd1, 0x00003f11, 0xffffc0ef, 0x0000113f, 0xffffeec1, 0x00004141, 0xffffbebf, 0x000047ff,
+ 0xffffb801, 0xffffff48, 0x000000b8, 0x00002dd2, 0xffffd22e, 0x00003edd, 0xffffc123, 0xffffdd3f,
+ 0x000022c1, 0x00006b2b, 0xffff94d5, 0x00002b6b, 0xffffd495, 0x00006e4b, 0xffff91b5, 0x00004b6e,
+ 0xffffb492, 0x000058e8, 0xffffa718, 0xffffe859, 0x000017a7, 0x00007211, 0xffff8def, 0x00001172,
+ 0xffffee8e, 0x00007979, 0xffff8687, 0x00005ab8, 0xffffa548, 0xffffb85b, 0x000047a5, 0x000077c6,
+ 0xffff883a, 0xffffc678, 0x00003988, 0x00003131, 0xffffcecf, 0x00005c5c, 0xffffa3a4, 0x00000000,
+ 0x08080000, 0xf7f80000, 0x0afd0000, 0xf5030000, 0xfd0b0000, 0x02f50000, 0x12120000, 0xedee0000,
+ 0x14050000, 0xebfb0000, 0x05140000, 0x00000808, 0x08080808, 0xf7f80808, 0x0afd0808, 0xf5030808,
+ 0xfd0b0808, 0x02f50808, 0x12120808, 0xedee0808, 0x14050808, 0xebfb0808, 0x05140808, 0xfffff7f8,
+ 0x0807f7f8, 0xf7f7f7f8, 0x0afcf7f8, 0xf502f7f8, 0xfd0af7f8, 0x02f4f7f8, 0x1211f7f8, 0xededf7f8,
+ 0x1404f7f8, 0xebfaf7f8, 0x0513f7f8, 0x00000afd, 0x08080afd, 0xf7f80afd, 0x0afd0afd, 0xf5030afd,
+ 0xfd0b0afd, 0x02f50afd, 0x12120afd, 0xedee0afd, 0x14050afd, 0xebfb0afd, 0x05140afd, 0xfffff503,
+ 0x0807f503, 0xf7f7f503, 0x0afcf503, 0xf502f503, 0xfd0af503, 0x02f4f503, 0x1211f503, 0xededf503,
+ 0x1404f503, 0xebfaf503, 0x0513f503, 0xfffffd0b, 0x0807fd0b, 0xf7f7fd0b, 0x0afcfd0b, 0xf502fd0b,
+ 0xfd0afd0b, 0x02f4fd0b, 0x1211fd0b, 0xededfd0b, 0x1404fd0b, 0xebfafd0b, 0x0513fd0b, 0x000002f5,
+ 0x080802f5, 0xf7f802f5, 0x0afd02f5, 0xf50302f5, 0xfd0b02f5, 0x02f502f5, 0x121202f5, 0xedee02f5,
+ 0x140502f5, 0xebfb02f5, 0x051402f5, 0x00001212, 0x08081212, 0xf7f81212, 0x0afd1212, 0xf5031212,
+ 0xfd0b1212, 0x02f51212, 0x12121212, 0xedee1212, 0x14051212, 0xebfb1212, 0x05141212, 0xffffedee,
+ 0x0807edee, 0xf7f7edee, 0x0afcedee, 0xf502edee, 0xfd0aedee, 0x02f4edee, 0x1211edee, 0xedededee,
+ 0x1404edee, 0xebfaedee, 0x0513edee, 0x00001405, 0x08081405, 0xf7f81405, 0x0afd1405, 0xf5031405,
+ 0xfd0b1405, 0x02f51405, 0x12121405, 0xedee1405, 0x14051405, 0xebfb1405, 0x05141405, 0xffffebfb,
+ 0x0807ebfb, 0xf7f7ebfb, 0x0afcebfb, 0xf502ebfb, 0xfd0aebfb, 0x02f4ebfb, 0x1211ebfb, 0xededebfb,
+ 0x1404ebfb, 0xebfaebfb, 0x0513ebfb, 0x00000514, 0x08080514, 0xf7f80514, 0x0afd0514, 0xf5030514,
+ 0xfd0b0514, 0x02f50514, 0x12120514, 0xedee0514, 0x14050514, 0xebfb0514, 0x05140514, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000909, 0xfffff6f7, 0x00000bfd, 0xfffff403, 0xfffffd0c, 0x000002f4, 0x00001414,
+ 0xffffebec, 0x00001706, 0xffffe8fa, 0x00000617, 0xfffff9e9, 0x000010ef, 0xffffef11, 0x00001af9,
+ 0xffffe507, 0xfffff91b, 0x000006e5, 0x00002713, 0xffffd8ed, 0x00001327, 0xffffecd9, 0x00002727,
+ 0xffffd8d9, 0x00002b03, 0xffffd4fd, 0x0000032b, 0xfffffcd5, 0x000023e8, 0xffffdc18, 0xffffe824,
+ 0x000017dc, 0x0000452a, 0xffffbad6, 0x00002a45, 0xffffd5bb, 0x000034f2, 0xffffcb0e, 0xfffff235,
+ 0x00000dcb, 0x00004713, 0xffffb8ed, 0x00001347, 0xffffecb9, 0x00004949, 0xffffb6b7, 0x00004ffe,
+ 0xffffb002, 0xfffffe50, 0x000001b0, 0x000033cc, 0xffffcc34, 0x000045d9, 0xffffba27, 0xffffd946,
+ 0x000026ba, 0x00007930, 0xffff86d0, 0x00003079, 0xffffcf87, 0x00007c54, 0xffff83ac, 0x0000547c,
+ 0xffffab84, 0x000063e5, 0xffff9c1b, 0xffffe564, 0x00001a9c, 0x000065af, 0xffff9a51, 0xffffaf66,
+ 0x0000509a, 0x00003737, 0xffffc8c9, 0x00006868, 0xffff9798, 0x00000000, 0x09090000, 0xf6f70000,
+ 0x0bfd0000, 0xf4030000, 0xfd0c0000, 0x02f40000, 0x14140000, 0xebec0000, 0x17060000, 0xe8fa0000,
+ 0x06170000, 0xf9e90000, 0x00000909, 0x09090909, 0xf6f70909, 0x0bfd0909, 0xf4030909, 0xfd0c0909,
+ 0x02f40909, 0x14140909, 0xebec0909, 0x17060909, 0xe8fa0909, 0x06170909, 0xf9e90909, 0xfffff6f7,
+ 0x0908f6f7, 0xf6f6f6f7, 0x0bfcf6f7, 0xf402f6f7, 0xfd0bf6f7, 0x02f3f6f7, 0x1413f6f7, 0xebebf6f7,
+ 0x1705f6f7, 0xe8f9f6f7, 0x0616f6f7, 0xf9e8f6f7, 0x00000bfd, 0x09090bfd, 0xf6f70bfd, 0x0bfd0bfd,
+ 0xf4030bfd, 0xfd0c0bfd, 0x02f40bfd, 0x14140bfd, 0xebec0bfd, 0x17060bfd, 0xe8fa0bfd, 0x06170bfd,
+ 0xf9e90bfd, 0xfffff403, 0x0908f403, 0xf6f6f403, 0x0bfcf403, 0xf402f403, 0xfd0bf403, 0x02f3f403,
+ 0x1413f403, 0xebebf403, 0x1705f403, 0xe8f9f403, 0x0616f403, 0xf9e8f403, 0xfffffd0c, 0x0908fd0c,
+ 0xf6f6fd0c, 0x0bfcfd0c, 0xf402fd0c, 0xfd0bfd0c, 0x02f3fd0c, 0x1413fd0c, 0xebebfd0c, 0x1705fd0c,
+ 0xe8f9fd0c, 0x0616fd0c, 0xf9e8fd0c, 0x000002f4, 0x090902f4, 0xf6f702f4, 0x0bfd02f4, 0xf40302f4,
+ 0xfd0c02f4, 0x02f402f4, 0x141402f4, 0xebec02f4, 0x170602f4, 0xe8fa02f4, 0x061702f4, 0xf9e902f4,
+ 0x00001414, 0x09091414, 0xf6f71414, 0x0bfd1414, 0xf4031414, 0xfd0c1414, 0x02f41414, 0x14141414,
+ 0xebec1414, 0x17061414, 0xe8fa1414, 0x06171414, 0xf9e91414, 0xffffebec, 0x0908ebec, 0xf6f6ebec,
+ 0x0bfcebec, 0xf402ebec, 0xfd0bebec, 0x02f3ebec, 0x1413ebec, 0xebebebec, 0x1705ebec, 0xe8f9ebec,
+ 0x0616ebec, 0xf9e8ebec, 0x00001706, 0x09091706, 0xf6f71706, 0x0bfd1706, 0xf4031706, 0xfd0c1706,
+ 0x02f41706, 0x14141706, 0xebec1706, 0x17061706, 0xe8fa1706, 0x06171706, 0xf9e91706, 0xffffe8fa,
+ 0x0908e8fa, 0xf6f6e8fa, 0x0bfce8fa, 0xf402e8fa, 0xfd0be8fa, 0x02f3e8fa, 0x1413e8fa, 0xebebe8fa,
+ 0x1705e8fa, 0xe8f9e8fa, 0x0616e8fa, 0xf9e8e8fa, 0x00000617, 0x09090617, 0xf6f70617, 0x0bfd0617,
+ 0xf4030617, 0xfd0c0617, 0x02f40617, 0x14140617, 0xebec0617, 0x17060617, 0xe8fa0617, 0x06170617,
+ 0xf9e90617, 0xfffff9e9, 0x0908f9e9, 0xf6f6f9e9, 0x0bfcf9e9, 0xf402f9e9, 0xfd0bf9e9, 0x02f3f9e9,
+ 0x1413f9e9, 0xebebf9e9, 0x1705f9e9, 0xe8f9f9e9, 0x0616f9e9, 0xf9e8f9e9, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000200, 0xfffffe00, 0x00000002, 0xfffffffe, 0x00000404,
+ 0xfffffbfc, 0x00000400, 0xfffffc00, 0x00000004, 0xfffffffc, 0x000003fc, 0xfffffc04, 0x000005fe,
+ 0xfffffa02, 0xfffffe06, 0x000001fa, 0x00000804, 0xfffff7fc, 0x00000408, 0xfffffbf8, 0x00000808,
+ 0xfffff7f8, 0x00000a00, 0xfffff600, 0x0000000a, 0xfffffff6, 0x000007fc, 0xfffff804, 0xfffffc08,
+ 0x000003f8, 0x00000e08, 0xfffff1f8, 0x0000080e, 0xfffff7f2, 0x00000bfe, 0xfffff402, 0xfffffe0c,
+ 0x000001f4, 0x00001004, 0xffffeffc, 0x00000410, 0xfffffbf0, 0x00001010, 0xffffeff0, 0x00001200,
+ 0xffffee00, 0x00000012, 0xffffffee, 0x00000bf4, 0xfffff40c, 0x00000ff8, 0xfffff008, 0xfffff810,
+ 0x000007f0, 0x00001a0a, 0xffffe5f6, 0x00000a1a, 0xfffff5e6, 0x00001c12, 0xffffe3ee, 0x0000121c,
+ 0xffffede4, 0x000015fa, 0xffffea06, 0xfffffa16, 0x000005ea, 0x00001c04, 0xffffe3fc, 0x0000041c,
+ 0xfffffbe4, 0x00001e1e, 0xffffe1e2, 0x00001ffe, 0xffffe002, 0xfffffe20, 0x000001e0, 0x000015ee,
+ 0xffffea12, 0xffffee16, 0x000011ea, 0x00001df2, 0xffffe20e, 0xfffff21e, 0x00000de2, 0x00002e16,
+ 0xffffd1ea, 0x0000162e, 0xffffe9d2, 0x00002e0c, 0xffffd1f4, 0x00000c2e, 0xfffff3d2, 0x00003022,
+ 0xffffcfde, 0x00002230, 0xffffddd0, 0x000027f6, 0xffffd80a, 0xfffff628, 0x000009d8, 0x00003204,
+ 0xffffcdfc, 0x00000432, 0xfffffbce, 0x00003636, 0xffffc9ca, 0x000021de, 0xffffde22, 0x000029e4,
+ 0xffffd61c, 0xffffe42a, 0x00001bd6, 0x00003bfa, 0xffffc406, 0xfffffa3c, 0x000005c4, 0x00004c1a,
+ 0xffffb3e6, 0x00001a4c, 0xffffe5b4, 0x00004c2a, 0xffffb3d6, 0x00002a4c, 0xffffd5b4, 0x000035e8,
+ 0xffffca18, 0xffffe836, 0x000017ca, 0x00004e0e, 0xffffb1f2, 0x00000e4e, 0xfffff1b2, 0x0000523e,
+ 0xffffadc2, 0x00003e52, 0xffffc1ae, 0x000049ec, 0xffffb614, 0xffffec4a, 0x000013b6, 0x00005802,
+ 0xffffa7fe, 0x00000258, 0xfffffda8, 0x00005c5c, 0xffffa3a4, 0x00003bcc, 0xffffc434, 0xffffcc3c,
+ 0x000033c4, 0x00007634, 0xffff89cc, 0x00003476, 0xffffcb8a, 0x000049d4, 0xffffb62c, 0xffffd44a,
+ 0x00002bb6, 0x0000764a, 0xffff89b6, 0x00004a76, 0xffffb58a, 0x00007620, 0xffff89e0, 0x00002076,
+ 0xffffdf8a, 0x000065f4, 0xffff9a0c, 0xfffff466, 0x00000b9a, 0x00005fd8, 0xffffa028, 0xffffd860,
+ 0x000027a0, 0x000075de, 0xffff8a22, 0xffffde76, 0x0000218a, 0x000057a8, 0xffffa858, 0x000067b2,
+ 0xffff984e, 0xffffb268, 0x00004d98, 0x00000c0c, 0xfffff3f4, 0x00001616, 0xffffe9ea, 0x00002a2a,
+ 0xffffd5d6, 0x00004848, 0xffffb7b8, 0x00000000, 0x02020000, 0xfdfe0000, 0x02000000, 0xfe000000,
+ 0x00020000, 0xfffe0000, 0x00000202, 0x02020202, 0xfdfe0202, 0x02000202, 0xfe000202, 0x00020202,
+ 0xfffe0202, 0xfffffdfe, 0x0201fdfe, 0xfdfdfdfe, 0x01fffdfe, 0xfdfffdfe, 0x0001fdfe, 0xfffdfdfe,
+ 0x00000200, 0x02020200, 0xfdfe0200, 0x02000200, 0xfe000200, 0x00020200, 0xfffe0200, 0xfffffe00,
+ 0x0201fe00, 0xfdfdfe00, 0x01fffe00, 0xfdfffe00, 0x0001fe00, 0xfffdfe00, 0x00000002, 0x02020002,
+ 0xfdfe0002, 0x02000002, 0xfe000002, 0x00020002, 0xfffe0002, 0xfffffffe, 0x0201fffe, 0xfdfdfffe,
+ 0x01fffffe, 0xfdfffffe, 0x0001fffe, 0xfffdfffe, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000303, 0xfffffcfd, 0x00000300, 0xfffffd00, 0x00000003, 0xfffffffd, 0x00000606,
+ 0xfffff9fa, 0x00000903, 0xfffff6fd, 0x00000309, 0xfffffcf7, 0x000008fd, 0xfffff703, 0xfffffd09,
+ 0x000002f7, 0x000005fa, 0xfffffa06, 0x00000c06, 0xfffff3fa, 0x0000060c, 0xfffff9f4, 0x00000c0c,
+ 0xfffff3f4, 0x00000f00, 0xfffff100, 0x0000000f, 0xfffffff1, 0x00000bf7, 0xfffff409, 0xfffff70c,
+ 0x000008f4, 0x0000180f, 0xffffe7f1, 0x00000f18, 0xfffff0e8, 0x000011fa, 0xffffee06, 0xfffffa12,
+ 0x000005ee, 0x00001806, 0xffffe7fa, 0x00000618, 0xfffff9e8, 0x00001818, 0xffffe7e8, 0x00001b00,
+ 0xffffe500, 0x0000001b, 0xffffffe5, 0x000011ee, 0xffffee12, 0x000017f4, 0xffffe80c, 0xfffff418,
+ 0x00000be8, 0x0000270f, 0xffffd8f1, 0x00000f27, 0xfffff0d9, 0x00002a1b, 0xffffd5e5, 0x00001b2a,
+ 0xffffe4d6, 0x000020f7, 0xffffdf09, 0xfffff721, 0x000008df, 0x00002a06, 0xffffd5fa, 0x0000062a,
+ 0xfffff9d6, 0x00002d2d, 0xffffd2d3, 0x000032fd, 0xffffcd03, 0xfffffd33, 0x000002cd, 0x000020e5,
+ 0xffffdf1b, 0xffffe521, 0x00001adf, 0x00002ceb, 0xffffd315, 0xffffeb2d, 0x000014d3, 0x00004521,
+ 0xffffbadf, 0x00002145, 0xffffdebb, 0x00004512, 0xffffbaee, 0x00001245, 0xffffedbb, 0x00004836,
+ 0xffffb7ca, 0x00003648, 0xffffc9b8, 0x00003eee, 0xffffc112, 0xffffee3f, 0x000011c1, 0x00004e06,
+ 0xffffb1fa, 0x0000064e, 0xfffff9b2, 0x00005151, 0xffffaeaf, 0x000032cd, 0xffffcd33, 0x00003ed6,
+ 0xffffc12a, 0xffffd63f, 0x000029c1, 0x000059f7, 0xffffa609, 0xfffff75a, 0x000008a6, 0x0000722a,
+ 0xffff8dd6, 0x00002a72, 0xffffd58e, 0x0000753f, 0xffff8ac1, 0x00003f75, 0xffffc08b, 0x000050dc,
+ 0xffffaf24, 0xffffdc51, 0x000023af, 0x00007815, 0xffff87eb, 0x00001578, 0xffffea88, 0x00007b60,
+ 0xffff84a0, 0x0000607b, 0xffff9f85, 0x00006ee2, 0xffff911e, 0xffffe26f, 0x00001d91, 0x00005cb2,
+ 0xffffa34e, 0xffffb25d, 0x00004da3, 0x000071bb, 0xffff8e45, 0xffffbb72, 0x0000448e, 0x00001212,
+ 0xffffedee, 0x00002121, 0xffffdedf, 0x00003f3f, 0xffffc0c1, 0x00006c6c, 0xffff9394, 0x00000000,
+ 0x03030000, 0xfcfd0000, 0x03000000, 0xfd000000, 0x00030000, 0xfffd0000, 0x06060000, 0xf9fa0000,
+ 0x00000303, 0x03030303, 0xfcfd0303, 0x03000303, 0xfd000303, 0x00030303, 0xfffd0303, 0x06060303,
+ 0xf9fa0303, 0xfffffcfd, 0x0302fcfd, 0xfcfcfcfd, 0x02fffcfd, 0xfcfffcfd, 0x0002fcfd, 0xfffcfcfd,
+ 0x0605fcfd, 0xf9f9fcfd, 0x00000300, 0x03030300, 0xfcfd0300, 0x03000300, 0xfd000300, 0x00030300,
+ 0xfffd0300, 0x06060300, 0xf9fa0300, 0xfffffd00, 0x0302fd00, 0xfcfcfd00, 0x02fffd00, 0xfcfffd00,
+ 0x0002fd00, 0xfffcfd00, 0x0605fd00, 0xf9f9fd00, 0x00000003, 0x03030003, 0xfcfd0003, 0x03000003,
+ 0xfd000003, 0x00030003, 0xfffd0003, 0x06060003, 0xf9fa0003, 0xfffffffd, 0x0302fffd, 0xfcfcfffd,
+ 0x02fffffd, 0xfcfffffd, 0x0002fffd, 0xfffcfffd, 0x0605fffd, 0xf9f9fffd, 0x00000606, 0x03030606,
+ 0xfcfd0606, 0x03000606, 0xfd000606, 0x00030606, 0xfffd0606, 0x06060606, 0xf9fa0606, 0xfffff9fa,
+ 0x0302f9fa, 0xfcfcf9fa, 0x02fff9fa, 0xfcfff9fa, 0x0002f9fa, 0xfffcf9fa, 0x0605f9fa, 0xf9f9f9fa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000404, 0xfffffbfc, 0x00000400, 0xfffffc00, 0x00000004, 0xfffffffc, 0x00000804,
+ 0xfffff7fc, 0x00000408, 0xfffffbf8, 0x00000808, 0xfffff7f8, 0x000007f8, 0xfffff808, 0x00000bfc,
+ 0xfffff404, 0xfffffc0c, 0x000003f4, 0x00001008, 0xffffeff8, 0x00000810, 0xfffff7f0, 0x00001010,
+ 0xffffeff0, 0x00001400, 0xffffec00, 0x00000014, 0xffffffec, 0x00000ff4, 0xfffff00c, 0xfffff410,
+ 0x00000bf0, 0x000017fc, 0xffffe804, 0xfffffc18, 0x000003e8, 0x00002010, 0xffffdff0, 0x00001020,
+ 0xffffefe0, 0x00002008, 0xffffdff8, 0x00000820, 0xfffff7e0, 0x00002020, 0xffffdfe0, 0x00002400,
+ 0xffffdc00, 0x00000024, 0xffffffdc, 0x000017e8, 0xffffe818, 0x00001ff0, 0xffffe010, 0xfffff020,
+ 0x00000fe0, 0x00003414, 0xffffcbec, 0x00001434, 0xffffebcc, 0x00003824, 0xffffc7dc, 0x00002438,
+ 0xffffdbc8, 0x00002bf4, 0xffffd40c, 0xfffff42c, 0x00000bd4, 0x00003808, 0xffffc7f8, 0x00000838,
+ 0xfffff7c8, 0x00003c3c, 0xffffc3c4, 0x00003ffc, 0xffffc004, 0xfffffc40, 0x000003c0, 0x00002bdc,
+ 0xffffd424, 0xffffdc2c, 0x000023d4, 0x00003be4, 0xffffc41c, 0xffffe43c, 0x00001bc4, 0x00005c2c,
+ 0xffffa3d4, 0x00002c5c, 0xffffd3a4, 0x00005c18, 0xffffa3e8, 0x0000185c, 0xffffe7a4, 0x00006048,
+ 0xffff9fb8, 0x00004860, 0xffffb7a0, 0x000053ec, 0xffffac14, 0xffffec54, 0x000013ac, 0x00006408,
+ 0xffff9bf8, 0x00000864, 0xfffff79c, 0x00006c6c, 0xffff9394, 0x000043bc, 0xffffbc44, 0x000053c8,
+ 0xffffac38, 0xffffc854, 0x000037ac, 0x000077f4, 0xffff880c, 0xfffff478, 0x00000b88, 0x00006bd0,
+ 0xffff9430, 0xffffd06c, 0x00002f94, 0x00007b98, 0xffff8468, 0xffff987c, 0x00006784, 0x00001818,
+ 0xffffe7e8, 0x00002c2c, 0xffffd3d4, 0x00005454, 0xffffabac, 0x00000000, 0x04040000, 0xfbfc0000,
+ 0x04000000, 0xfc000000, 0x00040000, 0xfffc0000, 0x08040000, 0xf7fc0000, 0x04080000, 0x00000404,
+ 0x04040404, 0xfbfc0404, 0x04000404, 0xfc000404, 0x00040404, 0xfffc0404, 0x08040404, 0xf7fc0404,
+ 0x04080404, 0xfffffbfc, 0x0403fbfc, 0xfbfbfbfc, 0x03fffbfc, 0xfbfffbfc, 0x0003fbfc, 0xfffbfbfc,
+ 0x0803fbfc, 0xf7fbfbfc, 0x0407fbfc, 0x00000400, 0x04040400, 0xfbfc0400, 0x04000400, 0xfc000400,
+ 0x00040400, 0xfffc0400, 0x08040400, 0xf7fc0400, 0x04080400, 0xfffffc00, 0x0403fc00, 0xfbfbfc00,
+ 0x03fffc00, 0xfbfffc00, 0x0003fc00, 0xfffbfc00, 0x0803fc00, 0xf7fbfc00, 0x0407fc00, 0x00000004,
+ 0x04040004, 0xfbfc0004, 0x04000004, 0xfc000004, 0x00040004, 0xfffc0004, 0x08040004, 0xf7fc0004,
+ 0x04080004, 0xfffffffc, 0x0403fffc, 0xfbfbfffc, 0x03fffffc, 0xfbfffffc, 0x0003fffc, 0xfffbfffc,
+ 0x0803fffc, 0xf7fbfffc, 0x0407fffc, 0x00000804, 0x04040804, 0xfbfc0804, 0x04000804, 0xfc000804,
+ 0x00040804, 0xfffc0804, 0x08040804, 0xf7fc0804, 0x04080804, 0xfffff7fc, 0x0403f7fc, 0xfbfbf7fc,
+ 0x03fff7fc, 0xfbfff7fc, 0x0003f7fc, 0xfffbf7fc, 0x0803f7fc, 0xf7fbf7fc, 0x0407f7fc, 0x00000408,
+ 0x04040408, 0xfbfc0408, 0x04000408, 0xfc000408, 0x00040408, 0xfffc0408, 0x08040408, 0xf7fc0408,
+ 0x04080408, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000505, 0xfffffafb, 0x00000500, 0xfffffb00, 0x00000005, 0xfffffffb, 0x00000a0a,
+ 0xfffff5f6, 0x00000f05, 0xfffff0fb, 0x0000050f, 0xfffffaf1, 0x000009f6, 0xfffff60a, 0x00000efb,
+ 0xfffff105, 0xfffffb0f, 0x000004f1, 0x0000140a, 0xffffebf6, 0x00000a14, 0xfffff5ec, 0x00001414,
+ 0xffffebec, 0x00001900, 0xffffe700, 0x00000019, 0xffffffe7, 0x000013f1, 0xffffec0f, 0xfffff114,
+ 0x00000eec, 0x00002819, 0xffffd7e7, 0x00001928, 0xffffe6d8, 0x00001df6, 0xffffe20a, 0xfffff61e,
+ 0x000009e2, 0x0000280a, 0xffffd7f6, 0x00000a28, 0xfffff5d8, 0x00002828, 0xffffd7d8, 0x00002d00,
+ 0xffffd300, 0x0000002d, 0xffffffd3, 0x00001de2, 0xffffe21e, 0x000027ec, 0xffffd814, 0xffffec28,
+ 0x000013d8, 0x00004119, 0xffffbee7, 0x00001941, 0xffffe6bf, 0x0000462d, 0xffffb9d3, 0x00002d46,
+ 0xffffd2ba, 0x000036f1, 0xffffc90f, 0xfffff137, 0x00000ec9, 0x0000460a, 0xffffb9f6, 0x00000a46,
+ 0xfffff5ba, 0x00004b4b, 0xffffb4b5, 0x000054fb, 0xffffab05, 0xfffffb55, 0x000004ab, 0x000036d3,
+ 0xffffc92d, 0xffffd337, 0x00002cc9, 0x00004add, 0xffffb523, 0xffffdd4b, 0x000022b5, 0x00007337,
+ 0xffff8cc9, 0x00003773, 0xffffc88d, 0x0000731e, 0xffff8ce2, 0x00001e73, 0xffffe18d, 0x0000785a,
+ 0xffff87a6, 0x00005a78, 0xffffa588, 0x000068e2, 0xffff971e, 0xffffe269, 0x00001d97, 0x000054ab,
+ 0xffffab55, 0x000068ba, 0xffff9746, 0xffffba69, 0x00004597, 0x00001e1e, 0xffffe1e2, 0x00003c3c,
+ 0xffffc3c4, 0x00006969, 0xffff9697, 0x00000000, 0x05050000, 0xfafb0000, 0x05000000, 0xfb000000,
+ 0x00050000, 0xfffb0000, 0x0a0a0000, 0xf5f60000, 0x0f050000, 0xf0fb0000, 0x00000505, 0x05050505,
+ 0xfafb0505, 0x05000505, 0xfb000505, 0x00050505, 0xfffb0505, 0x0a0a0505, 0xf5f60505, 0x0f050505,
+ 0xf0fb0505, 0xfffffafb, 0x0504fafb, 0xfafafafb, 0x04fffafb, 0xfafffafb, 0x0004fafb, 0xfffafafb,
+ 0x0a09fafb, 0xf5f5fafb, 0x0f04fafb, 0xf0fafafb, 0x00000500, 0x05050500, 0xfafb0500, 0x05000500,
+ 0xfb000500, 0x00050500, 0xfffb0500, 0x0a0a0500, 0xf5f60500, 0x0f050500, 0xf0fb0500, 0xfffffb00,
+ 0x0504fb00, 0xfafafb00, 0x04fffb00, 0xfafffb00, 0x0004fb00, 0xfffafb00, 0x0a09fb00, 0xf5f5fb00,
+ 0x0f04fb00, 0xf0fafb00, 0x00000005, 0x05050005, 0xfafb0005, 0x05000005, 0xfb000005, 0x00050005,
+ 0xfffb0005, 0x0a0a0005, 0xf5f60005, 0x0f050005, 0xf0fb0005, 0xfffffffb, 0x0504fffb, 0xfafafffb,
+ 0x04fffffb, 0xfafffffb, 0x0004fffb, 0xfffafffb, 0x0a09fffb, 0xf5f5fffb, 0x0f04fffb, 0xf0fafffb,
+ 0x00000a0a, 0x05050a0a, 0xfafb0a0a, 0x05000a0a, 0xfb000a0a, 0x00050a0a, 0xfffb0a0a, 0x0a0a0a0a,
+ 0xf5f60a0a, 0x0f050a0a, 0xf0fb0a0a, 0xfffff5f6, 0x0504f5f6, 0xfafaf5f6, 0x04fff5f6, 0xfafff5f6,
+ 0x0004f5f6, 0xfffaf5f6, 0x0a09f5f6, 0xf5f5f5f6, 0x0f04f5f6, 0xf0faf5f6, 0x00000f05, 0x05050f05,
+ 0xfafb0f05, 0x05000f05, 0xfb000f05, 0x00050f05, 0xfffb0f05, 0x0a0a0f05, 0xf5f60f05, 0x0f050f05,
+ 0xf0fb0f05, 0xfffff0fb, 0x0504f0fb, 0xfafaf0fb, 0x04fff0fb, 0xfafff0fb, 0x0004f0fb, 0xfffaf0fb,
+ 0x0a09f0fb, 0xf5f5f0fb, 0x0f04f0fb, 0xf0faf0fb, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000606, 0xfffff9fa, 0x00000600, 0xfffffa00, 0x00000006, 0xfffffffa, 0x00000c0c,
+ 0xfffff3f4, 0x00000c06, 0xfffff3fa, 0x0000060c, 0xfffff9f4, 0x00000bf4, 0xfffff40c, 0x000011fa,
+ 0xffffee06, 0xfffffa12, 0x000005ee, 0x0000180c, 0xffffe7f4, 0x00000c18, 0xfffff3e8, 0x00001818,
+ 0xffffe7e8, 0x00001e00, 0xffffe200, 0x0000001e, 0xffffffe2, 0x000017ee, 0xffffe812, 0xffffee18,
+ 0x000011e8, 0x0000301e, 0xffffcfe2, 0x00001e30, 0xffffe1d0, 0x000023fa, 0xffffdc06, 0xfffffa24,
+ 0x000005dc, 0x0000300c, 0xffffcff4, 0x00000c30, 0xfffff3d0, 0x00003030, 0xffffcfd0, 0x00003600,
+ 0xffffca00, 0x00000036, 0xffffffca, 0x000023dc, 0xffffdc24, 0x00002fe8, 0xffffd018, 0xffffe830,
+ 0x000017d0, 0x00004e1e, 0xffffb1e2, 0x00001e4e, 0xffffe1b2, 0x00005436, 0xffffabca, 0x00003654,
+ 0xffffc9ac, 0x000041ee, 0xffffbe12, 0xffffee42, 0x000011be, 0x0000540c, 0xffffabf4, 0x00000c54,
+ 0xfffff3ac, 0x00005a5a, 0xffffa5a6, 0x00005ffa, 0xffffa006, 0xfffffa60, 0x000005a0, 0x000041ca,
+ 0xffffbe36, 0xffffca42, 0x000035be, 0x000059d6, 0xffffa62a, 0xffffd65a, 0x000029a6, 0x00007de2,
+ 0xffff821e, 0xffffe27e, 0x00001d82, 0x0000659a, 0xffff9a66, 0x00007dac, 0xffff8254, 0xffffac7e,
+ 0x00005382, 0x00002424, 0xffffdbdc, 0x00004242, 0xffffbdbe, 0x00000000, 0x06060000, 0xf9fa0000,
+ 0x06000000, 0xfa000000, 0x00060000, 0xfffa0000, 0x0c0c0000, 0xf3f40000, 0x0c060000, 0xf3fa0000,
+ 0x060c0000, 0x00000606, 0x06060606, 0xf9fa0606, 0x06000606, 0xfa000606, 0x00060606, 0xfffa0606,
+ 0x0c0c0606, 0xf3f40606, 0x0c060606, 0xf3fa0606, 0x060c0606, 0xfffff9fa, 0x0605f9fa, 0xf9f9f9fa,
+ 0x05fff9fa, 0xf9fff9fa, 0x0005f9fa, 0xfff9f9fa, 0x0c0bf9fa, 0xf3f3f9fa, 0x0c05f9fa, 0xf3f9f9fa,
+ 0x060bf9fa, 0x00000600, 0x06060600, 0xf9fa0600, 0x06000600, 0xfa000600, 0x00060600, 0xfffa0600,
+ 0x0c0c0600, 0xf3f40600, 0x0c060600, 0xf3fa0600, 0x060c0600, 0xfffffa00, 0x0605fa00, 0xf9f9fa00,
+ 0x05fffa00, 0xf9fffa00, 0x0005fa00, 0xfff9fa00, 0x0c0bfa00, 0xf3f3fa00, 0x0c05fa00, 0xf3f9fa00,
+ 0x060bfa00, 0x00000006, 0x06060006, 0xf9fa0006, 0x06000006, 0xfa000006, 0x00060006, 0xfffa0006,
+ 0x0c0c0006, 0xf3f40006, 0x0c060006, 0xf3fa0006, 0x060c0006, 0xfffffffa, 0x0605fffa, 0xf9f9fffa,
+ 0x05fffffa, 0xf9fffffa, 0x0005fffa, 0xfff9fffa, 0x0c0bfffa, 0xf3f3fffa, 0x0c05fffa, 0xf3f9fffa,
+ 0x060bfffa, 0x00000c0c, 0x06060c0c, 0xf9fa0c0c, 0x06000c0c, 0xfa000c0c, 0x00060c0c, 0xfffa0c0c,
+ 0x0c0c0c0c, 0xf3f40c0c, 0x0c060c0c, 0xf3fa0c0c, 0x060c0c0c, 0xfffff3f4, 0x0605f3f4, 0xf9f9f3f4,
+ 0x05fff3f4, 0xf9fff3f4, 0x0005f3f4, 0xfff9f3f4, 0x0c0bf3f4, 0xf3f3f3f4, 0x0c05f3f4, 0xf3f9f3f4,
+ 0x060bf3f4, 0x00000c06, 0x06060c06, 0xf9fa0c06, 0x06000c06, 0xfa000c06, 0x00060c06, 0xfffa0c06,
+ 0x0c0c0c06, 0xf3f40c06, 0x0c060c06, 0xf3fa0c06, 0x060c0c06, 0xfffff3fa, 0x0605f3fa, 0xf9f9f3fa,
+ 0x05fff3fa, 0xf9fff3fa, 0x0005f3fa, 0xfff9f3fa, 0x0c0bf3fa, 0xf3f3f3fa, 0x0c05f3fa, 0xf3f9f3fa,
+ 0x060bf3fa, 0x0000060c, 0x0606060c, 0xf9fa060c, 0x0600060c, 0xfa00060c, 0x0006060c, 0xfffa060c,
+ 0x0c0c060c, 0xf3f4060c, 0x0c06060c, 0xf3fa060c, 0x060c060c, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000707, 0xfffff8f9, 0x00000700, 0xfffff900, 0x00000007, 0xfffffff9, 0x00000e0e,
+ 0xfffff1f2, 0x00001507, 0xffffeaf9, 0x00000715, 0xfffff8eb, 0x00000df2, 0xfffff20e, 0x000014f9,
+ 0xffffeb07, 0xfffff915, 0x000006eb, 0x00001c0e, 0xffffe3f2, 0x00000e1c, 0xfffff1e4, 0x00001c1c,
+ 0xffffe3e4, 0x00002300, 0xffffdd00, 0x00000023, 0xffffffdd, 0x00001beb, 0xffffe415, 0xffffeb1c,
+ 0x000014e4, 0x00003823, 0xffffc7dd, 0x00002338, 0xffffdcc8, 0x000029f2, 0xffffd60e, 0xfffff22a,
+ 0x00000dd6, 0x0000380e, 0xffffc7f2, 0x00000e38, 0xfffff1c8, 0x00003838, 0xffffc7c8, 0x00003f00,
+ 0xffffc100, 0x0000003f, 0xffffffc1, 0x000029d6, 0xffffd62a, 0x000037e4, 0xffffc81c, 0xffffe438,
+ 0x00001bc8, 0x00005b23, 0xffffa4dd, 0x0000235b, 0xffffdca5, 0x0000623f, 0xffff9dc1, 0x00003f62,
+ 0xffffc09e, 0x00004ceb, 0xffffb315, 0xffffeb4d, 0x000014b3, 0x0000620e, 0xffff9df2, 0x00000e62,
+ 0xfffff19e, 0x00006969, 0xffff9697, 0x000076f9, 0xffff8907, 0xfffff977, 0x00000689, 0x00004cc1,
+ 0xffffb33f, 0xffffc14d, 0x00003eb3, 0x000068cf, 0xffff9731, 0xffffcf69, 0x00003097, 0x00007689,
+ 0xffff8977, 0x00002a2a, 0xffffd5d6, 0x00004d4d, 0xffffb2b3, 0x00000000, 0x07070000, 0xf8f90000,
+ 0x07000000, 0xf9000000, 0x00070000, 0xfff90000, 0x0e0e0000, 0xf1f20000, 0x15070000, 0xeaf90000,
+ 0x07150000, 0x00000707, 0x07070707, 0xf8f90707, 0x07000707, 0xf9000707, 0x00070707, 0xfff90707,
+ 0x0e0e0707, 0xf1f20707, 0x15070707, 0xeaf90707, 0x07150707, 0xfffff8f9, 0x0706f8f9, 0xf8f8f8f9,
+ 0x06fff8f9, 0xf8fff8f9, 0x0006f8f9, 0xfff8f8f9, 0x0e0df8f9, 0xf1f1f8f9, 0x1506f8f9, 0xeaf8f8f9,
+ 0x0714f8f9, 0x00000700, 0x07070700, 0xf8f90700, 0x07000700, 0xf9000700, 0x00070700, 0xfff90700,
+ 0x0e0e0700, 0xf1f20700, 0x15070700, 0xeaf90700, 0x07150700, 0xfffff900, 0x0706f900, 0xf8f8f900,
+ 0x06fff900, 0xf8fff900, 0x0006f900, 0xfff8f900, 0x0e0df900, 0xf1f1f900, 0x1506f900, 0xeaf8f900,
+ 0x0714f900, 0x00000007, 0x07070007, 0xf8f90007, 0x07000007, 0xf9000007, 0x00070007, 0xfff90007,
+ 0x0e0e0007, 0xf1f20007, 0x15070007, 0xeaf90007, 0x07150007, 0xfffffff9, 0x0706fff9, 0xf8f8fff9,
+ 0x06fffff9, 0xf8fffff9, 0x0006fff9, 0xfff8fff9, 0x0e0dfff9, 0xf1f1fff9, 0x1506fff9, 0xeaf8fff9,
+ 0x0714fff9, 0x00000e0e, 0x07070e0e, 0xf8f90e0e, 0x07000e0e, 0xf9000e0e, 0x00070e0e, 0xfff90e0e,
+ 0x0e0e0e0e, 0xf1f20e0e, 0x15070e0e, 0xeaf90e0e, 0x07150e0e, 0xfffff1f2, 0x0706f1f2, 0xf8f8f1f2,
+ 0x06fff1f2, 0xf8fff1f2, 0x0006f1f2, 0xfff8f1f2, 0x0e0df1f2, 0xf1f1f1f2, 0x1506f1f2, 0xeaf8f1f2,
+ 0x0714f1f2, 0x00001507, 0x07071507, 0xf8f91507, 0x07001507, 0xf9001507, 0x00071507, 0xfff91507,
+ 0x0e0e1507, 0xf1f21507, 0x15071507, 0xeaf91507, 0x07151507, 0xffffeaf9, 0x0706eaf9, 0xf8f8eaf9,
+ 0x06ffeaf9, 0xf8ffeaf9, 0x0006eaf9, 0xfff8eaf9, 0x0e0deaf9, 0xf1f1eaf9, 0x1506eaf9, 0xeaf8eaf9,
+ 0x0714eaf9, 0x00000715, 0x07070715, 0xf8f90715, 0x07000715, 0xf9000715, 0x00070715, 0xfff90715,
+ 0x0e0e0715, 0xf1f20715, 0x15070715, 0xeaf90715, 0x07150715, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000808, 0xfffff7f8, 0x00000800, 0xfffff800, 0x00000008, 0xfffffff8, 0x00001010,
+ 0xffffeff0, 0x00001008, 0xffffeff8, 0x00000810, 0xfffff7f0, 0x00000ff0, 0xfffff010, 0x000017f8,
+ 0xffffe808, 0xfffff818, 0x000007e8, 0x00002010, 0xffffdff0, 0x00001020, 0xffffefe0, 0x00002020,
+ 0xffffdfe0, 0x00002800, 0xffffd800, 0x00000028, 0xffffffd8, 0x00001fe8, 0xffffe018, 0xffffe820,
+ 0x000017e0, 0x00004028, 0xffffbfd8, 0x00002840, 0xffffd7c0, 0x00002ff0, 0xffffd010, 0xfffff030,
+ 0x00000fd0, 0x00004010, 0xffffbff0, 0x00001040, 0xffffefc0, 0x00004040, 0xffffbfc0, 0x00004800,
+ 0xffffb800, 0x00000048, 0xffffffb8, 0x00002fd0, 0xffffd030, 0x00003fe0, 0xffffc020, 0xffffe040,
+ 0x00001fc0, 0x00006828, 0xffff97d8, 0x00002868, 0xffffd798, 0x00007048, 0xffff8fb8, 0x00004870,
+ 0xffffb790, 0x000057e8, 0xffffa818, 0xffffe858, 0x000017a8, 0x00007010, 0xffff8ff0, 0x00001070,
+ 0xffffef90, 0x00007878, 0xffff8788, 0x000057b8, 0xffffa848, 0xffffb858, 0x000047a8, 0x000077c8,
+ 0xffff8838, 0xffffc878, 0x00003788, 0x00003030, 0xffffcfd0, 0x00005858, 0xffffa7a8, 0x00000000,
+ 0x08080000, 0xf7f80000, 0x08000000, 0xf8000000, 0x00080000, 0xfff80000, 0x10100000, 0xeff00000,
+ 0x10080000, 0xeff80000, 0x08100000, 0x00000808, 0x08080808, 0xf7f80808, 0x08000808, 0xf8000808,
+ 0x00080808, 0xfff80808, 0x10100808, 0xeff00808, 0x10080808, 0xeff80808, 0x08100808, 0xfffff7f8,
+ 0x0807f7f8, 0xf7f7f7f8, 0x07fff7f8, 0xf7fff7f8, 0x0007f7f8, 0xfff7f7f8, 0x100ff7f8, 0xefeff7f8,
+ 0x1007f7f8, 0xeff7f7f8, 0x080ff7f8, 0x00000800, 0x08080800, 0xf7f80800, 0x08000800, 0xf8000800,
+ 0x00080800, 0xfff80800, 0x10100800, 0xeff00800, 0x10080800, 0xeff80800, 0x08100800, 0xfffff800,
+ 0x0807f800, 0xf7f7f800, 0x07fff800, 0xf7fff800, 0x0007f800, 0xfff7f800, 0x100ff800, 0xefeff800,
+ 0x1007f800, 0xeff7f800, 0x080ff800, 0x00000008, 0x08080008, 0xf7f80008, 0x08000008, 0xf8000008,
+ 0x00080008, 0xfff80008, 0x10100008, 0xeff00008, 0x10080008, 0xeff80008, 0x08100008, 0xfffffff8,
+ 0x0807fff8, 0xf7f7fff8, 0x07fffff8, 0xf7fffff8, 0x0007fff8, 0xfff7fff8, 0x100ffff8, 0xefeffff8,
+ 0x1007fff8, 0xeff7fff8, 0x080ffff8, 0x00001010, 0x08081010, 0xf7f81010, 0x08001010, 0xf8001010,
+ 0x00081010, 0xfff81010, 0x10101010, 0xeff01010, 0x10081010, 0xeff81010, 0x08101010, 0xffffeff0,
+ 0x0807eff0, 0xf7f7eff0, 0x07ffeff0, 0xf7ffeff0, 0x0007eff0, 0xfff7eff0, 0x100feff0, 0xefefeff0,
+ 0x1007eff0, 0xeff7eff0, 0x080feff0, 0x00001008, 0x08081008, 0xf7f81008, 0x08001008, 0xf8001008,
+ 0x00081008, 0xfff81008, 0x10101008, 0xeff01008, 0x10081008, 0xeff81008, 0x08101008, 0xffffeff8,
+ 0x0807eff8, 0xf7f7eff8, 0x07ffeff8, 0xf7ffeff8, 0x0007eff8, 0xfff7eff8, 0x100feff8, 0xefefeff8,
+ 0x1007eff8, 0xeff7eff8, 0x080feff8, 0x00000810, 0x08080810, 0xf7f80810, 0x08000810, 0xf8000810,
+ 0x00080810, 0xfff80810, 0x10100810, 0xeff00810, 0x10080810, 0xeff80810, 0x08100810, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000909, 0xfffff6f7, 0x00000900, 0xfffff700, 0x00000009, 0xfffffff7, 0x00001212,
+ 0xffffedee, 0x00001b09, 0xffffe4f7, 0x0000091b, 0xfffff6e5, 0x000011ee, 0xffffee12, 0x00001af7,
+ 0xffffe509, 0xfffff71b, 0x000008e5, 0x00002412, 0xffffdbee, 0x00001224, 0xffffeddc, 0x00002424,
+ 0xffffdbdc, 0x00002d00, 0xffffd300, 0x0000002d, 0xffffffd3, 0x000023e5, 0xffffdc1b, 0xffffe524,
+ 0x00001adc, 0x0000482d, 0xffffb7d3, 0x00002d48, 0xffffd2b8, 0x000035ee, 0xffffca12, 0xffffee36,
+ 0x000011ca, 0x00004812, 0xffffb7ee, 0x00001248, 0xffffedb8, 0x00004848, 0xffffb7b8, 0x00005100,
+ 0xffffaf00, 0x00000051, 0xffffffaf, 0x000035ca, 0xffffca36, 0x000047dc, 0xffffb824, 0xffffdc48,
+ 0x000023b8, 0x0000752d, 0xffff8ad3, 0x00002d75, 0xffffd28b, 0x00007e51, 0xffff81af, 0x0000517e,
+ 0xffffae82, 0x000062e5, 0xffff9d1b, 0xffffe563, 0x00001a9d, 0x000062af, 0xffff9d51, 0xffffaf63,
+ 0x0000509d, 0x00003636, 0xffffc9ca, 0x00006c6c, 0xffff9394, 0x00000000, 0x09090000, 0xf6f70000,
+ 0x09000000, 0xf7000000, 0x00090000, 0xfff70000, 0x12120000, 0xedee0000, 0x1b090000, 0xe4f70000,
+ 0x091b0000, 0xf6e50000, 0x00000909, 0x09090909, 0xf6f70909, 0x09000909, 0xf7000909, 0x00090909,
+ 0xfff70909, 0x12120909, 0xedee0909, 0x1b090909, 0xe4f70909, 0x091b0909, 0xf6e50909, 0xfffff6f7,
+ 0x0908f6f7, 0xf6f6f6f7, 0x08fff6f7, 0xf6fff6f7, 0x0008f6f7, 0xfff6f6f7, 0x1211f6f7, 0xededf6f7,
+ 0x1b08f6f7, 0xe4f6f6f7, 0x091af6f7, 0xf6e4f6f7, 0x00000900, 0x09090900, 0xf6f70900, 0x09000900,
+ 0xf7000900, 0x00090900, 0xfff70900, 0x12120900, 0xedee0900, 0x1b090900, 0xe4f70900, 0x091b0900,
+ 0xf6e50900, 0xfffff700, 0x0908f700, 0xf6f6f700, 0x08fff700, 0xf6fff700, 0x0008f700, 0xfff6f700,
+ 0x1211f700, 0xededf700, 0x1b08f700, 0xe4f6f700, 0x091af700, 0xf6e4f700, 0x00000009, 0x09090009,
+ 0xf6f70009, 0x09000009, 0xf7000009, 0x00090009, 0xfff70009, 0x12120009, 0xedee0009, 0x1b090009,
+ 0xe4f70009, 0x091b0009, 0xf6e50009, 0xfffffff7, 0x0908fff7, 0xf6f6fff7, 0x08fffff7, 0xf6fffff7,
+ 0x0008fff7, 0xfff6fff7, 0x1211fff7, 0xededfff7, 0x1b08fff7, 0xe4f6fff7, 0x091afff7, 0xf6e4fff7,
+ 0x00001212, 0x09091212, 0xf6f71212, 0x09001212, 0xf7001212, 0x00091212, 0xfff71212, 0x12121212,
+ 0xedee1212, 0x1b091212, 0xe4f71212, 0x091b1212, 0xf6e51212, 0xffffedee, 0x0908edee, 0xf6f6edee,
+ 0x08ffedee, 0xf6ffedee, 0x0008edee, 0xfff6edee, 0x1211edee, 0xedededee, 0x1b08edee, 0xe4f6edee,
+ 0x091aedee, 0xf6e4edee, 0x00001b09, 0x09091b09, 0xf6f71b09, 0x09001b09, 0xf7001b09, 0x00091b09,
+ 0xfff71b09, 0x12121b09, 0xedee1b09, 0x1b091b09, 0xe4f71b09, 0x091b1b09, 0xf6e51b09, 0xffffe4f7,
+ 0x0908e4f7, 0xf6f6e4f7, 0x08ffe4f7, 0xf6ffe4f7, 0x0008e4f7, 0xfff6e4f7, 0x1211e4f7, 0xedede4f7,
+ 0x1b08e4f7, 0xe4f6e4f7, 0x091ae4f7, 0xf6e4e4f7, 0x0000091b, 0x0909091b, 0xf6f7091b, 0x0900091b,
+ 0xf700091b, 0x0009091b, 0xfff7091b, 0x1212091b, 0xedee091b, 0x1b09091b, 0xe4f7091b, 0x091b091b,
+ 0xf6e5091b, 0xfffff6e5, 0x0908f6e5, 0xf6f6f6e5, 0x08fff6e5, 0xf6fff6e5, 0x0008f6e5, 0xfff6f6e5,
+ 0x1211f6e5, 0xededf6e5, 0x1b08f6e5, 0xe4f6f6e5, 0x091af6e5, 0xf6e4f6e5, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000300, 0xfffffd00, 0x00000003, 0xfffffffd, 0x00000606,
+ 0xfffff9fa, 0x00000700, 0xfffff900, 0x00000007, 0xfffffff9, 0x000004fb, 0xfffffb05, 0xfffffb05,
+ 0x000004fb, 0x00000b06, 0xfffff4fa, 0x0000060b, 0xfffff9f5, 0x00000800, 0xfffff800, 0x00000008,
+ 0xfffffff8, 0x00000b0b, 0xfffff4f5, 0x00000c00, 0xfffff400, 0x0000000c, 0xfffffff4, 0x0000110c,
+ 0xffffeef4, 0x00000c11, 0xfffff3ef, 0x00001111, 0xffffeeef, 0x00001206, 0xffffedfa, 0x00000612,
+ 0xfffff9ee, 0x00000af8, 0xfffff508, 0xfffff80b, 0x000007f5, 0x00000f00, 0xfffff100, 0x0000000f,
+ 0xfffffff1, 0x00001400, 0xffffec00, 0x00000014, 0xffffffec, 0x00001912, 0xffffe6ee, 0x00001219,
+ 0xffffede7, 0x0000190b, 0xffffe6f5, 0x00000b19, 0xfffff4e7, 0x00001919, 0xffffe6e7, 0x00000df2,
+ 0xfffff20e, 0xfffff20e, 0x00000df2, 0x00001a00, 0xffffe600, 0x0000001a, 0xffffffe6, 0x000011f5,
+ 0xffffee0b, 0xfffff512, 0x00000aee, 0x000015f9, 0xffffea07, 0xfffff916, 0x000006ea, 0x0000221a,
+ 0xffffdde6, 0x00001a22, 0xffffe5de, 0x00002212, 0xffffddee, 0x00001222, 0xffffedde, 0x00002222,
+ 0xffffddde, 0x0000230b, 0xffffdcf5, 0x00000b23, 0xfffff4dd, 0x00001d00, 0xffffe300, 0x0000001d,
+ 0xffffffe3, 0x000015ed, 0xffffea13, 0xffffed16, 0x000012ea, 0x000019f1, 0xffffe60f, 0xfffff11a,
+ 0x00000ee6, 0x00002500, 0xffffdb00, 0x00000025, 0xffffffdb, 0x00002c1b, 0xffffd3e5, 0x00001b2c,
+ 0xffffe4d4, 0x00002c24, 0xffffd3dc, 0x0000242c, 0xffffdbd4, 0x00002c12, 0xffffd3ee, 0x0000122c,
+ 0xffffedd4, 0x000020f6, 0xffffdf0a, 0xfffff621, 0x000009df, 0x00002d2d, 0xffffd2d3, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000300, 0xfffffd00, 0x00000003, 0xfffffffd, 0x00000606,
+ 0xfffff9fa, 0x00000700, 0xfffff900, 0x02020000, 0x02020202, 0x0201fdfe, 0x02020300, 0x0201fd00,
+ 0x02020003, 0x0201fffd, 0x02020606, 0x0201f9fa, 0x02020700, 0x0201f900, 0xfdfe0000, 0xfdfe0202,
+ 0xfdfdfdfe, 0xfdfe0300, 0xfdfdfd00, 0xfdfe0003, 0xfdfdfffd, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0700,
+ 0xfdfdf900, 0x03000000, 0x03000202, 0x02fffdfe, 0x03000300, 0x02fffd00, 0x03000003, 0x02fffffd,
+ 0x03000606, 0x02fff9fa, 0x03000700, 0x02fff900, 0xfd000000, 0xfd000202, 0xfcfffdfe, 0xfd000300,
+ 0xfcfffd00, 0xfd000003, 0xfcfffffd, 0xfd000606, 0xfcfff9fa, 0xfd000700, 0xfcfff900, 0x00030000,
+ 0x00030202, 0x0002fdfe, 0x00030300, 0x0002fd00, 0x00030003, 0x0002fffd, 0x00030606, 0x0002f9fa,
+ 0x00030700, 0x0002f900, 0xfffd0000, 0xfffd0202, 0xfffcfdfe, 0xfffd0300, 0xfffcfd00, 0xfffd0003,
+ 0xfffcfffd, 0xfffd0606, 0xfffcf9fa, 0xfffd0700, 0xfffcf900, 0x06060000, 0x06060202, 0x0605fdfe,
+ 0x06060300, 0x0605fd00, 0x06060003, 0x0605fffd, 0x06060606, 0x0605f9fa, 0x06060700, 0x0605f900,
+ 0xf9fa0000, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0300, 0xf9f9fd00, 0xf9fa0003, 0xf9f9fffd, 0xf9fa0606,
+ 0xf9f9f9fa, 0xf9fa0700, 0xf9f9f900, 0x07000000, 0x07000202, 0x06fffdfe, 0x07000300, 0x06fffd00,
+ 0x07000003, 0x06fffffd, 0x07000606, 0x06fff9fa, 0x07000700, 0x06fff900, 0xf9000000, 0xf9000202,
+ 0xf8fffdfe, 0xf9000300, 0xf8fffd00, 0xf9000003, 0xf8fffffd, 0xf9000606, 0xf8fff9fa, 0xf9000700,
+ 0xf8fff900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000200, 0xfffffe00, 0x00000002, 0xfffffffe, 0x00000202, 0xfffffdfe, 0x00000606,
+ 0xfffff9fa, 0x00000600, 0xfffffa00, 0x00000006, 0xfffffffa, 0x000003fc, 0xfffffc04, 0xfffffa0a,
+ 0x000005f6, 0xfffff400, 0x00000c00, 0xfffff3fa, 0xfffff406, 0x00000bfa, 0x00000c06, 0xfffffff2,
+ 0x0000000e, 0x00000c0c, 0xfffff3f4, 0xffffee00, 0x00001200, 0xfffff40e, 0x00000bf2, 0xfffff9ee,
+ 0xfffffa12, 0x000005ee, 0x00000612, 0xffffedf6, 0xffffee0a, 0x000011f6, 0x0000120a, 0xffffffea,
+ 0x00000016, 0xffffe800, 0x00001800, 0xfffff3ea, 0xfffff416, 0x00000bea, 0x00000c16, 0xffffe7f8,
+ 0xffffe808, 0x000017f8, 0x00001808, 0xfffff9e6, 0xfffffa1a, 0x000005e6, 0x0000061a, 0xffffffe4,
+ 0x0000001c, 0x00001414, 0xffffebec, 0xffffe5f2, 0x00001a0e, 0xfffff3e2, 0x00000c1e, 0xffffdff6,
+ 0x0000200a, 0xffffdfee, 0x00002012, 0xffffe5e6, 0x00001a1a, 0xffffebde, 0x00001422, 0xfffff3da,
+ 0x00000c26, 0xffffdfe0, 0x00002020, 0x00002020, 0xffffd7ea, 0xffffddde, 0x00002222, 0x00000000,
+ 0x00000200, 0xfffffe00, 0x00000002, 0xfffffffe, 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa,
+ 0x00000600, 0xfffffa00, 0x00000006, 0xfffffffa, 0x02000000, 0x02000200, 0x01fffe00, 0x02000002,
+ 0x01fffffe, 0x02000202, 0x01fffdfe, 0x02000606, 0x01fff9fa, 0x02000600, 0x01fffa00, 0x02000006,
+ 0x01fffffa, 0xfe000000, 0xfe000200, 0xfdfffe00, 0xfe000002, 0xfdfffffe, 0xfe000202, 0xfdfffdfe,
+ 0xfe000606, 0xfdfff9fa, 0xfe000600, 0xfdfffa00, 0xfe000006, 0xfdfffffa, 0x00020000, 0x00020200,
+ 0x0001fe00, 0x00020002, 0x0001fffe, 0x00020202, 0x0001fdfe, 0x00020606, 0x0001f9fa, 0x00020600,
+ 0x0001fa00, 0x00020006, 0x0001fffa, 0xfffe0000, 0xfffe0200, 0xfffdfe00, 0xfffe0002, 0xfffdfffe,
+ 0xfffe0202, 0xfffdfdfe, 0xfffe0606, 0xfffdf9fa, 0xfffe0600, 0xfffdfa00, 0xfffe0006, 0xfffdfffa,
+ 0x02020000, 0x02020200, 0x0201fe00, 0x02020002, 0x0201fffe, 0x02020202, 0x0201fdfe, 0x02020606,
+ 0x0201f9fa, 0x02020600, 0x0201fa00, 0x02020006, 0x0201fffa, 0xfdfe0000, 0xfdfe0200, 0xfdfdfe00,
+ 0xfdfe0002, 0xfdfdfffe, 0xfdfe0202, 0xfdfdfdfe, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0600, 0xfdfdfa00,
+ 0xfdfe0006, 0xfdfdfffa, 0x06060000, 0x06060200, 0x0605fe00, 0x06060002, 0x0605fffe, 0x06060202,
+ 0x0605fdfe, 0x06060606, 0x0605f9fa, 0x06060600, 0x0605fa00, 0x06060006, 0x0605fffa, 0xf9fa0000,
+ 0xf9fa0200, 0xf9f9fe00, 0xf9fa0002, 0xf9f9fffe, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0606, 0xf9f9f9fa,
+ 0xf9fa0600, 0xf9f9fa00, 0xf9fa0006, 0xf9f9fffa, 0x06000000, 0x06000200, 0x05fffe00, 0x06000002,
+ 0x05fffffe, 0x06000202, 0x05fffdfe, 0x06000606, 0x05fff9fa, 0x06000600, 0x05fffa00, 0x06000006,
+ 0x05fffffa, 0xfa000000, 0xfa000200, 0xf9fffe00, 0xfa000002, 0xf9fffffe, 0xfa000202, 0xf9fffdfe,
+ 0xfa000606, 0xf9fff9fa, 0xfa000600, 0xf9fffa00, 0xfa000006, 0xf9fffffa, 0x00060000, 0x00060200,
+ 0x0005fe00, 0x00060002, 0x0005fffe, 0x00060202, 0x0005fdfe, 0x00060606, 0x0005f9fa, 0x00060600,
+ 0x0005fa00, 0x00060006, 0x0005fffa, 0xfffa0000, 0xfffa0200, 0xfff9fe00, 0xfffa0002, 0xfff9fffe,
+ 0xfffa0202, 0xfff9fdfe, 0xfffa0606, 0xfff9f9fa, 0xfffa0600, 0xfff9fa00, 0xfffa0006, 0xfff9fffa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000200, 0xfffffe00, 0x00000002, 0xfffffffe, 0x00000404, 0xfffffbfc, 0x00000a0a,
+ 0xfffff5f6, 0x00000a00, 0xfffff600, 0x0000000a, 0xfffffff6, 0x000005fa, 0xfffffa06, 0xfffff80e,
+ 0x000007f2, 0xffffffee, 0x00000012, 0xfffff00a, 0x00000ff6, 0xffffe800, 0x00001800, 0xfffff7e8,
+ 0xfffff818, 0x000007e8, 0x00000818, 0x00001212, 0xffffedee, 0xfffff014, 0x00000fec, 0xffffe5f2,
+ 0xffffe60e, 0x000019f2, 0x00001a0e, 0xffffffe2, 0x0000001e, 0xffffde00, 0x00002200, 0xfffff7de,
+ 0xfffff822, 0x000007de, 0x00000822, 0xffffede2, 0xffffee1e, 0x000011e2, 0x0000121e, 0xffffddf6,
+ 0xffffde0a, 0x000021f6, 0x0000220a, 0xffffddec, 0x00002214, 0xffffffd8, 0x00000028, 0x00001e1e,
+ 0xffffe1e2, 0xffffedd8, 0x00001228, 0xffffd400, 0x00002c00, 0xffffd3f0, 0x00002c10, 0xffffdbdc,
+ 0xffffdbdc, 0x00002424, 0xffffd3e6, 0x00002c1a, 0xffffe5d2, 0x00001a2e, 0xffffedcc, 0x00001234,
+ 0xffffc9ec, 0xffffd3d4, 0x00002c2c, 0xffffc9e0, 0xffffd1d2, 0xffffd1d2, 0x00002e2e, 0x00000000,
+ 0x00000200, 0xfffffe00, 0x00000002, 0xfffffffe, 0x00000404, 0xfffffbfc, 0x00000a0a, 0xfffff5f6,
+ 0x00000a00, 0xfffff600, 0x0000000a, 0xfffffff6, 0x02000000, 0x02000200, 0x01fffe00, 0x02000002,
+ 0x01fffffe, 0x02000404, 0x01fffbfc, 0x02000a0a, 0x01fff5f6, 0x02000a00, 0x01fff600, 0x0200000a,
+ 0x01fffff6, 0xfe000000, 0xfe000200, 0xfdfffe00, 0xfe000002, 0xfdfffffe, 0xfe000404, 0xfdfffbfc,
+ 0xfe000a0a, 0xfdfff5f6, 0xfe000a00, 0xfdfff600, 0xfe00000a, 0xfdfffff6, 0x00020000, 0x00020200,
+ 0x0001fe00, 0x00020002, 0x0001fffe, 0x00020404, 0x0001fbfc, 0x00020a0a, 0x0001f5f6, 0x00020a00,
+ 0x0001f600, 0x0002000a, 0x0001fff6, 0xfffe0000, 0xfffe0200, 0xfffdfe00, 0xfffe0002, 0xfffdfffe,
+ 0xfffe0404, 0xfffdfbfc, 0xfffe0a0a, 0xfffdf5f6, 0xfffe0a00, 0xfffdf600, 0xfffe000a, 0xfffdfff6,
+ 0x04040000, 0x04040200, 0x0403fe00, 0x04040002, 0x0403fffe, 0x04040404, 0x0403fbfc, 0x04040a0a,
+ 0x0403f5f6, 0x04040a00, 0x0403f600, 0x0404000a, 0x0403fff6, 0xfbfc0000, 0xfbfc0200, 0xfbfbfe00,
+ 0xfbfc0002, 0xfbfbfffe, 0xfbfc0404, 0xfbfbfbfc, 0xfbfc0a0a, 0xfbfbf5f6, 0xfbfc0a00, 0xfbfbf600,
+ 0xfbfc000a, 0xfbfbfff6, 0x0a0a0000, 0x0a0a0200, 0x0a09fe00, 0x0a0a0002, 0x0a09fffe, 0x0a0a0404,
+ 0x0a09fbfc, 0x0a0a0a0a, 0x0a09f5f6, 0x0a0a0a00, 0x0a09f600, 0x0a0a000a, 0x0a09fff6, 0xf5f60000,
+ 0xf5f60200, 0xf5f5fe00, 0xf5f60002, 0xf5f5fffe, 0xf5f60404, 0xf5f5fbfc, 0xf5f60a0a, 0xf5f5f5f6,
+ 0xf5f60a00, 0xf5f5f600, 0xf5f6000a, 0xf5f5fff6, 0x0a000000, 0x0a000200, 0x09fffe00, 0x0a000002,
+ 0x09fffffe, 0x0a000404, 0x09fffbfc, 0x0a000a0a, 0x09fff5f6, 0x0a000a00, 0x09fff600, 0x0a00000a,
+ 0x09fffff6, 0xf6000000, 0xf6000200, 0xf5fffe00, 0xf6000002, 0xf5fffffe, 0xf6000404, 0xf5fffbfc,
+ 0xf6000a0a, 0xf5fff5f6, 0xf6000a00, 0xf5fff600, 0xf600000a, 0xf5fffff6, 0x000a0000, 0x000a0200,
+ 0x0009fe00, 0x000a0002, 0x0009fffe, 0x000a0404, 0x0009fbfc, 0x000a0a0a, 0x0009f5f6, 0x000a0a00,
+ 0x0009f600, 0x000a000a, 0x0009fff6, 0xfff60000, 0xfff60200, 0xfff5fe00, 0xfff60002, 0xfff5fffe,
+ 0xfff60404, 0xfff5fbfc, 0xfff60a0a, 0xfff5f5f6, 0xfff60a00, 0xfff5f600, 0xfff6000a, 0xfff5fff6,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000400, 0xfffffc00, 0x00000004, 0xfffffffc, 0x00000404, 0xfffffbfc, 0x00000c0c,
+ 0xfffff3f4, 0x00000c00, 0xfffff400, 0x0000000c, 0xfffffff4, 0x000007f8, 0xfffff808, 0xfffff008,
+ 0x00000ff8, 0xffffe800, 0x00001800, 0xfffff7e8, 0xfffff818, 0x000007e8, 0x00000818, 0xfffff014,
+ 0x00000fec, 0xffffffe4, 0x0000001c, 0xffffe7f0, 0xffffe810, 0x000017f0, 0x00001810, 0xffffe000,
+ 0x00002000, 0xffffefe4, 0xfffff01c, 0x00000fe4, 0x0000101c, 0xffffdff8, 0xffffe008, 0xfffff7e0,
+ 0xfffff820, 0x000007e0, 0x00000820, 0x00001ff8, 0x00002008, 0x00001818, 0xffffe7e8, 0xffffe818,
+ 0x000017e8, 0xffffdfec, 0x00002014, 0xffffffd8, 0x00000028, 0xffffefd8, 0x00001028, 0xffffd400,
+ 0xffffd400, 0xffffffd4, 0x0000002c, 0x00002c00, 0x00002c00, 0xffffdfe0, 0x00002020, 0xffffd3f0,
+ 0x00002c10, 0xffffd3e8, 0xffffe7d4, 0x0000182c, 0x00002c18, 0xffffefd0, 0x00001030, 0xffffdbdc,
+ 0xffffdbdc, 0x00002424, 0x00002424, 0xffffcbec, 0x00002828, 0xffffd7d8, 0xffffcbe0, 0x00000000,
+ 0x00000400, 0xfffffc00, 0x00000004, 0xfffffffc, 0x00000404, 0xfffffbfc, 0x00000c0c, 0xfffff3f4,
+ 0x00000c00, 0xfffff400, 0x0000000c, 0xfffffff4, 0x04000000, 0x04000400, 0x03fffc00, 0x04000004,
+ 0x03fffffc, 0x04000404, 0x03fffbfc, 0x04000c0c, 0x03fff3f4, 0x04000c00, 0x03fff400, 0x0400000c,
+ 0x03fffff4, 0xfc000000, 0xfc000400, 0xfbfffc00, 0xfc000004, 0xfbfffffc, 0xfc000404, 0xfbfffbfc,
+ 0xfc000c0c, 0xfbfff3f4, 0xfc000c00, 0xfbfff400, 0xfc00000c, 0xfbfffff4, 0x00040000, 0x00040400,
+ 0x0003fc00, 0x00040004, 0x0003fffc, 0x00040404, 0x0003fbfc, 0x00040c0c, 0x0003f3f4, 0x00040c00,
+ 0x0003f400, 0x0004000c, 0x0003fff4, 0xfffc0000, 0xfffc0400, 0xfffbfc00, 0xfffc0004, 0xfffbfffc,
+ 0xfffc0404, 0xfffbfbfc, 0xfffc0c0c, 0xfffbf3f4, 0xfffc0c00, 0xfffbf400, 0xfffc000c, 0xfffbfff4,
+ 0x04040000, 0x04040400, 0x0403fc00, 0x04040004, 0x0403fffc, 0x04040404, 0x0403fbfc, 0x04040c0c,
+ 0x0403f3f4, 0x04040c00, 0x0403f400, 0x0404000c, 0x0403fff4, 0xfbfc0000, 0xfbfc0400, 0xfbfbfc00,
+ 0xfbfc0004, 0xfbfbfffc, 0xfbfc0404, 0xfbfbfbfc, 0xfbfc0c0c, 0xfbfbf3f4, 0xfbfc0c00, 0xfbfbf400,
+ 0xfbfc000c, 0xfbfbfff4, 0x0c0c0000, 0x0c0c0400, 0x0c0bfc00, 0x0c0c0004, 0x0c0bfffc, 0x0c0c0404,
+ 0x0c0bfbfc, 0x0c0c0c0c, 0x0c0bf3f4, 0x0c0c0c00, 0x0c0bf400, 0x0c0c000c, 0x0c0bfff4, 0xf3f40000,
+ 0xf3f40400, 0xf3f3fc00, 0xf3f40004, 0xf3f3fffc, 0xf3f40404, 0xf3f3fbfc, 0xf3f40c0c, 0xf3f3f3f4,
+ 0xf3f40c00, 0xf3f3f400, 0xf3f4000c, 0xf3f3fff4, 0x0c000000, 0x0c000400, 0x0bfffc00, 0x0c000004,
+ 0x0bfffffc, 0x0c000404, 0x0bfffbfc, 0x0c000c0c, 0x0bfff3f4, 0x0c000c00, 0x0bfff400, 0x0c00000c,
+ 0x0bfffff4, 0xf4000000, 0xf4000400, 0xf3fffc00, 0xf4000004, 0xf3fffffc, 0xf4000404, 0xf3fffbfc,
+ 0xf4000c0c, 0xf3fff3f4, 0xf4000c00, 0xf3fff400, 0xf400000c, 0xf3fffff4, 0x000c0000, 0x000c0400,
+ 0x000bfc00, 0x000c0004, 0x000bfffc, 0x000c0404, 0x000bfbfc, 0x000c0c0c, 0x000bf3f4, 0x000c0c00,
+ 0x000bf400, 0x000c000c, 0x000bfff4, 0xfff40000, 0xfff40400, 0xfff3fc00, 0xfff40004, 0xfff3fffc,
+ 0xfff40404, 0xfff3fbfc, 0xfff40c0c, 0xfff3f3f4, 0xfff40c00, 0xfff3f400, 0xfff4000c, 0xfff3fff4,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414,
+ 0xffffebec, 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414, 0xffffebec,
+ 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x02020000, 0x02020202, 0x0201fdfe, 0x02020606,
+ 0x0201f9fa, 0x02020c0c, 0x0201f3f4, 0x02021414, 0x0201ebec, 0x02022020, 0x0201dfe0, 0x02022e2e,
+ 0x0201d1d2, 0xfdfe0000, 0xfdfe0202, 0xfdfdfdfe, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0c0c, 0xfdfdf3f4,
+ 0xfdfe1414, 0xfdfdebec, 0xfdfe2020, 0xfdfddfe0, 0xfdfe2e2e, 0xfdfdd1d2, 0x06060000, 0x06060202,
+ 0x0605fdfe, 0x06060606, 0x0605f9fa, 0x06060c0c, 0x0605f3f4, 0x06061414, 0x0605ebec, 0x06062020,
+ 0x0605dfe0, 0x06062e2e, 0x0605d1d2, 0xf9fa0000, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0606, 0xf9f9f9fa,
+ 0xf9fa0c0c, 0xf9f9f3f4, 0xf9fa1414, 0xf9f9ebec, 0xf9fa2020, 0xf9f9dfe0, 0xf9fa2e2e, 0xf9f9d1d2,
+ 0x0c0c0000, 0x0c0c0202, 0x0c0bfdfe, 0x0c0c0606, 0x0c0bf9fa, 0x0c0c0c0c, 0x0c0bf3f4, 0x0c0c1414,
+ 0x0c0bebec, 0x0c0c2020, 0x0c0bdfe0, 0x0c0c2e2e, 0x0c0bd1d2, 0xf3f40000, 0xf3f40202, 0xf3f3fdfe,
+ 0xf3f40606, 0xf3f3f9fa, 0xf3f40c0c, 0xf3f3f3f4, 0xf3f41414, 0xf3f3ebec, 0xf3f42020, 0xf3f3dfe0,
+ 0xf3f42e2e, 0xf3f3d1d2, 0x14140000, 0x14140202, 0x1413fdfe, 0x14140606, 0x1413f9fa, 0x14140c0c,
+ 0x1413f3f4, 0x14141414, 0x1413ebec, 0x14142020, 0x1413dfe0, 0x14142e2e, 0x1413d1d2, 0xebec0000,
+ 0xebec0202, 0xebebfdfe, 0xebec0606, 0xebebf9fa, 0xebec0c0c, 0xebebf3f4, 0xebec1414, 0xebebebec,
+ 0xebec2020, 0xebebdfe0, 0xebec2e2e, 0xebebd1d2, 0x20200000, 0x20200202, 0x201ffdfe, 0x20200606,
+ 0x201ff9fa, 0x20200c0c, 0x201ff3f4, 0x20201414, 0x201febec, 0x20202020, 0x201fdfe0, 0x20202e2e,
+ 0x201fd1d2, 0xdfe00000, 0xdfe00202, 0xdfdffdfe, 0xdfe00606, 0xdfdff9fa, 0xdfe00c0c, 0xdfdff3f4,
+ 0xdfe01414, 0xdfdfebec, 0xdfe02020, 0xdfdfdfe0, 0xdfe02e2e, 0xdfdfd1d2, 0x2e2e0000, 0x2e2e0202,
+ 0x2e2dfdfe, 0x2e2e0606, 0x2e2df9fa, 0x2e2e0c0c, 0x2e2df3f4, 0x2e2e1414, 0x2e2debec, 0x2e2e2020,
+ 0x2e2ddfe0, 0x2e2e2e2e, 0x2e2dd1d2, 0xd1d20000, 0xd1d20202, 0xd1d1fdfe, 0xd1d20606, 0xd1d1f9fa,
+ 0xd1d20c0c, 0xd1d1f3f4, 0xd1d21414, 0xd1d1ebec, 0xd1d22020, 0xd1d1dfe0, 0xd1d22e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414,
+ 0xffffebec, 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414, 0xffffebec,
+ 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x02020000, 0x02020202, 0x0201fdfe, 0x02020606,
+ 0x0201f9fa, 0x02020c0c, 0x0201f3f4, 0x02021414, 0x0201ebec, 0x02022020, 0x0201dfe0, 0x02022e2e,
+ 0x0201d1d2, 0xfdfe0000, 0xfdfe0202, 0xfdfdfdfe, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0c0c, 0xfdfdf3f4,
+ 0xfdfe1414, 0xfdfdebec, 0xfdfe2020, 0xfdfddfe0, 0xfdfe2e2e, 0xfdfdd1d2, 0x06060000, 0x06060202,
+ 0x0605fdfe, 0x06060606, 0x0605f9fa, 0x06060c0c, 0x0605f3f4, 0x06061414, 0x0605ebec, 0x06062020,
+ 0x0605dfe0, 0x06062e2e, 0x0605d1d2, 0xf9fa0000, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0606, 0xf9f9f9fa,
+ 0xf9fa0c0c, 0xf9f9f3f4, 0xf9fa1414, 0xf9f9ebec, 0xf9fa2020, 0xf9f9dfe0, 0xf9fa2e2e, 0xf9f9d1d2,
+ 0x0c0c0000, 0x0c0c0202, 0x0c0bfdfe, 0x0c0c0606, 0x0c0bf9fa, 0x0c0c0c0c, 0x0c0bf3f4, 0x0c0c1414,
+ 0x0c0bebec, 0x0c0c2020, 0x0c0bdfe0, 0x0c0c2e2e, 0x0c0bd1d2, 0xf3f40000, 0xf3f40202, 0xf3f3fdfe,
+ 0xf3f40606, 0xf3f3f9fa, 0xf3f40c0c, 0xf3f3f3f4, 0xf3f41414, 0xf3f3ebec, 0xf3f42020, 0xf3f3dfe0,
+ 0xf3f42e2e, 0xf3f3d1d2, 0x14140000, 0x14140202, 0x1413fdfe, 0x14140606, 0x1413f9fa, 0x14140c0c,
+ 0x1413f3f4, 0x14141414, 0x1413ebec, 0x14142020, 0x1413dfe0, 0x14142e2e, 0x1413d1d2, 0xebec0000,
+ 0xebec0202, 0xebebfdfe, 0xebec0606, 0xebebf9fa, 0xebec0c0c, 0xebebf3f4, 0xebec1414, 0xebebebec,
+ 0xebec2020, 0xebebdfe0, 0xebec2e2e, 0xebebd1d2, 0x20200000, 0x20200202, 0x201ffdfe, 0x20200606,
+ 0x201ff9fa, 0x20200c0c, 0x201ff3f4, 0x20201414, 0x201febec, 0x20202020, 0x201fdfe0, 0x20202e2e,
+ 0x201fd1d2, 0xdfe00000, 0xdfe00202, 0xdfdffdfe, 0xdfe00606, 0xdfdff9fa, 0xdfe00c0c, 0xdfdff3f4,
+ 0xdfe01414, 0xdfdfebec, 0xdfe02020, 0xdfdfdfe0, 0xdfe02e2e, 0xdfdfd1d2, 0x2e2e0000, 0x2e2e0202,
+ 0x2e2dfdfe, 0x2e2e0606, 0x2e2df9fa, 0x2e2e0c0c, 0x2e2df3f4, 0x2e2e1414, 0x2e2debec, 0x2e2e2020,
+ 0x2e2ddfe0, 0x2e2e2e2e, 0x2e2dd1d2, 0xd1d20000, 0xd1d20202, 0xd1d1fdfe, 0xd1d20606, 0xd1d1f9fa,
+ 0xd1d20c0c, 0xd1d1f3f4, 0xd1d21414, 0xd1d1ebec, 0xd1d22020, 0xd1d1dfe0, 0xd1d22e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414,
+ 0xffffebec, 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414, 0xffffebec,
+ 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x02020000, 0x02020202, 0x0201fdfe, 0x02020606,
+ 0x0201f9fa, 0x02020c0c, 0x0201f3f4, 0x02021414, 0x0201ebec, 0x02022020, 0x0201dfe0, 0x02022e2e,
+ 0x0201d1d2, 0xfdfe0000, 0xfdfe0202, 0xfdfdfdfe, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0c0c, 0xfdfdf3f4,
+ 0xfdfe1414, 0xfdfdebec, 0xfdfe2020, 0xfdfddfe0, 0xfdfe2e2e, 0xfdfdd1d2, 0x06060000, 0x06060202,
+ 0x0605fdfe, 0x06060606, 0x0605f9fa, 0x06060c0c, 0x0605f3f4, 0x06061414, 0x0605ebec, 0x06062020,
+ 0x0605dfe0, 0x06062e2e, 0x0605d1d2, 0xf9fa0000, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0606, 0xf9f9f9fa,
+ 0xf9fa0c0c, 0xf9f9f3f4, 0xf9fa1414, 0xf9f9ebec, 0xf9fa2020, 0xf9f9dfe0, 0xf9fa2e2e, 0xf9f9d1d2,
+ 0x0c0c0000, 0x0c0c0202, 0x0c0bfdfe, 0x0c0c0606, 0x0c0bf9fa, 0x0c0c0c0c, 0x0c0bf3f4, 0x0c0c1414,
+ 0x0c0bebec, 0x0c0c2020, 0x0c0bdfe0, 0x0c0c2e2e, 0x0c0bd1d2, 0xf3f40000, 0xf3f40202, 0xf3f3fdfe,
+ 0xf3f40606, 0xf3f3f9fa, 0xf3f40c0c, 0xf3f3f3f4, 0xf3f41414, 0xf3f3ebec, 0xf3f42020, 0xf3f3dfe0,
+ 0xf3f42e2e, 0xf3f3d1d2, 0x14140000, 0x14140202, 0x1413fdfe, 0x14140606, 0x1413f9fa, 0x14140c0c,
+ 0x1413f3f4, 0x14141414, 0x1413ebec, 0x14142020, 0x1413dfe0, 0x14142e2e, 0x1413d1d2, 0xebec0000,
+ 0xebec0202, 0xebebfdfe, 0xebec0606, 0xebebf9fa, 0xebec0c0c, 0xebebf3f4, 0xebec1414, 0xebebebec,
+ 0xebec2020, 0xebebdfe0, 0xebec2e2e, 0xebebd1d2, 0x20200000, 0x20200202, 0x201ffdfe, 0x20200606,
+ 0x201ff9fa, 0x20200c0c, 0x201ff3f4, 0x20201414, 0x201febec, 0x20202020, 0x201fdfe0, 0x20202e2e,
+ 0x201fd1d2, 0xdfe00000, 0xdfe00202, 0xdfdffdfe, 0xdfe00606, 0xdfdff9fa, 0xdfe00c0c, 0xdfdff3f4,
+ 0xdfe01414, 0xdfdfebec, 0xdfe02020, 0xdfdfdfe0, 0xdfe02e2e, 0xdfdfd1d2, 0x2e2e0000, 0x2e2e0202,
+ 0x2e2dfdfe, 0x2e2e0606, 0x2e2df9fa, 0x2e2e0c0c, 0x2e2df3f4, 0x2e2e1414, 0x2e2debec, 0x2e2e2020,
+ 0x2e2ddfe0, 0x2e2e2e2e, 0x2e2dd1d2, 0xd1d20000, 0xd1d20202, 0xd1d1fdfe, 0xd1d20606, 0xd1d1f9fa,
+ 0xd1d20c0c, 0xd1d1f3f4, 0xd1d21414, 0xd1d1ebec, 0xd1d22020, 0xd1d1dfe0, 0xd1d22e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414,
+ 0xffffebec, 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414, 0xffffebec,
+ 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x02020000, 0x02020202, 0x0201fdfe, 0x02020606,
+ 0x0201f9fa, 0x02020c0c, 0x0201f3f4, 0x02021414, 0x0201ebec, 0x02022020, 0x0201dfe0, 0x02022e2e,
+ 0x0201d1d2, 0xfdfe0000, 0xfdfe0202, 0xfdfdfdfe, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0c0c, 0xfdfdf3f4,
+ 0xfdfe1414, 0xfdfdebec, 0xfdfe2020, 0xfdfddfe0, 0xfdfe2e2e, 0xfdfdd1d2, 0x06060000, 0x06060202,
+ 0x0605fdfe, 0x06060606, 0x0605f9fa, 0x06060c0c, 0x0605f3f4, 0x06061414, 0x0605ebec, 0x06062020,
+ 0x0605dfe0, 0x06062e2e, 0x0605d1d2, 0xf9fa0000, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0606, 0xf9f9f9fa,
+ 0xf9fa0c0c, 0xf9f9f3f4, 0xf9fa1414, 0xf9f9ebec, 0xf9fa2020, 0xf9f9dfe0, 0xf9fa2e2e, 0xf9f9d1d2,
+ 0x0c0c0000, 0x0c0c0202, 0x0c0bfdfe, 0x0c0c0606, 0x0c0bf9fa, 0x0c0c0c0c, 0x0c0bf3f4, 0x0c0c1414,
+ 0x0c0bebec, 0x0c0c2020, 0x0c0bdfe0, 0x0c0c2e2e, 0x0c0bd1d2, 0xf3f40000, 0xf3f40202, 0xf3f3fdfe,
+ 0xf3f40606, 0xf3f3f9fa, 0xf3f40c0c, 0xf3f3f3f4, 0xf3f41414, 0xf3f3ebec, 0xf3f42020, 0xf3f3dfe0,
+ 0xf3f42e2e, 0xf3f3d1d2, 0x14140000, 0x14140202, 0x1413fdfe, 0x14140606, 0x1413f9fa, 0x14140c0c,
+ 0x1413f3f4, 0x14141414, 0x1413ebec, 0x14142020, 0x1413dfe0, 0x14142e2e, 0x1413d1d2, 0xebec0000,
+ 0xebec0202, 0xebebfdfe, 0xebec0606, 0xebebf9fa, 0xebec0c0c, 0xebebf3f4, 0xebec1414, 0xebebebec,
+ 0xebec2020, 0xebebdfe0, 0xebec2e2e, 0xebebd1d2, 0x20200000, 0x20200202, 0x201ffdfe, 0x20200606,
+ 0x201ff9fa, 0x20200c0c, 0x201ff3f4, 0x20201414, 0x201febec, 0x20202020, 0x201fdfe0, 0x20202e2e,
+ 0x201fd1d2, 0xdfe00000, 0xdfe00202, 0xdfdffdfe, 0xdfe00606, 0xdfdff9fa, 0xdfe00c0c, 0xdfdff3f4,
+ 0xdfe01414, 0xdfdfebec, 0xdfe02020, 0xdfdfdfe0, 0xdfe02e2e, 0xdfdfd1d2, 0x2e2e0000, 0x2e2e0202,
+ 0x2e2dfdfe, 0x2e2e0606, 0x2e2df9fa, 0x2e2e0c0c, 0x2e2df3f4, 0x2e2e1414, 0x2e2debec, 0x2e2e2020,
+ 0x2e2ddfe0, 0x2e2e2e2e, 0x2e2dd1d2, 0xd1d20000, 0xd1d20202, 0xd1d1fdfe, 0xd1d20606, 0xd1d1f9fa,
+ 0xd1d20c0c, 0xd1d1f3f4, 0xd1d21414, 0xd1d1ebec, 0xd1d22020, 0xd1d1dfe0, 0xd1d22e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+
+const uint32 Indeo3Decoder::correctionloworder[] = {
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd, 0x04040404,
+ 0xfbfbfbfc, 0x05050101, 0xfafafeff, 0x01010505, 0xfefefafb, 0x0403fbfc, 0xfbfc0404, 0x0605fdfe,
+ 0xf9fa0202, 0xfdfe0606, 0x0201f9fa, 0x09090404, 0xf6f6fbfc, 0x04040909, 0xfbfbf6f7, 0x09090909,
+ 0xf6f6f6f7, 0x0a0a0101, 0xf5f5feff, 0x01010a0a, 0xfefef5f6, 0x0807fafb, 0xf7f80505, 0xfafb0808,
+ 0x0504f7f8, 0x0f0f0909, 0xf0f0f6f7, 0x09090f0f, 0xf6f6f0f1, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c,
+ 0x0302f3f4, 0x10100404, 0xefeffbfc, 0x04041010, 0xfbfbeff0, 0x10101010, 0xefefeff0, 0x12120000,
+ 0xedee0000, 0x00001212, 0xffffedee, 0x0c0bf3f4, 0xf3f40c0c, 0x100ff6f7, 0xeff00909, 0xf6f71010,
+ 0x0908eff0, 0x1b1b0b0b, 0xe4e4f4f5, 0x0b0b1b1b, 0xf4f4e4e5, 0x1c1c1313, 0xe3e3eced, 0x13131c1c,
+ 0xecece3e4, 0x1615f9fa, 0xe9ea0606, 0xf9fa1616, 0x0605e9ea, 0x1d1d0404, 0xe2e2fbfc, 0x04041d1d,
+ 0xfbfbe2e3, 0x1e1e1e1e, 0xe1e1e1e2, 0x2120fdfe, 0xdedf0202, 0xfdfe2121, 0x0201dedf, 0x1716edee,
+ 0xe8e91212, 0xedee1717, 0x1211e8e9, 0x1e1df0f1, 0xe1e20f0f, 0xf0f11e1e, 0x0f0ee1e2, 0x2e2e1616,
+ 0xd1d1e9ea, 0x16162e2e, 0xe9e9d1d2, 0x2f2f0d0d, 0xd0d0f2f3, 0x0d0d2f2f, 0xf2f2d0d1, 0x31312323,
+ 0xcecedcdd, 0x23233131, 0xdcdccecf, 0x2928f4f5, 0xd6d70b0b, 0xf4f52929, 0x0b0ad6d7, 0x33330404,
+ 0xccccfbfc, 0x04043333, 0xfbfbcccd, 0x36363636, 0xc9c9c9ca, 0x2221ddde, 0xddde2222, 0x2a29e2e3,
+ 0xd5d61d1d, 0xe2e32a2a, 0x1d1cd5d6, 0x3c3bf9fa, 0xc3c40606, 0xf9fa3c3c, 0x0605c3c4, 0x4c4c1b1b,
+ 0xb3b3e4e5, 0x1b1b4c4c, 0xe4e4b3b4, 0x4d4d2b2b, 0xb2b2d4d5, 0x2b2b4d4d, 0xd4d4b2b3, 0x3736e7e8,
+ 0xc8c91818, 0xe7e83737, 0x1817c8c9, 0x4f4f0e0e, 0xb0b0f1f2, 0x0e0e4f4f, 0xf1f1b0b1, 0x53533f3f,
+ 0xacacc0c1, 0x3f3f5353, 0xc0c0acad, 0x4a49ebec, 0xb5b61414, 0xebec4a4a, 0x1413b5b6, 0x58580202,
+ 0xa7a7fdfe, 0x02025858, 0xfdfda7a8, 0x5d5d5d5d, 0xa2a2a2a3, 0x3d3ccbcc, 0xc2c33434, 0xcbcc3d3d,
+ 0x3433c2c3, 0x78783434, 0x8787cbcc, 0x34347878, 0xcbcb8788, 0x4b4ad2d3, 0xb4b52d2d, 0xd2d34b4b,
+ 0x2d2cb4b5, 0x7d7d4b4b, 0x8282b4b5, 0x4b4b7d7d, 0xb4b48283, 0x7a7a2121, 0x8585dedf, 0x21217a7a,
+ 0xdede8586, 0x6766f2f3, 0x98990d0d, 0xf2f36767, 0x0d0c9899, 0x605fd7d8, 0x9fa02828, 0xd7d86060,
+ 0x28279fa0, 0x7f7eddde, 0x80812222, 0xddde7f7f, 0x22218081, 0x5958a6a7, 0xa6a75959, 0x6968b1b2,
+ 0x96974e4e, 0xb1b26969, 0x4e4d9697, 0x0c0c0c0c, 0xf3f3f3f4, 0x17171717, 0xe8e8e8e9, 0x2a2a2a2a,
+ 0xd5d5d5d6, 0x49494949, 0xb6b6b6b7, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0x0302feff, 0x0302feff, 0x0302feff, 0x0302feff, 0x0302feff, 0x0302feff, 0x0302feff, 0xfcfd0101,
+ 0xfcfd0101, 0xfcfd0101, 0xfcfd0101, 0xfcfd0101, 0xfcfd0101, 0xfcfd0101, 0xfeff0303, 0xfeff0303,
+ 0xfeff0303, 0xfeff0303, 0xfeff0303, 0xfeff0303, 0xfeff0303, 0x0100fcfd, 0x0100fcfd, 0x0100fcfd,
+ 0x0100fcfd, 0x0100fcfd, 0x0100fcfd, 0x0100fcfd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707,
+ 0xf8f8f8f9, 0x08080202, 0xf7f7fdfe, 0x02020808, 0xfdfdf7f8, 0x0908fdfe, 0xf6f70202, 0xfdfe0909,
+ 0x0201f6f7, 0x0605f9fa, 0xf9fa0606, 0x0d0d0606, 0xf2f2f9fa, 0x06060d0d, 0xf9f9f2f3, 0x0d0d0d0d,
+ 0xf2f2f2f3, 0x0e0e0101, 0xf1f1feff, 0x01010e0e, 0xfefef1f2, 0x0c0bf7f8, 0xf3f40808, 0xf7f80c0c,
+ 0x0807f3f4, 0x17170e0e, 0xe8e8f1f2, 0x0e0e1717, 0xf1f1e8e9, 0x1211fafb, 0xedee0505, 0xfafb1212,
+ 0x0504edee, 0x18180606, 0xe7e7f9fa, 0x06061818, 0xf9f9e7e8, 0x18181818, 0xe7e7e7e8, 0x1b1afeff,
+ 0xe4e50101, 0xfeff1b1b, 0x0100e4e5, 0x1110eeef, 0xeeef1111, 0x1716f2f3, 0xe8e90d0d, 0xf2f31717,
+ 0x0d0ce8e9, 0x28281010, 0xd7d7eff0, 0x10102828, 0xefefd7d8, 0x29291c1c, 0xd6d6e3e4, 0x1c1c2929,
+ 0xe3e3d6d7, 0x2120f6f7, 0xdedf0909, 0xf6f72121, 0x0908dedf, 0x2b2b0606, 0xd4d4f9fa, 0x06062b2b,
+ 0xf9f9d4d5, 0x2e2e2e2e, 0xd1d1d1d2, 0x3231fbfc, 0xcdce0404, 0xfbfc3232, 0x0403cdce, 0x2221e4e5,
+ 0xddde1b1b, 0xe4e52222, 0x1b1addde, 0x2d2ce9ea, 0xd2d31616, 0xe9ea2d2d, 0x1615d2d3, 0x45452222,
+ 0xbabaddde, 0x22224545, 0xddddbabb, 0x46461313, 0xb9b9eced, 0x13134646, 0xececb9ba, 0x49493535,
+ 0xb6b6cacb, 0x35354949, 0xcacab6b7, 0x3e3deeef, 0xc1c21111, 0xeeef3e3e, 0x1110c1c2, 0x4d4d0505,
+ 0xb2b2fafb, 0x05054d4d, 0xfafab2b3, 0x52525252, 0xadadadae, 0x3332cccd, 0xcccd3333, 0x403fd4d5,
+ 0xbfc02b2b, 0xd4d54040, 0x2b2abfc0, 0x5a59f5f6, 0xa5a60a0a, 0xf5f65a5a, 0x0a09a5a6, 0x72722929,
+ 0x8d8dd6d7, 0x29297272, 0xd6d68d8e, 0x74744040, 0x8b8bbfc0, 0x40407474, 0xbfbf8b8c, 0x5251dadb,
+ 0xadae2525, 0xdadb5252, 0x2524adae, 0x77771616, 0x8888e9ea, 0x16167777, 0xe9e98889, 0x7c7c5f5f,
+ 0x8383a0a1, 0x5f5f7c7c, 0xa0a08384, 0x6f6ee1e2, 0x90911e1e, 0xe1e26f6f, 0x1e1d9091, 0x5c5bb1b2,
+ 0xa3a44e4e, 0xb1b25c5c, 0x4e4da3a4, 0x7170bbbc, 0x8e8f4444, 0xbbbc7171, 0x44438e8f, 0x12121212,
+ 0xedededee, 0x22222222, 0xddddddde, 0x3f3f3f3f, 0xc0c0c0c1, 0x6d6d6d6d, 0x92929293, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303,
+ 0x03030303, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd,
+ 0xfcfcfcfd, 0xfcfcfcfd, 0x0403feff, 0x0403feff, 0x0403feff, 0x0403feff, 0x0403feff, 0x0403feff,
+ 0x0403feff, 0x0403feff, 0x0403feff, 0xfbfc0101, 0xfbfc0101, 0xfbfc0101, 0xfbfc0101, 0xfbfc0101,
+ 0xfbfc0101, 0xfbfc0101, 0xfbfc0101, 0xfbfc0101, 0xfeff0404, 0xfeff0404, 0xfeff0404, 0xfeff0404,
+ 0xfeff0404, 0xfeff0404, 0xfeff0404, 0xfeff0404, 0xfeff0404, 0x0100fbfc, 0x0100fbfc, 0x0100fbfc,
+ 0x0100fbfc, 0x0100fbfc, 0x0100fbfc, 0x0100fbfc, 0x0100fbfc, 0x0100fbfc, 0x07070707, 0x07070707,
+ 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0xf8f8f8f9,
+ 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303,
+ 0xf5f5fcfd, 0x03030a0a, 0xfcfcf5f6, 0x09090909, 0xf6f6f6f7, 0x0706f8f9, 0xf8f90707, 0x0c0bfcfd,
+ 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x11110808, 0xeeeef7f8, 0x08081111, 0xf7f7eeef, 0x11111111,
+ 0xeeeeeeef, 0x13130101, 0xececfeff, 0x01011313, 0xfefeeced, 0x100ff4f5, 0xeff00b0b, 0xf4f51010,
+ 0x0b0aeff0, 0x1716f9fa, 0xe8e90606, 0xf9fa1717, 0x0605e8e9, 0x1f1f1212, 0xe0e0edee, 0x12121f1f,
+ 0xedede0e1, 0x20200808, 0xdfdff7f8, 0x08082020, 0xf7f7dfe0, 0x21212121, 0xdedededf, 0x2423feff,
+ 0xdbdc0101, 0xfeff2424, 0x0100dbdc, 0x1716e8e9, 0xe8e91717, 0x1f1eeeef, 0xe0e11111, 0xeeef1f1f,
+ 0x1110e0e1, 0x36361515, 0xc9c9eaeb, 0x15153636, 0xeaeac9ca, 0x37372525, 0xc8c8dadb, 0x25253737,
+ 0xdadac8c9, 0x2c2bf3f4, 0xd3d40c0c, 0xf3f42c2c, 0x0c0bd3d4, 0x39390808, 0xc6c6f7f8, 0x08083939,
+ 0xf7f7c6c7, 0x3d3d3d3d, 0xc2c2c2c3, 0x4241fafb, 0xbdbe0505, 0xfafb4242, 0x0504bdbe, 0x2d2cdbdc,
+ 0xd2d32424, 0xdbdc2d2d, 0x2423d2d3, 0x3c3be2e3, 0xc3c41d1d, 0xe2e33c3c, 0x1d1cc3c4, 0x5c5c2d2d,
+ 0xa3a3d2d3, 0x2d2d5c5c, 0xd2d2a3a4, 0x5d5d1919, 0xa2a2e6e7, 0x19195d5d, 0xe6e6a2a3, 0x61614747,
+ 0x9e9eb8b9, 0x47476161, 0xb8b89e9f, 0x5352e9ea, 0xacad1616, 0xe9ea5353, 0x1615acad, 0x66660707,
+ 0x9999f8f9, 0x07076666, 0xf8f8999a, 0x6d6d6d6d, 0x92929293, 0x4443bbbc, 0xbbbc4444, 0x5554c6c7,
+ 0xaaab3939, 0xc6c75555, 0x3938aaab, 0x7877f2f3, 0x87880d0d, 0xf2f37878, 0x0d0c8788, 0x6e6dcecf,
+ 0x91923131, 0xcecf6e6e, 0x31309192, 0x7b7a9798, 0x84856868, 0x97987b7b, 0x68678485, 0x18181818,
+ 0xe7e7e7e8, 0x2e2e2e2e, 0xd1d1d1d2, 0x54545454, 0xabababac, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04040404,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404,
+ 0x04040404, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0x0504feff, 0x0504feff, 0x0504feff, 0x0504feff, 0x0504feff,
+ 0x0504feff, 0x0504feff, 0x0504feff, 0x0504feff, 0x0504feff, 0xfafb0101, 0xfafb0101, 0xfafb0101,
+ 0xfafb0101, 0xfafb0101, 0xfafb0101, 0xfafb0101, 0xfafb0101, 0xfafb0101, 0xfafb0101, 0xfeff0505,
+ 0xfeff0505, 0xfeff0505, 0xfeff0505, 0xfeff0505, 0xfeff0505, 0xfeff0505, 0xfeff0505, 0xfeff0505,
+ 0xfeff0505, 0x0100fafb, 0x0100fafb, 0x0100fafb, 0x0100fafb, 0x0100fafb, 0x0100fafb, 0x0100fafb,
+ 0x0100fafb, 0x0100fafb, 0x0100fafb, 0x0a0a0303, 0x0a0a0303, 0x0a0a0303, 0x0a0a0303, 0x0a0a0303,
+ 0x0a0a0303, 0x0a0a0303, 0x0a0a0303, 0x0a0a0303, 0x0a0a0303, 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd,
+ 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd, 0x03030a0a,
+ 0x03030a0a, 0x03030a0a, 0x03030a0a, 0x03030a0a, 0x03030a0a, 0x03030a0a, 0x03030a0a, 0x03030a0a,
+ 0x03030a0a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b,
+ 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x03030d0d, 0xfcfcf2f3, 0x0908f6f7, 0xf6f70909, 0x0f0efbfc,
+ 0xf0f10404, 0xfbfc0f0f, 0x0403f0f1, 0x16160b0b, 0xe9e9f4f5, 0x0b0b1616, 0xf4f4e9ea, 0x15151515,
+ 0xeaeaeaeb, 0x18180202, 0xe7e7fdfe, 0x02021818, 0xfdfde7e8, 0x1413f1f2, 0xebec0e0e, 0xf1f21414,
+ 0x0e0debec, 0x26261717, 0xd9d9e8e9, 0x17172626, 0xe8e8d9da, 0x1d1cf7f8, 0xe2e30808, 0xf7f81d1d,
+ 0x0807e2e3, 0x27270b0b, 0xd8d8f4f5, 0x0b0b2727, 0xf4f4d8d9, 0x29292929, 0xd6d6d6d7, 0x2d2cfeff,
+ 0xd2d30101, 0xfeff2d2d, 0x0100d2d3, 0x1d1ce2e3, 0xe2e31d1d, 0x2726e9ea, 0xd8d91616, 0xe9ea2727,
+ 0x1615d8d9, 0x43431b1b, 0xbcbce4e5, 0x1b1b4343, 0xe4e4bcbd, 0x45452f2f, 0xbabad0d1, 0x2f2f4545,
+ 0xd0d0babb, 0x3837f0f1, 0xc7c80f0f, 0xf0f13838, 0x0f0ec7c8, 0x47470b0b, 0xb8b8f4f5, 0x0b0b4747,
+ 0xf4f4b8b9, 0x4c4c4c4c, 0xb3b3b3b4, 0x5352f9fa, 0xacad0606, 0xf9fa5353, 0x0605acad, 0x3938d2d3,
+ 0xc6c72d2d, 0xd2d33939, 0x2d2cc6c7, 0x4b4adbdc, 0xb4b52424, 0xdbdc4b4b, 0x2423b4b5, 0x73733838,
+ 0x8c8cc7c8, 0x38387373, 0xc7c78c8d, 0x75751f1f, 0x8a8ae0e1, 0x1f1f7575, 0xe0e08a8b, 0x7a7a5858,
+ 0x8585a7a8, 0x58587a7a, 0xa7a78586, 0x6867e3e4, 0x97981c1c, 0xe3e46868, 0x1c1b9798, 0x5554aaab,
+ 0xaaab5555, 0x6a69b7b8, 0x95964848, 0xb7b86a6a, 0x48479596, 0x1e1e1e1e, 0xe1e1e1e2, 0x3a3a3a3a,
+ 0xc5c5c5c6, 0x69696969, 0x96969697, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x05050505, 0x05050505,
+ 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505,
+ 0x05050505, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb,
+ 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe,
+ 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0xf8f90202,
+ 0xf8f90202, 0xf8f90202, 0xf8f90202, 0xf8f90202, 0xf8f90202, 0xf8f90202, 0xf8f90202, 0xf8f90202,
+ 0xf8f90202, 0xf8f90202, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707,
+ 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9,
+ 0x0201f8f9, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9,
+ 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b,
+ 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5,
+ 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0x0d0d0303, 0x0d0d0303,
+ 0x0d0d0303, 0x0d0d0303, 0x0d0d0303, 0x0d0d0303, 0x0d0d0303, 0x0d0d0303, 0x0d0d0303, 0x0d0d0303,
+ 0x0d0d0303, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd,
+ 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d,
+ 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0xfbfbf0f1, 0x0b0af4f5, 0xf4f50b0b, 0x1211fafb,
+ 0xedee0505, 0xfafb1212, 0x0504edee, 0x1a1a0d0d, 0xe5e5f2f3, 0x0d0d1a1a, 0xf2f2e5e6, 0x1a1a1a1a,
+ 0xe5e5e5e6, 0x1d1d0202, 0xe2e2fdfe, 0x02021d1d, 0xfdfde2e3, 0x1817eff0, 0xe7e81010, 0xeff01818,
+ 0x100fe7e8, 0x2e2e1c1c, 0xd1d1e3e4, 0x1c1c2e2e, 0xe3e3d1d2, 0x2322f6f7, 0xdcdd0909, 0xf6f72323,
+ 0x0908dcdd, 0x2f2f0d0d, 0xd0d0f2f3, 0x0d0d2f2f, 0xf2f2d0d1, 0x31313131, 0xcecececf, 0x3635feff,
+ 0xc9ca0101, 0xfeff3636, 0x0100c9ca, 0x2322dcdd, 0xdcdd2323, 0x2f2ee5e6, 0xd0d11a1a, 0xe5e62f2f,
+ 0x1a19d0d1, 0x51512020, 0xaeaedfe0, 0x20205151, 0xdfdfaeaf, 0x53533838, 0xacacc7c8, 0x38385353,
+ 0xc7c7acad, 0x4342edee, 0xbcbd1212, 0xedee4343, 0x1211bcbd, 0x56560d0d, 0xa9a9f2f3, 0x0d0d5656,
+ 0xf2f2a9aa, 0x5b5b5b5b, 0xa4a4a4a5, 0x6362f8f9, 0x9c9d0707, 0xf8f96363, 0x07069c9d, 0x4443c9ca,
+ 0xbbbc3636, 0xc9ca4444, 0x3635bbbc, 0x5a59d3d4, 0xa5a62c2c, 0xd3d45a5a, 0x2c2ba5a6, 0x7c7bdedf,
+ 0x83842121, 0xdedf7c7c, 0x21208384, 0x67669899, 0x98996767, 0x7f7ea9aa, 0x80815656, 0xa9aa7f7f,
+ 0x56558081, 0x25252525, 0xdadadadb, 0x45454545, 0xbabababb, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe,
+ 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0xf7f80202, 0xf7f80202, 0xf7f80202,
+ 0xf7f80202, 0xf7f80202, 0xf7f80202, 0xf7f80202, 0xf7f80202, 0xf7f80202, 0xf7f80202, 0xf7f80202,
+ 0xf7f80202, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808,
+ 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8,
+ 0x0201f7f8, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8,
+ 0x0201f7f8, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d,
+ 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3,
+ 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3,
+ 0xf2f2f2f3, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404,
+ 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc,
+ 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc,
+ 0xf0f0fbfc, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f,
+ 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010,
+ 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0xfafaedee, 0x0d0cf2f3, 0xf2f30d0d, 0x1514f9fa,
+ 0xeaeb0606, 0xf9fa1515, 0x0605eaeb, 0x1e1e0f0f, 0xe1e1f0f1, 0x0f0f1e1e, 0xf0f0e1e2, 0x1e1e1e1e,
+ 0xe1e1e1e2, 0x22220202, 0xddddfdfe, 0x02022222, 0xfdfdddde, 0x1c1beced, 0xe3e41313, 0xeced1c1c,
+ 0x1312e3e4, 0x36362020, 0xc9c9dfe0, 0x20203636, 0xdfdfc9ca, 0x2928f4f5, 0xd6d70b0b, 0xf4f52929,
+ 0x0b0ad6d7, 0x37370f0f, 0xc8c8f0f1, 0x0f0f3737, 0xf0f0c8c9, 0x39393939, 0xc6c6c6c7, 0x3f3efeff,
+ 0xc0c10101, 0xfeff3f3f, 0x0100c0c1, 0x2827d7d8, 0xd7d82828, 0x3736e1e2, 0xc8c91e1e, 0xe1e23737,
+ 0x1e1dc8c9, 0x5e5e2525, 0xa1a1dadb, 0x25255e5e, 0xdadaa1a2, 0x60604141, 0x9f9fbebf, 0x41416060,
+ 0xbebe9fa0, 0x4e4deaeb, 0xb1b21515, 0xeaeb4e4e, 0x1514b1b2, 0x64640f0f, 0x9b9bf0f1, 0x0f0f6464,
+ 0xf0f09b9c, 0x6a6a6a6a, 0x95959596, 0x7473f7f8, 0x8b8c0808, 0xf7f87474, 0x08078b8c, 0x4f4ec0c1,
+ 0xb0b13f3f, 0xc0c14f4f, 0x3f3eb0b1, 0x6968cccd, 0x96973333, 0xcccd6969, 0x33329697, 0x78778788,
+ 0x87887878, 0x2b2b2b2b, 0xd4d4d4d5, 0x50505050, 0xafafafb0, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707,
+ 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9,
+ 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9,
+ 0xf8f8f8f9, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd,
+ 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0xf5f60303, 0xf5f60303, 0xf5f60303,
+ 0xf5f60303, 0xf5f60303, 0xf5f60303, 0xf5f60303, 0xf5f60303, 0xf5f60303, 0xf5f60303, 0xf5f60303,
+ 0xf5f60303, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a,
+ 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6,
+ 0x0302f5f6, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6,
+ 0x0302f5f6, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0xefefeff0, 0xefefeff0, 0xefefeff0,
+ 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0,
+ 0xefefeff0, 0x12120505, 0x12120505, 0x12120505, 0x12120505, 0x12120505, 0x12120505, 0x12120505,
+ 0x12120505, 0x12120505, 0x12120505, 0x12120505, 0x12120505, 0xededfafb, 0xededfafb, 0xededfafb,
+ 0xededfafb, 0xededfafb, 0xededfafb, 0xededfafb, 0xededfafb, 0xededfafb, 0xededfafb, 0xededfafb,
+ 0xededfafb, 0x05051212, 0x05051212, 0x05051212, 0x05051212, 0x05051212, 0x05051212, 0x05051212,
+ 0x05051212, 0x05051212, 0x05051212, 0x05051212, 0x05051212, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212,
+ 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0xfafaebec, 0x0f0ef0f1, 0xf0f10f0f, 0x1817f8f9,
+ 0xe7e80707, 0xf8f91818, 0x0706e7e8, 0x23231111, 0xdcdceeef, 0x11112323, 0xeeeedcdd, 0x22222222,
+ 0xddddddde, 0x26260303, 0xd9d9fcfd, 0x03032626, 0xfcfcd9da, 0x201fe9ea, 0xdfe01616, 0xe9ea2020,
+ 0x1615dfe0, 0x3d3d2525, 0xc2c2dadb, 0x25253d3d, 0xdadac2c3, 0x2f2ef2f3, 0xd0d10d0d, 0xf2f32f2f,
+ 0x0d0cd0d1, 0x3f3f1111, 0xc0c0eeef, 0x11113f3f, 0xeeeec0c1, 0x41414141, 0xbebebebf, 0x4847feff,
+ 0xb7b80101, 0xfeff4848, 0x0100b7b8, 0x2e2dd1d2, 0xd1d22e2e, 0x3f3edcdd, 0xc0c12323, 0xdcdd3f3f,
+ 0x2322c0c1, 0x6b6b2b2b, 0x9494d4d5, 0x2b2b6b6b, 0xd4d49495, 0x6e6e4b4b, 0x9191b4b5, 0x4b4b6e6e,
+ 0xb4b49192, 0x5958e7e8, 0xa6a71818, 0xe7e85959, 0x1817a6a7, 0x72721111, 0x8d8deeef, 0x11117272,
+ 0xeeee8d8e, 0x79797979, 0x86868687, 0x5b5ab7b8, 0xa4a54848, 0xb7b85b5b, 0x4847a4a5, 0x7877c5c6,
+ 0x87883a3a, 0xc5c67878, 0x3a398788, 0x31313131, 0xcecececf, 0x5c5c5c5c, 0xa3a3a3a4, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808,
+ 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0xf7f7f7f8,
+ 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8,
+ 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd,
+ 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0xf4f50303,
+ 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xf4f50303,
+ 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b,
+ 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0x0302f4f5,
+ 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x0302f4f5,
+ 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212,
+ 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0xedededee,
+ 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee,
+ 0xedededee, 0xedededee, 0xedededee, 0x14140505, 0x14140505, 0x14140505, 0x14140505, 0x14140505,
+ 0x14140505, 0x14140505, 0x14140505, 0x14140505, 0x14140505, 0x14140505, 0x14140505, 0xebebfafb,
+ 0xebebfafb, 0xebebfafb, 0xebebfafb, 0xebebfafb, 0xebebfafb, 0xebebfafb, 0xebebfafb, 0xebebfafb,
+ 0xebebfafb, 0xebebfafb, 0xebebfafb, 0x05051414, 0x05051414, 0x05051414, 0x05051414, 0x05051414,
+ 0x05051414, 0x05051414, 0x05051414, 0x05051414, 0x05051414, 0x05051414, 0x05051414, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414,
+ 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x1110eeef, 0xeeef1111, 0x1b1af8f9,
+ 0xe4e50707, 0xf8f91b1b, 0x0706e4e5, 0x27271313, 0xd8d8eced, 0x13132727, 0xececd8d9, 0x27272727,
+ 0xd8d8d8d9, 0x2b2b0303, 0xd4d4fcfd, 0x03032b2b, 0xfcfcd4d5, 0x2423e7e8, 0xdbdc1818, 0xe7e82424,
+ 0x1817dbdc, 0x45452a2a, 0xbabad5d6, 0x2a2a4545, 0xd5d5babb, 0x3534f1f2, 0xcacb0e0e, 0xf1f23535,
+ 0x0e0dcacb, 0x47471313, 0xb8b8eced, 0x13134747, 0xececb8b9, 0x49494949, 0xb6b6b6b7, 0x504ffdfe,
+ 0xafb00202, 0xfdfe5050, 0x0201afb0, 0x3433cbcc, 0xcbcc3434, 0x4645d8d9, 0xb9ba2727, 0xd8d94646,
+ 0x2726b9ba, 0x79793030, 0x8686cfd0, 0x30307979, 0xcfcf8687, 0x7c7c5454, 0x8383abac, 0x54547c7c,
+ 0xabab8384, 0x6463e4e5, 0x9b9c1b1b, 0xe4e56464, 0x1b1a9b9c, 0x6665aeaf, 0x999a5151, 0xaeaf6666,
+ 0x5150999a, 0x37373737, 0xc8c8c8c9, 0x68686868, 0x97979798, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909,
+ 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0xf6f6f6f7,
+ 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7,
+ 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd,
+ 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd,
+ 0x0c0bfcfd, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303,
+ 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xfcfd0c0c, 0xfcfd0c0c,
+ 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c,
+ 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4,
+ 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0x17170606,
+ 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0xe8e8f9fa,
+ 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa,
+ 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0x06061717, 0x06061717, 0x06061717, 0x06061717,
+ 0x06061717, 0x06061717, 0x06061717, 0x06061717, 0x06061717, 0x06061717, 0x06061717, 0x06061717,
+ 0x06061717, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9,
+ 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404,
+ 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x0403fbfc, 0xfbfc0404, 0x0605fdfe,
+ 0xf9fa0202, 0xfdfe0606, 0x0201f9fa, 0x08080404, 0xf7f7fbfc, 0x04040808, 0xfbfbf7f8, 0x08080808,
+ 0xf7f7f7f8, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x0807fbfc, 0xf7f80404, 0xfbfc0808,
+ 0x0403f7f8, 0x0e0e0808, 0xf1f1f7f8, 0x08080e0e, 0xf7f7f1f2, 0x0c0bfdfe, 0xf3f40202, 0xfdfe0c0c,
+ 0x0201f3f4, 0x10100404, 0xefeffbfc, 0x04041010, 0xfbfbeff0, 0x10101010, 0xefefeff0, 0x12120000,
+ 0xedee0000, 0x00001212, 0xffffedee, 0x0c0bf3f4, 0xf3f40c0c, 0x100ff7f8, 0xeff00808, 0xf7f81010,
+ 0x0807eff0, 0x1a1a0a0a, 0xe5e5f5f6, 0x0a0a1a1a, 0xf5f5e5e6, 0x1c1c1212, 0xe3e3edee, 0x12121c1c,
+ 0xedede3e4, 0x1615f9fa, 0xe9ea0606, 0xf9fa1616, 0x0605e9ea, 0x1c1c0404, 0xe3e3fbfc, 0x04041c1c,
+ 0xfbfbe3e4, 0x1e1e1e1e, 0xe1e1e1e2, 0x201ffdfe, 0xdfe00202, 0xfdfe2020, 0x0201dfe0, 0x1615edee,
+ 0xe9ea1212, 0xedee1616, 0x1211e9ea, 0x1e1df1f2, 0xe1e20e0e, 0xf1f21e1e, 0x0e0de1e2, 0x2e2e1616,
+ 0xd1d1e9ea, 0x16162e2e, 0xe9e9d1d2, 0x2e2e0c0c, 0xd1d1f3f4, 0x0c0c2e2e, 0xf3f3d1d2, 0x30302222,
+ 0xcfcfddde, 0x22223030, 0xddddcfd0, 0x2827f5f6, 0xd7d80a0a, 0xf5f62828, 0x0a09d7d8, 0x32320404,
+ 0xcdcdfbfc, 0x04043232, 0xfbfbcdce, 0x36363636, 0xc9c9c9ca, 0x2221ddde, 0xddde2222, 0x2a29e3e4,
+ 0xd5d61c1c, 0xe3e42a2a, 0x1c1bd5d6, 0x3c3bf9fa, 0xc3c40606, 0xf9fa3c3c, 0x0605c3c4, 0x4c4c1a1a,
+ 0xb3b3e5e6, 0x1a1a4c4c, 0xe5e5b3b4, 0x4c4c2a2a, 0xb3b3d5d6, 0x2a2a4c4c, 0xd5d5b3b4, 0x3635e7e8,
+ 0xc9ca1818, 0xe7e83636, 0x1817c9ca, 0x4e4e0e0e, 0xb1b1f1f2, 0x0e0e4e4e, 0xf1f1b1b2, 0x52523e3e,
+ 0xadadc1c2, 0x3e3e5252, 0xc1c1adae, 0x4a49ebec, 0xb5b61414, 0xebec4a4a, 0x1413b5b6, 0x58580202,
+ 0xa7a7fdfe, 0x02025858, 0xfdfda7a8, 0x5c5c5c5c, 0xa3a3a3a4, 0x3c3bcbcc, 0xc3c43434, 0xcbcc3c3c,
+ 0x3433c3c4, 0x76763434, 0x8989cbcc, 0x34347676, 0xcbcb898a, 0x4a49d3d4, 0xb5b62c2c, 0xd3d44a4a,
+ 0x2c2bb5b6, 0x76764a4a, 0x8989b5b6, 0x4a4a7676, 0xb5b5898a, 0x76762020, 0x8989dfe0, 0x20207676,
+ 0xdfdf898a, 0x6665f3f4, 0x999a0c0c, 0xf3f46666, 0x0c0b999a, 0x605fd7d8, 0x9fa02828, 0xd7d86060,
+ 0x28279fa0, 0x7675ddde, 0x898a2222, 0xddde7676, 0x2221898a, 0x5857a7a8, 0xa7a85858, 0x6867b1b2,
+ 0x97984e4e, 0xb1b26868, 0x4e4d9798, 0x0c0c0c0c, 0xf3f3f3f4, 0x16161616, 0xe9e9e9ea, 0x2a2a2a2a,
+ 0xd5d5d5d6, 0x48484848, 0xb7b7b7b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0xfdfe0000,
+ 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0x00000202, 0x00000202,
+ 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe,
+ 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606,
+ 0xf9f9f9fa, 0x09090303, 0xf6f6fcfd, 0x03030909, 0xfcfcf6f7, 0x0908fcfd, 0xf6f70303, 0xfcfd0909,
+ 0x0302f6f7, 0x0605f9fa, 0xf9fa0606, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0xf9f9f3f4, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x0f0f0000, 0xf0f10000, 0x00000f0f, 0xfffff0f1, 0x0c0bf6f7, 0xf3f40909, 0xf6f70c0c,
+ 0x0908f3f4, 0x18180f0f, 0xe7e7f0f1, 0x0f0f1818, 0xf0f0e7e8, 0x1211f9fa, 0xedee0606, 0xf9fa1212,
+ 0x0605edee, 0x18180606, 0xe7e7f9fa, 0x06061818, 0xf9f9e7e8, 0x18181818, 0xe7e7e7e8, 0x1b1b0000,
+ 0xe4e50000, 0x00001b1b, 0xffffe4e5, 0x1211edee, 0xedee1212, 0x1817f3f4, 0xe7e80c0c, 0xf3f41818,
+ 0x0c0be7e8, 0x27270f0f, 0xd8d8f0f1, 0x0f0f2727, 0xf0f0d8d9, 0x2a2a1b1b, 0xd5d5e4e5, 0x1b1b2a2a,
+ 0xe4e4d5d6, 0x2120f6f7, 0xdedf0909, 0xf6f72121, 0x0908dedf, 0x2a2a0606, 0xd5d5f9fa, 0x06062a2a,
+ 0xf9f9d5d6, 0x2d2d2d2d, 0xd2d2d2d3, 0x3332fcfd, 0xcccd0303, 0xfcfd3333, 0x0302cccd, 0x2120e4e5,
+ 0xdedf1b1b, 0xe4e52121, 0x1b1adedf, 0x2d2ceaeb, 0xd2d31515, 0xeaeb2d2d, 0x1514d2d3, 0x45452121,
+ 0xbabadedf, 0x21214545, 0xdedebabb, 0x45451212, 0xbabaedee, 0x12124545, 0xededbabb, 0x48483636,
+ 0xb7b7c9ca, 0x36364848, 0xc9c9b7b8, 0x3f3eedee, 0xc0c11212, 0xedee3f3f, 0x1211c0c1, 0x4e4e0606,
+ 0xb1b1f9fa, 0x06064e4e, 0xf9f9b1b2, 0x51515151, 0xaeaeaeaf, 0x3332cccd, 0xcccd3333, 0x3f3ed5d6,
+ 0xc0c12a2a, 0xd5d63f3f, 0x2a29c0c1, 0x5a59f6f7, 0xa5a60909, 0xf6f75a5a, 0x0908a5a6, 0x72722a2a,
+ 0x8d8dd5d6, 0x2a2a7272, 0xd5d58d8e, 0x75753f3f, 0x8a8ac0c1, 0x3f3f7575, 0xc0c08a8b, 0x5150dbdc,
+ 0xaeaf2424, 0xdbdc5151, 0x2423aeaf, 0x78781515, 0x8787eaeb, 0x15157878, 0xeaea8788, 0x7b7b6060,
+ 0x84849fa0, 0x60607b7b, 0x9f9f8485, 0x6f6ee1e2, 0x90911e1e, 0xe1e26f6f, 0x1e1d9091, 0x5d5cb1b2,
+ 0xa2a34e4e, 0xb1b25d5d, 0x4e4da2a3, 0x7271babb, 0x8d8e4545, 0xbabb7272, 0x45448d8e, 0x12121212,
+ 0xedededee, 0x21212121, 0xdedededf, 0x3f3f3f3f, 0xc0c0c0c1, 0x6c6c6c6c, 0x93939394, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303,
+ 0x03030303, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd,
+ 0xfcfcfcfd, 0xfcfcfcfd, 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0x03030000,
+ 0x03030000, 0x03030000, 0x03030000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000,
+ 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0x00000303, 0x00000303, 0x00000303, 0x00000303,
+ 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd,
+ 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404,
+ 0xf7f7fbfc, 0x04040808, 0xfbfbf7f8, 0x08080808, 0xf7f7f7f8, 0x0807f7f8, 0xf7f80808, 0x0c0bfbfc,
+ 0xf3f40404, 0xfbfc0c0c, 0x0403f3f4, 0x10100808, 0xefeff7f8, 0x08081010, 0xf7f7eff0, 0x10101010,
+ 0xefefeff0, 0x14140000, 0xebec0000, 0x00001414, 0xffffebec, 0x100ff3f4, 0xeff00c0c, 0xf3f41010,
+ 0x0c0beff0, 0x1817fbfc, 0xe7e80404, 0xfbfc1818, 0x0403e7e8, 0x20201010, 0xdfdfeff0, 0x10102020,
+ 0xefefdfe0, 0x20200808, 0xdfdff7f8, 0x08082020, 0xf7f7dfe0, 0x20202020, 0xdfdfdfe0, 0x24240000,
+ 0xdbdc0000, 0x00002424, 0xffffdbdc, 0x1817e7e8, 0xe7e81818, 0x201feff0, 0xdfe01010, 0xeff02020,
+ 0x100fdfe0, 0x34341414, 0xcbcbebec, 0x14143434, 0xebebcbcc, 0x38382424, 0xc7c7dbdc, 0x24243838,
+ 0xdbdbc7c8, 0x2c2bf3f4, 0xd3d40c0c, 0xf3f42c2c, 0x0c0bd3d4, 0x38380808, 0xc7c7f7f8, 0x08083838,
+ 0xf7f7c7c8, 0x3c3c3c3c, 0xc3c3c3c4, 0x403ffbfc, 0xbfc00404, 0xfbfc4040, 0x0403bfc0, 0x2c2bdbdc,
+ 0xd3d42424, 0xdbdc2c2c, 0x2423d3d4, 0x3c3be3e4, 0xc3c41c1c, 0xe3e43c3c, 0x1c1bc3c4, 0x5c5c2c2c,
+ 0xa3a3d3d4, 0x2c2c5c5c, 0xd3d3a3a4, 0x5c5c1818, 0xa3a3e7e8, 0x18185c5c, 0xe7e7a3a4, 0x60604848,
+ 0x9f9fb7b8, 0x48486060, 0xb7b79fa0, 0x5453ebec, 0xabac1414, 0xebec5454, 0x1413abac, 0x64640808,
+ 0x9b9bf7f8, 0x08086464, 0xf7f79b9c, 0x6c6c6c6c, 0x93939394, 0x4443bbbc, 0xbbbc4444, 0x5453c7c8,
+ 0xabac3838, 0xc7c85454, 0x3837abac, 0x7877f3f4, 0x87880c0c, 0xf3f47878, 0x0c0b8788, 0x6c6bcfd0,
+ 0x93943030, 0xcfd06c6c, 0x302f9394, 0x7c7b9798, 0x83846868, 0x97987c7c, 0x68678384, 0x18181818,
+ 0xe7e7e7e8, 0x2c2c2c2c, 0xd3d3d3d4, 0x54545454, 0xabababac, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04040404,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404,
+ 0x04040404, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000,
+ 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000,
+ 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0x00000404,
+ 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404,
+ 0x00000404, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc,
+ 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0x08080404, 0x08080404, 0x08080404, 0x08080404, 0x08080404,
+ 0x08080404, 0x08080404, 0x08080404, 0x08080404, 0x08080404, 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc,
+ 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc, 0x04040808,
+ 0x04040808, 0x04040808, 0x04040808, 0x04040808, 0x04040808, 0x04040808, 0x04040808, 0x04040808,
+ 0x04040808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a,
+ 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x05050f0f, 0xfafaf0f1, 0x0a09f5f6, 0xf5f60a0a, 0x0f0efafb,
+ 0xf0f10505, 0xfafb0f0f, 0x0504f0f1, 0x14140a0a, 0xebebf5f6, 0x0a0a1414, 0xf5f5ebec, 0x14141414,
+ 0xebebebec, 0x19190000, 0xe6e70000, 0x00001919, 0xffffe6e7, 0x1413f0f1, 0xebec0f0f, 0xf0f11414,
+ 0x0f0eebec, 0x28281919, 0xd7d7e6e7, 0x19192828, 0xe6e6d7d8, 0x1e1df5f6, 0xe1e20a0a, 0xf5f61e1e,
+ 0x0a09e1e2, 0x28280a0a, 0xd7d7f5f6, 0x0a0a2828, 0xf5f5d7d8, 0x28282828, 0xd7d7d7d8, 0x2d2d0000,
+ 0xd2d30000, 0x00002d2d, 0xffffd2d3, 0x1e1de1e2, 0xe1e21e1e, 0x2827ebec, 0xd7d81414, 0xebec2828,
+ 0x1413d7d8, 0x41411919, 0xbebee6e7, 0x19194141, 0xe6e6bebf, 0x46462d2d, 0xb9b9d2d3, 0x2d2d4646,
+ 0xd2d2b9ba, 0x3736f0f1, 0xc8c90f0f, 0xf0f13737, 0x0f0ec8c9, 0x46460a0a, 0xb9b9f5f6, 0x0a0a4646,
+ 0xf5f5b9ba, 0x4b4b4b4b, 0xb4b4b4b5, 0x5554fafb, 0xaaab0505, 0xfafb5555, 0x0504aaab, 0x3736d2d3,
+ 0xc8c92d2d, 0xd2d33737, 0x2d2cc8c9, 0x4b4adcdd, 0xb4b52323, 0xdcdd4b4b, 0x2322b4b5, 0x73733737,
+ 0x8c8cc8c9, 0x37377373, 0xc8c88c8d, 0x73731e1e, 0x8c8ce1e2, 0x1e1e7373, 0xe1e18c8d, 0x78785a5a,
+ 0x8787a5a6, 0x5a5a7878, 0xa5a58788, 0x6968e1e2, 0x96971e1e, 0xe1e26969, 0x1e1d9697, 0x5554aaab,
+ 0xaaab5555, 0x6968b9ba, 0x96974646, 0xb9ba6969, 0x46459697, 0x1e1e1e1e, 0xe1e1e1e2, 0x3c3c3c3c,
+ 0xc3c3c3c4, 0x69696969, 0x96969697, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x05050505, 0x05050505,
+ 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505,
+ 0x05050505, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb,
+ 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0x05050000, 0x05050000, 0x05050000, 0x05050000,
+ 0x05050000, 0x05050000, 0x05050000, 0x05050000, 0x05050000, 0x05050000, 0x05050000, 0xfafb0000,
+ 0xfafb0000, 0xfafb0000, 0xfafb0000, 0xfafb0000, 0xfafb0000, 0xfafb0000, 0xfafb0000, 0xfafb0000,
+ 0xfafb0000, 0xfafb0000, 0x00000505, 0x00000505, 0x00000505, 0x00000505, 0x00000505, 0x00000505,
+ 0x00000505, 0x00000505, 0x00000505, 0x00000505, 0x00000505, 0xfffffafb, 0xfffffafb, 0xfffffafb,
+ 0xfffffafb, 0xfffffafb, 0xfffffafb, 0xfffffafb, 0xfffffafb, 0xfffffafb, 0xfffffafb, 0xfffffafb,
+ 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a,
+ 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6,
+ 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0x0f0f0505, 0x0f0f0505,
+ 0x0f0f0505, 0x0f0f0505, 0x0f0f0505, 0x0f0f0505, 0x0f0f0505, 0x0f0f0505, 0x0f0f0505, 0x0f0f0505,
+ 0x0f0f0505, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb,
+ 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0xf9f9f3f4, 0x0c0bf3f4, 0xf3f40c0c, 0x1211f9fa,
+ 0xedee0606, 0xf9fa1212, 0x0605edee, 0x18180c0c, 0xe7e7f3f4, 0x0c0c1818, 0xf3f3e7e8, 0x18181818,
+ 0xe7e7e7e8, 0x1e1e0000, 0xe1e20000, 0x00001e1e, 0xffffe1e2, 0x1817edee, 0xe7e81212, 0xedee1818,
+ 0x1211e7e8, 0x30301e1e, 0xcfcfe1e2, 0x1e1e3030, 0xe1e1cfd0, 0x2423f9fa, 0xdbdc0606, 0xf9fa2424,
+ 0x0605dbdc, 0x30300c0c, 0xcfcff3f4, 0x0c0c3030, 0xf3f3cfd0, 0x30303030, 0xcfcfcfd0, 0x36360000,
+ 0xc9ca0000, 0x00003636, 0xffffc9ca, 0x2423dbdc, 0xdbdc2424, 0x302fe7e8, 0xcfd01818, 0xe7e83030,
+ 0x1817cfd0, 0x4e4e1e1e, 0xb1b1e1e2, 0x1e1e4e4e, 0xe1e1b1b2, 0x54543636, 0xababc9ca, 0x36365454,
+ 0xc9c9abac, 0x4241edee, 0xbdbe1212, 0xedee4242, 0x1211bdbe, 0x54540c0c, 0xababf3f4, 0x0c0c5454,
+ 0xf3f3abac, 0x5a5a5a5a, 0xa5a5a5a6, 0x605ff9fa, 0x9fa00606, 0xf9fa6060, 0x06059fa0, 0x4241c9ca,
+ 0xbdbe3636, 0xc9ca4242, 0x3635bdbe, 0x5a59d5d6, 0xa5a62a2a, 0xd5d65a5a, 0x2a29a5a6, 0x7e7de1e2,
+ 0x81821e1e, 0xe1e27e7e, 0x1e1d8182, 0x6665999a, 0x999a6666, 0x7e7dabac, 0x81825454, 0xabac7e7e,
+ 0x54538182, 0x24242424, 0xdbdbdbdc, 0x42424242, 0xbdbdbdbe, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000,
+ 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000,
+ 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000,
+ 0xf9fa0000, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606,
+ 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa,
+ 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa,
+ 0xfffff9fa, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606,
+ 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa,
+ 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa,
+ 0xf3f3f9fa, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c,
+ 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e,
+ 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0xf8f8eaeb, 0x0e0df1f2, 0xf1f20e0e, 0x1514f8f9,
+ 0xeaeb0707, 0xf8f91515, 0x0706eaeb, 0x1c1c0e0e, 0xe3e3f1f2, 0x0e0e1c1c, 0xf1f1e3e4, 0x1c1c1c1c,
+ 0xe3e3e3e4, 0x23230000, 0xdcdd0000, 0x00002323, 0xffffdcdd, 0x1c1beaeb, 0xe3e41515, 0xeaeb1c1c,
+ 0x1514e3e4, 0x38382323, 0xc7c7dcdd, 0x23233838, 0xdcdcc7c8, 0x2a29f1f2, 0xd5d60e0e, 0xf1f22a2a,
+ 0x0e0dd5d6, 0x38380e0e, 0xc7c7f1f2, 0x0e0e3838, 0xf1f1c7c8, 0x38383838, 0xc7c7c7c8, 0x3f3f0000,
+ 0xc0c10000, 0x00003f3f, 0xffffc0c1, 0x2a29d5d6, 0xd5d62a2a, 0x3837e3e4, 0xc7c81c1c, 0xe3e43838,
+ 0x1c1bc7c8, 0x5b5b2323, 0xa4a4dcdd, 0x23235b5b, 0xdcdca4a5, 0x62623f3f, 0x9d9dc0c1, 0x3f3f6262,
+ 0xc0c09d9e, 0x4d4ceaeb, 0xb2b31515, 0xeaeb4d4d, 0x1514b2b3, 0x62620e0e, 0x9d9df1f2, 0x0e0e6262,
+ 0xf1f19d9e, 0x69696969, 0x96969697, 0x7776f8f9, 0x88890707, 0xf8f97777, 0x07068889, 0x4d4cc0c1,
+ 0xb2b33f3f, 0xc0c14d4d, 0x3f3eb2b3, 0x6968cecf, 0x96973131, 0xcecf6969, 0x31309697, 0x77768889,
+ 0x88897777, 0x2a2a2a2a, 0xd5d5d5d6, 0x4d4d4d4d, 0xb2b2b2b3, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707,
+ 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9,
+ 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9,
+ 0xf8f8f8f9, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000,
+ 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0xf8f90000, 0xf8f90000, 0xf8f90000,
+ 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000,
+ 0xf8f90000, 0x00000707, 0x00000707, 0x00000707, 0x00000707, 0x00000707, 0x00000707, 0x00000707,
+ 0x00000707, 0x00000707, 0x00000707, 0x00000707, 0x00000707, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9,
+ 0xfffff8f9, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9,
+ 0xfffff8f9, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e,
+ 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2,
+ 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2,
+ 0xf1f1f1f2, 0x15150707, 0x15150707, 0x15150707, 0x15150707, 0x15150707, 0x15150707, 0x15150707,
+ 0x15150707, 0x15150707, 0x15150707, 0x15150707, 0x15150707, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9,
+ 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9,
+ 0xeaeaf8f9, 0x07071515, 0x07071515, 0x07071515, 0x07071515, 0x07071515, 0x07071515, 0x07071515,
+ 0x07071515, 0x07071515, 0x07071515, 0x07071515, 0x07071515, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010,
+ 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0xf7f7eff0, 0x100feff0, 0xeff01010, 0x1817f7f8,
+ 0xe7e80808, 0xf7f81818, 0x0807e7e8, 0x20201010, 0xdfdfeff0, 0x10102020, 0xefefdfe0, 0x20202020,
+ 0xdfdfdfe0, 0x28280000, 0xd7d80000, 0x00002828, 0xffffd7d8, 0x201fe7e8, 0xdfe01818, 0xe7e82020,
+ 0x1817dfe0, 0x40402828, 0xbfbfd7d8, 0x28284040, 0xd7d7bfc0, 0x302feff0, 0xcfd01010, 0xeff03030,
+ 0x100fcfd0, 0x40401010, 0xbfbfeff0, 0x10104040, 0xefefbfc0, 0x40404040, 0xbfbfbfc0, 0x48480000,
+ 0xb7b80000, 0x00004848, 0xffffb7b8, 0x302fcfd0, 0xcfd03030, 0x403fdfe0, 0xbfc02020, 0xdfe04040,
+ 0x201fbfc0, 0x68682828, 0x9797d7d8, 0x28286868, 0xd7d79798, 0x70704848, 0x8f8fb7b8, 0x48487070,
+ 0xb7b78f90, 0x5857e7e8, 0xa7a81818, 0xe7e85858, 0x1817a7a8, 0x70701010, 0x8f8feff0, 0x10107070,
+ 0xefef8f90, 0x78787878, 0x87878788, 0x5857b7b8, 0xa7a84848, 0xb7b85858, 0x4847a7a8, 0x7877c7c8,
+ 0x87883838, 0xc7c87878, 0x38378788, 0x30303030, 0xcfcfcfd0, 0x58585858, 0xa7a7a7a8, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808,
+ 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0xf7f7f7f8,
+ 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8,
+ 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0x08080000, 0x08080000, 0x08080000, 0x08080000, 0x08080000,
+ 0x08080000, 0x08080000, 0x08080000, 0x08080000, 0x08080000, 0x08080000, 0x08080000, 0xf7f80000,
+ 0xf7f80000, 0xf7f80000, 0xf7f80000, 0xf7f80000, 0xf7f80000, 0xf7f80000, 0xf7f80000, 0xf7f80000,
+ 0xf7f80000, 0xf7f80000, 0xf7f80000, 0x00000808, 0x00000808, 0x00000808, 0x00000808, 0x00000808,
+ 0x00000808, 0x00000808, 0x00000808, 0x00000808, 0x00000808, 0x00000808, 0x00000808, 0xfffff7f8,
+ 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0xfffff7f8,
+ 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0xefefeff0,
+ 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0,
+ 0xefefeff0, 0xefefeff0, 0xefefeff0, 0x10100808, 0x10100808, 0x10100808, 0x10100808, 0x10100808,
+ 0x10100808, 0x10100808, 0x10100808, 0x10100808, 0x10100808, 0x10100808, 0x10100808, 0xefeff7f8,
+ 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0xefeff7f8,
+ 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0x08081010, 0x08081010, 0x08081010, 0x08081010, 0x08081010,
+ 0x08081010, 0x08081010, 0x08081010, 0x08081010, 0x08081010, 0x08081010, 0x08081010, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212,
+ 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x1211edee, 0xedee1212, 0x1b1af6f7,
+ 0xe4e50909, 0xf6f71b1b, 0x0908e4e5, 0x24241212, 0xdbdbedee, 0x12122424, 0xededdbdc, 0x24242424,
+ 0xdbdbdbdc, 0x2d2d0000, 0xd2d30000, 0x00002d2d, 0xffffd2d3, 0x2423e4e5, 0xdbdc1b1b, 0xe4e52424,
+ 0x1b1adbdc, 0x48482d2d, 0xb7b7d2d3, 0x2d2d4848, 0xd2d2b7b8, 0x3635edee, 0xc9ca1212, 0xedee3636,
+ 0x1211c9ca, 0x48481212, 0xb7b7edee, 0x12124848, 0xededb7b8, 0x48484848, 0xb7b7b7b8, 0x51510000,
+ 0xaeaf0000, 0x00005151, 0xffffaeaf, 0x3635c9ca, 0xc9ca3636, 0x4847dbdc, 0xb7b82424, 0xdbdc4848,
+ 0x2423b7b8, 0x75752d2d, 0x8a8ad2d3, 0x2d2d7575, 0xd2d28a8b, 0x7e7e5151, 0x8181aeaf, 0x51517e7e,
+ 0xaeae8182, 0x6362e4e5, 0x9c9d1b1b, 0xe4e56363, 0x1b1a9c9d, 0x6362aeaf, 0x9c9d5151, 0xaeaf6363,
+ 0x51509c9d, 0x36363636, 0xc9c9c9ca, 0x6c6c6c6c, 0x93939394, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909,
+ 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0xf6f6f6f7,
+ 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7,
+ 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0x09090000, 0x09090000, 0x09090000, 0x09090000,
+ 0x09090000, 0x09090000, 0x09090000, 0x09090000, 0x09090000, 0x09090000, 0x09090000, 0x09090000,
+ 0x09090000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000,
+ 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0x00000909, 0x00000909,
+ 0x00000909, 0x00000909, 0x00000909, 0x00000909, 0x00000909, 0x00000909, 0x00000909, 0x00000909,
+ 0x00000909, 0x00000909, 0x00000909, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7,
+ 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7,
+ 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212,
+ 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0xedededee, 0xedededee, 0xedededee,
+ 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee,
+ 0xedededee, 0xedededee, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909,
+ 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0xe4e4f6f7,
+ 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7,
+ 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b,
+ 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b,
+ 0x09091b1b, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5,
+ 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606,
+ 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0504fafb, 0xfafb0505, 0xfafb0505,
+ 0x0504fafb, 0x0b0b0606, 0xf4f4f9fa, 0x06060b0b, 0xf9f9f4f5, 0x08080000, 0xf7f80000, 0x00000808,
+ 0xfffff7f8, 0x0b0b0b0b, 0xf4f4f4f5, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x11110c0c,
+ 0xeeeef3f4, 0x0c0c1111, 0xf3f3eeef, 0x11111111, 0xeeeeeeef, 0x12120606, 0xededf9fa, 0x06061212,
+ 0xf9f9edee, 0x0b0af7f8, 0xf4f50808, 0xf7f80b0b, 0x0807f4f5, 0x0f0f0000, 0xf0f10000, 0x00000f0f,
+ 0xfffff0f1, 0x14140000, 0xebec0000, 0x00001414, 0xffffebec, 0x19191212, 0xe6e6edee, 0x12121919,
+ 0xedede6e7, 0x19190b0b, 0xe6e6f4f5, 0x0b0b1919, 0xf4f4e6e7, 0x19191919, 0xe6e6e6e7, 0x0e0df1f2,
+ 0xf1f20e0e, 0xf1f20e0e, 0x0e0df1f2, 0x1a1a0000, 0xe5e60000, 0x00001a1a, 0xffffe5e6, 0x1211f4f5,
+ 0xedee0b0b, 0xf4f51212, 0x0b0aedee, 0x1615f8f9, 0xe9ea0707, 0xf8f91616, 0x0706e9ea, 0x22221a1a,
+ 0xdddde5e6, 0x1a1a2222, 0xe5e5ddde, 0x22221212, 0xddddedee, 0x12122222, 0xededddde, 0x22222222,
+ 0xddddddde, 0x23230b0b, 0xdcdcf4f5, 0x0b0b2323, 0xf4f4dcdd, 0x1d1d0000, 0xe2e30000, 0x00001d1d,
+ 0xffffe2e3, 0x1615eced, 0xe9ea1313, 0xeced1616, 0x1312e9ea, 0x1a19f0f1, 0xe5e60f0f, 0xf0f11a1a,
+ 0x0f0ee5e6, 0x25250000, 0xdadb0000, 0x00002525, 0xffffdadb, 0x2c2c1b1b, 0xd3d3e4e5, 0x1b1b2c2c,
+ 0xe4e4d3d4, 0x2c2c2424, 0xd3d3dbdc, 0x24242c2c, 0xdbdbd3d4, 0x2c2c1212, 0xd3d3edee, 0x12122c2c,
+ 0xededd3d4, 0x2120f5f6, 0xdedf0a0a, 0xf5f62121, 0x0a09dedf, 0x2d2d2d2d, 0xd2d2d2d3, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606,
+ 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000,
+ 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000,
+ 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd,
+ 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000,
+ 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa,
+ 0x07070000, 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303,
+ 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606,
+ 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000,
+ 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000,
+ 0xf8f90000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0403fbfc, 0xfbfc0404, 0xf9fa0a0a,
+ 0x0605f5f6, 0xf3f40000, 0x0c0c0000, 0xf3f3f9fa, 0xf3f40606, 0x0c0bf9fa, 0x0c0c0606, 0xfffff1f2,
+ 0x00000e0e, 0x0c0c0c0c, 0xf3f3f3f4, 0xedee0000, 0x12120000, 0xf3f40e0e, 0x0c0bf1f2, 0xf9f9edee,
+ 0xf9fa1212, 0x0605edee, 0x06061212, 0xededf5f6, 0xedee0a0a, 0x1211f5f6, 0x12120a0a, 0xffffe9ea,
+ 0x00001616, 0xe7e80000, 0x18180000, 0xf3f3e9ea, 0xf3f41616, 0x0c0be9ea, 0x0c0c1616, 0xe7e7f7f8,
+ 0xe7e80808, 0x1817f7f8, 0x18180808, 0xf9f9e5e6, 0xf9fa1a1a, 0x0605e5e6, 0x06061a1a, 0xffffe3e4,
+ 0x00001c1c, 0x14141414, 0xebebebec, 0xe5e5f1f2, 0x1a1a0e0e, 0xf3f3e1e2, 0x0c0c1e1e, 0xdfdff5f6,
+ 0x20200a0a, 0xdfdfedee, 0x20201212, 0xe5e5e5e6, 0x1a1a1a1a, 0xebebddde, 0x14142222, 0xf3f3d9da,
+ 0x0c0c2626, 0xdfdfdfe0, 0x20202020, 0x20202020, 0xd7d7e9ea, 0xddddddde, 0x22222222, 0x00000000,
+ 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202,
+ 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606,
+ 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000,
+ 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000,
+ 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000,
+ 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000,
+ 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000,
+ 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202,
+ 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606,
+ 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000,
+ 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000,
+ 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a,
+ 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x0605f9fa, 0xf9fa0606, 0xf7f80e0e,
+ 0x0807f1f2, 0xffffedee, 0x00001212, 0xeff00a0a, 0x100ff5f6, 0xe7e80000, 0x18180000, 0xf7f7e7e8,
+ 0xf7f81818, 0x0807e7e8, 0x08081818, 0x12121212, 0xedededee, 0xeff01414, 0x100febec, 0xe5e5f1f2,
+ 0xe5e60e0e, 0x1a19f1f2, 0x1a1a0e0e, 0xffffe1e2, 0x00001e1e, 0xddde0000, 0x22220000, 0xf7f7ddde,
+ 0xf7f82222, 0x0807ddde, 0x08082222, 0xedede1e2, 0xedee1e1e, 0x1211e1e2, 0x12121e1e, 0xddddf5f6,
+ 0xddde0a0a, 0x2221f5f6, 0x22220a0a, 0xddddebec, 0x22221414, 0xffffd7d8, 0x00002828, 0x1e1e1e1e,
+ 0xe1e1e1e2, 0xededd7d8, 0x12122828, 0xd3d40000, 0x2c2c0000, 0xd3d3eff0, 0x2c2c1010, 0xdbdbdbdc,
+ 0xdbdbdbdc, 0x24242424, 0xd3d3e5e6, 0x2c2c1a1a, 0xe5e5d1d2, 0x1a1a2e2e, 0xededcbcc, 0x12123434,
+ 0xc9c9ebec, 0xd3d3d3d4, 0x2c2c2c2c, 0xc9c9dfe0, 0xd1d1d1d2, 0xd1d1d1d2, 0x2e2e2e2e, 0x00000000,
+ 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6,
+ 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202,
+ 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a,
+ 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc,
+ 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000,
+ 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000,
+ 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe,
+ 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6,
+ 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a,
+ 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000,
+ 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000,
+ 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404,
+ 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000,
+ 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6,
+ 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202,
+ 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a,
+ 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc,
+ 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000,
+ 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000,
+ 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe,
+ 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x0807f7f8, 0xf7f80808, 0xeff00808,
+ 0x100ff7f8, 0xe7e80000, 0x18180000, 0xf7f7e7e8, 0xf7f81818, 0x0807e7e8, 0x08081818, 0xeff01414,
+ 0x100febec, 0xffffe3e4, 0x00001c1c, 0xe7e7eff0, 0xe7e81010, 0x1817eff0, 0x18181010, 0xdfe00000,
+ 0x20200000, 0xefefe3e4, 0xeff01c1c, 0x100fe3e4, 0x10101c1c, 0xdfdff7f8, 0xdfe00808, 0xf7f7dfe0,
+ 0xf7f82020, 0x0807dfe0, 0x08082020, 0x201ff7f8, 0x20200808, 0x18181818, 0xe7e7e7e8, 0xe7e81818,
+ 0x1817e7e8, 0xdfdfebec, 0x20201414, 0xffffd7d8, 0x00002828, 0xefefd7d8, 0x10102828, 0xd3d40000,
+ 0xd3d40000, 0xffffd3d4, 0x00002c2c, 0x2c2c0000, 0x2c2c0000, 0xdfdfdfe0, 0x20202020, 0xd3d3eff0,
+ 0x2c2c1010, 0xd3d3e7e8, 0xe7e7d3d4, 0x18182c2c, 0x2c2c1818, 0xefefcfd0, 0x10103030, 0xdbdbdbdc,
+ 0xdbdbdbdc, 0x24242424, 0x24242424, 0xcbcbebec, 0x28282828, 0xd7d7d7d8, 0xcbcbdfe0, 0x00000000,
+ 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404,
+ 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c,
+ 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000,
+ 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000,
+ 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc,
+ 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4,
+ 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000,
+ 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000,
+ 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404,
+ 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000,
+ 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404,
+ 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c,
+ 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000,
+ 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000,
+ 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc,
+ 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0,
+ 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0,
+ 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0,
+ 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0,
+ 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+
+const uint32 Indeo3Decoder::correctionhighorder[] = {
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101,
+ 0xfeff0303, 0x0100fcfd, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303,
+ 0x0100fcfd, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9,
+ 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707,
+ 0xf8f8f8f9, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc,
+ 0x07070707, 0xf8f8f8f9, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404,
+ 0x0100fbfc, 0x07070707, 0xf8f8f8f9, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101,
+ 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff,
+ 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9, 0x00000000, 0x03030303, 0xfcfcfcfd,
+ 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9, 0x00000000, 0x03030303,
+ 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9, 0x00000000,
+ 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd,
+ 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb,
+ 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101,
+ 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd,
+ 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb,
+ 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101,
+ 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd,
+ 0x03030a0a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202,
+ 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505,
+ 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303,
+ 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9,
+ 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe,
+ 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000,
+ 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5,
+ 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707,
+ 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb,
+ 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd,
+ 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b,
+ 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202,
+ 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505,
+ 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303,
+ 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9,
+ 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x09090909, 0xf6f6f6f7,
+ 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa,
+ 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c,
+ 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000,
+ 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec,
+ 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd,
+ 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717,
+ 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4,
+ 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909,
+ 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606,
+ 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303,
+ 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9,
+ 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414,
+ 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7,
+ 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa,
+ 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c,
+ 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000,
+ 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec,
+ 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd,
+ 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717,
+ 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4,
+ 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000,
+ 0x00000202, 0xfffffdfe, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202,
+ 0xfffffdfe, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa,
+ 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606,
+ 0xf9f9f9fa, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd,
+ 0x06060606, 0xf9f9f9fa, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303,
+ 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000,
+ 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000,
+ 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x00000000, 0x03030303, 0xfcfcfcfd,
+ 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x00000000, 0x03030303,
+ 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x00000000,
+ 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc,
+ 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc,
+ 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000,
+ 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc,
+ 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc,
+ 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000,
+ 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc,
+ 0x04040808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000,
+ 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505,
+ 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505,
+ 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb,
+ 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000,
+ 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000,
+ 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6,
+ 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505,
+ 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb,
+ 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb,
+ 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a,
+ 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000,
+ 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505,
+ 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505,
+ 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb,
+ 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x09090909, 0xf6f6f6f7,
+ 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7,
+ 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909,
+ 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000,
+ 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee,
+ 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000,
+ 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b,
+ 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7,
+ 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909,
+ 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909,
+ 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000,
+ 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5,
+ 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212,
+ 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7,
+ 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7,
+ 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909,
+ 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000,
+ 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee,
+ 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000,
+ 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b,
+ 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7,
+ 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0x03030000,
+ 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000,
+ 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0x00000303,
+ 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0x00000303,
+ 0x00000303, 0x00000303, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd,
+ 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000,
+ 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0xf8f90000, 0xf8f90000,
+ 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000,
+ 0xf8f90000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020000, 0x02020000, 0x02020000, 0x02020000,
+ 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000,
+ 0x02020000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000,
+ 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0x00000202, 0x00000202,
+ 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202,
+ 0x00000202, 0x00000202, 0x00000202, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe,
+ 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0x06060000, 0x06060000, 0x06060000, 0x06060000,
+ 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000,
+ 0x06060000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000,
+ 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0x00000606, 0x00000606,
+ 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606,
+ 0x00000606, 0x00000606, 0x00000606, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa,
+ 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020000, 0x02020000, 0x02020000, 0x02020000,
+ 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000,
+ 0x02020000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000,
+ 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0x00000202, 0x00000202,
+ 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202,
+ 0x00000202, 0x00000202, 0x00000202, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe,
+ 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a,
+ 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0xf5f5f5f6,
+ 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6,
+ 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000,
+ 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000,
+ 0x0a0a0000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000,
+ 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0x00000a0a, 0x00000a0a,
+ 0x00000a0a, 0x00000a0a, 0x00000a0a, 0x00000a0a, 0x00000a0a, 0x00000a0a, 0x00000a0a, 0x00000a0a,
+ 0x00000a0a, 0x00000a0a, 0x00000a0a, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6,
+ 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04040000, 0x04040000, 0x04040000, 0x04040000,
+ 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000,
+ 0x04040000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000,
+ 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0x00000404, 0x00000404,
+ 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404,
+ 0x00000404, 0x00000404, 0x00000404, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc,
+ 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000,
+ 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000,
+ 0x0c0c0000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000,
+ 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0x00000c0c, 0x00000c0c,
+ 0x00000c0c, 0x00000c0c, 0x00000c0c, 0x00000c0c, 0x00000c0c, 0x00000c0c, 0x00000c0c, 0x00000c0c,
+ 0x00000c0c, 0x00000c0c, 0x00000c0c, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4,
+ 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0,
+ 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0,
+ 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0,
+ 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0,
+ 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+} // End of namespace Graphics
+
+#endif // USE_INDEO3
diff --git a/graphics/video/codecs/indeo3.h b/graphics/video/codecs/indeo3.h
new file mode 100644
index 0000000000..8d50b74b1e
--- /dev/null
+++ b/graphics/video/codecs/indeo3.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$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#ifdef USE_INDEO3
+
+/* Intel Indeo 3 decompressor, derived from ffmpeg.
+ *
+ * Original copyright note:
+ * Intel Indeo 3 (IV31, IV32, etc.) video decoder for ffmpeg
+ * written, produced, and directed by Alan Smithee
+ */
+
+#ifndef GRAPHICS_INDEO3_H
+#define GRAPHICS_INDEO3_H
+
+#include "graphics/video/codecs/codec.h"
+
+namespace Graphics {
+
+class Indeo3Decoder : public Codec {
+public:
+ Indeo3Decoder(uint16 width, uint16 height);
+ ~Indeo3Decoder();
+
+ Surface *decodeImage(Common::SeekableReadStream *stream);
+ PixelFormat getPixelFormat() const;
+
+ static bool isIndeo3(byte *data, uint32 dataLen);
+
+private:
+ Surface *_surface;
+
+ PixelFormat _pixelFormat;
+
+ static const int _corrector_type_0[24];
+ static const int _corrector_type_2[8];
+ static const uint32 correction[];
+ static const uint32 correctionloworder[];
+ static const uint32 correctionhighorder[];
+
+ struct YUVBufs {
+ byte *Ybuf;
+ byte *Ubuf;
+ byte *Vbuf;
+ byte *the_buf;
+ uint32 the_buf_size;
+ uint16 y_w, y_h;
+ uint16 uv_w, uv_h;
+ };
+
+ YUVBufs _iv_frame[2];
+ YUVBufs *_cur_frame;
+ YUVBufs *_ref_frame;
+
+ byte *_ModPred;
+ uint16 *_corrector_type;
+
+ void buildModPred();
+ void allocFrames();
+
+ void decodeChunk(byte *cur, byte *ref, int width, int height,
+ const byte *buf1, uint32 fflags2, const byte *hdr,
+ const byte *buf2, int min_width_160);
+};
+
+} // End of namespace Graphics
+
+#endif // GRAPHICS_INDEO3_H
+
+#endif // USE_INDEO3
diff --git a/graphics/video/codecs/mjpeg.cpp b/graphics/video/codecs/mjpeg.cpp
new file mode 100644
index 0000000000..76363036ee
--- /dev/null
+++ b/graphics/video/codecs/mjpeg.cpp
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/system.h"
+#include "graphics/conversion.h" // For YUV2RGB
+
+#include "graphics/video/codecs/mjpeg.h"
+
+namespace Graphics {
+
+JPEGDecoder::JPEGDecoder() : Codec() {
+ _jpeg = new JPEG();
+ _pixelFormat = g_system->getScreenFormat();
+ _surface = NULL;
+}
+
+JPEGDecoder::~JPEGDecoder() {
+ delete _jpeg;
+
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ }
+}
+
+Surface *JPEGDecoder::decodeImage(Common::SeekableReadStream* stream) {
+ _jpeg->read(stream);
+ Surface *ySurface = _jpeg->getComponent(1);
+ Surface *uSurface = _jpeg->getComponent(2);
+ Surface *vSurface = _jpeg->getComponent(3);
+
+ if (!_surface) {
+ _surface = new Surface();
+ _surface->create(ySurface->w, ySurface->h, _pixelFormat.bytesPerPixel);
+ }
+
+ for (uint16 i = 0; i < _surface->h; i++) {
+ for (uint16 j = 0; j < _surface->w; j++) {
+ byte r = 0, g = 0, b = 0;
+ YUV2RGB(*((byte *)ySurface->getBasePtr(j, i)), *((byte *)uSurface->getBasePtr(j, i)), *((byte *)vSurface->getBasePtr(j, i)), r, g, b);
+ if (_pixelFormat.bytesPerPixel == 2)
+ *((uint16 *)_surface->getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
+ else
+ *((uint32 *)_surface->getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
+ }
+ }
+
+ return _surface;
+}
+
+} // End of namespace Graphics
diff --git a/engines/mohawk/jpeg.h b/graphics/video/codecs/mjpeg.h
index ec87b1e7af..ab364fb5be 100644
--- a/engines/mohawk/jpeg.h
+++ b/graphics/video/codecs/mjpeg.h
@@ -23,8 +23,8 @@
*
*/
-#ifndef MOHAWK_JPEG_H
-#define MOHAWK_JPEG_H
+#ifndef GRAPHICS_MJPEG_H
+#define GRAPHICS_MJPEG_H
#include "common/scummsys.h"
#include "common/stream.h"
@@ -33,27 +33,26 @@
#include "graphics/jpeg.h"
#include "graphics/pixelformat.h"
-namespace Mohawk {
+namespace Graphics {
-// Mohawk's JPEG Decoder
+// Motion JPEG Decoder
// Basically a wrapper around JPEG which converts to RGB and also functions
// as a Codec.
-class JPEGDecoder : public Graphics::Codec {
+class JPEGDecoder : public Codec {
public:
- JPEGDecoder(bool freeSurfaceAfterUse);
+ JPEGDecoder();
~JPEGDecoder();
- Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
- Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
+ Surface *decodeImage(Common::SeekableReadStream *stream);
+ PixelFormat getPixelFormat() const { return _pixelFormat; }
private:
- Graphics::PixelFormat _pixelFormat;
- Graphics::JPEG *_jpeg;
- Graphics::Surface *_surface;
- bool _freeSurfaceAfterUse;
+ PixelFormat _pixelFormat;
+ JPEG *_jpeg;
+ Surface *_surface;
};
-} // End of namespace Mohawk
+} // End of namespace Graphics
#endif
diff --git a/graphics/video/codecs/qdm2.cpp b/graphics/video/codecs/qdm2.cpp
new file mode 100644
index 0000000000..9f151b4ba8
--- /dev/null
+++ b/graphics/video/codecs/qdm2.cpp
@@ -0,0 +1,3282 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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$
+ *
+ */
+
+// Based off ffmpeg's QDM2 decoder
+
+#include "graphics/video/codecs/qdm2.h"
+
+#ifdef GRAPHICS_QDM2_H
+
+#include "sound/audiostream.h"
+#include "graphics/video/codecs/qdm2data.h"
+
+#include "common/array.h"
+#include "common/stream.h"
+#include "common/system.h"
+
+namespace Graphics {
+
+enum {
+ SOFTCLIP_THRESHOLD = 27600,
+ HARDCLIP_THRESHOLD = 35716,
+ MPA_MAX_CHANNELS = 2,
+ MPA_FRAME_SIZE = 1152,
+ FF_INPUT_BUFFER_PADDING_SIZE = 8
+};
+
+typedef int8 sb_int8_array[2][30][64];
+
+/* bit input */
+/* buffer, buffer_end and size_in_bits must be present and used by every reader */
+struct GetBitContext {
+ const uint8 *buffer, *bufferEnd;
+ int index;
+ int sizeInBits;
+};
+
+struct QDM2SubPacket {
+ int type;
+ unsigned int size;
+ const uint8 *data; // pointer to subpacket data (points to input data buffer, it's not a private copy)
+};
+
+struct QDM2SubPNode {
+ QDM2SubPacket *packet;
+ struct QDM2SubPNode *next; // pointer to next packet in the list, NULL if leaf node
+};
+
+struct QDM2Complex {
+ float re;
+ float im;
+};
+
+struct FFTTone {
+ float level;
+ QDM2Complex *complex;
+ const float *table;
+ int phase;
+ int phase_shift;
+ int duration;
+ short time_index;
+ short cutoff;
+};
+
+struct FFTCoefficient {
+ int16 sub_packet;
+ uint8 channel;
+ int16 offset;
+ int16 exp;
+ uint8 phase;
+};
+
+struct VLC {
+ int32 bits;
+ int16 (*table)[2]; // code, bits
+ int32 table_size;
+ int32 table_allocated;
+};
+
+#include "common/pack-start.h"
+struct QDM2FFT {
+ QDM2Complex complex[MPA_MAX_CHANNELS][256];
+} PACKED_STRUCT;
+#include "common/pack-end.h"
+
+enum RDFTransformType {
+ RDFT,
+ IRDFT,
+ RIDFT,
+ IRIDFT
+};
+
+struct FFTComplex {
+ float re, im;
+};
+
+struct FFTContext {
+ int nbits;
+ int inverse;
+ uint16 *revtab;
+ FFTComplex *exptab;
+ FFTComplex *tmpBuf;
+ int mdctSize; // size of MDCT (i.e. number of input data * 2)
+ int mdctBits; // n = 2^nbits
+ // pre/post rotation tables
+ float *tcos;
+ float *tsin;
+ void (*fftPermute)(struct FFTContext *s, FFTComplex *z);
+ void (*fftCalc)(struct FFTContext *s, FFTComplex *z);
+ void (*imdctCalc)(struct FFTContext *s, float *output, const float *input);
+ void (*imdctHalf)(struct FFTContext *s, float *output, const float *input);
+ void (*mdctCalc)(struct FFTContext *s, float *output, const float *input);
+ int splitRadix;
+ int permutation;
+};
+
+enum {
+ FF_MDCT_PERM_NONE = 0,
+ FF_MDCT_PERM_INTERLEAVE = 1
+};
+
+struct RDFTContext {
+ int nbits;
+ int inverse;
+ int signConvention;
+
+ // pre/post rotation tables
+ float *tcos;
+ float *tsin;
+ FFTContext fft;
+};
+
+class QDM2Stream : public Audio::AudioStream {
+public:
+ QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadStream *extraData);
+ ~QDM2Stream();
+
+ bool isStereo() const { return _channels == 2; }
+ bool endOfData() const { return _stream->pos() >= _stream->size() && _outputSamples.size() == 0 && _subPacket == 0; }
+ int getRate() const { return _sampleRate; }
+ int readBuffer(int16 *buffer, const int numSamples);
+
+private:
+ Common::SeekableReadStream *_stream;
+
+ // Parameters from codec header, do not change during playback
+ uint8 _channels;
+ uint16 _sampleRate;
+ uint16 _bitRate;
+ uint16 _blockSize; // Group
+ uint16 _frameSize; // FFT
+ uint16 _packetSize; // Checksum
+
+ // Parameters built from header parameters, do not change during playback
+ int _groupOrder; // order of frame group
+ int _fftOrder; // order of FFT (actually fft order+1)
+ int _fftFrameSize; // size of fft frame, in components (1 comples = re + im)
+ int _sFrameSize; // size of data frame
+ int _frequencyRange;
+ int _subSampling; // subsampling: 0=25%, 1=50%, 2=100% */
+ int _coeffPerSbSelect; // selector for "num. of coeffs. per subband" tables. Can be 0, 1, 2
+ int _cmTableSelect; // selector for "coding method" tables. Can be 0, 1 (from init: 0-4)
+
+ // Packets and packet lists
+ QDM2SubPacket _subPackets[16]; // the packets themselves
+ QDM2SubPNode _subPacketListA[16]; // list of all packets
+ QDM2SubPNode _subPacketListB[16]; // FFT packets B are on list
+ int _subPacketsB; // number of packets on 'B' list
+ QDM2SubPNode _subPacketListC[16]; // packets with errors?
+ QDM2SubPNode _subPacketListD[16]; // DCT packets
+
+ // FFT and tones
+ FFTTone _fftTones[1000];
+ int _fftToneStart;
+ int _fftToneEnd;
+ FFTCoefficient _fftCoefs[1000];
+ int _fftCoefsIndex;
+ int _fftCoefsMinIndex[5];
+ int _fftCoefsMaxIndex[5];
+ int _fftLevelExp[6];
+ RDFTContext _rdftCtx;
+ QDM2FFT _fft;
+
+ // I/O data
+ uint8 *_compressedData;
+ float _outputBuffer[1024];
+ Common::Array<int16> _outputSamples;
+
+ // Synthesis filter
+ int16 ff_mpa_synth_window[512];
+ int16 _synthBuf[MPA_MAX_CHANNELS][512*2];
+ int _synthBufOffset[MPA_MAX_CHANNELS];
+ int32 _sbSamples[MPA_MAX_CHANNELS][128][32];
+
+ // Mixed temporary data used in decoding
+ float _toneLevel[MPA_MAX_CHANNELS][30][64];
+ int8 _codingMethod[MPA_MAX_CHANNELS][30][64];
+ int8 _quantizedCoeffs[MPA_MAX_CHANNELS][10][8];
+ int8 _toneLevelIdxBase[MPA_MAX_CHANNELS][30][8];
+ int8 _toneLevelIdxHi1[MPA_MAX_CHANNELS][3][8][8];
+ int8 _toneLevelIdxMid[MPA_MAX_CHANNELS][26][8];
+ int8 _toneLevelIdxHi2[MPA_MAX_CHANNELS][26];
+ int8 _toneLevelIdx[MPA_MAX_CHANNELS][30][64];
+ int8 _toneLevelIdxTemp[MPA_MAX_CHANNELS][30][64];
+
+ // Flags
+ bool _hasErrors; // packet has errors
+ int _superblocktype_2_3; // select fft tables and some algorithm based on superblock type
+ int _doSynthFilter; // used to perform or skip synthesis filter
+
+ uint8 _subPacket; // 0 to 15
+ uint32 _superBlockStart;
+ int _noiseIdx; // index for dithering noise table
+
+ byte _emptyBuffer[FF_INPUT_BUFFER_PADDING_SIZE];
+
+ VLC _vlcTabLevel;
+ VLC _vlcTabDiff;
+ VLC _vlcTabRun;
+ VLC _fftLevelExpAltVlc;
+ VLC _fftLevelExpVlc;
+ VLC _fftStereoExpVlc;
+ VLC _fftStereoPhaseVlc;
+ VLC _vlcTabToneLevelIdxHi1;
+ VLC _vlcTabToneLevelIdxMid;
+ VLC _vlcTabToneLevelIdxHi2;
+ VLC _vlcTabType30;
+ VLC _vlcTabType34;
+ VLC _vlcTabFftToneOffset[5];
+ bool _vlcsInitialized;
+ void initVlc(void);
+
+ uint16 _softclipTable[HARDCLIP_THRESHOLD - SOFTCLIP_THRESHOLD + 1];
+ void softclipTableInit(void);
+
+ float _noiseTable[4096];
+ byte _randomDequantIndex[256][5];
+ byte _randomDequantType24[128][3];
+ void rndTableInit(void);
+
+ float _noiseSamples[128];
+ void initNoiseSamples(void);
+
+ void average_quantized_coeffs(void);
+ void build_sb_samples_from_noise(int sb);
+ void fix_coding_method_array(int sb, int channels, sb_int8_array coding_method);
+ void fill_tone_level_array(int flag);
+ void fill_coding_method_array(sb_int8_array tone_level_idx, sb_int8_array tone_level_idx_temp,
+ sb_int8_array coding_method, int nb_channels,
+ int c, int superblocktype_2_3, int cm_table_select);
+ void synthfilt_build_sb_samples(GetBitContext *gb, int length, int sb_min, int sb_max);
+ void init_quantized_coeffs_elem0(int8 *quantized_coeffs, GetBitContext *gb, int length);
+ void init_tone_level_dequantization(GetBitContext *gb, int length);
+ void process_subpacket_9(QDM2SubPNode *node);
+ void process_subpacket_10(QDM2SubPNode *node, int length);
+ void process_subpacket_11(QDM2SubPNode *node, int length);
+ void process_subpacket_12(QDM2SubPNode *node, int length);
+ void process_synthesis_subpackets(QDM2SubPNode *list);
+ void qdm2_decode_super_block(void);
+ void qdm2_fft_init_coefficient(int sub_packet, int offset, int duration,
+ int channel, int exp, int phase);
+ void qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b);
+ void qdm2_decode_fft_packets(void);
+ void qdm2_fft_generate_tone(FFTTone *tone);
+ void qdm2_fft_tone_synthesizer(uint8 sub_packet);
+ void qdm2_calculate_fft(int channel);
+ void qdm2_synthesis_filter(uint8 index);
+ int qdm2_decodeFrame(Common::SeekableReadStream *in);
+};
+
+// Fix compilation for non C99-compliant compilers, like MSVC
+#ifndef int64_t
+typedef signed long long int int64_t;
+#endif
+
+// Integer log2 function. This is much faster than invoking
+// double precision C99 log2 math functions or equivalent, since
+// this is only used to determine maximum number of bits needed
+// i.e. only non-fractional part is needed. Also, the double
+// version is incorrect for exact cases due to floating point
+// rounding errors.
+static inline int scummvm_log2(int n) {
+ int ret = -1;
+ while(n != 0) {
+ n /= 2;
+ ret++;
+ }
+ return ret;
+}
+
+#define QDM2_LIST_ADD(list, size, packet) \
+ do { \
+ if (size > 0) \
+ list[size - 1].next = &list[size]; \
+ list[size].packet = packet; \
+ list[size].next = NULL; \
+ size++; \
+ } while(0)
+
+// Result is 8, 16 or 30
+#define QDM2_SB_USED(subSampling) (((subSampling) >= 2) ? 30 : 8 << (subSampling))
+
+#define FIX_NOISE_IDX(noiseIdx) \
+ if ((noiseIdx) >= 3840) \
+ (noiseIdx) -= 3840 \
+
+#define SB_DITHERING_NOISE(sb, noiseIdx) (_noiseTable[(noiseIdx)++] * sb_noise_attenuation[(sb)])
+
+static inline void initGetBits(GetBitContext *s, const uint8 *buffer, int bitSize) {
+ int bufferSize = (bitSize + 7) >> 3;
+
+ if (bufferSize < 0 || bitSize < 0) {
+ bufferSize = bitSize = 0;
+ buffer = NULL;
+ }
+
+ s->buffer = buffer;
+ s->sizeInBits = bitSize;
+ s->bufferEnd = buffer + bufferSize;
+ s->index = 0;
+}
+
+static inline int getBitsCount(GetBitContext *s) {
+ return s->index;
+}
+
+static inline unsigned int getBits1(GetBitContext *s) {
+ int index;
+ uint8 result;
+
+ index = s->index;
+ result = s->buffer[index >> 3];
+
+ result >>= (index & 0x07);
+ result &= 1;
+ index++;
+ s->index = index;
+
+ return result;
+}
+
+static inline unsigned int getBits(GetBitContext *s, int n) {
+ int tmp, reCache, reIndex;
+
+ reIndex = s->index;
+
+ reCache = READ_LE_UINT32((const uint8 *)s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
+
+ tmp = (reCache) & ((uint32)0xffffffff >> (32 - n));
+
+ s->index = reIndex + n;
+
+ return tmp;
+}
+
+static inline void skipBits(GetBitContext *s, int n) {
+ int reIndex, reCache;
+
+ reIndex = s->index;
+ reCache = 0;
+
+ reCache = READ_LE_UINT32((const uint8 *)s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
+ s->index = reIndex + n;
+}
+
+#define BITS_LEFT(length, gb) ((length) - getBitsCount((gb)))
+
+static int splitRadixPermutation(int i, int n, int inverse) {
+ if (n <= 2)
+ return i & 1;
+
+ int m = n >> 1;
+
+ if(!(i & m))
+ return splitRadixPermutation(i, m, inverse) * 2;
+
+ m >>= 1;
+
+ if (inverse == !(i & m))
+ return splitRadixPermutation(i, m, inverse) * 4 + 1;
+
+ return splitRadixPermutation(i, m, inverse) * 4 - 1;
+}
+
+// sin(2*pi*x/n) for 0<=x<n/4, followed by n/2<=x<3n/4
+float ff_sin_16[8];
+float ff_sin_32[16];
+float ff_sin_64[32];
+float ff_sin_128[64];
+float ff_sin_256[128];
+float ff_sin_512[256];
+float ff_sin_1024[512];
+float ff_sin_2048[1024];
+float ff_sin_4096[2048];
+float ff_sin_8192[4096];
+float ff_sin_16384[8192];
+float ff_sin_32768[16384];
+float ff_sin_65536[32768];
+
+float *ff_sin_tabs[] = {
+ NULL, NULL, NULL, NULL,
+ ff_sin_16, ff_sin_32, ff_sin_64, ff_sin_128, ff_sin_256, ff_sin_512, ff_sin_1024,
+ ff_sin_2048, ff_sin_4096, ff_sin_8192, ff_sin_16384, ff_sin_32768, ff_sin_65536,
+};
+
+// cos(2*pi*x/n) for 0<=x<=n/4, followed by its reverse
+float ff_cos_16[8];
+float ff_cos_32[16];
+float ff_cos_64[32];
+float ff_cos_128[64];
+float ff_cos_256[128];
+float ff_cos_512[256];
+float ff_cos_1024[512];
+float ff_cos_2048[1024];
+float ff_cos_4096[2048];
+float ff_cos_8192[4096];
+float ff_cos_16384[8192];
+float ff_cos_32768[16384];
+float ff_cos_65536[32768];
+
+float *ff_cos_tabs[] = {
+ NULL, NULL, NULL, NULL,
+ ff_cos_16, ff_cos_32, ff_cos_64, ff_cos_128, ff_cos_256, ff_cos_512, ff_cos_1024,
+ ff_cos_2048, ff_cos_4096, ff_cos_8192, ff_cos_16384, ff_cos_32768, ff_cos_65536,
+};
+
+void initCosineTables(int index) {
+ int m = 1 << index;
+ double freq = 2 * PI / m;
+ float *tab = ff_cos_tabs[index];
+
+ for (int i = 0; i <= m / 4; i++)
+ tab[i] = cos(i * freq);
+
+ for (int i = 1; i < m / 4; i++)
+ tab[m / 2 - i] = tab[i];
+}
+
+void fftPermute(FFTContext *s, FFTComplex *z) {
+ const uint16 *revtab = s->revtab;
+ int np = 1 << s->nbits;
+
+ if (s->tmpBuf) {
+ // TODO: handle split-radix permute in a more optimal way, probably in-place
+ for (int j = 0; j < np; j++)
+ s->tmpBuf[revtab[j]] = z[j];
+ memcpy(z, s->tmpBuf, np * sizeof(FFTComplex));
+ return;
+ }
+
+ // reverse
+ for (int j = 0; j < np; j++) {
+ int k = revtab[j];
+ if (k < j) {
+ FFTComplex tmp = z[k];
+ z[k] = z[j];
+ z[j] = tmp;
+ }
+ }
+}
+
+#define DECL_FFT(n,n2,n4) \
+static void fft##n(FFTComplex *z) { \
+ fft##n2(z); \
+ fft##n4(z + n4 * 2); \
+ fft##n4(z + n4 * 3); \
+ pass(z, ff_cos_##n, n4 / 2); \
+}
+
+#ifndef M_SQRT1_2
+#define M_SQRT1_2 7.0710678118654752440E-1
+#endif
+
+#define sqrthalf (float)M_SQRT1_2
+
+#define BF(x,y,a,b) { \
+ x = a - b; \
+ y = a + b; \
+}
+
+#define BUTTERFLIES(a0, a1, a2, a3) { \
+ BF(t3, t5, t5, t1); \
+ BF(a2.re, a0.re, a0.re, t5); \
+ BF(a3.im, a1.im, a1.im, t3); \
+ BF(t4, t6, t2, t6); \
+ BF(a3.re, a1.re, a1.re, t4); \
+ BF(a2.im, a0.im, a0.im, t6); \
+}
+
+// force loading all the inputs before storing any.
+// this is slightly slower for small data, but avoids store->load aliasing
+// for addresses separated by large powers of 2.
+#define BUTTERFLIES_BIG(a0, a1, a2, a3) { \
+ float r0 = a0.re, i0 = a0.im, r1 = a1.re, i1 = a1.im; \
+ BF(t3, t5, t5, t1); \
+ BF(a2.re, a0.re, r0, t5); \
+ BF(a3.im, a1.im, i1, t3); \
+ BF(t4, t6, t2, t6); \
+ BF(a3.re, a1.re, r1, t4); \
+ BF(a2.im, a0.im, i0, t6); \
+}
+
+#define TRANSFORM(a0, a1, a2, a3, wre, wim) { \
+ t1 = a2.re * wre + a2.im * wim; \
+ t2 = a2.im * wre - a2.re * wim; \
+ t5 = a3.re * wre - a3.im * wim; \
+ t6 = a3.im * wre + a3.re * wim; \
+ BUTTERFLIES(a0, a1, a2, a3) \
+}
+
+#define TRANSFORM_ZERO(a0, a1, a2, a3) { \
+ t1 = a2.re; \
+ t2 = a2.im; \
+ t5 = a3.re; \
+ t6 = a3.im; \
+ BUTTERFLIES(a0, a1, a2, a3) \
+}
+
+// z[0...8n-1], w[1...2n-1]
+#define PASS(name) \
+static void name(FFTComplex *z, const float *wre, unsigned int n) { \
+ float t1, t2, t3, t4, t5, t6; \
+ int o1 = 2 * n; \
+ int o2 = 4 * n; \
+ int o3 = 6 * n; \
+ const float *wim = wre + o1; \
+ n--; \
+ \
+ TRANSFORM_ZERO(z[0], z[o1], z[o2], z[o3]); \
+ TRANSFORM(z[1], z[o1 + 1], z[o2 + 1], z[o3 + 1], wre[1], wim[-1]); \
+ \
+ do { \
+ z += 2; \
+ wre += 2; \
+ wim -= 2; \
+ TRANSFORM(z[0], z[o1], z[o2], z[o3], wre[0], wim[0]); \
+ TRANSFORM(z[1], z[o1 + 1],z[o2 + 1], z[o3 + 1], wre[1], wim[-1]); \
+ } while(--n); \
+}
+
+PASS(pass)
+#undef BUTTERFLIES
+#define BUTTERFLIES BUTTERFLIES_BIG
+PASS(pass_big)
+
+static void fft4(FFTComplex *z) {
+ float t1, t2, t3, t4, t5, t6, t7, t8;
+
+ BF(t3, t1, z[0].re, z[1].re);
+ BF(t8, t6, z[3].re, z[2].re);
+ BF(z[2].re, z[0].re, t1, t6);
+ BF(t4, t2, z[0].im, z[1].im);
+ BF(t7, t5, z[2].im, z[3].im);
+ BF(z[3].im, z[1].im, t4, t8);
+ BF(z[3].re, z[1].re, t3, t7);
+ BF(z[2].im, z[0].im, t2, t5);
+}
+
+static void fft8(FFTComplex *z) {
+ float t1, t2, t3, t4, t5, t6, t7, t8;
+
+ fft4(z);
+
+ BF(t1, z[5].re, z[4].re, -z[5].re);
+ BF(t2, z[5].im, z[4].im, -z[5].im);
+ BF(t3, z[7].re, z[6].re, -z[7].re);
+ BF(t4, z[7].im, z[6].im, -z[7].im);
+ BF(t8, t1, t3, t1);
+ BF(t7, t2, t2, t4);
+ BF(z[4].re, z[0].re, z[0].re, t1);
+ BF(z[4].im, z[0].im, z[0].im, t2);
+ BF(z[6].re, z[2].re, z[2].re, t7);
+ BF(z[6].im, z[2].im, z[2].im, t8);
+
+ TRANSFORM(z[1], z[3], z[5], z[7], sqrthalf, sqrthalf);
+}
+
+#undef BF
+
+DECL_FFT(16,8,4)
+DECL_FFT(32,16,8)
+DECL_FFT(64,32,16)
+DECL_FFT(128,64,32)
+DECL_FFT(256,128,64)
+DECL_FFT(512,256,128)
+#define pass pass_big
+DECL_FFT(1024,512,256)
+DECL_FFT(2048,1024,512)
+DECL_FFT(4096,2048,1024)
+DECL_FFT(8192,4096,2048)
+DECL_FFT(16384,8192,4096)
+DECL_FFT(32768,16384,8192)
+DECL_FFT(65536,32768,16384)
+
+void fftCalc(FFTContext *s, FFTComplex *z) {
+ static void (* const fftDispatch[])(FFTComplex*) = {
+ fft4, fft8, fft16, fft32, fft64, fft128, fft256, fft512, fft1024,
+ fft2048, fft4096, fft8192, fft16384, fft32768, fft65536,
+ };
+
+ fftDispatch[s->nbits - 2](z);
+}
+
+// complex multiplication: p = a * b
+#define CMUL(pre, pim, are, aim, bre, bim) \
+{\
+ float _are = (are); \
+ float _aim = (aim); \
+ float _bre = (bre); \
+ float _bim = (bim); \
+ (pre) = _are * _bre - _aim * _bim; \
+ (pim) = _are * _bim + _aim * _bre; \
+}
+
+/**
+ * Compute the middle half of the inverse MDCT of size N = 2^nbits,
+ * thus excluding the parts that can be derived by symmetry
+ * @param output N/2 samples
+ * @param input N/2 samples
+ */
+void imdctHalfC(FFTContext *s, float *output, const float *input) {
+ const uint16 *revtab = s->revtab;
+ const float *tcos = s->tcos;
+ const float *tsin = s->tsin;
+ FFTComplex *z = (FFTComplex *)output;
+
+ int n = 1 << s->mdctBits;
+ int n2 = n >> 1;
+ int n4 = n >> 2;
+ int n8 = n >> 3;
+
+ // pre rotation
+ const float *in1 = input;
+ const float *in2 = input + n2 - 1;
+ for (int k = 0; k < n4; k++) {
+ int j = revtab[k];
+ CMUL(z[j].re, z[j].im, *in2, *in1, tcos[k], tsin[k]);
+ in1 += 2;
+ in2 -= 2;
+ }
+
+ fftCalc(s, z);
+
+ // post rotation + reordering
+ for (int k = 0; k < n8; k++) {
+ float r0, i0, r1, i1;
+ CMUL(r0, i1, z[n8 - k - 1].im, z[n8 - k - 1].re, tsin[n8 - k - 1], tcos[n8 - k - 1]);
+ CMUL(r1, i0, z[n8 + k].im, z[n8 + k].re, tsin[n8 + k], tcos[n8 + k]);
+ z[n8 - k - 1].re = r0;
+ z[n8 - k - 1].im = i0;
+ z[n8 + k].re = r1;
+ z[n8 + k].im = i1;
+ }
+}
+
+/**
+ * Compute inverse MDCT of size N = 2^nbits
+ * @param output N samples
+ * @param input N/2 samples
+ */
+void imdctCalcC(FFTContext *s, float *output, const float *input) {
+ int n = 1 << s->mdctBits;
+ int n2 = n >> 1;
+ int n4 = n >> 2;
+
+ imdctHalfC(s, output + n4, input);
+
+ for (int k = 0; k < n4; k++) {
+ output[k] = -output[n2 - k - 1];
+ output[n - k - 1] = output[n2 + k];
+ }
+}
+
+/**
+ * Compute MDCT of size N = 2^nbits
+ * @param input N samples
+ * @param out N/2 samples
+ */
+void mdctCalcC(FFTContext *s, float *out, const float *input) {
+ const uint16 *revtab = s->revtab;
+ const float *tcos = s->tcos;
+ const float *tsin = s->tsin;
+ FFTComplex *x = (FFTComplex *)out;
+
+ int n = 1 << s->mdctBits;
+ int n2 = n >> 1;
+ int n4 = n >> 2;
+ int n8 = n >> 3;
+ int n3 = 3 * n4;
+
+ // pre rotation
+ for (int i = 0; i < n8; i++) {
+ float re = -input[2 * i + 3 * n4] - input[n3 - 1 - 2 * i];
+ float im = -input[n4 + 2 * i] + input[n4 - 1 - 2 * i];
+ int j = revtab[i];
+ CMUL(x[j].re, x[j].im, re, im, -tcos[i], tsin[i]);
+
+ re = input[2 * i] - input[n2 - 1 - 2 * i];
+ im = -(input[n2 + 2 * i] + input[n - 1 - 2 * i]);
+ j = revtab[n8 + i];
+ CMUL(x[j].re, x[j].im, re, im, -tcos[n8 + i], tsin[n8 + i]);
+ }
+
+ fftCalc(s, x);
+
+ // post rotation
+ for (int i = 0; i < n8; i++) {
+ float r0, i0, r1, i1;
+ CMUL(i1, r0, x[n8 - i - 1].re, x[n8 - i - 1].im, -tsin[n8 - i - 1], -tcos[n8 - i - 1]);
+ CMUL(i0, r1, x[n8 + i].re, x[n8 + i].im, -tsin[n8 + i], -tcos[n8 + i]);
+ x[n8 - i - 1].re = r0;
+ x[n8 - i - 1].im = i0;
+ x[n8 + i].re = r1;
+ x[n8 + i].im = i1;
+ }
+}
+
+int fftInit(FFTContext *s, int nbits, int inverse) {
+ int i, j, m, n;
+ float alpha, c1, s1, s2;
+
+ if (nbits < 2 || nbits > 16)
+ goto fail;
+
+ s->nbits = nbits;
+ n = 1 << nbits;
+ s->tmpBuf = NULL;
+
+ s->exptab = (FFTComplex *)malloc((n / 2) * sizeof(FFTComplex));
+ if (!s->exptab)
+ goto fail;
+
+ s->revtab = (uint16 *)malloc(n * sizeof(uint16));
+ if (!s->revtab)
+ goto fail;
+ s->inverse = inverse;
+
+ s2 = inverse ? 1.0 : -1.0;
+
+ s->fftPermute = fftPermute;
+ s->fftCalc = fftCalc;
+ s->imdctCalc = imdctCalcC;
+ s->imdctHalf = imdctHalfC;
+ s->mdctCalc = mdctCalcC;
+ s->splitRadix = 1;
+
+ if (s->splitRadix) {
+ for (j = 4; j <= nbits; j++)
+ initCosineTables(j);
+
+ for (i = 0; i < n; i++)
+ s->revtab[-splitRadixPermutation(i, n, s->inverse) & (n - 1)] = i;
+
+ s->tmpBuf = (FFTComplex *)malloc(n * sizeof(FFTComplex));
+ } else {
+ for (i = 0; i < n / 2; i++) {
+ alpha = 2 * PI * (float)i / (float)n;
+ c1 = cos(alpha);
+ s1 = sin(alpha) * s2;
+ s->exptab[i].re = c1;
+ s->exptab[i].im = s1;
+ }
+
+ //int np = 1 << nbits;
+ //int nblocks = np >> 3;
+ //int np2 = np >> 1;
+
+ // compute bit reverse table
+ for (i = 0; i < n; i++) {
+ m = 0;
+
+ for (j = 0; j < nbits; j++)
+ m |= ((i >> j) & 1) << (nbits - j - 1);
+
+ s->revtab[i] = m;
+ }
+ }
+
+ return 0;
+
+ fail:
+ free(&s->revtab);
+ free(&s->exptab);
+ free(&s->tmpBuf);
+ return -1;
+}
+
+/**
+ * Sets up a real FFT.
+ * @param nbits log2 of the length of the input array
+ * @param trans the type of transform
+ */
+int rdftInit(RDFTContext *s, int nbits, RDFTransformType trans) {
+ int n = 1 << nbits;
+ const double theta = (trans == RDFT || trans == IRIDFT ? -1 : 1) * 2 * PI / n;
+
+ s->nbits = nbits;
+ s->inverse = trans == IRDFT || trans == IRIDFT;
+ s->signConvention = trans == RIDFT || trans == IRIDFT ? 1 : -1;
+
+ if (nbits < 4 || nbits > 16)
+ return -1;
+
+ if (fftInit(&s->fft, nbits - 1, trans == IRDFT || trans == RIDFT) < 0)
+ return -1;
+
+ initCosineTables(nbits);
+ s->tcos = ff_cos_tabs[nbits];
+ s->tsin = ff_sin_tabs[nbits] + (trans == RDFT || trans == IRIDFT) * (n >> 2);
+
+ for (int i = 0; i < n >> 2; i++)
+ s->tsin[i] = sin(i*theta);
+
+ return 0;
+}
+
+/** Map one real FFT into two parallel real even and odd FFTs. Then interleave
+ * the two real FFTs into one complex FFT. Unmangle the results.
+ * ref: http://www.engineeringproductivitytools.com/stuff/T0001/PT10.HTM
+ */
+void rdftCalc(RDFTContext *s, float *data) {
+ FFTComplex ev, od;
+
+ const int n = 1 << s->nbits;
+ const float k1 = 0.5;
+ const float k2 = 0.5 - s->inverse;
+ const float *tcos = s->tcos;
+ const float *tsin = s->tsin;
+
+ if (!s->inverse) {
+ fftPermute(&s->fft, (FFTComplex *)data);
+ fftCalc(&s->fft, (FFTComplex *)data);
+ }
+
+ // i=0 is a special case because of packing, the DC term is real, so we
+ // are going to throw the N/2 term (also real) in with it.
+ ev.re = data[0];
+ data[0] = ev.re + data[1];
+ data[1] = ev.re - data[1];
+
+ int i;
+
+ for (i = 1; i < n >> 2; i++) {
+ int i1 = i * 2;
+ int i2 = n - i1;
+
+ // Separate even and odd FFTs
+ ev.re = k1 * (data[i1] + data[i2]);
+ od.im = -k2 * (data[i1] - data[i2]);
+ ev.im = k1 * (data[i1 + 1] - data[i2 + 1]);
+ od.re = k2 * (data[i1 + 1] + data[i2 + 1]);
+
+ // Apply twiddle factors to the odd FFT and add to the even FFT
+ data[i1] = ev.re + od.re * tcos[i] - od.im * tsin[i];
+ data[i1 + 1] = ev.im + od.im * tcos[i] + od.re * tsin[i];
+ data[i2] = ev.re - od.re * tcos[i] + od.im * tsin[i];
+ data[i2 + 1] = -ev.im + od.im * tcos[i] + od.re * tsin[i];
+ }
+
+ data[i * 2 + 1] = s->signConvention * data[i * 2 + 1];
+ if (s->inverse) {
+ data[0] *= k1;
+ data[1] *= k1;
+ fftPermute(&s->fft, (FFTComplex*)data);
+ fftCalc(&s->fft, (FFTComplex*)data);
+ }
+}
+
+// half mpeg encoding window (full precision)
+const int32 ff_mpa_enwindow[257] = {
+ 0, -1, -1, -1, -1, -1, -1, -2,
+ -2, -2, -2, -3, -3, -4, -4, -5,
+ -5, -6, -7, -7, -8, -9, -10, -11,
+ -13, -14, -16, -17, -19, -21, -24, -26,
+ -29, -31, -35, -38, -41, -45, -49, -53,
+ -58, -63, -68, -73, -79, -85, -91, -97,
+ -104, -111, -117, -125, -132, -139, -147, -154,
+ -161, -169, -176, -183, -190, -196, -202, -208,
+ 213, 218, 222, 225, 227, 228, 228, 227,
+ 224, 221, 215, 208, 200, 189, 177, 163,
+ 146, 127, 106, 83, 57, 29, -2, -36,
+ -72, -111, -153, -197, -244, -294, -347, -401,
+ -459, -519, -581, -645, -711, -779, -848, -919,
+ -991, -1064, -1137, -1210, -1283, -1356, -1428, -1498,
+ -1567, -1634, -1698, -1759, -1817, -1870, -1919, -1962,
+ -2001, -2032, -2057, -2075, -2085, -2087, -2080, -2063,
+ 2037, 2000, 1952, 1893, 1822, 1739, 1644, 1535,
+ 1414, 1280, 1131, 970, 794, 605, 402, 185,
+ -45, -288, -545, -814, -1095, -1388, -1692, -2006,
+ -2330, -2663, -3004, -3351, -3705, -4063, -4425, -4788,
+ -5153, -5517, -5879, -6237, -6589, -6935, -7271, -7597,
+ -7910, -8209, -8491, -8755, -8998, -9219, -9416, -9585,
+ -9727, -9838, -9916, -9959, -9966, -9935, -9863, -9750,
+ -9592, -9389, -9139, -8840, -8492, -8092, -7640, -7134,
+ 6574, 5959, 5288, 4561, 3776, 2935, 2037, 1082,
+ 70, -998, -2122, -3300, -4533, -5818, -7154, -8540,
+ -9975,-11455,-12980,-14548,-16155,-17799,-19478,-21189,
+-22929,-24694,-26482,-28289,-30112,-31947,-33791,-35640,
+-37489,-39336,-41176,-43006,-44821,-46617,-48390,-50137,
+-51853,-53534,-55178,-56778,-58333,-59838,-61289,-62684,
+-64019,-65290,-66494,-67629,-68692,-69679,-70590,-71420,
+-72169,-72835,-73415,-73908,-74313,-74630,-74856,-74992,
+ 75038
+};
+
+void ff_mpa_synth_init(int16 *window) {
+ int i;
+ int32 v;
+
+ // max = 18760, max sum over all 16 coefs : 44736
+ for(i = 0; i < 257; i++) {
+ v = ff_mpa_enwindow[i];
+ v = (v + 2) >> 2;
+ window[i] = v;
+
+ if ((i & 63) != 0)
+ v = -v;
+
+ if (i != 0)
+ window[512 - i] = v;
+ }
+}
+
+static inline uint16 round_sample(int *sum) {
+ int sum1;
+ sum1 = (*sum) >> 14;
+ *sum &= (1 << 14)-1;
+ if (sum1 < (-0x7fff - 1))
+ sum1 = (-0x7fff - 1);
+ if (sum1 > 0x7fff)
+ sum1 = 0x7fff;
+ return sum1;
+}
+
+static inline int MULH(int a, int b) {
+ return ((int64_t)(a) * (int64_t)(b))>>32;
+}
+
+// signed 16x16 -> 32 multiply add accumulate
+#define MACS(rt, ra, rb) rt += (ra) * (rb)
+
+#define MLSS(rt, ra, rb) ((rt) -= (ra) * (rb))
+
+#define SUM8(op, sum, w, p)\
+{\
+ op(sum, (w)[0 * 64], (p)[0 * 64]);\
+ op(sum, (w)[1 * 64], (p)[1 * 64]);\
+ op(sum, (w)[2 * 64], (p)[2 * 64]);\
+ op(sum, (w)[3 * 64], (p)[3 * 64]);\
+ op(sum, (w)[4 * 64], (p)[4 * 64]);\
+ op(sum, (w)[5 * 64], (p)[5 * 64]);\
+ op(sum, (w)[6 * 64], (p)[6 * 64]);\
+ op(sum, (w)[7 * 64], (p)[7 * 64]);\
+}
+
+#define SUM8P2(sum1, op1, sum2, op2, w1, w2, p) \
+{\
+ tmp_s = p[0 * 64];\
+ op1(sum1, (w1)[0 * 64], tmp_s);\
+ op2(sum2, (w2)[0 * 64], tmp_s);\
+ tmp_s = p[1 * 64];\
+ op1(sum1, (w1)[1 * 64], tmp_s);\
+ op2(sum2, (w2)[1 * 64], tmp_s);\
+ tmp_s = p[2 * 64];\
+ op1(sum1, (w1)[2 * 64], tmp_s);\
+ op2(sum2, (w2)[2 * 64], tmp_s);\
+ tmp_s = p[3 * 64];\
+ op1(sum1, (w1)[3 * 64], tmp_s);\
+ op2(sum2, (w2)[3 * 64], tmp_s);\
+ tmp_s = p[4 * 64];\
+ op1(sum1, (w1)[4 * 64], tmp_s);\
+ op2(sum2, (w2)[4 * 64], tmp_s);\
+ tmp_s = p[5 * 64];\
+ op1(sum1, (w1)[5 * 64], tmp_s);\
+ op2(sum2, (w2)[5 * 64], tmp_s);\
+ tmp_s = p[6 * 64];\
+ op1(sum1, (w1)[6 * 64], tmp_s);\
+ op2(sum2, (w2)[6 * 64], tmp_s);\
+ tmp_s = p[7 * 64];\
+ op1(sum1, (w1)[7 * 64], tmp_s);\
+ op2(sum2, (w2)[7 * 64], tmp_s);\
+}
+
+#define FIXHR(a) ((int)((a) * (1LL<<32) + 0.5))
+
+// tab[i][j] = 1.0 / (2.0 * cos(pi*(2*k+1) / 2^(6 - j)))
+
+// cos(i*pi/64)
+
+#define COS0_0 FIXHR(0.50060299823519630134/2)
+#define COS0_1 FIXHR(0.50547095989754365998/2)
+#define COS0_2 FIXHR(0.51544730992262454697/2)
+#define COS0_3 FIXHR(0.53104259108978417447/2)
+#define COS0_4 FIXHR(0.55310389603444452782/2)
+#define COS0_5 FIXHR(0.58293496820613387367/2)
+#define COS0_6 FIXHR(0.62250412303566481615/2)
+#define COS0_7 FIXHR(0.67480834145500574602/2)
+#define COS0_8 FIXHR(0.74453627100229844977/2)
+#define COS0_9 FIXHR(0.83934964541552703873/2)
+#define COS0_10 FIXHR(0.97256823786196069369/2)
+#define COS0_11 FIXHR(1.16943993343288495515/4)
+#define COS0_12 FIXHR(1.48416461631416627724/4)
+#define COS0_13 FIXHR(2.05778100995341155085/8)
+#define COS0_14 FIXHR(3.40760841846871878570/8)
+#define COS0_15 FIXHR(10.19000812354805681150/32)
+
+#define COS1_0 FIXHR(0.50241928618815570551/2)
+#define COS1_1 FIXHR(0.52249861493968888062/2)
+#define COS1_2 FIXHR(0.56694403481635770368/2)
+#define COS1_3 FIXHR(0.64682178335999012954/2)
+#define COS1_4 FIXHR(0.78815462345125022473/2)
+#define COS1_5 FIXHR(1.06067768599034747134/4)
+#define COS1_6 FIXHR(1.72244709823833392782/4)
+#define COS1_7 FIXHR(5.10114861868916385802/16)
+
+#define COS2_0 FIXHR(0.50979557910415916894/2)
+#define COS2_1 FIXHR(0.60134488693504528054/2)
+#define COS2_2 FIXHR(0.89997622313641570463/2)
+#define COS2_3 FIXHR(2.56291544774150617881/8)
+
+#define COS3_0 FIXHR(0.54119610014619698439/2)
+#define COS3_1 FIXHR(1.30656296487637652785/4)
+
+#define COS4_0 FIXHR(0.70710678118654752439/2)
+
+/* butterfly operator */
+#define BF(a, b, c, s)\
+{\
+ tmp0 = tab[a] + tab[b];\
+ tmp1 = tab[a] - tab[b];\
+ tab[a] = tmp0;\
+ tab[b] = MULH(tmp1<<(s), c);\
+}
+
+#define BF1(a, b, c, d)\
+{\
+ BF(a, b, COS4_0, 1);\
+ BF(c, d,-COS4_0, 1);\
+ tab[c] += tab[d];\
+}
+
+#define BF2(a, b, c, d)\
+{\
+ BF(a, b, COS4_0, 1);\
+ BF(c, d,-COS4_0, 1);\
+ tab[c] += tab[d];\
+ tab[a] += tab[c];\
+ tab[c] += tab[b];\
+ tab[b] += tab[d];\
+}
+
+#define ADD(a, b) tab[a] += tab[b]
+
+// DCT32 without 1/sqrt(2) coef zero scaling.
+static void dct32(int32 *out, int32 *tab) {
+ int tmp0, tmp1;
+
+ // pass 1
+ BF( 0, 31, COS0_0 , 1);
+ BF(15, 16, COS0_15, 5);
+ // pass 2
+ BF( 0, 15, COS1_0 , 1);
+ BF(16, 31,-COS1_0 , 1);
+ // pass 1
+ BF( 7, 24, COS0_7 , 1);
+ BF( 8, 23, COS0_8 , 1);
+ // pass 2
+ BF( 7, 8, COS1_7 , 4);
+ BF(23, 24,-COS1_7 , 4);
+ // pass 3
+ BF( 0, 7, COS2_0 , 1);
+ BF( 8, 15,-COS2_0 , 1);
+ BF(16, 23, COS2_0 , 1);
+ BF(24, 31,-COS2_0 , 1);
+ // pass 1
+ BF( 3, 28, COS0_3 , 1);
+ BF(12, 19, COS0_12, 2);
+ // pass 2
+ BF( 3, 12, COS1_3 , 1);
+ BF(19, 28,-COS1_3 , 1);
+ // pass 1
+ BF( 4, 27, COS0_4 , 1);
+ BF(11, 20, COS0_11, 2);
+ // pass 2
+ BF( 4, 11, COS1_4 , 1);
+ BF(20, 27,-COS1_4 , 1);
+ // pass 3
+ BF( 3, 4, COS2_3 , 3);
+ BF(11, 12,-COS2_3 , 3);
+ BF(19, 20, COS2_3 , 3);
+ BF(27, 28,-COS2_3 , 3);
+ // pass 4
+ BF( 0, 3, COS3_0 , 1);
+ BF( 4, 7,-COS3_0 , 1);
+ BF( 8, 11, COS3_0 , 1);
+ BF(12, 15,-COS3_0 , 1);
+ BF(16, 19, COS3_0 , 1);
+ BF(20, 23,-COS3_0 , 1);
+ BF(24, 27, COS3_0 , 1);
+ BF(28, 31,-COS3_0 , 1);
+
+ // pass 1
+ BF( 1, 30, COS0_1 , 1);
+ BF(14, 17, COS0_14, 3);
+ // pass 2
+ BF( 1, 14, COS1_1 , 1);
+ BF(17, 30,-COS1_1 , 1);
+ // pass 1
+ BF( 6, 25, COS0_6 , 1);
+ BF( 9, 22, COS0_9 , 1);
+ // pass 2
+ BF( 6, 9, COS1_6 , 2);
+ BF(22, 25,-COS1_6 , 2);
+ // pass 3
+ BF( 1, 6, COS2_1 , 1);
+ BF( 9, 14,-COS2_1 , 1);
+ BF(17, 22, COS2_1 , 1);
+ BF(25, 30,-COS2_1 , 1);
+
+ // pass 1
+ BF( 2, 29, COS0_2 , 1);
+ BF(13, 18, COS0_13, 3);
+ // pass 2
+ BF( 2, 13, COS1_2 , 1);
+ BF(18, 29,-COS1_2 , 1);
+ // pass 1
+ BF( 5, 26, COS0_5 , 1);
+ BF(10, 21, COS0_10, 1);
+ // pass 2
+ BF( 5, 10, COS1_5 , 2);
+ BF(21, 26,-COS1_5 , 2);
+ // pass 3
+ BF( 2, 5, COS2_2 , 1);
+ BF(10, 13,-COS2_2 , 1);
+ BF(18, 21, COS2_2 , 1);
+ BF(26, 29,-COS2_2 , 1);
+ // pass 4
+ BF( 1, 2, COS3_1 , 2);
+ BF( 5, 6,-COS3_1 , 2);
+ BF( 9, 10, COS3_1 , 2);
+ BF(13, 14,-COS3_1 , 2);
+ BF(17, 18, COS3_1 , 2);
+ BF(21, 22,-COS3_1 , 2);
+ BF(25, 26, COS3_1 , 2);
+ BF(29, 30,-COS3_1 , 2);
+
+ // pass 5
+ BF1( 0, 1, 2, 3);
+ BF2( 4, 5, 6, 7);
+ BF1( 8, 9, 10, 11);
+ BF2(12, 13, 14, 15);
+ BF1(16, 17, 18, 19);
+ BF2(20, 21, 22, 23);
+ BF1(24, 25, 26, 27);
+ BF2(28, 29, 30, 31);
+
+ // pass 6
+ ADD( 8, 12);
+ ADD(12, 10);
+ ADD(10, 14);
+ ADD(14, 9);
+ ADD( 9, 13);
+ ADD(13, 11);
+ ADD(11, 15);
+
+ out[ 0] = tab[0];
+ out[16] = tab[1];
+ out[ 8] = tab[2];
+ out[24] = tab[3];
+ out[ 4] = tab[4];
+ out[20] = tab[5];
+ out[12] = tab[6];
+ out[28] = tab[7];
+ out[ 2] = tab[8];
+ out[18] = tab[9];
+ out[10] = tab[10];
+ out[26] = tab[11];
+ out[ 6] = tab[12];
+ out[22] = tab[13];
+ out[14] = tab[14];
+ out[30] = tab[15];
+
+ ADD(24, 28);
+ ADD(28, 26);
+ ADD(26, 30);
+ ADD(30, 25);
+ ADD(25, 29);
+ ADD(29, 27);
+ ADD(27, 31);
+
+ out[ 1] = tab[16] + tab[24];
+ out[17] = tab[17] + tab[25];
+ out[ 9] = tab[18] + tab[26];
+ out[25] = tab[19] + tab[27];
+ out[ 5] = tab[20] + tab[28];
+ out[21] = tab[21] + tab[29];
+ out[13] = tab[22] + tab[30];
+ out[29] = tab[23] + tab[31];
+ out[ 3] = tab[24] + tab[20];
+ out[19] = tab[25] + tab[21];
+ out[11] = tab[26] + tab[22];
+ out[27] = tab[27] + tab[23];
+ out[ 7] = tab[28] + tab[18];
+ out[23] = tab[29] + tab[19];
+ out[15] = tab[30] + tab[17];
+ out[31] = tab[31];
+}
+
+// 32 sub band synthesis filter. Input: 32 sub band samples, Output:
+// 32 samples.
+// XXX: optimize by avoiding ring buffer usage
+void ff_mpa_synth_filter(int16 *synth_buf_ptr, int *synth_buf_offset,
+ int16 *window, int *dither_state,
+ int16 *samples, int incr,
+ int32 sb_samples[32])
+{
+ int16 *synth_buf;
+ const int16 *w, *w2, *p;
+ int j, offset;
+ int16 *samples2;
+ int32 tmp[32];
+ int sum, sum2;
+ int tmp_s;
+
+ offset = *synth_buf_offset;
+ synth_buf = synth_buf_ptr + offset;
+
+ dct32(tmp, sb_samples);
+ for(j = 0; j < 32; j++) {
+ // NOTE: can cause a loss in precision if very high amplitude sound
+ if (tmp[j] < (-0x7fff - 1))
+ synth_buf[j] = (-0x7fff - 1);
+ else if (tmp[j] > 0x7fff)
+ synth_buf[j] = 0x7fff;
+ else
+ synth_buf[j] = tmp[j];
+ }
+
+ // copy to avoid wrap
+ memcpy(synth_buf + 512, synth_buf, 32 * sizeof(int16));
+
+ samples2 = samples + 31 * incr;
+ w = window;
+ w2 = window + 31;
+
+ sum = *dither_state;
+ p = synth_buf + 16;
+ SUM8(MACS, sum, w, p);
+ p = synth_buf + 48;
+ SUM8(MLSS, sum, w + 32, p);
+ *samples = round_sample(&sum);
+ samples += incr;
+ w++;
+
+ // we calculate two samples at the same time to avoid one memory
+ // access per two sample
+ for(j = 1; j < 16; j++) {
+ sum2 = 0;
+ p = synth_buf + 16 + j;
+ SUM8P2(sum, MACS, sum2, MLSS, w, w2, p);
+ p = synth_buf + 48 - j;
+ SUM8P2(sum, MLSS, sum2, MLSS, w + 32, w2 + 32, p);
+
+ *samples = round_sample(&sum);
+ samples += incr;
+ sum += sum2;
+ *samples2 = round_sample(&sum);
+ samples2 -= incr;
+ w++;
+ w2--;
+ }
+
+ p = synth_buf + 32;
+ SUM8(MLSS, sum, w + 32, p);
+ *samples = round_sample(&sum);
+ *dither_state= sum;
+
+ offset = (offset - 32) & 511;
+ *synth_buf_offset = offset;
+}
+
+/**
+ * parses a vlc code, faster then get_vlc()
+ * @param bits is the number of bits which will be read at once, must be
+ * identical to nb_bits in init_vlc()
+ * @param max_depth is the number of times bits bits must be read to completely
+ * read the longest vlc code
+ * = (max_vlc_length + bits - 1) / bits
+ */
+static int getVlc2(GetBitContext *s, int16 (*table)[2], int bits, int maxDepth) {
+ int reIndex;
+ int reCache;
+ int index;
+ int code;
+ int n;
+
+ reIndex = s->index;
+ reCache = READ_LE_UINT32(s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
+ index = reCache & (0xffffffff >> (32 - bits));
+ code = table[index][0];
+ n = table[index][1];
+
+ if (maxDepth > 1 && n < 0){
+ reIndex += bits;
+ reCache = READ_LE_UINT32(s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
+
+ int nbBits = -n;
+
+ index = (reCache & (0xffffffff >> (32 - nbBits))) + code;
+ code = table[index][0];
+ n = table[index][1];
+
+ if(maxDepth > 2 && n < 0) {
+ reIndex += nbBits;
+ reCache = READ_LE_UINT32(s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
+
+ nbBits = -n;
+
+ index = (reCache & (0xffffffff >> (32 - nbBits))) + code;
+ code = table[index][0];
+ n = table[index][1];
+ }
+ }
+
+ reCache >>= n;
+ s->index = reIndex + n;
+ return code;
+}
+
+static int allocTable(VLC *vlc, int size, int use_static) {
+ int index;
+ index = vlc->table_size;
+ vlc->table_size += size;
+ if (vlc->table_size > vlc->table_allocated) {
+ if(use_static)
+ error("QDM2 cant do anything, init_vlc() is used with too little memory");
+ vlc->table_allocated += (1 << vlc->bits);
+ vlc->table = (int16 (*)[2])realloc(vlc->table, sizeof(int16 *) * 2 * vlc->table_allocated);
+ if (!vlc->table)
+ return -1;
+ }
+ return index;
+}
+
+#define GET_DATA(v, table, i, wrap, size)\
+{\
+ const uint8 *ptr = (const uint8 *)table + i * wrap;\
+ switch(size) {\
+ case 1:\
+ v = *(const uint8 *)ptr;\
+ break;\
+ case 2:\
+ v = *(const uint16 *)ptr;\
+ break;\
+ default:\
+ v = *(const uint32 *)ptr;\
+ break;\
+ }\
+}
+
+static int build_table(VLC *vlc, int table_nb_bits,
+ int nb_codes,
+ const void *bits, int bits_wrap, int bits_size,
+ const void *codes, int codes_wrap, int codes_size,
+ const void *symbols, int symbols_wrap, int symbols_size,
+ int code_prefix, int n_prefix, int flags)
+{
+ int i, j, k, n, table_size, table_index, nb, n1, index, code_prefix2, symbol;
+ uint32 code;
+ int16 (*table)[2];
+
+ table_size = 1 << table_nb_bits;
+ table_index = allocTable(vlc, table_size, flags & 4);
+ if (table_index < 0)
+ return -1;
+ table = &vlc->table[table_index];
+
+ for(i = 0; i < table_size; i++) {
+ table[i][1] = 0; //bits
+ table[i][0] = -1; //codes
+ }
+
+ // first pass: map codes and compute auxillary table sizes
+ for(i = 0; i < nb_codes; i++) {
+ GET_DATA(n, bits, i, bits_wrap, bits_size);
+ GET_DATA(code, codes, i, codes_wrap, codes_size);
+ // we accept tables with holes
+ if (n <= 0)
+ continue;
+ if (!symbols)
+ symbol = i;
+ else
+ GET_DATA(symbol, symbols, i, symbols_wrap, symbols_size);
+ // if code matches the prefix, it is in the table
+ n -= n_prefix;
+ if(flags & 2)
+ code_prefix2= code & (n_prefix>=32 ? 0xffffffff : (1 << n_prefix)-1);
+ else
+ code_prefix2= code >> n;
+ if (n > 0 && code_prefix2 == code_prefix) {
+ if (n <= table_nb_bits) {
+ // no need to add another table
+ j = (code << (table_nb_bits - n)) & (table_size - 1);
+ nb = 1 << (table_nb_bits - n);
+ for(k = 0; k < nb; k++) {
+ if(flags & 2)
+ j = (code >> n_prefix) + (k<<n);
+ if (table[j][1] /*bits*/ != 0) {
+ error("QDM2 incorrect codes");
+ return -1;
+ }
+ table[j][1] = n; //bits
+ table[j][0] = symbol;
+ j++;
+ }
+ } else {
+ n -= table_nb_bits;
+ j = (code >> ((flags & 2) ? n_prefix : n)) & ((1 << table_nb_bits) - 1);
+ // compute table size
+ n1 = -table[j][1]; //bits
+ if (n > n1)
+ n1 = n;
+ table[j][1] = -n1; //bits
+ }
+ }
+ }
+
+ // second pass : fill auxillary tables recursively
+ for(i = 0;i < table_size; i++) {
+ n = table[i][1]; //bits
+ if (n < 0) {
+ n = -n;
+ if (n > table_nb_bits) {
+ n = table_nb_bits;
+ table[i][1] = -n; //bits
+ }
+ index = build_table(vlc, n, nb_codes,
+ bits, bits_wrap, bits_size,
+ codes, codes_wrap, codes_size,
+ symbols, symbols_wrap, symbols_size,
+ (flags & 2) ? (code_prefix | (i << n_prefix)) : ((code_prefix << table_nb_bits) | i),
+ n_prefix + table_nb_bits, flags);
+ if (index < 0)
+ return -1;
+ // note: realloc has been done, so reload tables
+ table = &vlc->table[table_index];
+ table[i][0] = index; //code
+ }
+ }
+ return table_index;
+}
+
+/* Build VLC decoding tables suitable for use with get_vlc().
+
+ 'nb_bits' set thee decoding table size (2^nb_bits) entries. The
+ bigger it is, the faster is the decoding. But it should not be too
+ big to save memory and L1 cache. '9' is a good compromise.
+
+ 'nb_codes' : number of vlcs codes
+
+ 'bits' : table which gives the size (in bits) of each vlc code.
+
+ 'codes' : table which gives the bit pattern of of each vlc code.
+
+ 'symbols' : table which gives the values to be returned from get_vlc().
+
+ 'xxx_wrap' : give the number of bytes between each entry of the
+ 'bits' or 'codes' tables.
+
+ 'xxx_size' : gives the number of bytes of each entry of the 'bits'
+ or 'codes' tables.
+
+ 'wrap' and 'size' allows to use any memory configuration and types
+ (byte/word/long) to store the 'bits', 'codes', and 'symbols' tables.
+
+ 'use_static' should be set to 1 for tables, which should be freed
+ with av_free_static(), 0 if free_vlc() will be used.
+*/
+void initVlcSparse(VLC *vlc, int nb_bits, int nb_codes,
+ const void *bits, int bits_wrap, int bits_size,
+ const void *codes, int codes_wrap, int codes_size,
+ const void *symbols, int symbols_wrap, int symbols_size) {
+ vlc->bits = nb_bits;
+
+ if(vlc->table_size && vlc->table_size == vlc->table_allocated) {
+ return;
+ } else if(vlc->table_size) {
+ error("called on a partially initialized table");
+ }
+
+ if (build_table(vlc, nb_bits, nb_codes,
+ bits, bits_wrap, bits_size,
+ codes, codes_wrap, codes_size,
+ symbols, symbols_wrap, symbols_size,
+ 0, 0, 4 | 2) < 0) {
+ free(&vlc->table);
+ return; // Error
+ }
+
+ if(vlc->table_size != vlc->table_allocated)
+ error("QDM2 needed %d had %d", vlc->table_size, vlc->table_allocated);
+}
+
+void QDM2Stream::softclipTableInit(void) {
+ uint16 i;
+ double dfl = SOFTCLIP_THRESHOLD - 32767;
+ float delta = 1.0 / -dfl;
+
+ for (i = 0; i < ARRAYSIZE(_softclipTable); i++)
+ _softclipTable[i] = SOFTCLIP_THRESHOLD - ((int)(sin((float)i * delta) * dfl) & 0x0000FFFF);
+}
+
+// random generated table
+void QDM2Stream::rndTableInit(void) {
+ uint16 i;
+ uint16 j;
+ uint32 ldw, hdw;
+ // TODO: Replace Code with uint64 less version...
+ int64_t tmp64_1;
+ int64_t random_seed = 0;
+ float delta = 1.0 / 16384.0;
+
+ for(i = 0; i < ARRAYSIZE(_noiseTable); i++) {
+ random_seed = random_seed * 214013 + 2531011;
+ _noiseTable[i] = (delta * (float)(((int32)random_seed >> 16) & 0x00007FFF)- 1.0) * 1.3;
+ }
+
+ for (i = 0; i < 256; i++) {
+ random_seed = 81;
+ ldw = i;
+ for (j = 0; j < 5; j++) {
+ _randomDequantIndex[i][j] = (uint8)((ldw / random_seed) & 0xFF);
+ ldw = (uint32)ldw % (uint32)random_seed;
+ tmp64_1 = (random_seed * 0x55555556);
+ hdw = (uint32)(tmp64_1 >> 32);
+ random_seed = (int64_t)(hdw + (ldw >> 31));
+ }
+ }
+
+ for (i = 0; i < 128; i++) {
+ random_seed = 25;
+ ldw = i;
+ for (j = 0; j < 3; j++) {
+ _randomDequantType24[i][j] = (uint8)((ldw / random_seed) & 0xFF);
+ ldw = (uint32)ldw % (uint32)random_seed;
+ tmp64_1 = (random_seed * 0x66666667);
+ hdw = (uint32)(tmp64_1 >> 33);
+ random_seed = hdw + (ldw >> 31);
+ }
+ }
+}
+
+void QDM2Stream::initNoiseSamples(void) {
+ uint16 i;
+ uint32 random_seed = 0;
+ float delta = 1.0 / 16384.0;
+
+ for (i = 0; i < ARRAYSIZE(_noiseSamples); i++) {
+ random_seed = random_seed * 214013 + 2531011;
+ _noiseSamples[i] = (delta * (float)((random_seed >> 16) & 0x00007fff) - 1.0);
+ }
+}
+
+static const uint16 qdm2_vlc_offs[18] = {
+ 0, 260, 566, 598, 894, 1166, 1230, 1294, 1678, 1950, 2214, 2278, 2310, 2570, 2834, 3124, 3448, 3838
+};
+
+void QDM2Stream::initVlc(void) {
+ static int16 qdm2_table[3838][2];
+
+ if (!_vlcsInitialized) {
+ _vlcTabLevel.table = &qdm2_table[qdm2_vlc_offs[0]];
+ _vlcTabLevel.table_allocated = qdm2_vlc_offs[1] - qdm2_vlc_offs[0];
+ _vlcTabLevel.table_size = 0;
+ initVlcSparse(&_vlcTabLevel, 8, 24,
+ vlc_tab_level_huffbits, 1, 1,
+ vlc_tab_level_huffcodes, 2, 2, NULL, 0, 0);
+
+ _vlcTabDiff.table = &qdm2_table[qdm2_vlc_offs[1]];
+ _vlcTabDiff.table_allocated = qdm2_vlc_offs[2] - qdm2_vlc_offs[1];
+ _vlcTabDiff.table_size = 0;
+ initVlcSparse(&_vlcTabDiff, 8, 37,
+ vlc_tab_diff_huffbits, 1, 1,
+ vlc_tab_diff_huffcodes, 2, 2, NULL, 0, 0);
+
+ _vlcTabRun.table = &qdm2_table[qdm2_vlc_offs[2]];
+ _vlcTabRun.table_allocated = qdm2_vlc_offs[3] - qdm2_vlc_offs[2];
+ _vlcTabRun.table_size = 0;
+ initVlcSparse(&_vlcTabRun, 5, 6,
+ vlc_tab_run_huffbits, 1, 1,
+ vlc_tab_run_huffcodes, 1, 1, NULL, 0, 0);
+
+ _fftLevelExpAltVlc.table = &qdm2_table[qdm2_vlc_offs[3]];
+ _fftLevelExpAltVlc.table_allocated = qdm2_vlc_offs[4] - qdm2_vlc_offs[3];
+ _fftLevelExpAltVlc.table_size = 0;
+ initVlcSparse(&_fftLevelExpAltVlc, 8, 28,
+ fft_level_exp_alt_huffbits, 1, 1,
+ fft_level_exp_alt_huffcodes, 2, 2, NULL, 0, 0);
+
+ _fftLevelExpVlc.table = &qdm2_table[qdm2_vlc_offs[4]];
+ _fftLevelExpVlc.table_allocated = qdm2_vlc_offs[5] - qdm2_vlc_offs[4];
+ _fftLevelExpVlc.table_size = 0;
+ initVlcSparse(&_fftLevelExpVlc, 8, 20,
+ fft_level_exp_huffbits, 1, 1,
+ fft_level_exp_huffcodes, 2, 2, NULL, 0, 0);
+
+ _fftStereoExpVlc.table = &qdm2_table[qdm2_vlc_offs[5]];
+ _fftStereoExpVlc.table_allocated = qdm2_vlc_offs[6] - qdm2_vlc_offs[5];
+ _fftStereoExpVlc.table_size = 0;
+ initVlcSparse(&_fftStereoExpVlc, 6, 7,
+ fft_stereo_exp_huffbits, 1, 1,
+ fft_stereo_exp_huffcodes, 1, 1, NULL, 0, 0);
+
+ _fftStereoPhaseVlc.table = &qdm2_table[qdm2_vlc_offs[6]];
+ _fftStereoPhaseVlc.table_allocated = qdm2_vlc_offs[7] - qdm2_vlc_offs[6];
+ _fftStereoPhaseVlc.table_size = 0;
+ initVlcSparse(&_fftStereoPhaseVlc, 6, 9,
+ fft_stereo_phase_huffbits, 1, 1,
+ fft_stereo_phase_huffcodes, 1, 1, NULL, 0, 0);
+
+ _vlcTabToneLevelIdxHi1.table = &qdm2_table[qdm2_vlc_offs[7]];
+ _vlcTabToneLevelIdxHi1.table_allocated = qdm2_vlc_offs[8] - qdm2_vlc_offs[7];
+ _vlcTabToneLevelIdxHi1.table_size = 0;
+ initVlcSparse(&_vlcTabToneLevelIdxHi1, 8, 20,
+ vlc_tab_tone_level_idx_hi1_huffbits, 1, 1,
+ vlc_tab_tone_level_idx_hi1_huffcodes, 2, 2, NULL, 0, 0);
+
+ _vlcTabToneLevelIdxMid.table = &qdm2_table[qdm2_vlc_offs[8]];
+ _vlcTabToneLevelIdxMid.table_allocated = qdm2_vlc_offs[9] - qdm2_vlc_offs[8];
+ _vlcTabToneLevelIdxMid.table_size = 0;
+ initVlcSparse(&_vlcTabToneLevelIdxMid, 8, 24,
+ vlc_tab_tone_level_idx_mid_huffbits, 1, 1,
+ vlc_tab_tone_level_idx_mid_huffcodes, 2, 2, NULL, 0, 0);
+
+ _vlcTabToneLevelIdxHi2.table = &qdm2_table[qdm2_vlc_offs[9]];
+ _vlcTabToneLevelIdxHi2.table_allocated = qdm2_vlc_offs[10] - qdm2_vlc_offs[9];
+ _vlcTabToneLevelIdxHi2.table_size = 0;
+ initVlcSparse(&_vlcTabToneLevelIdxHi2, 8, 24,
+ vlc_tab_tone_level_idx_hi2_huffbits, 1, 1,
+ vlc_tab_tone_level_idx_hi2_huffcodes, 2, 2, NULL, 0, 0);
+
+ _vlcTabType30.table = &qdm2_table[qdm2_vlc_offs[10]];
+ _vlcTabType30.table_allocated = qdm2_vlc_offs[11] - qdm2_vlc_offs[10];
+ _vlcTabType30.table_size = 0;
+ initVlcSparse(&_vlcTabType30, 6, 9,
+ vlc_tab_type30_huffbits, 1, 1,
+ vlc_tab_type30_huffcodes, 1, 1, NULL, 0, 0);
+
+ _vlcTabType34.table = &qdm2_table[qdm2_vlc_offs[11]];
+ _vlcTabType34.table_allocated = qdm2_vlc_offs[12] - qdm2_vlc_offs[11];
+ _vlcTabType34.table_size = 0;
+ initVlcSparse(&_vlcTabType34, 5, 10,
+ vlc_tab_type34_huffbits, 1, 1,
+ vlc_tab_type34_huffcodes, 1, 1, NULL, 0, 0);
+
+ _vlcTabFftToneOffset[0].table = &qdm2_table[qdm2_vlc_offs[12]];
+ _vlcTabFftToneOffset[0].table_allocated = qdm2_vlc_offs[13] - qdm2_vlc_offs[12];
+ _vlcTabFftToneOffset[0].table_size = 0;
+ initVlcSparse(&_vlcTabFftToneOffset[0], 8, 23,
+ vlc_tab_fft_tone_offset_0_huffbits, 1, 1,
+ vlc_tab_fft_tone_offset_0_huffcodes, 2, 2, NULL, 0, 0);
+
+ _vlcTabFftToneOffset[1].table = &qdm2_table[qdm2_vlc_offs[13]];
+ _vlcTabFftToneOffset[1].table_allocated = qdm2_vlc_offs[14] - qdm2_vlc_offs[13];
+ _vlcTabFftToneOffset[1].table_size = 0;
+ initVlcSparse(&_vlcTabFftToneOffset[1], 8, 28,
+ vlc_tab_fft_tone_offset_1_huffbits, 1, 1,
+ vlc_tab_fft_tone_offset_1_huffcodes, 2, 2, NULL, 0, 0);
+
+ _vlcTabFftToneOffset[2].table = &qdm2_table[qdm2_vlc_offs[14]];
+ _vlcTabFftToneOffset[2].table_allocated = qdm2_vlc_offs[15] - qdm2_vlc_offs[14];
+ _vlcTabFftToneOffset[2].table_size = 0;
+ initVlcSparse(&_vlcTabFftToneOffset[2], 8, 32,
+ vlc_tab_fft_tone_offset_2_huffbits, 1, 1,
+ vlc_tab_fft_tone_offset_2_huffcodes, 2, 2, NULL, 0, 0);
+
+ _vlcTabFftToneOffset[3].table = &qdm2_table[qdm2_vlc_offs[15]];
+ _vlcTabFftToneOffset[3].table_allocated = qdm2_vlc_offs[16] - qdm2_vlc_offs[15];
+ _vlcTabFftToneOffset[3].table_size = 0;
+ initVlcSparse(&_vlcTabFftToneOffset[3], 8, 35,
+ vlc_tab_fft_tone_offset_3_huffbits, 1, 1,
+ vlc_tab_fft_tone_offset_3_huffcodes, 2, 2, NULL, 0, 0);
+
+ _vlcTabFftToneOffset[4].table = &qdm2_table[qdm2_vlc_offs[16]];
+ _vlcTabFftToneOffset[4].table_allocated = qdm2_vlc_offs[17] - qdm2_vlc_offs[16];
+ _vlcTabFftToneOffset[4].table_size = 0;
+ initVlcSparse(&_vlcTabFftToneOffset[4], 8, 38,
+ vlc_tab_fft_tone_offset_4_huffbits, 1, 1,
+ vlc_tab_fft_tone_offset_4_huffcodes, 2, 2, NULL, 0, 0);
+
+ _vlcsInitialized = true;
+ }
+}
+
+QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadStream *extraData) {
+ uint32 tmp;
+ int32 tmp_s;
+ int tmp_val;
+ int i;
+
+ debug(1, "QDM2Stream::QDM2Stream() Call");
+
+ _stream = stream;
+ _compressedData = NULL;
+ _subPacket = 0;
+ _superBlockStart = 0;
+ memset(_quantizedCoeffs, 0, sizeof(_quantizedCoeffs));
+ memset(_fftLevelExp, 0, sizeof(_fftLevelExp));
+ _noiseIdx = 0;
+ memset(_fftCoefsMinIndex, 0, sizeof(_fftCoefsMinIndex));
+ memset(_fftCoefsMaxIndex, 0, sizeof(_fftCoefsMaxIndex));
+ _fftToneStart = 0;
+ _fftToneEnd = 0;
+ for(i = 0; i < ARRAYSIZE(_subPacketListA); i++) {
+ _subPacketListA[i].packet = NULL;
+ _subPacketListA[i].next = NULL;
+ }
+ _subPacketsB = 0;
+ for(i = 0; i < ARRAYSIZE(_subPacketListB); i++) {
+ _subPacketListB[i].packet = NULL;
+ _subPacketListB[i].next = NULL;
+ }
+ for(i = 0; i < ARRAYSIZE(_subPacketListC); i++) {
+ _subPacketListC[i].packet = NULL;
+ _subPacketListC[i].next = NULL;
+ }
+ for(i = 0; i < ARRAYSIZE(_subPacketListD); i++) {
+ _subPacketListD[i].packet = NULL;
+ _subPacketListD[i].next = NULL;
+ }
+ memset(_synthBuf, 0, sizeof(_synthBuf));
+ memset(_synthBufOffset, 0, sizeof(_synthBufOffset));
+ memset(_sbSamples, 0, sizeof(_sbSamples));
+ memset(_outputBuffer, 0, sizeof(_outputBuffer));
+ _vlcsInitialized = false;
+ _superblocktype_2_3 = 0;
+ _hasErrors = false;
+
+ // Rewind extraData stream from any previous calls...
+ extraData->seek(0, SEEK_SET);
+
+ tmp_s = extraData->readSint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() extraSize: %d", tmp_s);
+ if ((extraData->size() - extraData->pos()) / 4 + 1 != tmp_s)
+ warning("QDM2Stream::QDM2Stream() extraSize mismatch - Expected %d", (extraData->size() - extraData->pos()) / 4 + 1);
+ if (tmp_s < 12)
+ error("QDM2Stream::QDM2Stream() Insufficient extraData");
+
+ tmp = extraData->readUint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() extraTag: %d", tmp);
+ if (tmp != MKID_BE('frma'))
+ warning("QDM2Stream::QDM2Stream() extraTag mismatch");
+
+ tmp = extraData->readUint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() extraType: %d", tmp);
+ if (tmp == MKID_BE('QDMC'))
+ warning("QDM2Stream::QDM2Stream() QDMC stream type not supported.");
+ else if (tmp != MKID_BE('QDM2'))
+ error("QDM2Stream::QDM2Stream() Unsupported stream type");
+
+ tmp_s = extraData->readSint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() extraSize2: %d", tmp_s);
+ if ((extraData->size() - extraData->pos()) + 4 != tmp_s)
+ warning("QDM2Stream::QDM2Stream() extraSize2 mismatch - Expected %d", (extraData->size() - extraData->pos()) + 4);
+
+ tmp = extraData->readUint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() extraTag2: %d", tmp);
+ if (tmp != MKID_BE('QDCA'))
+ warning("QDM2Stream::QDM2Stream() extraTag2 mismatch");
+
+ if (extraData->readUint32BE() != 1)
+ warning("QDM2Stream::QDM2Stream() u0 field not 1");
+
+ _channels = extraData->readUint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() channels: %d", _channels);
+
+ _sampleRate = extraData->readUint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() sampleRate: %d", _sampleRate);
+
+ _bitRate = extraData->readUint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() bitRate: %d", _bitRate);
+
+ _blockSize = extraData->readUint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() blockSize: %d", _blockSize);
+
+ _frameSize = extraData->readUint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() frameSize: %d", _frameSize);
+
+ _packetSize = extraData->readUint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() packetSize: %d", _packetSize);
+
+ if (extraData->size() - extraData->pos() != 0) {
+ tmp_s = extraData->readSint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() extraSize3: %d", tmp_s);
+ if (extraData->size() + 4 != tmp_s)
+ warning("QDM2Stream::QDM2Stream() extraSize3 mismatch - Expected %d", extraData->size() + 4);
+
+ tmp = extraData->readUint32BE();
+ debug(1, "QDM2Stream::QDM2Stream() extraTag3: %d", tmp);
+ if (tmp != MKID_BE('QDCP'))
+ warning("QDM2Stream::QDM2Stream() extraTag3 mismatch");
+
+ if ((float)extraData->readUint32BE() != 1.0)
+ warning("QDM2Stream::QDM2Stream() uf0 field not 1.0");
+
+ if (extraData->readUint32BE() != 0)
+ warning("QDM2Stream::QDM2Stream() u1 field not 0");
+
+ if ((float)extraData->readUint32BE() != 1.0)
+ warning("QDM2Stream::QDM2Stream() uf1 field not 1.0");
+
+ if ((float)extraData->readUint32BE() != 1.0)
+ warning("QDM2Stream::QDM2Stream() uf2 field not 1.0");
+
+ if (extraData->readUint32BE() != 27)
+ warning("QDM2Stream::QDM2Stream() u2 field not 27");
+
+ if (extraData->readUint32BE() != 8)
+ warning("QDM2Stream::QDM2Stream() u3 field not 8");
+
+ if (extraData->readUint32BE() != 0)
+ warning("QDM2Stream::QDM2Stream() u4 field not 0");
+ }
+
+ _fftOrder = scummvm_log2(_frameSize) + 1;
+ _fftFrameSize = 2 * _frameSize; // complex has two floats
+
+ // something like max decodable tones
+ _groupOrder = scummvm_log2(_blockSize) + 1;
+ _sFrameSize = _blockSize / 16; // 16 iterations per super block
+
+ _subSampling = _fftOrder - 7;
+ _frequencyRange = 255 / (1 << (2 - _subSampling));
+
+ switch ((_subSampling * 2 + _channels - 1)) {
+ case 0:
+ tmp = 40;
+ break;
+ case 1:
+ tmp = 48;
+ break;
+ case 2:
+ tmp = 56;
+ break;
+ case 3:
+ tmp = 72;
+ break;
+ case 4:
+ tmp = 80;
+ break;
+ case 5:
+ tmp = 100;
+ break;
+ default:
+ tmp = _subSampling;
+ break;
+ }
+
+ tmp_val = 0;
+ if ((tmp * 1000) < _bitRate) tmp_val = 1;
+ if ((tmp * 1440) < _bitRate) tmp_val = 2;
+ if ((tmp * 1760) < _bitRate) tmp_val = 3;
+ if ((tmp * 2240) < _bitRate) tmp_val = 4;
+ _cmTableSelect = tmp_val;
+
+ if (_subSampling == 0)
+ tmp = 7999;
+ else
+ tmp = ((-(_subSampling -1)) & 8000) + 20000;
+
+ if (tmp < 8000)
+ _coeffPerSbSelect = 0;
+ else if (tmp <= 16000)
+ _coeffPerSbSelect = 1;
+ else
+ _coeffPerSbSelect = 2;
+
+ if (_fftOrder < 7 || _fftOrder > 9)
+ error("QDM2Stream::QDM2Stream() Unsupported fft_order: %d", _fftOrder);
+
+ rdftInit(&_rdftCtx, _fftOrder, IRDFT);
+
+ initVlc();
+ ff_mpa_synth_init(ff_mpa_synth_window);
+ softclipTableInit();
+ rndTableInit();
+ initNoiseSamples();
+
+ _compressedData = new uint8[_packetSize];
+}
+
+QDM2Stream::~QDM2Stream() {
+ delete[] _compressedData;
+ delete _stream;
+}
+
+static int qdm2_get_vlc(GetBitContext *gb, VLC *vlc, int flag, int depth) {
+ int value = getVlc2(gb, vlc->table, vlc->bits, depth);
+
+ // stage-2, 3 bits exponent escape sequence
+ if (value-- == 0)
+ value = getBits(gb, getBits (gb, 3) + 1);
+
+ // stage-3, optional
+ if (flag) {
+ int tmp = vlc_stage3_values[value];
+
+ if ((value & ~3) > 0)
+ tmp += getBits(gb, (value >> 2));
+ value = tmp;
+ }
+
+ return value;
+}
+
+static int qdm2_get_se_vlc(VLC *vlc, GetBitContext *gb, int depth)
+{
+ int value = qdm2_get_vlc(gb, vlc, 0, depth);
+
+ return (value & 1) ? ((value + 1) >> 1) : -(value >> 1);
+}
+
+/**
+ * QDM2 checksum
+ *
+ * @param data pointer to data to be checksum'ed
+ * @param length data length
+ * @param value checksum value
+ *
+ * @return 0 if checksum is OK
+ */
+static uint16 qdm2_packet_checksum(const uint8 *data, int length, int value) {
+ int i;
+
+ for (i = 0; i < length; i++)
+ value -= data[i];
+
+ return (uint16)(value & 0xffff);
+}
+
+/**
+ * Fills a QDM2SubPacket structure with packet type, size, and data pointer.
+ *
+ * @param gb bitreader context
+ * @param sub_packet packet under analysis
+ */
+static void qdm2_decode_sub_packet_header(GetBitContext *gb, QDM2SubPacket *sub_packet)
+{
+ sub_packet->type = getBits (gb, 8);
+
+ if (sub_packet->type == 0) {
+ sub_packet->size = 0;
+ sub_packet->data = NULL;
+ } else {
+ sub_packet->size = getBits (gb, 8);
+
+ if (sub_packet->type & 0x80) {
+ sub_packet->size <<= 8;
+ sub_packet->size |= getBits (gb, 8);
+ sub_packet->type &= 0x7f;
+ }
+
+ if (sub_packet->type == 0x7f)
+ sub_packet->type |= (getBits (gb, 8) << 8);
+
+ sub_packet->data = &gb->buffer[getBitsCount(gb) / 8]; // FIXME: this depends on bitreader internal data
+ }
+}
+
+/**
+ * Return node pointer to first packet of requested type in list.
+ *
+ * @param list list of subpackets to be scanned
+ * @param type type of searched subpacket
+ * @return node pointer for subpacket if found, else NULL
+ */
+static QDM2SubPNode* qdm2_search_subpacket_type_in_list(QDM2SubPNode *list, int type)
+{
+ while (list != NULL && list->packet != NULL) {
+ if (list->packet->type == type)
+ return list;
+ list = list->next;
+ }
+ return NULL;
+}
+
+/**
+ * Replaces 8 elements with their average value.
+ * Called by qdm2_decode_superblock before starting subblock decoding.
+ */
+void QDM2Stream::average_quantized_coeffs(void) {
+ int i, j, n, ch, sum;
+
+ n = coeff_per_sb_for_avg[_coeffPerSbSelect][QDM2_SB_USED(_subSampling) - 1] + 1;
+
+ for (ch = 0; ch < _channels; ch++) {
+ for (i = 0; i < n; i++) {
+ sum = 0;
+
+ for (j = 0; j < 8; j++)
+ sum += _quantizedCoeffs[ch][i][j];
+
+ sum /= 8;
+ if (sum > 0)
+ sum--;
+
+ for (j = 0; j < 8; j++)
+ _quantizedCoeffs[ch][i][j] = sum;
+ }
+ }
+}
+
+/**
+ * Build subband samples with noise weighted by q->tone_level.
+ * Called by synthfilt_build_sb_samples.
+ *
+ * @param sb subband index
+ */
+void QDM2Stream::build_sb_samples_from_noise(int sb) {
+ int ch, j;
+
+ FIX_NOISE_IDX(_noiseIdx);
+
+ if (!_channels)
+ return;
+
+ for (ch = 0; ch < _channels; ch++) {
+ for (j = 0; j < 64; j++) {
+ _sbSamples[ch][j * 2][sb] = (int32)(SB_DITHERING_NOISE(sb, _noiseIdx) * _toneLevel[ch][sb][j] + .5);
+ _sbSamples[ch][j * 2 + 1][sb] = (int32)(SB_DITHERING_NOISE(sb, _noiseIdx) * _toneLevel[ch][sb][j] + .5);
+ }
+ }
+}
+
+/**
+ * Called while processing data from subpackets 11 and 12.
+ * Used after making changes to coding_method array.
+ *
+ * @param sb subband index
+ * @param channels number of channels
+ * @param coding_method q->coding_method[0][0][0]
+ */
+void QDM2Stream::fix_coding_method_array(int sb, int channels, sb_int8_array coding_method)
+{
+ int j, k;
+ int ch;
+ int run, case_val;
+ int switchtable[23] = {0,5,1,5,5,5,5,5,2,5,5,5,5,5,5,5,3,5,5,5,5,5,4};
+
+ for (ch = 0; ch < channels; ch++) {
+ for (j = 0; j < 64; ) {
+ if((coding_method[ch][sb][j] - 8) > 22) {
+ run = 1;
+ case_val = 8;
+ } else {
+ switch (switchtable[coding_method[ch][sb][j]-8]) {
+ case 0: run = 10; case_val = 10; break;
+ case 1: run = 1; case_val = 16; break;
+ case 2: run = 5; case_val = 24; break;
+ case 3: run = 3; case_val = 30; break;
+ case 4: run = 1; case_val = 30; break;
+ case 5: run = 1; case_val = 8; break;
+ default: run = 1; case_val = 8; break;
+ }
+ }
+ for (k = 0; k < run; k++)
+ if (j + k < 128)
+ if (coding_method[ch][sb + (j + k) / 64][(j + k) % 64] > coding_method[ch][sb][j])
+ if (k > 0) {
+ warning("QDM2 Untested Code: not debugged, almost never used");
+ memset(&coding_method[ch][sb][j + k], case_val, k * sizeof(int8));
+ memset(&coding_method[ch][sb][j + k], case_val, 3 * sizeof(int8));
+ }
+ j += run;
+ }
+ }
+}
+
+/**
+ * Related to synthesis filter
+ * Called by process_subpacket_10
+ *
+ * @param flag 1 if called after getting data from subpacket 10, 0 if no subpacket 10
+ */
+void QDM2Stream::fill_tone_level_array(int flag) {
+ int i, sb, ch, sb_used;
+ int tmp, tab;
+
+ // This should never happen
+ if (_channels <= 0)
+ return;
+
+ for (ch = 0; ch < _channels; ch++) {
+ for (sb = 0; sb < 30; sb++) {
+ for (i = 0; i < 8; i++) {
+ if ((tab=coeff_per_sb_for_dequant[_coeffPerSbSelect][sb]) < (last_coeff[_coeffPerSbSelect] - 1))
+ tmp = _quantizedCoeffs[ch][tab + 1][i] * dequant_table[_coeffPerSbSelect][tab + 1][sb]+
+ _quantizedCoeffs[ch][tab][i] * dequant_table[_coeffPerSbSelect][tab][sb];
+ else
+ tmp = _quantizedCoeffs[ch][tab][i] * dequant_table[_coeffPerSbSelect][tab][sb];
+ if(tmp < 0)
+ tmp += 0xff;
+ _toneLevelIdxBase[ch][sb][i] = (tmp / 256) & 0xff;
+ }
+ }
+ }
+
+ sb_used = QDM2_SB_USED(_subSampling);
+
+ if ((_superblocktype_2_3 != 0) && !flag) {
+ for (sb = 0; sb < sb_used; sb++) {
+ for (ch = 0; ch < _channels; ch++) {
+ for (i = 0; i < 64; i++) {
+ _toneLevelIdx[ch][sb][i] = _toneLevelIdxBase[ch][sb][i / 8];
+ if (_toneLevelIdx[ch][sb][i] < 0)
+ _toneLevel[ch][sb][i] = 0;
+ else
+ _toneLevel[ch][sb][i] = fft_tone_level_table[0][_toneLevelIdx[ch][sb][i] & 0x3f];
+ }
+ }
+ }
+ } else {
+ tab = _superblocktype_2_3 ? 0 : 1;
+ for (sb = 0; sb < sb_used; sb++) {
+ if ((sb >= 4) && (sb <= 23)) {
+ for (ch = 0; ch < _channels; ch++) {
+ for (i = 0; i < 64; i++) {
+ tmp = _toneLevelIdxBase[ch][sb][i / 8] -
+ _toneLevelIdxHi1[ch][sb / 8][i / 8][i % 8] -
+ _toneLevelIdxMid[ch][sb - 4][i / 8] -
+ _toneLevelIdxHi2[ch][sb - 4];
+ _toneLevelIdx[ch][sb][i] = tmp & 0xff;
+ if ((tmp < 0) || (!_superblocktype_2_3 && !tmp))
+ _toneLevel[ch][sb][i] = 0;
+ else
+ _toneLevel[ch][sb][i] = fft_tone_level_table[tab][tmp & 0x3f];
+ }
+ }
+ } else {
+ if (sb > 4) {
+ for (ch = 0; ch < _channels; ch++) {
+ for (i = 0; i < 64; i++) {
+ tmp = _toneLevelIdxBase[ch][sb][i / 8] -
+ _toneLevelIdxHi1[ch][2][i / 8][i % 8] -
+ _toneLevelIdxHi2[ch][sb - 4];
+ _toneLevelIdx[ch][sb][i] = tmp & 0xff;
+ if ((tmp < 0) || (!_superblocktype_2_3 && !tmp))
+ _toneLevel[ch][sb][i] = 0;
+ else
+ _toneLevel[ch][sb][i] = fft_tone_level_table[tab][tmp & 0x3f];
+ }
+ }
+ } else {
+ for (ch = 0; ch < _channels; ch++) {
+ for (i = 0; i < 64; i++) {
+ tmp = _toneLevelIdx[ch][sb][i] = _toneLevelIdxBase[ch][sb][i / 8];
+ if ((tmp < 0) || (!_superblocktype_2_3 && !tmp))
+ _toneLevel[ch][sb][i] = 0;
+ else
+ _toneLevel[ch][sb][i] = fft_tone_level_table[tab][tmp & 0x3f];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Related to synthesis filter
+ * Called by process_subpacket_11
+ * c is built with data from subpacket 11
+ * Most of this function is used only if superblock_type_2_3 == 0, never seen it in samples
+ *
+ * @param tone_level_idx
+ * @param tone_level_idx_temp
+ * @param coding_method q->coding_method[0][0][0]
+ * @param nb_channels number of channels
+ * @param c coming from subpacket 11, passed as 8*c
+ * @param superblocktype_2_3 flag based on superblock packet type
+ * @param cm_table_select q->cm_table_select
+ */
+void QDM2Stream::fill_coding_method_array(sb_int8_array tone_level_idx, sb_int8_array tone_level_idx_temp,
+ sb_int8_array coding_method, int nb_channels,
+ int c, int superblocktype_2_3, int cm_table_select) {
+ int ch, sb, j;
+ int tmp, acc, esp_40, comp;
+ int add1, add2, add3, add4;
+ // TODO : Remove multres 64 bit variable necessity...
+ int64_t multres;
+
+ // This should never happen
+ if (nb_channels <= 0)
+ return;
+ if (!superblocktype_2_3) {
+ warning("QDM2 This case is untested, no samples available");
+ for (ch = 0; ch < nb_channels; ch++)
+ for (sb = 0; sb < 30; sb++) {
+ for (j = 1; j < 63; j++) { // The loop only iterates to 63 so the code doesn't overflow the buffer
+ add1 = tone_level_idx[ch][sb][j] - 10;
+ if (add1 < 0)
+ add1 = 0;
+ add2 = add3 = add4 = 0;
+ if (sb > 1) {
+ add2 = tone_level_idx[ch][sb - 2][j] + tone_level_idx_offset_table[sb][0] - 6;
+ if (add2 < 0)
+ add2 = 0;
+ }
+ if (sb > 0) {
+ add3 = tone_level_idx[ch][sb - 1][j] + tone_level_idx_offset_table[sb][1] - 6;
+ if (add3 < 0)
+ add3 = 0;
+ }
+ if (sb < 29) {
+ add4 = tone_level_idx[ch][sb + 1][j] + tone_level_idx_offset_table[sb][3] - 6;
+ if (add4 < 0)
+ add4 = 0;
+ }
+ tmp = tone_level_idx[ch][sb][j + 1] * 2 - add4 - add3 - add2 - add1;
+ if (tmp < 0)
+ tmp = 0;
+ tone_level_idx_temp[ch][sb][j + 1] = tmp & 0xff;
+ }
+ tone_level_idx_temp[ch][sb][0] = tone_level_idx_temp[ch][sb][1];
+ }
+ acc = 0;
+ for (ch = 0; ch < nb_channels; ch++)
+ for (sb = 0; sb < 30; sb++)
+ for (j = 0; j < 64; j++)
+ acc += tone_level_idx_temp[ch][sb][j];
+
+ multres = 0x66666667 * (acc * 10);
+ esp_40 = (multres >> 32) / 8 + ((multres & 0xffffffff) >> 31);
+ for (ch = 0; ch < nb_channels; ch++)
+ for (sb = 0; sb < 30; sb++)
+ for (j = 0; j < 64; j++) {
+ comp = tone_level_idx_temp[ch][sb][j]* esp_40 * 10;
+ if (comp < 0)
+ comp += 0xff;
+ comp /= 256; // signed shift
+ switch(sb) {
+ case 0:
+ if (comp < 30)
+ comp = 30;
+ comp += 15;
+ break;
+ case 1:
+ if (comp < 24)
+ comp = 24;
+ comp += 10;
+ break;
+ case 2:
+ case 3:
+ case 4:
+ if (comp < 16)
+ comp = 16;
+ }
+ if (comp <= 5)
+ tmp = 0;
+ else if (comp <= 10)
+ tmp = 10;
+ else if (comp <= 16)
+ tmp = 16;
+ else if (comp <= 24)
+ tmp = -1;
+ else
+ tmp = 0;
+ coding_method[ch][sb][j] = ((tmp & 0xfffa) + 30 )& 0xff;
+ }
+ for (sb = 0; sb < 30; sb++)
+ fix_coding_method_array(sb, nb_channels, coding_method);
+ for (ch = 0; ch < nb_channels; ch++)
+ for (sb = 0; sb < 30; sb++)
+ for (j = 0; j < 64; j++)
+ if (sb >= 10) {
+ if (coding_method[ch][sb][j] < 10)
+ coding_method[ch][sb][j] = 10;
+ } else {
+ if (sb >= 2) {
+ if (coding_method[ch][sb][j] < 16)
+ coding_method[ch][sb][j] = 16;
+ } else {
+ if (coding_method[ch][sb][j] < 30)
+ coding_method[ch][sb][j] = 30;
+ }
+ }
+ } else { // superblocktype_2_3 != 0
+ for (ch = 0; ch < nb_channels; ch++)
+ for (sb = 0; sb < 30; sb++)
+ for (j = 0; j < 64; j++)
+ coding_method[ch][sb][j] = coding_method_table[cm_table_select][sb];
+ }
+}
+
+/**
+ *
+ * Called by process_subpacket_11 to process more data from subpacket 11 with sb 0-8
+ * Called by process_subpacket_12 to process data from subpacket 12 with sb 8-sb_used
+ *
+ * @param gb bitreader context
+ * @param length packet length in bits
+ * @param sb_min lower subband processed (sb_min included)
+ * @param sb_max higher subband processed (sb_max excluded)
+ */
+void QDM2Stream::synthfilt_build_sb_samples(GetBitContext *gb, int length, int sb_min, int sb_max) {
+ int sb, j, k, n, ch, run, channels;
+ int joined_stereo, zero_encoding, chs;
+ int type34_first;
+ float type34_div = 0;
+ float type34_predictor;
+ float samples[10], sign_bits[16];
+
+ if (length == 0) {
+ // If no data use noise
+ for (sb = sb_min; sb < sb_max; sb++)
+ build_sb_samples_from_noise(sb);
+
+ return;
+ }
+
+ for (sb = sb_min; sb < sb_max; sb++) {
+ FIX_NOISE_IDX(_noiseIdx);
+
+ channels = _channels;
+
+ if (_channels <= 1 || sb < 12)
+ joined_stereo = 0;
+ else if (sb >= 24)
+ joined_stereo = 1;
+ else
+ joined_stereo = (BITS_LEFT(length,gb) >= 1) ? getBits1 (gb) : 0;
+
+ if (joined_stereo) {
+ if (BITS_LEFT(length,gb) >= 16)
+ for (j = 0; j < 16; j++)
+ sign_bits[j] = getBits1(gb);
+
+ for (j = 0; j < 64; j++)
+ if (_codingMethod[1][sb][j] > _codingMethod[0][sb][j])
+ _codingMethod[0][sb][j] = _codingMethod[1][sb][j];
+
+ fix_coding_method_array(sb, _channels, _codingMethod);
+ channels = 1;
+ }
+
+ for (ch = 0; ch < channels; ch++) {
+ zero_encoding = (BITS_LEFT(length,gb) >= 1) ? getBits1(gb) : 0;
+ type34_predictor = 0.0;
+ type34_first = 1;
+
+ for (j = 0; j < 128; ) {
+ switch (_codingMethod[ch][sb][j / 2]) {
+ case 8:
+ if (BITS_LEFT(length,gb) >= 10) {
+ if (zero_encoding) {
+ for (k = 0; k < 5; k++) {
+ if ((j + 2 * k) >= 128)
+ break;
+ samples[2 * k] = getBits1(gb) ? dequant_1bit[joined_stereo][2 * getBits1(gb)] : 0;
+ }
+ } else {
+ n = getBits(gb, 8);
+ for (k = 0; k < 5; k++)
+ samples[2 * k] = dequant_1bit[joined_stereo][_randomDequantIndex[n][k]];
+ }
+ for (k = 0; k < 5; k++)
+ samples[2 * k + 1] = SB_DITHERING_NOISE(sb, _noiseIdx);
+ } else {
+ for (k = 0; k < 10; k++)
+ samples[k] = SB_DITHERING_NOISE(sb, _noiseIdx);
+ }
+ run = 10;
+ break;
+
+ case 10:
+ if (BITS_LEFT(length,gb) >= 1) {
+ double f = 0.81;
+
+ if (getBits1(gb))
+ f = -f;
+ f -= _noiseSamples[((sb + 1) * (j +5 * ch + 1)) & 127] * 9.0 / 40.0;
+ samples[0] = f;
+ } else {
+ samples[0] = SB_DITHERING_NOISE(sb, _noiseIdx);
+ }
+ run = 1;
+ break;
+
+ case 16:
+ if (BITS_LEFT(length,gb) >= 10) {
+ if (zero_encoding) {
+ for (k = 0; k < 5; k++) {
+ if ((j + k) >= 128)
+ break;
+ samples[k] = (getBits1(gb) == 0) ? 0 : dequant_1bit[joined_stereo][2 * getBits1(gb)];
+ }
+ } else {
+ n = getBits (gb, 8);
+ for (k = 0; k < 5; k++)
+ samples[k] = dequant_1bit[joined_stereo][_randomDequantIndex[n][k]];
+ }
+ } else {
+ for (k = 0; k < 5; k++)
+ samples[k] = SB_DITHERING_NOISE(sb, _noiseIdx);
+ }
+ run = 5;
+ break;
+
+ case 24:
+ if (BITS_LEFT(length,gb) >= 7) {
+ n = getBits(gb, 7);
+ for (k = 0; k < 3; k++)
+ samples[k] = (_randomDequantType24[n][k] - 2.0) * 0.5;
+ } else {
+ for (k = 0; k < 3; k++)
+ samples[k] = SB_DITHERING_NOISE(sb, _noiseIdx);
+ }
+ run = 3;
+ break;
+
+ case 30:
+ if (BITS_LEFT(length,gb) >= 4)
+ samples[0] = type30_dequant[qdm2_get_vlc(gb, &_vlcTabType30, 0, 1)];
+ else
+ samples[0] = SB_DITHERING_NOISE(sb, _noiseIdx);
+
+ run = 1;
+ break;
+
+ case 34:
+ if (BITS_LEFT(length,gb) >= 7) {
+ if (type34_first) {
+ type34_div = (float)(1 << getBits(gb, 2));
+ samples[0] = ((float)getBits(gb, 5) - 16.0) / 15.0;
+ type34_predictor = samples[0];
+ type34_first = 0;
+ } else {
+ samples[0] = type34_delta[qdm2_get_vlc(gb, &_vlcTabType34, 0, 1)] / type34_div + type34_predictor;
+ type34_predictor = samples[0];
+ }
+ } else {
+ samples[0] = SB_DITHERING_NOISE(sb, _noiseIdx);
+ }
+ run = 1;
+ break;
+
+ default:
+ samples[0] = SB_DITHERING_NOISE(sb, _noiseIdx);
+ run = 1;
+ break;
+ }
+
+ if (joined_stereo) {
+ float tmp[10][MPA_MAX_CHANNELS];
+
+ for (k = 0; k < run; k++) {
+ tmp[k][0] = samples[k];
+ tmp[k][1] = (sign_bits[(j + k) / 8]) ? -samples[k] : samples[k];
+ }
+ for (chs = 0; chs < _channels; chs++)
+ for (k = 0; k < run; k++)
+ if ((j + k) < 128)
+ _sbSamples[chs][j + k][sb] = (int32)(_toneLevel[chs][sb][((j + k)/2)] * tmp[k][chs] + .5);
+ } else {
+ for (k = 0; k < run; k++)
+ if ((j + k) < 128)
+ _sbSamples[ch][j + k][sb] = (int32)(_toneLevel[ch][sb][(j + k)/2] * samples[k] + .5);
+ }
+
+ j += run;
+ } // j loop
+ } // channel loop
+ } // subband loop
+}
+
+/**
+ * Init the first element of a channel in quantized_coeffs with data from packet 10 (quantized_coeffs[ch][0]).
+ * This is similar to process_subpacket_9, but for a single channel and for element [0]
+ * same VLC tables as process_subpacket_9 are used.
+ *
+ * @param quantized_coeffs pointer to quantized_coeffs[ch][0]
+ * @param gb bitreader context
+ * @param length packet length in bits
+ */
+void QDM2Stream::init_quantized_coeffs_elem0(int8 *quantized_coeffs, GetBitContext *gb, int length) {
+ int i, k, run, level, diff;
+
+ if (BITS_LEFT(length,gb) < 16)
+ return;
+ level = qdm2_get_vlc(gb, &_vlcTabLevel, 0, 2);
+
+ quantized_coeffs[0] = level;
+
+ for (i = 0; i < 7; ) {
+ if (BITS_LEFT(length,gb) < 16)
+ break;
+ run = qdm2_get_vlc(gb, &_vlcTabRun, 0, 1) + 1;
+
+ if (BITS_LEFT(length,gb) < 16)
+ break;
+ diff = qdm2_get_se_vlc(&_vlcTabDiff, gb, 2);
+
+ for (k = 1; k <= run; k++)
+ quantized_coeffs[i + k] = (level + ((k * diff) / run));
+
+ level += diff;
+ i += run;
+ }
+}
+
+/**
+ * Related to synthesis filter, process data from packet 10
+ * Init part of quantized_coeffs via function init_quantized_coeffs_elem0
+ * Init tone_level_idx_hi1, tone_level_idx_hi2, tone_level_idx_mid with data from packet 10
+ *
+ * @param gb bitreader context
+ * @param length packet length in bits
+ */
+void QDM2Stream::init_tone_level_dequantization(GetBitContext *gb, int length) {
+ int sb, j, k, n, ch;
+
+ for (ch = 0; ch < _channels; ch++) {
+ init_quantized_coeffs_elem0(_quantizedCoeffs[ch][0], gb, length);
+
+ if (BITS_LEFT(length,gb) < 16) {
+ memset(_quantizedCoeffs[ch][0], 0, 8);
+ break;
+ }
+ }
+
+ n = _subSampling + 1;
+
+ for (sb = 0; sb < n; sb++)
+ for (ch = 0; ch < _channels; ch++)
+ for (j = 0; j < 8; j++) {
+ if (BITS_LEFT(length,gb) < 1)
+ break;
+ if (getBits1(gb)) {
+ for (k=0; k < 8; k++) {
+ if (BITS_LEFT(length,gb) < 16)
+ break;
+ _toneLevelIdxHi1[ch][sb][j][k] = qdm2_get_vlc(gb, &_vlcTabToneLevelIdxHi1, 0, 2);
+ }
+ } else {
+ for (k=0; k < 8; k++)
+ _toneLevelIdxHi1[ch][sb][j][k] = 0;
+ }
+ }
+
+ n = QDM2_SB_USED(_subSampling) - 4;
+
+ for (sb = 0; sb < n; sb++)
+ for (ch = 0; ch < _channels; ch++) {
+ if (BITS_LEFT(length,gb) < 16)
+ break;
+ _toneLevelIdxHi2[ch][sb] = qdm2_get_vlc(gb, &_vlcTabToneLevelIdxHi2, 0, 2);
+ if (sb > 19)
+ _toneLevelIdxHi2[ch][sb] -= 16;
+ else
+ for (j = 0; j < 8; j++)
+ _toneLevelIdxMid[ch][sb][j] = -16;
+ }
+
+ n = QDM2_SB_USED(_subSampling) - 5;
+
+ for (sb = 0; sb < n; sb++) {
+ for (ch = 0; ch < _channels; ch++) {
+ for (j = 0; j < 8; j++) {
+ if (BITS_LEFT(length,gb) < 16)
+ break;
+ _toneLevelIdxMid[ch][sb][j] = qdm2_get_vlc(gb, &_vlcTabToneLevelIdxMid, 0, 2) - 32;
+ }
+ }
+ }
+}
+
+/**
+ * Process subpacket 9, init quantized_coeffs with data from it
+ *
+ * @param node pointer to node with packet
+ */
+void QDM2Stream::process_subpacket_9(QDM2SubPNode *node) {
+ GetBitContext gb;
+ int i, j, k, n, ch, run, level, diff;
+
+ initGetBits(&gb, node->packet->data, node->packet->size*8);
+
+ n = coeff_per_sb_for_avg[_coeffPerSbSelect][QDM2_SB_USED(_subSampling) - 1] + 1; // same as averagesomething function
+
+ for (i = 1; i < n; i++)
+ for (ch = 0; ch < _channels; ch++) {
+ level = qdm2_get_vlc(&gb, &_vlcTabLevel, 0, 2);
+ _quantizedCoeffs[ch][i][0] = level;
+
+ for (j = 0; j < (8 - 1); ) {
+ run = qdm2_get_vlc(&gb, &_vlcTabRun, 0, 1) + 1;
+ diff = qdm2_get_se_vlc(&_vlcTabDiff, &gb, 2);
+
+ for (k = 1; k <= run; k++)
+ _quantizedCoeffs[ch][i][j + k] = (level + ((k*diff) / run));
+
+ level += diff;
+ j += run;
+ }
+ }
+
+ for (ch = 0; ch < _channels; ch++)
+ for (i = 0; i < 8; i++)
+ _quantizedCoeffs[ch][0][i] = 0;
+}
+
+/**
+ * Process subpacket 10 if not null, else
+ *
+ * @param node pointer to node with packet
+ * @param length packet length in bits
+ */
+void QDM2Stream::process_subpacket_10(QDM2SubPNode *node, int length) {
+ GetBitContext gb;
+
+ initGetBits(&gb, ((node == NULL) ? _emptyBuffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
+
+ if (length != 0) {
+ init_tone_level_dequantization(&gb, length);
+ fill_tone_level_array(1);
+ } else {
+ fill_tone_level_array(0);
+ }
+}
+
+/**
+ * Process subpacket 11
+ *
+ * @param node pointer to node with packet
+ * @param length packet length in bit
+ */
+void QDM2Stream::process_subpacket_11(QDM2SubPNode *node, int length) {
+ GetBitContext gb;
+
+ initGetBits(&gb, ((node == NULL) ? _emptyBuffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
+ if (length >= 32) {
+ int c = getBits (&gb, 13);
+
+ if (c > 3)
+ fill_coding_method_array(_toneLevelIdx, _toneLevelIdxTemp, _codingMethod,
+ _channels, 8*c, _superblocktype_2_3, _cmTableSelect);
+ }
+
+ synthfilt_build_sb_samples(&gb, length, 0, 8);
+}
+
+/**
+ * Process subpacket 12
+ *
+ * @param node pointer to node with packet
+ * @param length packet length in bits
+ */
+void QDM2Stream::process_subpacket_12(QDM2SubPNode *node, int length) {
+ GetBitContext gb;
+
+ initGetBits(&gb, ((node == NULL) ? _emptyBuffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
+ synthfilt_build_sb_samples(&gb, length, 8, QDM2_SB_USED(_subSampling));
+}
+
+/*
+ * Process new subpackets for synthesis filter
+ *
+ * @param list list with synthesis filter packets (list D)
+ */
+void QDM2Stream::process_synthesis_subpackets(QDM2SubPNode *list) {
+ struct QDM2SubPNode *nodes[4];
+
+ nodes[0] = qdm2_search_subpacket_type_in_list(list, 9);
+ if (nodes[0] != NULL)
+ process_subpacket_9(nodes[0]);
+
+ nodes[1] = qdm2_search_subpacket_type_in_list(list, 10);
+ if (nodes[1] != NULL)
+ process_subpacket_10(nodes[1], nodes[1]->packet->size << 3);
+ else
+ process_subpacket_10(NULL, 0);
+
+ nodes[2] = qdm2_search_subpacket_type_in_list(list, 11);
+ if (nodes[0] != NULL && nodes[1] != NULL && nodes[2] != NULL)
+ process_subpacket_11(nodes[2], (nodes[2]->packet->size << 3));
+ else
+ process_subpacket_11(NULL, 0);
+
+ nodes[3] = qdm2_search_subpacket_type_in_list(list, 12);
+ if (nodes[0] != NULL && nodes[1] != NULL && nodes[3] != NULL)
+ process_subpacket_12(nodes[3], (nodes[3]->packet->size << 3));
+ else
+ process_subpacket_12(NULL, 0);
+}
+
+/*
+ * Decode superblock, fill packet lists.
+ *
+ */
+void QDM2Stream::qdm2_decode_super_block(void) {
+ GetBitContext gb;
+ struct QDM2SubPacket header, *packet;
+ int i, packet_bytes, sub_packet_size, subPacketsD;
+ unsigned int next_index = 0;
+
+ memset(_toneLevelIdxHi1, 0, sizeof(_toneLevelIdxHi1));
+ memset(_toneLevelIdxMid, 0, sizeof(_toneLevelIdxMid));
+ memset(_toneLevelIdxHi2, 0, sizeof(_toneLevelIdxHi2));
+
+ _subPacketsB = 0;
+ subPacketsD = 0;
+
+ average_quantized_coeffs(); // average elements in quantized_coeffs[max_ch][10][8]
+
+ initGetBits(&gb, _compressedData, _packetSize*8);
+ qdm2_decode_sub_packet_header(&gb, &header);
+
+ if (header.type < 2 || header.type >= 8) {
+ _hasErrors = true;
+ error("QDM2 : bad superblock type");
+ return;
+ }
+
+ _superblocktype_2_3 = (header.type == 2 || header.type == 3);
+ packet_bytes = (_packetSize - getBitsCount(&gb) / 8);
+
+ initGetBits(&gb, header.data, header.size*8);
+
+ if (header.type == 2 || header.type == 4 || header.type == 5) {
+ int csum = 257 * getBits(&gb, 8) + 2 * getBits(&gb, 8);
+
+ csum = qdm2_packet_checksum(_compressedData, _packetSize, csum);
+
+ if (csum != 0) {
+ _hasErrors = true;
+ error("QDM2 : bad packet checksum");
+ return;
+ }
+ }
+
+ _subPacketListB[0].packet = NULL;
+ _subPacketListD[0].packet = NULL;
+
+ for (i = 0; i < 6; i++)
+ if (--_fftLevelExp[i] < 0)
+ _fftLevelExp[i] = 0;
+
+ for (i = 0; packet_bytes > 0; i++) {
+ int j;
+
+ _subPacketListA[i].next = NULL;
+
+ if (i > 0) {
+ _subPacketListA[i - 1].next = &_subPacketListA[i];
+
+ // seek to next block
+ initGetBits(&gb, header.data, header.size*8);
+ skipBits(&gb, next_index*8);
+
+ if (next_index >= header.size)
+ break;
+ }
+
+ // decode subpacket
+ packet = &_subPackets[i];
+ qdm2_decode_sub_packet_header(&gb, packet);
+ next_index = packet->size + getBitsCount(&gb) / 8;
+ sub_packet_size = ((packet->size > 0xff) ? 1 : 0) + packet->size + 2;
+
+ if (packet->type == 0)
+ break;
+
+ if (sub_packet_size > packet_bytes) {
+ if (packet->type != 10 && packet->type != 11 && packet->type != 12)
+ break;
+ packet->size += packet_bytes - sub_packet_size;
+ }
+
+ packet_bytes -= sub_packet_size;
+
+ // add subpacket to 'all subpackets' list
+ _subPacketListA[i].packet = packet;
+
+ // add subpacket to related list
+ if (packet->type == 8) {
+ error("Unsupported packet type 8");
+ return;
+ } else if (packet->type >= 9 && packet->type <= 12) {
+ // packets for MPEG Audio like Synthesis Filter
+ QDM2_LIST_ADD(_subPacketListD, subPacketsD, packet);
+ } else if (packet->type == 13) {
+ for (j = 0; j < 6; j++)
+ _fftLevelExp[j] = getBits(&gb, 6);
+ } else if (packet->type == 14) {
+ for (j = 0; j < 6; j++)
+ _fftLevelExp[j] = qdm2_get_vlc(&gb, &_fftLevelExpVlc, 0, 2);
+ } else if (packet->type == 15) {
+ error("Unsupported packet type 15");
+ return;
+ } else if (packet->type >= 16 && packet->type < 48 && !fft_subpackets[packet->type - 16]) {
+ // packets for FFT
+ QDM2_LIST_ADD(_subPacketListB, _subPacketsB, packet);
+ }
+ } // Packet bytes loop
+
+// ****************************************************************
+ if (_subPacketListD[0].packet != NULL) {
+ process_synthesis_subpackets(_subPacketListD);
+ _doSynthFilter = 1;
+ } else if (_doSynthFilter) {
+ process_subpacket_10(NULL, 0);
+ process_subpacket_11(NULL, 0);
+ process_subpacket_12(NULL, 0);
+ }
+// ****************************************************************
+}
+
+void QDM2Stream::qdm2_fft_init_coefficient(int sub_packet, int offset, int duration,
+ int channel, int exp, int phase) {
+ if (_fftCoefsMinIndex[duration] < 0)
+ _fftCoefsMinIndex[duration] = _fftCoefsIndex;
+
+ _fftCoefs[_fftCoefsIndex].sub_packet = ((sub_packet >= 16) ? (sub_packet - 16) : sub_packet);
+ _fftCoefs[_fftCoefsIndex].channel = channel;
+ _fftCoefs[_fftCoefsIndex].offset = offset;
+ _fftCoefs[_fftCoefsIndex].exp = exp;
+ _fftCoefs[_fftCoefsIndex].phase = phase;
+ _fftCoefsIndex++;
+}
+
+void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) {
+ int channel, stereo, phase, exp;
+ int local_int_4, local_int_8, stereo_phase, local_int_10;
+ int local_int_14, stereo_exp, local_int_20, local_int_28;
+ int n, offset;
+
+ local_int_4 = 0;
+ local_int_28 = 0;
+ local_int_20 = 2;
+ local_int_8 = (4 - duration);
+ local_int_10 = 1 << (_groupOrder - duration - 1);
+ offset = 1;
+
+ while (1) {
+ if (_superblocktype_2_3) {
+ while ((n = qdm2_get_vlc(gb, &_vlcTabFftToneOffset[local_int_8], 1, 2)) < 2) {
+ offset = 1;
+ if (n == 0) {
+ local_int_4 += local_int_10;
+ local_int_28 += (1 << local_int_8);
+ } else {
+ local_int_4 += 8*local_int_10;
+ local_int_28 += (8 << local_int_8);
+ }
+ }
+ offset += (n - 2);
+ } else {
+ offset += qdm2_get_vlc(gb, &_vlcTabFftToneOffset[local_int_8], 1, 2);
+ while (offset >= (local_int_10 - 1)) {
+ offset += (1 - (local_int_10 - 1));
+ local_int_4 += local_int_10;
+ local_int_28 += (1 << local_int_8);
+ }
+ }
+
+ if (local_int_4 >= _blockSize)
+ return;
+
+ local_int_14 = (offset >> local_int_8);
+
+ if (_channels > 1) {
+ channel = getBits1(gb);
+ stereo = getBits1(gb);
+ } else {
+ channel = 0;
+ stereo = 0;
+ }
+
+ exp = qdm2_get_vlc(gb, (b ? &_fftLevelExpVlc : &_fftLevelExpAltVlc), 0, 2);
+ exp += _fftLevelExp[fft_level_index_table[local_int_14]];
+ exp = (exp < 0) ? 0 : exp;
+
+ phase = getBits(gb, 3);
+ stereo_exp = 0;
+ stereo_phase = 0;
+
+ if (stereo) {
+ stereo_exp = (exp - qdm2_get_vlc(gb, &_fftStereoExpVlc, 0, 1));
+ stereo_phase = (phase - qdm2_get_vlc(gb, &_fftStereoPhaseVlc, 0, 1));
+ if (stereo_phase < 0)
+ stereo_phase += 8;
+ }
+
+ if (_frequencyRange > (local_int_14 + 1)) {
+ int sub_packet = (local_int_20 + local_int_28);
+
+ qdm2_fft_init_coefficient(sub_packet, offset, duration, channel, exp, phase);
+ if (stereo)
+ qdm2_fft_init_coefficient(sub_packet, offset, duration, (1 - channel), stereo_exp, stereo_phase);
+ }
+
+ offset++;
+ }
+}
+
+void QDM2Stream::qdm2_decode_fft_packets(void) {
+ int i, j, min, max, value, type, unknown_flag;
+ GetBitContext gb;
+
+ if (_subPacketListB[0].packet == NULL)
+ return;
+
+ // reset minimum indexes for FFT coefficients
+ _fftCoefsIndex = 0;
+ for (i=0; i < 5; i++)
+ _fftCoefsMinIndex[i] = -1;
+
+ // process subpackets ordered by type, largest type first
+ for (i = 0, max = 256; i < _subPacketsB; i++) {
+ QDM2SubPacket *packet= NULL;
+
+ // find subpacket with largest type less than max
+ for (j = 0, min = 0; j < _subPacketsB; j++) {
+ value = _subPacketListB[j].packet->type;
+ if (value > min && value < max) {
+ min = value;
+ packet = _subPacketListB[j].packet;
+ }
+ }
+
+ max = min;
+
+ // check for errors (?)
+ if (!packet)
+ return;
+
+ if (i == 0 && (packet->type < 16 || packet->type >= 48 || fft_subpackets[packet->type - 16]))
+ return;
+
+ // decode FFT tones
+ initGetBits(&gb, packet->data, packet->size*8);
+
+ if (packet->type >= 32 && packet->type < 48 && !fft_subpackets[packet->type - 16])
+ unknown_flag = 1;
+ else
+ unknown_flag = 0;
+
+ type = packet->type;
+
+ if ((type >= 17 && type < 24) || (type >= 33 && type < 40)) {
+ int duration = _subSampling + 5 - (type & 15);
+
+ if (duration >= 0 && duration < 4) { // TODO: Should be <= 4?
+ qdm2_fft_decode_tones(duration, &gb, unknown_flag);
+ }
+ } else if (type == 31) {
+ for (j=0; j < 4; j++) {
+ qdm2_fft_decode_tones(j, &gb, unknown_flag);
+ }
+ } else if (type == 46) {
+ for (j=0; j < 6; j++)
+ _fftLevelExp[j] = getBits(&gb, 6);
+ for (j=0; j < 4; j++) {
+ qdm2_fft_decode_tones(j, &gb, unknown_flag);
+ }
+ }
+ } // Loop on B packets
+
+ // calculate maximum indexes for FFT coefficients
+ for (i = 0, j = -1; i < 5; i++)
+ if (_fftCoefsMinIndex[i] >= 0) {
+ if (j >= 0)
+ _fftCoefsMaxIndex[j] = _fftCoefsMinIndex[i];
+ j = i;
+ }
+ if (j >= 0)
+ _fftCoefsMaxIndex[j] = _fftCoefsIndex;
+}
+
+void QDM2Stream::qdm2_fft_generate_tone(FFTTone *tone)
+{
+ float level, f[6];
+ int i;
+ QDM2Complex c;
+ const double iscale = 2.0 * PI / 512.0;
+
+ tone->phase += tone->phase_shift;
+
+ // calculate current level (maximum amplitude) of tone
+ level = fft_tone_envelope_table[tone->duration][tone->time_index] * tone->level;
+ c.im = level * sin(tone->phase*iscale);
+ c.re = level * cos(tone->phase*iscale);
+
+ // generate FFT coefficients for tone
+ if (tone->duration >= 3 || tone->cutoff >= 3) {
+ tone->complex[0].im += c.im;
+ tone->complex[0].re += c.re;
+ tone->complex[1].im -= c.im;
+ tone->complex[1].re -= c.re;
+ } else {
+ f[1] = -tone->table[4];
+ f[0] = tone->table[3] - tone->table[0];
+ f[2] = 1.0 - tone->table[2] - tone->table[3];
+ f[3] = tone->table[1] + tone->table[4] - 1.0;
+ f[4] = tone->table[0] - tone->table[1];
+ f[5] = tone->table[2];
+ for (i = 0; i < 2; i++) {
+ tone->complex[fft_cutoff_index_table[tone->cutoff][i]].re += c.re * f[i];
+ tone->complex[fft_cutoff_index_table[tone->cutoff][i]].im += c.im *((tone->cutoff <= i) ? -f[i] : f[i]);
+ }
+ for (i = 0; i < 4; i++) {
+ tone->complex[i].re += c.re * f[i+2];
+ tone->complex[i].im += c.im * f[i+2];
+ }
+ }
+
+ // copy the tone if it has not yet died out
+ if (++tone->time_index < ((1 << (5 - tone->duration)) - 1)) {
+ memcpy(&_fftTones[_fftToneEnd], tone, sizeof(FFTTone));
+ _fftToneEnd = (_fftToneEnd + 1) % 1000;
+ }
+}
+
+void QDM2Stream::qdm2_fft_tone_synthesizer(uint8 sub_packet) {
+ int i, j, ch;
+ const double iscale = 0.25 * PI;
+
+ for (ch = 0; ch < _channels; ch++) {
+ memset(_fft.complex[ch], 0, _frameSize * sizeof(QDM2Complex));
+ }
+
+ // apply FFT tones with duration 4 (1 FFT period)
+ if (_fftCoefsMinIndex[4] >= 0)
+ for (i = _fftCoefsMinIndex[4]; i < _fftCoefsMaxIndex[4]; i++) {
+ float level;
+ QDM2Complex c;
+
+ if (_fftCoefs[i].sub_packet != sub_packet)
+ break;
+
+ ch = (_channels == 1) ? 0 : _fftCoefs[i].channel;
+ level = (_fftCoefs[i].exp < 0) ? 0.0 : fft_tone_level_table[_superblocktype_2_3 ? 0 : 1][_fftCoefs[i].exp & 63];
+
+ c.re = level * cos(_fftCoefs[i].phase * iscale);
+ c.im = level * sin(_fftCoefs[i].phase * iscale);
+ _fft.complex[ch][_fftCoefs[i].offset + 0].re += c.re;
+ _fft.complex[ch][_fftCoefs[i].offset + 0].im += c.im;
+ _fft.complex[ch][_fftCoefs[i].offset + 1].re -= c.re;
+ _fft.complex[ch][_fftCoefs[i].offset + 1].im -= c.im;
+ }
+
+ // generate existing FFT tones
+ for (i = _fftToneEnd; i != _fftToneStart; ) {
+ qdm2_fft_generate_tone(&_fftTones[_fftToneStart]);
+ _fftToneStart = (_fftToneStart + 1) % 1000;
+ }
+
+ // create and generate new FFT tones with duration 0 (long) to 3 (short)
+ for (i = 0; i < 4; i++)
+ if (_fftCoefsMinIndex[i] >= 0) {
+ for (j = _fftCoefsMinIndex[i]; j < _fftCoefsMaxIndex[i]; j++) {
+ int offset, four_i;
+ FFTTone tone;
+
+ if (_fftCoefs[j].sub_packet != sub_packet)
+ break;
+
+ four_i = (4 - i);
+ offset = _fftCoefs[j].offset >> four_i;
+ ch = (_channels == 1) ? 0 : _fftCoefs[j].channel;
+
+ if (offset < _frequencyRange) {
+ if (offset < 2)
+ tone.cutoff = offset;
+ else
+ tone.cutoff = (offset >= 60) ? 3 : 2;
+
+ tone.level = (_fftCoefs[j].exp < 0) ? 0.0 : fft_tone_level_table[_superblocktype_2_3 ? 0 : 1][_fftCoefs[j].exp & 63];
+ tone.complex = &_fft.complex[ch][offset];
+ tone.table = fft_tone_sample_table[i][_fftCoefs[j].offset - (offset << four_i)];
+ tone.phase = 64 * _fftCoefs[j].phase - (offset << 8) - 128;
+ tone.phase_shift = (2 * _fftCoefs[j].offset + 1) << (7 - four_i);
+ tone.duration = i;
+ tone.time_index = 0;
+
+ qdm2_fft_generate_tone(&tone);
+ }
+ }
+ _fftCoefsMinIndex[i] = j;
+ }
+}
+
+void QDM2Stream::qdm2_calculate_fft(int channel) {
+ const float gain = (_channels == 1 && _channels == 2) ? 0.5f : 1.0f;
+ int i;
+
+ _fft.complex[channel][0].re *= 2.0f;
+ _fft.complex[channel][0].im = 0.0f;
+
+ rdftCalc(&_rdftCtx, (float *)_fft.complex[channel]);
+
+ // add samples to output buffer
+ for (i = 0; i < ((_fftFrameSize + 15) & ~15); i++)
+ _outputBuffer[_channels * i + channel] += ((float *) _fft.complex[channel])[i] * gain;
+}
+
+/**
+ * @param index subpacket number
+ */
+void QDM2Stream::qdm2_synthesis_filter(uint8 index)
+{
+ int16 samples[MPA_MAX_CHANNELS * MPA_FRAME_SIZE];
+ int i, k, ch, sb_used, sub_sampling, dither_state = 0;
+
+ // copy sb_samples
+ sb_used = QDM2_SB_USED(_subSampling);
+
+ for (ch = 0; ch < _channels; ch++)
+ for (i = 0; i < 8; i++)
+ for (k = sb_used; k < 32; k++)
+ _sbSamples[ch][(8 * index) + i][k] = 0;
+
+ for (ch = 0; ch < _channels; ch++) {
+ int16 *samples_ptr = samples + ch;
+
+ for (i = 0; i < 8; i++) {
+ ff_mpa_synth_filter(_synthBuf[ch], &(_synthBufOffset[ch]),
+ ff_mpa_synth_window, &dither_state,
+ samples_ptr, _channels,
+ _sbSamples[ch][(8 * index) + i]);
+ samples_ptr += 32 * _channels;
+ }
+ }
+
+ // add samples to output buffer
+ sub_sampling = (4 >> _subSampling);
+
+ for (ch = 0; ch < _channels; ch++)
+ for (i = 0; i < _sFrameSize; i++)
+ _outputBuffer[_channels * i + ch] += (float)(samples[_channels * sub_sampling * i + ch] >> (sizeof(int16)*8-16));
+}
+
+int QDM2Stream::qdm2_decodeFrame(Common::SeekableReadStream *in) {
+ debug(1, "QDM2Stream::qdm2_decodeFrame in->pos(): %d in->size(): %d", in->pos(), in->size());
+ int ch, i;
+ const int frame_size = (_sFrameSize * _channels);
+
+ // If we're in any packet but the first, seek back to the first
+ if (_subPacket == 0)
+ _superBlockStart = in->pos();
+ else
+ in->seek(_superBlockStart);
+
+ // select input buffer
+ if (in->eos() || in->pos() >= in->size()) {
+ debug(1, "QDM2Stream::qdm2_decodeFrame End of Input Stream");
+ return 0;
+ }
+
+ if ((in->size() - in->pos()) < _packetSize) {
+ debug(1, "QDM2Stream::qdm2_decodeFrame Insufficient Packet Data in Input Stream Found: %d Need: %d", in->size() - in->pos(), _packetSize);
+ return 0;
+ }
+
+ if (!in->eos()) {
+ in->read(_compressedData, _packetSize);
+ debug(1, "QDM2Stream::qdm2_decodeFrame constructed input data");
+ }
+
+ // copy old block, clear new block of output samples
+ memmove(_outputBuffer, &_outputBuffer[frame_size], frame_size * sizeof(float));
+ memset(&_outputBuffer[frame_size], 0, frame_size * sizeof(float));
+ debug(1, "QDM2Stream::qdm2_decodeFrame cleared outputBuffer");
+
+ if (!in->eos()) {
+ // decode block of QDM2 compressed data
+ debug(1, "QDM2Stream::qdm2_decodeFrame decode block of QDM2 compressed data");
+ if (_subPacket == 0) {
+ _hasErrors = false; // reset it for a new super block
+ debug(1, "QDM2 : Superblock follows");
+ qdm2_decode_super_block();
+ }
+
+ // parse subpackets
+ debug(1, "QDM2Stream::qdm2_decodeFrame parse subpackets");
+ if (!_hasErrors) {
+ if (_subPacket == 2) {
+ debug(1, "QDM2Stream::qdm2_decodeFrame qdm2_decode_fft_packets()");
+ qdm2_decode_fft_packets();
+ }
+
+ debug(1, "QDM2Stream::qdm2_decodeFrame qdm2_fft_tone_synthesizer(%d)", _subPacket);
+ qdm2_fft_tone_synthesizer(_subPacket);
+ }
+
+ // sound synthesis stage 1 (FFT)
+ debug(1, "QDM2Stream::qdm2_decodeFrame sound synthesis stage 1 (FFT)");
+ for (ch = 0; ch < _channels; ch++) {
+ qdm2_calculate_fft(ch);
+
+ if (!_hasErrors && _subPacketListC[0].packet != NULL) {
+ error("QDM2 : has errors, and C list is not empty");
+ return 0;
+ }
+ }
+
+ // sound synthesis stage 2 (MPEG audio like synthesis filter)
+ debug(1, "QDM2Stream::qdm2_decodeFrame sound synthesis stage 2 (MPEG audio like synthesis filter)");
+ if (!_hasErrors && _doSynthFilter)
+ qdm2_synthesis_filter(_subPacket);
+
+ _subPacket = (_subPacket + 1) % 16;
+
+ if(_hasErrors)
+ warning("QDM2 Packet error...");
+
+ // clip and convert output float[] to 16bit signed samples
+ debug(1, "QDM2Stream::qdm2_decodeFrame clip and convert output float[] to 16bit signed samples");
+ }
+
+ for (i = 0; i < frame_size; i++) {
+ int value = (int)_outputBuffer[i];
+
+ if (value > SOFTCLIP_THRESHOLD)
+ value = (value > HARDCLIP_THRESHOLD) ? 32767 : _softclipTable[ value - SOFTCLIP_THRESHOLD];
+ else if (value < -SOFTCLIP_THRESHOLD)
+ value = (value < -HARDCLIP_THRESHOLD) ? -32767 : -_softclipTable[-value - SOFTCLIP_THRESHOLD];
+
+ _outputSamples.push_back(value);
+ }
+ return frame_size;
+}
+
+int QDM2Stream::readBuffer(int16 *buffer, const int numSamples) {
+ debug(1, "QDM2Stream::readBuffer numSamples: %d", numSamples);
+ int32 decodedSamples = _outputSamples.size();
+ int32 i;
+
+ while (decodedSamples < numSamples) {
+ i = qdm2_decodeFrame(_stream);
+ if (i == 0)
+ break; // Out Of Decode Frames...
+ decodedSamples += i;
+ }
+
+ if (decodedSamples > numSamples)
+ decodedSamples = numSamples;
+
+ for (i = 0; i < decodedSamples; i++)
+ buffer[i] = _outputSamples.remove_at(0);
+
+ return decodedSamples;
+}
+
+Audio::AudioStream *makeQDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadStream *extraData) {
+ return new QDM2Stream(stream, extraData);
+}
+
+} // End of namespace Graphics
+
+#endif
diff --git a/backends/fs/palmos/palmos-fs-factory.cpp b/graphics/video/codecs/qdm2.h
index 97b3644205..9eb566d04d 100644
--- a/backends/fs/palmos/palmos-fs-factory.cpp
+++ b/graphics/video/codecs/qdm2.h
@@ -8,35 +8,47 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
+ *
*/
-#if defined(PALMOS_MODE)
-#include "backends/fs/palmos/palmos-fs-factory.h"
-#include "backends/fs/palmos/palmos-fs.cpp"
+// Only compile if Mohawk is enabled or if we're building dynamic modules
+#if defined(ENABLE_MOHAWK) || defined(DYNAMIC_MODULES)
-DECLARE_SINGLETON(PalmOSFilesystemFactory)
+#ifndef GRAPHICS_QDM2_H
+#define GRAPHICS_QDM2_H
-AbstractFSNode *PalmOSFilesystemFactory::makeRootFileNode() const {
- return new PalmOSFilesystemNode();
+namespace Common {
+ class SeekableReadStream;
}
-AbstractFSNode *PalmOSFilesystemFactory::makeCurrentDirectoryFileNode() const {
- return new PalmOSFilesystemNode();
+namespace Audio {
+ class AudioStream;
}
-AbstractFSNode *PalmOSFilesystemFactory::makeFileNodePath(const Common::String &path) const {
- return new PalmOSFilesystemNode(path);
-}
-#endif
+namespace Graphics {
+
+/**
+ * Create a new AudioStream from the QDM2 data in the given stream.
+ *
+ * @param stream the SeekableReadStream from which to read the FLAC data
+ * @param extraData the QuickTime extra data stream
+ * @return a new AudioStream, or NULL, if an error occurred
+ */
+Audio::AudioStream *makeQDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadStream *extraData);
+
+} // End of namespace Graphics
+
+#endif // GRAPHICS_QDM2_H
+#endif // Mohawk/Plugins guard
diff --git a/graphics/video/codecs/qdm2data.h b/graphics/video/codecs/qdm2data.h
new file mode 100644
index 0000000000..25ed102c4e
--- /dev/null
+++ b/graphics/video/codecs/qdm2data.h
@@ -0,0 +1,531 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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_QDM2DATA_H
+#define GRAPHICS_QDM2DATA_H
+
+#include "common/scummsys.h"
+
+namespace Graphics {
+
+/// VLC TABLES
+
+// values in this table range from -1..23; adjust retrieved value by -1
+static const uint16 vlc_tab_level_huffcodes[24] = {
+ 0x037c, 0x0004, 0x003c, 0x004c, 0x003a, 0x002c, 0x001c, 0x001a,
+ 0x0024, 0x0014, 0x0001, 0x0002, 0x0000, 0x0003, 0x0007, 0x0005,
+ 0x0006, 0x0008, 0x0009, 0x000a, 0x000c, 0x00fc, 0x007c, 0x017c
+};
+
+static const byte vlc_tab_level_huffbits[24] = {
+ 10, 6, 7, 7, 6, 6, 6, 6, 6, 5, 4, 4, 4, 3, 3, 3, 3, 4, 4, 5, 7, 8, 9, 10
+};
+
+// values in this table range from -1..36; adjust retrieved value by -1
+static const uint16 vlc_tab_diff_huffcodes[37] = {
+ 0x1c57, 0x0004, 0x0000, 0x0001, 0x0003, 0x0002, 0x000f, 0x000e,
+ 0x0007, 0x0016, 0x0037, 0x0027, 0x0026, 0x0066, 0x0006, 0x0097,
+ 0x0046, 0x01c6, 0x0017, 0x0786, 0x0086, 0x0257, 0x00d7, 0x0357,
+ 0x00c6, 0x0386, 0x0186, 0x0000, 0x0157, 0x0c57, 0x0057, 0x0000,
+ 0x0b86, 0x0000, 0x1457, 0x0000, 0x0457
+};
+
+static const byte vlc_tab_diff_huffbits[37] = {
+ 13, 3, 3, 2, 3, 3, 4, 4, 6, 5, 6, 6, 7, 7, 8, 8,
+ 8, 9, 8, 11, 9, 10, 8, 10, 9, 12, 10, 0, 10, 13, 11, 0,
+ 12, 0, 13, 0, 13
+};
+
+// values in this table range from -1..5; adjust retrieved value by -1
+static const byte vlc_tab_run_huffcodes[6] = {
+ 0x1f, 0x00, 0x01, 0x03, 0x07, 0x0f
+};
+
+static const byte vlc_tab_run_huffbits[6] = {
+ 5, 1, 2, 3, 4, 5
+};
+
+// values in this table range from -1..19; adjust retrieved value by -1
+static const uint16 vlc_tab_tone_level_idx_hi1_huffcodes[20] = {
+ 0x5714, 0x000c, 0x0002, 0x0001, 0x0000, 0x0004, 0x0034, 0x0054,
+ 0x0094, 0x0014, 0x0114, 0x0214, 0x0314, 0x0614, 0x0e14, 0x0f14,
+ 0x2714, 0x0714, 0x1714, 0x3714
+};
+
+static const byte vlc_tab_tone_level_idx_hi1_huffbits[20] = {
+ 15, 4, 2, 1, 3, 5, 6, 7, 8, 10, 10, 11, 11, 12, 12, 12, 14, 14, 15, 14
+};
+
+// values in this table range from -1..23; adjust retrieved value by -1
+static const uint16 vlc_tab_tone_level_idx_mid_huffcodes[24] = {
+ 0x0fea, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x03ea, 0x00ea, 0x002a, 0x001a,
+ 0x0006, 0x0001, 0x0000, 0x0002, 0x000a, 0x006a, 0x01ea, 0x07ea
+};
+
+static const byte vlc_tab_tone_level_idx_mid_huffbits[24] = {
+ 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 7, 5, 3, 1, 2, 4, 6, 8, 10, 12
+};
+
+// values in this table range from -1..23; adjust retrieved value by -1
+static const uint16 vlc_tab_tone_level_idx_hi2_huffcodes[24] = {
+ 0x0664, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0064, 0x00e4,
+ 0x00a4, 0x0068, 0x0004, 0x0008, 0x0014, 0x0018, 0x0000, 0x0001,
+ 0x0002, 0x0003, 0x000c, 0x0028, 0x0024, 0x0164, 0x0000, 0x0264
+};
+
+static const byte vlc_tab_tone_level_idx_hi2_huffbits[24] = {
+ 11, 0, 0, 0, 0, 0, 10, 8, 8, 7, 6, 6, 5, 5, 4, 2, 2, 2, 4, 7, 8, 9, 0, 11
+};
+
+// values in this table range from -1..8; adjust retrieved value by -1
+static const byte vlc_tab_type30_huffcodes[9] = {
+ 0x3c, 0x06, 0x00, 0x01, 0x03, 0x02, 0x04, 0x0c, 0x1c
+};
+
+static const byte vlc_tab_type30_huffbits[9] = {
+ 6, 3, 3, 2, 2, 3, 4, 5, 6
+};
+
+// values in this table range from -1..9; adjust retrieved value by -1
+static const byte vlc_tab_type34_huffcodes[10] = {
+ 0x18, 0x00, 0x01, 0x04, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08
+};
+
+static const byte vlc_tab_type34_huffbits[10] = {
+ 5, 4, 3, 3, 3, 3, 3, 3, 3, 5
+};
+
+// values in this table range from -1..22; adjust retrieved value by -1
+static const uint16 vlc_tab_fft_tone_offset_0_huffcodes[23] = {
+ 0x038e, 0x0001, 0x0000, 0x0022, 0x000a, 0x0006, 0x0012, 0x0002,
+ 0x001e, 0x003e, 0x0056, 0x0016, 0x000e, 0x0032, 0x0072, 0x0042,
+ 0x008e, 0x004e, 0x00f2, 0x002e, 0x0036, 0x00c2, 0x018e
+};
+
+static const byte vlc_tab_fft_tone_offset_0_huffbits[23] = {
+ 10, 1, 2, 6, 4, 5, 6, 7, 6, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 6, 6, 8, 10
+};
+
+// values in this table range from -1..27; adjust retrieved value by -1
+static const uint16 vlc_tab_fft_tone_offset_1_huffcodes[28] = {
+ 0x07a4, 0x0001, 0x0020, 0x0012, 0x001c, 0x0008, 0x0006, 0x0010,
+ 0x0000, 0x0014, 0x0004, 0x0032, 0x0070, 0x000c, 0x0002, 0x003a,
+ 0x001a, 0x002c, 0x002a, 0x0022, 0x0024, 0x000a, 0x0064, 0x0030,
+ 0x0062, 0x00a4, 0x01a4, 0x03a4
+};
+
+static const byte vlc_tab_fft_tone_offset_1_huffbits[28] = {
+ 11, 1, 6, 6, 5, 4, 3, 6, 6, 5, 6, 6, 7, 6, 6, 6,
+ 6, 6, 6, 7, 8, 6, 7, 7, 7, 9, 10, 11
+};
+
+// values in this table range from -1..31; adjust retrieved value by -1
+static const uint16 vlc_tab_fft_tone_offset_2_huffcodes[32] = {
+ 0x1760, 0x0001, 0x0000, 0x0082, 0x000c, 0x0006, 0x0003, 0x0007,
+ 0x0008, 0x0004, 0x0010, 0x0012, 0x0022, 0x001a, 0x0000, 0x0020,
+ 0x000a, 0x0040, 0x004a, 0x006a, 0x002a, 0x0042, 0x0002, 0x0060,
+ 0x00aa, 0x00e0, 0x00c2, 0x01c2, 0x0160, 0x0360, 0x0760, 0x0f60
+};
+
+static const byte vlc_tab_fft_tone_offset_2_huffbits[32] = {
+ 13, 2, 0, 8, 4, 3, 3, 3, 4, 4, 5, 5, 6, 5, 7, 7,
+ 7, 7, 7, 7, 8, 8, 8, 9, 8, 8, 9, 9, 10, 11, 13, 12
+};
+
+// values in this table range from -1..34; adjust retrieved value by -1
+static const uint16 vlc_tab_fft_tone_offset_3_huffcodes[35] = {
+ 0x33ea, 0x0005, 0x0000, 0x000c, 0x0000, 0x0006, 0x0003, 0x0008,
+ 0x0002, 0x0001, 0x0004, 0x0007, 0x001a, 0x000f, 0x001c, 0x002c,
+ 0x000a, 0x001d, 0x002d, 0x002a, 0x000d, 0x004c, 0x008c, 0x006a,
+ 0x00cd, 0x004d, 0x00ea, 0x020c, 0x030c, 0x010c, 0x01ea, 0x07ea,
+ 0x0bea, 0x03ea, 0x13ea
+};
+
+static const byte vlc_tab_fft_tone_offset_3_huffbits[35] = {
+ 14, 4, 0, 10, 4, 3, 3, 4, 4, 3, 4, 4, 5, 4, 5, 6,
+ 6, 5, 6, 7, 7, 7, 8, 8, 8, 8, 9, 10, 10, 10, 10, 11,
+ 12, 13, 14
+};
+
+// values in this table range from -1..37; adjust retrieved value by -1
+static const uint16 vlc_tab_fft_tone_offset_4_huffcodes[38] = {
+ 0x5282, 0x0016, 0x0000, 0x0136, 0x0004, 0x0000, 0x0007, 0x000a,
+ 0x000e, 0x0003, 0x0001, 0x000d, 0x0006, 0x0009, 0x0012, 0x0005,
+ 0x0025, 0x0022, 0x0015, 0x0002, 0x0076, 0x0035, 0x0042, 0x00c2,
+ 0x0182, 0x00b6, 0x0036, 0x03c2, 0x0482, 0x01c2, 0x0682, 0x0882,
+ 0x0a82, 0x0082, 0x0282, 0x1282, 0x3282, 0x2282
+};
+
+static const byte vlc_tab_fft_tone_offset_4_huffbits[38] = {
+ 15, 6, 0, 9, 3, 3, 3, 4, 4, 3, 4, 4, 5, 4, 5, 6,
+ 6, 6, 6, 8, 7, 6, 8, 9, 9, 8, 9, 10, 11, 10, 11, 12,
+ 12, 12, 14, 15, 14, 14
+};
+
+/// FFT TABLES
+
+// values in this table range from -1..27; adjust retrieved value by -1
+static const uint16 fft_level_exp_alt_huffcodes[28] = {
+ 0x1ec6, 0x0006, 0x00c2, 0x0142, 0x0242, 0x0246, 0x00c6, 0x0046,
+ 0x0042, 0x0146, 0x00a2, 0x0062, 0x0026, 0x0016, 0x000e, 0x0005,
+ 0x0004, 0x0003, 0x0000, 0x0001, 0x000a, 0x0012, 0x0002, 0x0022,
+ 0x01c6, 0x02c6, 0x06c6, 0x0ec6
+};
+
+static const byte fft_level_exp_alt_huffbits[28] = {
+ 13, 7, 8, 9, 10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3,
+ 3, 2, 3, 3, 4, 5, 7, 8, 9, 11, 12, 13
+};
+
+// values in this table range from -1..19; adjust retrieved value by -1
+static const uint16 fft_level_exp_huffcodes[20] = {
+ 0x0f24, 0x0001, 0x0002, 0x0000, 0x0006, 0x0005, 0x0007, 0x000c,
+ 0x000b, 0x0014, 0x0013, 0x0004, 0x0003, 0x0023, 0x0064, 0x00a4,
+ 0x0024, 0x0124, 0x0324, 0x0724
+};
+
+static const byte fft_level_exp_huffbits[20] = {
+ 12, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 10, 11, 12
+};
+
+// values in this table range from -1..6; adjust retrieved value by -1
+static const byte fft_stereo_exp_huffcodes[7] = {
+ 0x3e, 0x01, 0x00, 0x02, 0x06, 0x0e, 0x1e
+};
+
+static const byte fft_stereo_exp_huffbits[7] = {
+ 6, 1, 2, 3, 4, 5, 6
+};
+
+// values in this table range from -1..8; adjust retrieved value by -1
+static const byte fft_stereo_phase_huffcodes[9] = {
+ 0x35, 0x02, 0x00, 0x01, 0x0d, 0x15, 0x05, 0x09, 0x03
+};
+
+static const byte fft_stereo_phase_huffbits[9] = {
+ 6, 2, 2, 4, 4, 6, 5, 4, 2
+};
+
+static const int fft_cutoff_index_table[4][2] = {
+ { 1, 2 }, {-1, 0 }, {-1,-2 }, { 0, 0 }
+};
+
+static const int16 fft_level_index_table[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+};
+
+static const byte last_coeff[3] = {
+ 4, 7, 10
+};
+
+static const byte coeff_per_sb_for_avg[3][30] = {
+ { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+ { 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 },
+ { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9 }
+};
+
+static const uint32 dequant_table[3][10][30] = {
+ { { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 256, 256, 205, 154, 102, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 51, 102, 154, 205, 256, 238, 219, 201, 183, 165, 146, 128, 110, 91, 73, 55, 37, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 18, 37, 55, 73, 91, 110, 128, 146, 165, 183, 201, 219, 238, 256, 228, 199, 171, 142, 114, 85, 57, 28 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+ { { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 85, 171, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 85, 171, 256, 219, 183, 146, 110, 73, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 73, 110, 146, 183, 219, 256, 228, 199, 171, 142, 114, 85, 57, 28, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 57, 85, 114, 142, 171, 199, 228, 256, 213, 171, 128, 85, 43 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+ { { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 85, 171, 256, 192, 128, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 128, 192, 256, 205, 154, 102, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 102, 154, 205, 256, 213, 171, 128, 85, 43, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 85, 128, 171, 213, 256, 213, 171, 128, 85, 43 } }
+};
+
+static const byte coeff_per_sb_for_dequant[3][30] = {
+ { 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+ { 0, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6 },
+ { 0, 1, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9 }
+};
+
+// first index is subband, 2nd index is 0, 1 or 3 (2 is unused)
+static const int8 tone_level_idx_offset_table[30][4] = {
+ { -50, -50, 0, -50 },
+ { -50, -50, 0, -50 },
+ { -50, -9, 0, -19 },
+ { -16, -6, 0, -12 },
+ { -11, -4, 0, -8 },
+ { -8, -3, 0, -6 },
+ { -7, -3, 0, -5 },
+ { -6, -2, 0, -4 },
+ { -5, -2, 0, -3 },
+ { -4, -1, 0, -3 },
+ { -4, -1, 0, -2 },
+ { -3, -1, 0, -2 },
+ { -3, -1, 0, -2 },
+ { -3, -1, 0, -2 },
+ { -2, -1, 0, -1 },
+ { -2, -1, 0, -1 },
+ { -2, -1, 0, -1 },
+ { -2, 0, 0, -1 },
+ { -2, 0, 0, -1 },
+ { -1, 0, 0, -1 },
+ { -1, 0, 0, -1 },
+ { -1, 0, 0, -1 },
+ { -1, 0, 0, -1 },
+ { -1, 0, 0, -1 },
+ { -1, 0, 0, -1 },
+ { -1, 0, 0, -1 },
+ { -1, 0, 0, 0 },
+ { -1, 0, 0, 0 },
+ { -1, 0, 0, 0 },
+ { -1, 0, 0, 0 }
+};
+
+/* all my samples have 1st index 0 or 1 */
+/* second index is subband, only indexes 0-29 seem to be used */
+static const int8 coding_method_table[5][30] = {
+ { 34, 30, 24, 24, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
+ },
+ { 34, 30, 24, 24, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
+ },
+ { 34, 30, 30, 30, 24, 24, 16, 16, 16, 16, 16, 16, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
+ },
+ { 34, 34, 30, 30, 24, 24, 24, 24, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10, 10
+ },
+ { 34, 34, 30, 30, 30, 30, 30, 30, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+ },
+};
+
+static const int vlc_stage3_values[60] = {
+ 0, 1, 2, 3, 4, 6, 8, 10, 12, 16, 20, 24,
+ 28, 36, 44, 52, 60, 76, 92, 108, 124, 156, 188, 220,
+ 252, 316, 380, 444, 508, 636, 764, 892, 1020, 1276, 1532, 1788,
+ 2044, 2556, 3068, 3580, 4092, 5116, 6140, 7164, 8188, 10236, 12284, 14332,
+ 16380, 20476, 24572, 28668, 32764, 40956, 49148, 57340, 65532, 81916, 98300,114684
+};
+
+static const float fft_tone_sample_table[4][16][5] = {
+ { { .0100000000f,-.0037037037f,-.0020000000f,-.0069444444f,-.0018416207f },
+ { .0416666667f, .0000000000f, .0000000000f,-.0208333333f,-.0123456791f },
+ { .1250000000f, .0558035709f, .0330687836f,-.0164473690f,-.0097465888f },
+ { .1562500000f, .0625000000f, .0370370370f,-.0062500000f,-.0037037037f },
+ { .1996007860f, .0781250000f, .0462962948f, .0022727272f, .0013468013f },
+ { .2000000000f, .0625000000f, .0370370373f, .0208333333f, .0074074073f },
+ { .2127659619f, .0555555556f, .0329218097f, .0208333333f, .0123456791f },
+ { .2173913121f, .0473484844f, .0280583613f, .0347222239f, .0205761325f },
+ { .2173913121f, .0347222239f, .0205761325f, .0473484844f, .0280583613f },
+ { .2127659619f, .0208333333f, .0123456791f, .0555555556f, .0329218097f },
+ { .2000000000f, .0208333333f, .0074074073f, .0625000000f, .0370370370f },
+ { .1996007860f, .0022727272f, .0013468013f, .0781250000f, .0462962948f },
+ { .1562500000f,-.0062500000f,-.0037037037f, .0625000000f, .0370370370f },
+ { .1250000000f,-.0164473690f,-.0097465888f, .0558035709f, .0330687836f },
+ { .0416666667f,-.0208333333f,-.0123456791f, .0000000000f, .0000000000f },
+ { .0100000000f,-.0069444444f,-.0018416207f,-.0037037037f,-.0020000000f } },
+
+ { { .0050000000f,-.0200000000f, .0125000000f,-.3030303030f, .0020000000f },
+ { .1041666642f, .0400000000f,-.0250000000f, .0333333333f,-.0200000000f },
+ { .1250000000f, .0100000000f, .0142857144f,-.0500000007f,-.0200000000f },
+ { .1562500000f,-.0006250000f,-.00049382716f,-.000625000f,-.00049382716f },
+ { .1562500000f,-.0006250000f,-.00049382716f,-.000625000f,-.00049382716f },
+ { .1250000000f,-.0500000000f,-.0200000000f, .0100000000f, .0142857144f },
+ { .1041666667f, .0333333333f,-.0200000000f, .0400000000f,-.0250000000f },
+ { .0050000000f,-.3030303030f, .0020000001f,-.0200000000f, .0125000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f } },
+
+ { { .1428571492f, .1250000000f,-.0285714287f,-.0357142873f, .0208333333f },
+ { .1818181818f, .0588235296f, .0333333333f, .0212765951f, .0100000000f },
+ { .1818181818f, .0212765951f, .0100000000f, .0588235296f, .0333333333f },
+ { .1428571492f,-.0357142873f, .0208333333f, .1250000000f,-.0285714287f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f } },
+
+ { { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
+ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f } }
+};
+
+static const float fft_tone_level_table[2][64] = { {
+// pow ~ (i > 46) ? 0 : (((((i & 1) ? 431 : 304) << (i >> 1))) / 1024.0);
+ 0.17677669f, 0.42677650f, 0.60355347f, 0.85355347f,
+ 1.20710683f, 1.68359375f, 2.37500000f, 3.36718750f,
+ 4.75000000f, 6.73437500f, 9.50000000f, 13.4687500f,
+ 19.0000000f, 26.9375000f, 38.0000000f, 53.8750000f,
+ 76.0000000f, 107.750000f, 152.000000f, 215.500000f,
+ 304.000000f, 431.000000f, 608.000000f, 862.000000f,
+ 1216.00000f, 1724.00000f, 2432.00000f, 3448.00000f,
+ 4864.00000f, 6896.00000f, 9728.00000f, 13792.0000f,
+ 19456.0000f, 27584.0000f, 38912.0000f, 55168.0000f,
+ 77824.0000f, 110336.000f, 155648.000f, 220672.000f,
+ 311296.000f, 441344.000f, 622592.000f, 882688.000f,
+ 1245184.00f, 1765376.00f, 2490368.00f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ }, {
+// pow = (i > 45) ? 0 : ((((i & 1) ? 431 : 304) << (i >> 1)) / 512.0);
+ 0.59375000f, 0.84179688f, 1.18750000f, 1.68359375f,
+ 2.37500000f, 3.36718750f, 4.75000000f, 6.73437500f,
+ 9.50000000f, 13.4687500f, 19.0000000f, 26.9375000f,
+ 38.0000000f, 53.8750000f, 76.0000000f, 107.750000f,
+ 152.000000f, 215.500000f, 304.000000f, 431.000000f,
+ 608.000000f, 862.000000f, 1216.00000f, 1724.00000f,
+ 2432.00000f, 3448.00000f, 4864.00000f, 6896.00000f,
+ 9728.00000f, 13792.0000f, 19456.0000f, 27584.0000f,
+ 38912.0000f, 55168.0000f, 77824.0000f, 110336.000f,
+ 155648.000f, 220672.000f, 311296.000f, 441344.000f,
+ 622592.000f, 882688.000f, 1245184.00f, 1765376.00f,
+ 2490368.00f, 3530752.00f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f
+} };
+
+static const float fft_tone_envelope_table[4][31] = {
+ { .009607375f, .038060248f, .084265202f, .146446645f, .222214907f, .308658302f,
+ .402454883f, .500000060f, .597545207f, .691341758f, .777785182f, .853553414f,
+ .915734828f, .961939812f, .990392685f, 1.00000000f, .990392625f, .961939752f,
+ .915734768f, .853553295f, .777785063f, .691341639f, .597545087f, .500000000f,
+ .402454853f, .308658272f, .222214878f, .146446615f, .084265172f, .038060218f,
+ .009607345f },
+ { .038060248f, .146446645f, .308658302f, .500000060f, .691341758f, .853553414f,
+ .961939812f, 1.00000000f, .961939752f, .853553295f, .691341639f, .500000000f,
+ .308658272f, .146446615f, .038060218f, .000000000f, .000000000f, .000000000f,
+ .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
+ .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
+ .000000000f },
+ { .146446645f, .500000060f, .853553414f, 1.00000000f, .853553295f, .500000000f,
+ .146446615f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
+ .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
+ .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
+ .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
+ .000000000f },
+ { .500000060f, 1.00000000f, .500000000f, .000000000f, .000000000f, .000000000f,
+ .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
+ .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
+ .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
+ .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
+ .000000000f }
+};
+
+static const float sb_noise_attenuation[32] = {
+ 0.0f, 0.0f, 0.3f, 0.4f, 0.5f, 0.7f, 1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+};
+
+static const byte fft_subpackets[32] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0
+};
+
+// first index is joined_stereo, second index is 0 or 2 (1 is unused)
+static const float dequant_1bit[2][3] = {
+ {-0.920000f, 0.000000f, 0.920000f },
+ {-0.890000f, 0.000000f, 0.890000f }
+};
+
+static const float type30_dequant[8] = {
+ -1.0f,-0.625f,-0.291666656732559f,0.0f,
+ 0.25f,0.5f,0.75f,1.0f,
+};
+
+static const float type34_delta[10] = { // FIXME: covers 8 entries..
+ -1.0f,-0.60947573184967f,-0.333333343267441f,-0.138071194291115f,0.0f,
+ 0.138071194291115f,0.333333343267441f,0.60947573184967f,1.0f,0.0f,
+};
+
+} // End of namespace Graphics
+
+#endif
diff --git a/graphics/video/codecs/qtrle.cpp b/graphics/video/codecs/qtrle.cpp
new file mode 100644
index 0000000000..3e3fd4cfce
--- /dev/null
+++ b/graphics/video/codecs/qtrle.cpp
@@ -0,0 +1,420 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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$
+ *
+ */
+
+// QuickTime RLE Decoder
+// Based off ffmpeg's QuickTime RLE decoder (written by Mike Melanson)
+
+#include "graphics/video/codecs/qtrle.h"
+
+#include "common/scummsys.h"
+#include "common/stream.h"
+#include "common/system.h"
+#include "graphics/colormasks.h"
+#include "graphics/surface.h"
+
+namespace Graphics {
+
+QTRLEDecoder::QTRLEDecoder(uint16 width, uint16 height, byte bitsPerPixel) : Codec() {
+ _bitsPerPixel = bitsPerPixel;
+ _pixelFormat = g_system->getScreenFormat();
+
+ // We need to increase the surface size to a multiple of 4
+ uint16 wMod = width % 4;
+ if(wMod != 0)
+ width += 4 - wMod;
+
+ debug(2, "QTRLE corrected width: %d", width);
+
+ _surface = new Surface();
+ _surface->create(width, height, _bitsPerPixel <= 8 ? 1 : _pixelFormat.bytesPerPixel);
+}
+
+#define CHECK_STREAM_PTR(n) \
+ if ((stream->pos() + n) > stream->size()) { \
+ warning ("Problem: stream out of bounds (%d >= %d)", stream->pos() + n, stream->size()); \
+ return; \
+ }
+
+#define CHECK_PIXEL_PTR(n) \
+ if ((int32)pixelPtr + n > _surface->w * _surface->h) { \
+ warning ("Problem: pixel ptr = %d, pixel limit = %d", pixelPtr + n, _surface->w * _surface->h); \
+ return; \
+ } \
+
+void QTRLEDecoder::decode1(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
+ uint32 pixelPtr = 0;
+ byte *rgb = (byte *)_surface->pixels;
+
+ while (linesToChange) {
+ CHECK_STREAM_PTR(2);
+ byte skip = stream->readByte();
+ int8 rleCode = stream->readSByte();
+
+ if (rleCode == 0)
+ break;
+
+ if (skip & 0x80) {
+ linesToChange--;
+ rowPtr += _surface->w;
+ pixelPtr = rowPtr + 2 * (skip & 0x7f);
+ } else
+ pixelPtr += 2 * skip;
+
+ if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+ // get the next 2 bytes from the stream, treat them as groups of 8 pixels, and output them rleCode times */
+ CHECK_STREAM_PTR(2);
+ byte pi0 = stream->readByte();
+ byte pi1 = stream->readByte();
+ CHECK_PIXEL_PTR(rleCode * 2);
+
+ while (rleCode--) {
+ rgb[pixelPtr++] = pi0;
+ rgb[pixelPtr++] = pi1;
+ }
+ } else {
+ // copy the same pixel directly to output 2 times
+ rleCode *= 2;
+ CHECK_STREAM_PTR(rleCode);
+ CHECK_PIXEL_PTR(rleCode);
+
+ while (rleCode--)
+ rgb[pixelPtr++] = stream->readByte();
+ }
+ }
+}
+
+void QTRLEDecoder::decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange, byte bpp) {
+ uint32 pixelPtr = 0;
+ byte *rgb = (byte *)_surface->pixels;
+ byte numPixels = (bpp == 4) ? 8 : 16;
+
+ while (linesToChange--) {
+ CHECK_STREAM_PTR(2);
+ pixelPtr = rowPtr + (numPixels * (stream->readByte() - 1));
+
+ for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
+ if (rleCode == 0) {
+ // there's another skip code in the stream
+ CHECK_STREAM_PTR(1);
+ pixelPtr += (numPixels * (stream->readByte() - 1));
+ } else if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+
+ // get the next 4 bytes from the stream, treat them as palette indices, and output them rleCode times */
+ CHECK_STREAM_PTR(4);
+
+ byte pi[16]; // 16 palette indices
+
+ for (int8 i = numPixels - 1; i >= 0; i--) {
+ pi[numPixels - 1 - i] = (stream->readByte() >> ((i * bpp) & 0x07)) & ((1 << bpp) - 1);
+
+ // FIXME: Is this right?
+ //stream_ptr += ((i & ((num_pixels>>2)-1)) == 0);
+ if ((i & ((numPixels >> 2) - 1)) == 0)
+ stream->readByte();
+ }
+
+ CHECK_PIXEL_PTR(rleCode * numPixels);
+
+ while (rleCode--)
+ for (byte i = 0; i < numPixels; i++)
+ rgb[pixelPtr++] = pi[i];
+ } else {
+ // copy the same pixel directly to output 4 times
+ rleCode *= 4;
+ CHECK_STREAM_PTR(rleCode);
+ CHECK_PIXEL_PTR(rleCode * (numPixels >> 2));
+
+ while (rleCode--) {
+ byte temp = stream->readByte();
+ if (bpp == 4) {
+ rgb[pixelPtr++] = (temp >> 4) & 0x0f;
+ rgb[pixelPtr++] = temp & 0x0f;
+ } else {
+ rgb[pixelPtr++] = (temp >> 6) & 0x03;
+ rgb[pixelPtr++] = (temp >> 4) & 0x03;
+ rgb[pixelPtr++] = (temp >> 2) & 0x03;
+ rgb[pixelPtr++] = temp & 0x03;
+ }
+ }
+ }
+ }
+
+ rowPtr += _surface->w;
+ }
+}
+
+void QTRLEDecoder::decode8(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
+ uint32 pixelPtr = 0;
+ byte *rgb = (byte *)_surface->pixels;
+
+ while (linesToChange--) {
+ CHECK_STREAM_PTR(2);
+ pixelPtr = rowPtr + 4 * (stream->readByte() - 1);
+
+ for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
+ if (rleCode == 0) {
+ // there's another skip code in the stream
+ CHECK_STREAM_PTR(1);
+ pixelPtr += 4 * (stream->readByte() - 1);
+ } else if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+
+ // get the next 4 bytes from the stream, treat them as palette indices, and output them rleCode times
+ CHECK_STREAM_PTR(4);
+
+ byte pi[4]; // 4 palette indexes
+
+ for (byte i = 0; i < 4; i++)
+ pi[i] = stream->readByte();
+
+ CHECK_PIXEL_PTR(rleCode * 4);
+
+ while (rleCode--)
+ for (byte i = 0; i < 4; i++)
+ rgb[pixelPtr++] = pi[i];
+ } else {
+ // copy the same pixel directly to output 4 times
+ rleCode *= 4;
+ CHECK_STREAM_PTR(rleCode);
+ CHECK_PIXEL_PTR(rleCode);
+
+ while (rleCode--)
+ rgb[pixelPtr++] = stream->readByte();
+ }
+ }
+
+ rowPtr += _surface->w;
+ }
+}
+
+void QTRLEDecoder::decode16(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
+ uint32 pixelPtr = 0;
+ OverlayColor *rgb = (OverlayColor *)_surface->pixels;
+
+ while (linesToChange--) {
+ CHECK_STREAM_PTR(2);
+ pixelPtr = rowPtr + stream->readByte() - 1;
+
+ for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
+ if (rleCode == 0) {
+ // there's another skip code in the stream
+ CHECK_STREAM_PTR(1);
+ pixelPtr += stream->readByte() - 1;
+ } else if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+ CHECK_STREAM_PTR(2);
+
+ uint16 rgb16 = stream->readUint16BE();
+
+ CHECK_PIXEL_PTR(rleCode);
+
+ while (rleCode--) {
+ // Convert from RGB555 to the format specified by the Overlay
+ byte r = 0, g = 0, b = 0;
+ colorToRGB<ColorMasks<555> >(rgb16, r, g, b);
+ rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
+ }
+ } else {
+ CHECK_STREAM_PTR(rleCode * 2);
+ CHECK_PIXEL_PTR(rleCode);
+
+ // copy pixels directly to output
+ while (rleCode--) {
+ uint16 rgb16 = stream->readUint16BE();
+
+ // Convert from RGB555 to the format specified by the Overlay
+ byte r = 0, g = 0, b = 0;
+ colorToRGB<ColorMasks<555> >(rgb16, r, g, b);
+ rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
+ }
+ }
+ }
+
+ rowPtr += _surface->w;
+ }
+}
+
+void QTRLEDecoder::decode24(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
+ uint32 pixelPtr = 0;
+ OverlayColor *rgb = (OverlayColor *)_surface->pixels;
+
+ while (linesToChange--) {
+ CHECK_STREAM_PTR(2);
+ pixelPtr = rowPtr + stream->readByte() - 1;
+
+ for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
+ if (rleCode == 0) {
+ // there's another skip code in the stream
+ CHECK_STREAM_PTR(1);
+ pixelPtr += stream->readByte() - 1;
+ } else if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+
+ CHECK_STREAM_PTR(3);
+
+ byte r = stream->readByte();
+ byte g = stream->readByte();
+ byte b = stream->readByte();
+
+ CHECK_PIXEL_PTR(rleCode);
+
+ while (rleCode--)
+ rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
+ } else {
+ CHECK_STREAM_PTR(rleCode * 3);
+ CHECK_PIXEL_PTR(rleCode);
+
+ // copy pixels directly to output
+ while (rleCode--) {
+ byte r = stream->readByte();
+ byte g = stream->readByte();
+ byte b = stream->readByte();
+ rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
+ }
+ }
+ }
+
+ rowPtr += _surface->w;
+ }
+}
+
+void QTRLEDecoder::decode32(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
+ uint32 pixelPtr = 0;
+ OverlayColor *rgb = (OverlayColor *)_surface->pixels;
+
+ while (linesToChange--) {
+ CHECK_STREAM_PTR(2);
+ pixelPtr = rowPtr + stream->readByte() - 1;
+
+ for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
+ if (rleCode == 0) {
+ // there's another skip code in the stream
+ CHECK_STREAM_PTR(1);
+ pixelPtr += stream->readByte() - 1;
+ } else if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+
+ CHECK_STREAM_PTR(4);
+
+ byte a = stream->readByte();
+ byte r = stream->readByte();
+ byte g = stream->readByte();
+ byte b = stream->readByte();
+
+ CHECK_PIXEL_PTR(rleCode);
+
+ while (rleCode--)
+ rgb[pixelPtr++] = _pixelFormat.ARGBToColor(a, r, g, b);
+ } else {
+ CHECK_STREAM_PTR(rleCode * 4);
+ CHECK_PIXEL_PTR(rleCode);
+
+ // copy pixels directly to output
+ while (rleCode--) {
+ byte a = stream->readByte();
+ byte r = stream->readByte();
+ byte g = stream->readByte();
+ byte b = stream->readByte();
+ rgb[pixelPtr++] = _pixelFormat.ARGBToColor(a, r, g, b);
+ }
+ }
+ }
+
+ rowPtr += _surface->w;
+ }
+}
+
+Surface *QTRLEDecoder::decodeImage(Common::SeekableReadStream *stream) {
+ uint16 start_line = 0;
+ uint16 height = _surface->h;
+
+ // check if this frame is even supposed to change
+ if (stream->size() < 8)
+ return _surface;
+
+ // start after the chunk size
+ stream->readUint32BE();
+
+ // fetch the header
+ uint16 header = stream->readUint16BE();
+
+ // if a header is present, fetch additional decoding parameters
+ if (header & 8) {
+ if(stream->size() < 14)
+ return _surface;
+ start_line = stream->readUint16BE();
+ stream->readUint16BE(); // Unknown
+ height = stream->readUint16BE();
+ stream->readUint16BE(); // Unknown
+ }
+
+ uint32 row_ptr = _surface->w * start_line;
+
+ switch (_bitsPerPixel) {
+ case 1:
+ case 33:
+ decode1(stream, row_ptr, height);
+ break;
+ case 2:
+ case 34:
+ decode2_4(stream, row_ptr, height, 2);
+ break;
+ case 4:
+ case 36:
+ decode2_4(stream, row_ptr, height, 4);
+ break;
+ case 8:
+ case 40:
+ decode8(stream, row_ptr, height);
+ break;
+ case 16:
+ decode16(stream, row_ptr, height);
+ break;
+ case 24:
+ decode24(stream, row_ptr, height);
+ break;
+ case 32:
+ decode32(stream, row_ptr, height);
+ break;
+ default:
+ error ("Unsupported bits per pixel %d", _bitsPerPixel);
+ }
+
+ return _surface;
+}
+
+QTRLEDecoder::~QTRLEDecoder() {
+ _surface->free();
+}
+
+} // End of namespace Graphics
diff --git a/graphics/video/codecs/qtrle.h b/graphics/video/codecs/qtrle.h
new file mode 100644
index 0000000000..efbef14411
--- /dev/null
+++ b/graphics/video/codecs/qtrle.h
@@ -0,0 +1,58 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GRAPHICS_VIDEO_QTRLE_H
+#define GRAPHICS_VIDEO_QTRLE_H
+
+#include "graphics/pixelformat.h"
+#include "graphics/video/codecs/codec.h"
+
+namespace Graphics {
+
+class QTRLEDecoder : public Codec {
+public:
+ QTRLEDecoder(uint16 width, uint16 height, byte bitsPerPixel);
+ ~QTRLEDecoder();
+
+ Surface *decodeImage(Common::SeekableReadStream *stream);
+ PixelFormat getPixelFormat() const { return _pixelFormat; }
+
+private:
+ byte _bitsPerPixel;
+
+ Surface *_surface;
+ PixelFormat _pixelFormat;
+
+ void decode1(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
+ void decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange, byte bpp);
+ void decode8(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
+ void decode16(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
+ void decode24(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
+ void decode32(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
+};
+
+} // End of namespace Graphics
+
+#endif
diff --git a/graphics/video/codecs/rpza.cpp b/graphics/video/codecs/rpza.cpp
new file mode 100644
index 0000000000..f0ed72e730
--- /dev/null
+++ b/graphics/video/codecs/rpza.cpp
@@ -0,0 +1,208 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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$
+ *
+ */
+
+ // Based off ffmpeg's RPZA decoder
+
+#include "graphics/video/codecs/rpza.h"
+
+#include "common/system.h"
+#include "graphics/colormasks.h"
+
+namespace Graphics {
+
+RPZADecoder::RPZADecoder(uint16 width, uint16 height) : Codec() {
+ _pixelFormat = g_system->getScreenFormat();
+
+ // We need to increase the surface size to a multiple of 4
+ uint16 wMod = width % 4;
+ if(wMod != 0)
+ width += 4 - wMod;
+
+ debug(2, "RPZA corrected width: %d", width);
+
+ _surface = new Surface();
+ _surface->create(width, height, _pixelFormat.bytesPerPixel);
+}
+
+#define ADVANCE_BLOCK() \
+ pixelPtr += 4; \
+ if (pixelPtr >= _surface->w) { \
+ pixelPtr = 0; \
+ rowPtr += _surface->w * 4; \
+ } \
+ totalBlocks--; \
+ if (totalBlocks < 0) \
+ error("block counter just went negative (this should not happen)") \
+
+// Convert from RGB555 to the format specified by the screen
+#define PUT_PIXEL(color) \
+ if ((int32)blockPtr < _surface->w * _surface->h) { \
+ byte r = 0, g = 0, b = 0; \
+ colorToRGB<ColorMasks<555> >(color, r, g, b); \
+ if (_pixelFormat.bytesPerPixel == 2) \
+ *((uint16 *)_surface->pixels + blockPtr) = _pixelFormat.RGBToColor(r, g, b); \
+ else \
+ *((uint32 *)_surface->pixels + blockPtr) = _pixelFormat.RGBToColor(r, g, b); \
+ } \
+ blockPtr++
+
+Surface *RPZADecoder::decodeImage(Common::SeekableReadStream *stream) {
+ uint16 colorA = 0, colorB = 0;
+ uint16 color4[4];
+
+ uint32 rowPtr = 0;
+ uint32 pixelPtr = 0;
+ uint32 blockPtr = 0;
+ uint32 rowInc = _surface->w - 4;
+ uint16 ta;
+ uint16 tb;
+
+ // First byte is always 0xe1. Warn if it's different
+ byte firstByte = stream->readByte();
+ if (firstByte != 0xe1)
+ warning("First RPZA chunk byte is 0x%02x instead of 0xe1", firstByte);
+
+ // Get chunk size, ingnoring first byte
+ uint32 chunkSize = stream->readUint16BE() << 8;
+ chunkSize += stream->readByte();
+
+ // If length mismatch use size from MOV file and try to decode anyway
+ if (chunkSize != (uint32)stream->size()) {
+ warning("MOV chunk size != encoded chunk size; using MOV chunk size");
+ chunkSize = stream->size();
+ }
+
+ // Number of 4x4 blocks in frame
+ int32 totalBlocks = ((_surface->w + 3) / 4) * ((_surface->h + 3) / 4);
+
+ // Process chunk data
+ while ((uint32)stream->pos() < chunkSize) {
+ byte opcode = stream->readByte(); // Get opcode
+ byte numBlocks = (opcode & 0x1f) + 1; // Extract block counter from opcode
+
+ // If opcode MSbit is 0, we need more data to decide what to do
+ if ((opcode & 0x80) == 0) {
+ colorA = (opcode << 8) | stream->readByte();
+ opcode = 0;
+ if (stream->readByte() & 0x80) {
+ // Must behave as opcode 110xxxxx, using colorA computed
+ // above. Use fake opcode 0x20 to enter switch block at
+ // the right place
+ opcode = 0x20;
+ numBlocks = 1;
+ }
+ stream->seek(-1, SEEK_CUR);
+ }
+
+ switch (opcode & 0xe0) {
+ case 0x80: // Skip blocks
+ while (numBlocks--) {
+ ADVANCE_BLOCK();
+ }
+ break;
+ case 0xa0: // Fill blocks with one color
+ colorA = stream->readUint16BE();
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+ for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (byte pixel_x = 0; pixel_x < 4; pixel_x++) {
+ PUT_PIXEL(colorA);
+ }
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // Fill blocks with 4 colors
+ case 0xc0:
+ colorA = stream->readUint16BE();
+ case 0x20:
+ colorB = stream->readUint16BE();
+
+ // Sort out the colors
+ color4[0] = colorB;
+ color4[1] = 0;
+ color4[2] = 0;
+ color4[3] = colorA;
+
+ // Red components
+ ta = (colorA >> 10) & 0x1F;
+ tb = (colorB >> 10) & 0x1F;
+ color4[1] |= ((11 * ta + 21 * tb) >> 5) << 10;
+ color4[2] |= ((21 * ta + 11 * tb) >> 5) << 10;
+
+ // Green components
+ ta = (colorA >> 5) & 0x1F;
+ tb = (colorB >> 5) & 0x1F;
+ color4[1] |= ((11 * ta + 21 * tb) >> 5) << 5;
+ color4[2] |= ((21 * ta + 11 * tb) >> 5) << 5;
+
+ // Blue components
+ ta = colorA & 0x1F;
+ tb = colorB & 0x1F;
+ color4[1] |= ((11 * ta + 21 * tb) >> 5);
+ color4[2] |= ((21 * ta + 11 * tb) >> 5);
+
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+ for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
+ byte index = stream->readByte();
+ for (byte pixel_x = 0; pixel_x < 4; pixel_x++){
+ byte idx = (index >> (2 * (3 - pixel_x))) & 0x03;
+ PUT_PIXEL(color4[idx]);
+ }
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // Fill block with 16 colors
+ case 0x00:
+ blockPtr = rowPtr + pixelPtr;
+ for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (byte pixel_x = 0; pixel_x < 4; pixel_x++){
+ // We already have color of upper left pixel
+ if (pixel_y != 0 || pixel_x != 0)
+ colorA = stream->readUint16BE();
+
+ PUT_PIXEL(colorA);
+ }
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ break;
+
+ // Unknown opcode
+ default:
+ error("Unknown opcode %02x in rpza chunk", opcode);
+ }
+ }
+
+ return _surface;
+}
+
+} // End of namespace Graphics
diff --git a/backends/platform/PalmOS/Src/args.h b/graphics/video/codecs/rpza.h
index fa988fe35f..e6d32feb72 100644
--- a/backends/platform/PalmOS/Src/args.h
+++ b/graphics/video/codecs/rpza.h
@@ -23,22 +23,27 @@
*
*/
-#ifndef ARGS_H
-#define ARGS_H
+#ifndef GRAPHICS_VIDEO_RPZA_H
+#define GRAPHICS_VIDEO_RPZA_H
-#define MAX_ARG 25
+#include "graphics/pixelformat.h"
+#include "graphics/video/codecs/codec.h"
-#define ftrArgsData 1300
-#define ftrArgsCount 1301
-#define ftrVars 1302
-#define ftrStack 1303
+namespace Graphics {
-Char **ArgsInit();
-void ArgsAdd(Char **argvP, const Char *argP, const Char *parmP, UInt8 *countArgP);
-void ArgsFree(Char **argvP);
-void ArgsSetOwner(Char **argvP, UInt16 owner);
+class RPZADecoder : public Codec {
+public:
+ RPZADecoder(uint16 width, uint16 height);
+ ~RPZADecoder() { delete _surface; }
-void ArgsExportInit(Char **argvP, UInt32 countArg, Boolean arm);
-void ArgsExportRelease(Boolean arm);
+ Surface *decodeImage(Common::SeekableReadStream *stream);
+ PixelFormat getPixelFormat() const { return _pixelFormat; }
+
+private:
+ Surface *_surface;
+ PixelFormat _pixelFormat;
+};
+
+} // End of namespace Graphics
#endif
diff --git a/graphics/video/codecs/smc.cpp b/graphics/video/codecs/smc.cpp
new file mode 100644
index 0000000000..4661e3dc84
--- /dev/null
+++ b/graphics/video/codecs/smc.cpp
@@ -0,0 +1,385 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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$
+ *
+ */
+
+// Based off ffmpeg's SMC decoder
+
+#include "graphics/video/codecs/smc.h"
+
+namespace Graphics {
+
+#define GET_BLOCK_COUNT() \
+ (opcode & 0x10) ? (1 + stream->readByte()) : 1 + (opcode & 0x0F);
+
+#define ADVANCE_BLOCK() \
+{ \
+ pixelPtr += 4; \
+ if (pixelPtr >= _surface->w) { \
+ pixelPtr = 0; \
+ rowPtr += _surface->w * 4; \
+ } \
+ totalBlocks--; \
+ if (totalBlocks < 0) { \
+ warning("block counter just went negative (this should not happen)"); \
+ return _surface; \
+ } \
+}
+
+SMCDecoder::SMCDecoder(uint16 width, uint16 height) {
+ _surface = new Graphics::Surface();
+ _surface->create(width, height, 1);
+}
+
+Graphics::Surface *SMCDecoder::decodeImage(Common::SeekableReadStream *stream) {
+ byte *pixels = (byte *)_surface->pixels;
+
+ uint32 numBlocks = 0;
+ uint32 colorFlags = 0;
+ uint32 colorFlagsA = 0;
+ uint32 colorFlagsB = 0;
+
+ const uint16 rowInc = _surface->w - 4;
+ int32 rowPtr = 0;
+ int32 pixelPtr = 0;
+ uint32 blockPtr = 0;
+ uint32 prevBlockPtr = 0;
+ uint32 prevBlockPtr1 = 0, prevBlockPtr2 = 0;
+ byte prevBlockFlag = false;
+ byte pixel = 0;
+
+ uint32 colorPairIndex = 0;
+ uint32 colorQuadIndex = 0;
+ uint32 colorOctetIndex = 0;
+ uint32 colorTableIndex = 0; // indices to color pair, quad, or octet tables
+
+ int32 chunkSize = stream->readUint32BE() & 0x00FFFFFF;
+ if (chunkSize != stream->size())
+ warning("MOV chunk size != SMC chunk size (%d != %d); ignoring SMC chunk size", chunkSize, stream->size());
+
+ int32 totalBlocks = ((_surface->w + 3) / 4) * ((_surface->h + 3) / 4);
+
+ // traverse through the blocks
+ while (totalBlocks != 0) {
+ // sanity checks
+
+ // make sure stream ptr hasn't gone out of bounds
+ if (stream->pos() > stream->size()) {
+ warning("SMC decoder just went out of bounds (stream ptr = %d, chunk size = %d)", stream->pos(), stream->size());
+ return _surface;
+ }
+
+ // make sure the row pointer hasn't gone wild
+ if (rowPtr >= _surface->w * _surface->h) {
+ warning("SMC decoder just went out of bounds (row ptr = %d, size = %d)", rowPtr, _surface->w * _surface->h);
+ return _surface;
+ }
+
+ byte opcode = stream->readByte();
+
+ switch (opcode & 0xF0) {
+ // skip n blocks
+ case 0x00:
+ case 0x10:
+ numBlocks = GET_BLOCK_COUNT();
+ while (numBlocks--) {
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // repeat last block n times
+ case 0x20:
+ case 0x30:
+ numBlocks = GET_BLOCK_COUNT();
+
+ // sanity check
+ if (rowPtr == 0 && pixelPtr == 0) {
+ warning("encountered repeat block opcode (%02X) but no blocks rendered yet", opcode & 0xF0);
+ break;
+ }
+
+ // figure out where the previous block started
+ if (pixelPtr == 0)
+ prevBlockPtr1 = (rowPtr - _surface->w * 4) + _surface->w - 4;
+ else
+ prevBlockPtr1 = rowPtr + pixelPtr - 4;
+
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+ prevBlockPtr = prevBlockPtr1;
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++)
+ pixels[blockPtr++] = pixels[prevBlockPtr++];
+ blockPtr += rowInc;
+ prevBlockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // repeat previous pair of blocks n times
+ case 0x40:
+ case 0x50:
+ numBlocks = GET_BLOCK_COUNT();
+ numBlocks *= 2;
+
+ // sanity check
+ if (rowPtr == 0 && pixelPtr < 2 * 4) {
+ warning("encountered repeat block opcode (%02X) but not enough blocks rendered yet", opcode & 0xF0);
+ break;
+ }
+
+ // figure out where the previous 2 blocks started
+ if (pixelPtr == 0)
+ prevBlockPtr1 = (rowPtr - _surface->w * 4) + _surface->w - 4 * 2;
+ else if (pixelPtr == 4)
+ prevBlockPtr1 = (rowPtr - _surface->w * 4) + rowInc;
+ else
+ prevBlockPtr1 = rowPtr + pixelPtr - 4 * 2;
+
+ if (pixelPtr == 0)
+ prevBlockPtr2 = (rowPtr - _surface->w * 4) + rowInc;
+ else
+ prevBlockPtr2 = rowPtr + pixelPtr - 4;
+
+ prevBlockFlag = 0;
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+
+ if (prevBlockFlag)
+ prevBlockPtr = prevBlockPtr2;
+ else
+ prevBlockPtr = prevBlockPtr1;
+
+ prevBlockFlag = !prevBlockFlag;
+
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++)
+ pixels[blockPtr++] = pixels[prevBlockPtr++];
+
+ blockPtr += rowInc;
+ prevBlockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // 1-color block encoding
+ case 0x60:
+ case 0x70:
+ numBlocks = GET_BLOCK_COUNT();
+ pixel = stream->readByte();
+
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++)
+ pixels[blockPtr++] = pixel;
+
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // 2-color block encoding
+ case 0x80:
+ case 0x90:
+ numBlocks = (opcode & 0x0F) + 1;
+
+ // figure out which color pair to use to paint the 2-color block
+ if ((opcode & 0xF0) == 0x80) {
+ // fetch the next 2 colors from bytestream and store in next
+ // available entry in the color pair table
+ for (byte i = 0; i < CPAIR; i++) {
+ pixel = stream->readByte();
+ colorTableIndex = CPAIR * colorPairIndex + i;
+ _colorPairs[colorTableIndex] = pixel;
+ }
+
+ // this is the base index to use for this block
+ colorTableIndex = CPAIR * colorPairIndex;
+ colorPairIndex++;
+
+ // wraparound
+ if (colorPairIndex == COLORS_PER_TABLE)
+ colorPairIndex = 0;
+ } else
+ colorTableIndex = CPAIR * stream->readByte();
+
+ while (numBlocks--) {
+ colorFlags = stream->readUint16BE();
+ uint16 flagMask = 0x8000;
+ blockPtr = rowPtr + pixelPtr;
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++) {
+ if (colorFlags & flagMask)
+ pixel = colorTableIndex + 1;
+ else
+ pixel = colorTableIndex;
+
+ flagMask >>= 1;
+ pixels[blockPtr++] = _colorPairs[pixel];
+ }
+
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // 4-color block encoding
+ case 0xA0:
+ case 0xB0:
+ numBlocks = (opcode & 0x0F) + 1;
+
+ // figure out which color quad to use to paint the 4-color block
+ if ((opcode & 0xF0) == 0xA0) {
+ // fetch the next 4 colors from bytestream and store in next
+ // available entry in the color quad table
+ for (byte i = 0; i < CQUAD; i++) {
+ pixel = stream->readByte();
+ colorTableIndex = CQUAD * colorQuadIndex + i;
+ _colorQuads[colorTableIndex] = pixel;
+ }
+
+ // this is the base index to use for this block
+ colorTableIndex = CQUAD * colorQuadIndex;
+ colorQuadIndex++;
+
+ // wraparound
+ if (colorQuadIndex == COLORS_PER_TABLE)
+ colorQuadIndex = 0;
+ } else
+ colorTableIndex = CQUAD * stream->readByte();
+
+ while (numBlocks--) {
+ colorFlags = stream->readUint32BE();
+
+ // flag mask actually acts as a bit shift count here
+ byte flagMask = 30;
+ blockPtr = rowPtr + pixelPtr;
+
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++) {
+ pixel = colorTableIndex + ((colorFlags >> flagMask) & 0x03);
+ flagMask -= 2;
+ pixels[blockPtr++] = _colorQuads[pixel];
+ }
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // 8-color block encoding
+ case 0xC0:
+ case 0xD0:
+ numBlocks = (opcode & 0x0F) + 1;
+
+ // figure out which color octet to use to paint the 8-color block
+ if ((opcode & 0xF0) == 0xC0) {
+ // fetch the next 8 colors from bytestream and store in next
+ // available entry in the color octet table
+ for (byte i = 0; i < COCTET; i++) {
+ pixel = stream->readByte();
+ colorTableIndex = COCTET * colorOctetIndex + i;
+ _colorOctets[colorTableIndex] = pixel;
+ }
+
+ // this is the base index to use for this block
+ colorTableIndex = COCTET * colorOctetIndex;
+ colorOctetIndex++;
+
+ // wraparound
+ if (colorOctetIndex == COLORS_PER_TABLE)
+ colorOctetIndex = 0;
+ } else
+ colorTableIndex = COCTET * stream->readByte();
+
+ while (numBlocks--) {
+ /*
+ For this input of 6 hex bytes:
+ 01 23 45 67 89 AB
+ Mangle it to this output:
+ flags_a = xx012456, flags_b = xx89A37B
+ */
+
+ // build the color flags
+ byte flagData[6];
+ stream->read(flagData, 6);
+
+ colorFlagsA = ((READ_BE_UINT16(flagData) & 0xFFF0) << 8) | (READ_BE_UINT16(flagData + 2) >> 4);
+ colorFlagsB = ((READ_BE_UINT16(flagData + 4) & 0xFFF0) << 8) | ((flagData[1] & 0xF) << 8) |
+ ((flagData[3] & 0xF) << 4) | (flagData[5] & 0xf);
+
+ colorFlags = colorFlagsA;
+
+ // flag mask actually acts as a bit shift count here
+ byte flagMask = 21;
+ blockPtr = rowPtr + pixelPtr;
+ for (byte y = 0; y < 4; y++) {
+ // reload flags at third row (iteration y == 2)
+ if (y == 2) {
+ colorFlags = colorFlagsB;
+ flagMask = 21;
+ }
+
+ for (byte x = 0; x < 4; x++) {
+ pixel = colorTableIndex + ((colorFlags >> flagMask) & 0x07);
+ flagMask -= 3;
+ pixels[blockPtr++] = _colorOctets[pixel];
+ }
+
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // 16-color block encoding (every pixel is a different color)
+ case 0xE0:
+ numBlocks = (opcode & 0x0F) + 1;
+
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++)
+ pixels[blockPtr++] = stream->readByte();
+
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ case 0xF0:
+ warning("0xF0 opcode seen in SMC chunk (contact the developers)");
+ break;
+ }
+ }
+
+ return _surface;
+}
+
+} // End of namespace Graphics
diff --git a/backends/platform/PalmOS/Src/cd_aeroplayer.h b/graphics/video/codecs/smc.h
index e661e06d52..2d4355a83e 100644
--- a/backends/platform/PalmOS/Src/cd_aeroplayer.h
+++ b/graphics/video/codecs/smc.h
@@ -23,43 +23,37 @@
*
*/
-#ifndef CD_AEROPLAYER_H
-#define CD_AEROPLAYER_H
+#ifndef GRAPHICS_VIDEO_SMC_H
+#define GRAPHICS_VIDEO_SMC_H
-#include "cdaudio.h"
-#include "aeroplayer_public.h"
+#include "graphics/video/codecs/codec.h"
-class AeroCDPlayer : public CDAudio {
-public:
- AeroCDPlayer(OSystem *sys);
+namespace Graphics {
- bool init();
- void release();
+enum {
+ CPAIR = 2,
+ CQUAD = 4,
+ COCTET = 8,
+ COLORS_PER_TABLE = 256
+};
- bool poll();
- void update();
- void play(int track, int num_loops, int start_frame, int duration);
- void stop();
+class SMCDecoder : public Codec {
+public:
+ SMCDecoder(uint16 width, uint16 height);
+ ~SMCDecoder() { delete _surface; }
- void setVolume(int volume);
+ Surface *decodeImage(Common::SeekableReadStream *stream);
+ PixelFormat getPixelFormat() const { return PixelFormat::createFormatCLUT8(); }
private:
- OSystem *_sys;
- Char gameP[15];
+ Surface *_surface;
- UInt32 getStatus();
- void setPosition(UInt32 value);
- UInt32 getDuration();
- UInt32 getPosition();
- void forceStop();
-
- UInt16 _volumeLimit;
-
- Boolean _isPlaying;
- // cdrom
- UInt16 _pckLoops, _pckTrack;
- UInt32 _pckTrackStartFrame, _pckTrackEndFrame;
- UInt32 _pckStopTime, _pckEndTime, _pckTrackDuration;
+ // SMC color tables
+ byte _colorPairs[COLORS_PER_TABLE * CPAIR];
+ byte _colorQuads[COLORS_PER_TABLE * CQUAD];
+ byte _colorOctets[COLORS_PER_TABLE * COCTET];
};
+} // End of namespace Graphics
+
#endif
diff --git a/graphics/video/coktel_decoder.cpp b/graphics/video/coktel_decoder.cpp
new file mode 100644
index 0000000000..0709288091
--- /dev/null
+++ b/graphics/video/coktel_decoder.cpp
@@ -0,0 +1,2469 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/video/coktel_decoder.h"
+#include "graphics/video/codecs/codec.h"
+#include "graphics/video/codecs/indeo3.h"
+
+#ifdef GRAPHICS_VIDEO_COKTELDECODER_H
+
+#include "sound/audiostream.h"
+#include "sound/decoders/raw.h"
+
+static const uint32 kVideoCodecIndeo3 = MKID_BE('iv32');
+
+namespace Graphics {
+
+CoktelDecoder::State::State() : flags(0), speechId(0) {
+}
+
+
+CoktelDecoder::CoktelDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) :
+ _mixer(mixer), _soundType(soundType), _width(0), _height(0), _x(0), _y(0),
+ _defaultX(0), _defaultY(0), _features(0), _frameCount(0), _paletteDirty(false),
+ _ownSurface(true), _frameRate(12), _hasSound(false), _soundEnabled(false),
+ _soundStage(kSoundNone), _audioStream(0) {
+
+ assert(_mixer);
+
+ memset(_palette, 0, 768);
+}
+
+CoktelDecoder::~CoktelDecoder() {
+}
+
+bool CoktelDecoder::evaluateSeekFrame(int32 &frame, int whence) const {
+ if (!isVideoLoaded())
+ // Nothing to do
+ return false;
+
+ // Find the frame to which to seek
+ if (whence == SEEK_CUR)
+ frame += _curFrame;
+ else if (whence == SEEK_END)
+ frame = _frameCount - frame - 1;
+ else if (whence == SEEK_SET)
+ frame--;
+ else
+ return false;
+
+ if ((frame < -1) || (frame >= ((int32) _frameCount)))
+ // Out of range
+ return false;
+
+ return true;
+}
+
+void CoktelDecoder::setSurfaceMemory(void *mem, uint16 width, uint16 height, uint8 bpp) {
+ freeSurface();
+
+ // Sanity checks
+ assert((width > 0) && (height > 0));
+ assert(bpp == getPixelFormat().bytesPerPixel);
+
+ // Create a surface over this memory
+ _surface.w = width;
+ _surface.h = height;
+ _surface.pitch = width * bpp;
+ _surface.pixels = mem;
+ _surface.bytesPerPixel = bpp;
+
+ _ownSurface = false;
+}
+
+void CoktelDecoder::setSurfaceMemory() {
+ freeSurface();
+ createSurface();
+
+ _ownSurface = true;
+}
+
+const Surface *CoktelDecoder::getSurface() const {
+ if (!isVideoLoaded())
+ return 0;
+
+ return &_surface;
+}
+
+bool CoktelDecoder::hasSurface() {
+ return _surface.pixels != 0;
+}
+
+void CoktelDecoder::createSurface() {
+ if (hasSurface())
+ return;
+
+ if ((_width > 0) && (_height > 0))
+ _surface.create(_width, _height, getPixelFormat().bytesPerPixel);
+
+ _ownSurface = true;
+}
+
+void CoktelDecoder::freeSurface() {
+ if (!_ownSurface) {
+ _surface.w = 0;
+ _surface.h = 0;
+ _surface.pitch = 0;
+ _surface.pixels = 0;
+ _surface.bytesPerPixel = 0;
+ } else
+ _surface.free();
+
+ _ownSurface = true;
+}
+
+void CoktelDecoder::setXY(uint16 x, uint16 y) {
+ _x = x;
+ _y = y;
+}
+
+void CoktelDecoder::setXY() {
+ setXY(_defaultX, _defaultY);
+}
+
+void CoktelDecoder::setFrameRate(Common::Rational frameRate) {
+ _frameRate = frameRate;
+}
+
+uint16 CoktelDecoder::getDefaultX() const {
+ return _defaultX;
+}
+
+uint16 CoktelDecoder::getDefaultY() const {
+ return _defaultY;
+}
+
+const Common::List<Common::Rect> &CoktelDecoder::getDirtyRects() const {
+ return _dirtyRects;
+}
+
+bool CoktelDecoder::hasPalette() const {
+ return (_features & kFeaturesPalette) != 0;
+}
+
+bool CoktelDecoder::hasSound() const {
+ return _hasSound;
+}
+
+bool CoktelDecoder::isSoundEnabled() const {
+ return _soundEnabled;
+}
+
+bool CoktelDecoder::isSoundPlaying() const {
+ return _audioStream && _mixer->isSoundHandleActive(_audioHandle);
+}
+
+void CoktelDecoder::enableSound() {
+ if (!hasSound() || isSoundEnabled())
+ return;
+
+ // Sanity check
+ if (_mixer->getOutputRate() == 0)
+ return;
+
+ // Only possible on the first frame
+ if (_curFrame > -1)
+ return;
+
+ _soundEnabled = true;
+}
+
+void CoktelDecoder::disableSound() {
+ if (_audioStream) {
+
+ if (_soundStage == kSoundPlaying) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ } else
+ delete _audioStream;
+
+ }
+
+ _soundEnabled = false;
+ _soundStage = kSoundNone;
+
+ _audioStream = 0;
+}
+
+bool CoktelDecoder::getFrameCoords(int16 frame, int16 &x, int16 &y, int16 &width, int16 &height) {
+ return false;
+}
+
+bool CoktelDecoder::hasEmbeddedFiles() const {
+ return false;
+}
+
+bool CoktelDecoder::hasEmbeddedFile(const Common::String &fileName) const {
+ return false;
+}
+
+Common::MemoryReadStream *CoktelDecoder::getEmbeddedFile(const Common::String &fileName) const {
+ return 0;
+}
+
+int32 CoktelDecoder::getSubtitleIndex() const {
+ return -1;
+}
+
+void CoktelDecoder::close() {
+ disableSound();
+ freeSurface();
+
+ _x = 0;
+ _y = 0;
+
+ _defaultX = 0;
+ _defaultY = 0;
+
+ _features = 0;
+
+ _frameCount = 0;
+
+ _hasSound = false;
+}
+
+uint16 CoktelDecoder::getWidth() const {
+ return _width;
+}
+
+uint16 CoktelDecoder::getHeight() const {
+ return _height;
+}
+
+uint32 CoktelDecoder::getFrameCount() const {
+ return _frameCount;
+}
+
+byte *CoktelDecoder::getPalette() {
+ return _palette;
+}
+
+bool CoktelDecoder::hasDirtyPalette() const {
+ return (_features & kFeaturesPalette) && _paletteDirty;
+}
+
+void CoktelDecoder::deLZ77(byte *dest, byte *src) {
+ int i;
+ byte buf[4370];
+ uint16 chunkLength;
+ uint32 frameLength;
+ uint16 bufPos1;
+ uint16 bufPos2;
+ uint16 tmp;
+ uint8 chunkBitField;
+ uint8 chunkCount;
+ bool mode;
+
+ frameLength = READ_LE_UINT32(src);
+ src += 4;
+
+ if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
+ src += 4;
+ bufPos1 = 273;
+ mode = 1; // 123Ch (cmp al, 12h)
+ } else {
+ bufPos1 = 4078;
+ mode = 0; // 275h (jnz +2)
+ }
+
+ memset(buf, 32, bufPos1);
+ chunkCount = 1;
+ chunkBitField = 0;
+
+ while (frameLength > 0) {
+ chunkCount--;
+ if (chunkCount == 0) {
+ tmp = *src++;
+ chunkCount = 8;
+ chunkBitField = tmp;
+ }
+ if (chunkBitField % 2) {
+ chunkBitField >>= 1;
+ buf[bufPos1] = *src;
+ *dest++ = *src++;
+ bufPos1 = (bufPos1 + 1) % 4096;
+ frameLength--;
+ continue;
+ }
+ chunkBitField >>= 1;
+
+ tmp = READ_LE_UINT16(src);
+ src += 2;
+ chunkLength = ((tmp & 0xF00) >> 8) + 3;
+
+ if ((mode && ((chunkLength & 0xFF) == 0x12)) ||
+ (!mode && (chunkLength == 0)))
+ chunkLength = *src++ + 0x12;
+
+ bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
+ if (((tmp + chunkLength) >= 4096) ||
+ ((chunkLength + bufPos1) >= 4096)) {
+
+ for (i = 0; i < chunkLength; i++, dest++) {
+ *dest = buf[bufPos2];
+ buf[bufPos1] = buf[bufPos2];
+ bufPos1 = (bufPos1 + 1) % 4096;
+ bufPos2 = (bufPos2 + 1) % 4096;
+ }
+
+ } else if (((tmp + chunkLength) < bufPos1) ||
+ ((chunkLength + bufPos1) < bufPos2)) {
+
+ memcpy(dest, buf + bufPos2, chunkLength);
+ memmove(buf + bufPos1, buf + bufPos2, chunkLength);
+
+ dest += chunkLength;
+ bufPos1 += chunkLength;
+ bufPos2 += chunkLength;
+
+ } else {
+
+ for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
+ *dest = buf[bufPos2];
+ buf[bufPos1] = buf[bufPos2];
+ }
+
+ }
+ frameLength -= chunkLength;
+
+ }
+}
+
+void CoktelDecoder::deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen) {
+ srcPtr++;
+
+ if (srcLen & 1) {
+ byte data = *srcPtr++;
+
+ if (destLen > 0) {
+ *destPtr++ = data;
+ destLen--;
+ }
+ }
+
+ srcLen >>= 1;
+
+ while (srcLen > 0) {
+ uint8 tmp = *srcPtr++;
+ if (tmp & 0x80) { // Verbatim copy
+ tmp &= 0x7F;
+
+ int16 copyCount = MAX<int16>(0, MIN<int16>(destLen, tmp * 2));
+
+ memcpy(destPtr, srcPtr, copyCount);
+
+ srcPtr += tmp * 2;
+ destPtr += copyCount;
+ destLen -= copyCount;
+ } else { // 2 bytes tmp times
+ for (int i = 0; (i < tmp) && (destLen > 0); i++) {
+ for (int j = 0; j < 2; j++) {
+ if (destLen <= 0)
+ break;
+
+ *destPtr++ = srcPtr[j];
+ destLen--;
+ }
+ }
+ srcPtr += 2;
+ }
+ srcLen -= tmp;
+ }
+}
+
+// A whole, completely filled block
+void CoktelDecoder::renderBlockWhole(const byte *src, Common::Rect &rect) {
+ Common::Rect srcRect = rect;
+
+ rect.clip(_surface.w, _surface.h);
+
+ byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+ for (int i = 0; i < rect.height(); i++) {
+ memcpy(dst, src, rect.width());
+
+ src += srcRect.width();
+ dst += _surface.pitch;
+ }
+}
+
+// A quarter-wide whole, completely filled block
+void CoktelDecoder::renderBlockWhole4X(const byte *src, Common::Rect &rect) {
+ Common::Rect srcRect = rect;
+
+ rect.clip(_surface.w, _surface.h);
+
+ byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+ for (int i = 0; i < rect.height(); i++) {
+ byte *dstRow = dst;
+ const byte *srcRow = src;
+
+ int16 count = rect.width();
+ while (count >= 0) {
+ memset(dstRow, *srcRow, MIN<int16>(count, 4));
+
+ count -= 4;
+ dstRow += 4;
+ srcRow += 1;
+ }
+
+ src += srcRect.width() / 4;
+ dst += _surface.pitch;
+ }
+}
+
+// A half-high whole, completely filled block
+void CoktelDecoder::renderBlockWhole2Y(const byte *src, Common::Rect &rect) {
+ Common::Rect srcRect = rect;
+
+ rect.clip(_surface.w, _surface.h);
+
+ int16 height = rect.height();
+
+ byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+ while (height > 1) {
+ memcpy(dst , src, rect.width());
+ memcpy(dst + _surface.pitch, src, rect.width());
+
+ height -= 2;
+ src += srcRect.width();
+ dst += 2 * _surface.pitch;
+ }
+
+ if (height == 1)
+ memcpy(dst, src, rect.width());
+}
+
+// A sparse block
+void CoktelDecoder::renderBlockSparse(const byte *src, Common::Rect &rect) {
+ Common::Rect srcRect = rect;
+
+ rect.clip(_surface.w, _surface.h);
+
+ byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+ for (int i = 0; i < rect.height(); i++) {
+ byte *dstRow = dst;
+ int16 pixWritten = 0;
+
+ while (pixWritten < srcRect.width()) {
+ int16 pixCount = *src++;
+
+ if (pixCount & 0x80) { // Data
+ int16 copyCount;
+
+ pixCount = MIN((pixCount & 0x7F) + 1, srcRect.width() - pixWritten);
+ copyCount = CLIP<int16>(rect.width() - pixWritten, 0, pixCount);
+ memcpy(dstRow, src, copyCount);
+
+ pixWritten += pixCount;
+ dstRow += pixCount;
+ src += pixCount;
+ } else { // "Hole"
+ pixWritten += pixCount + 1;
+ dstRow += pixCount + 1;
+ }
+
+ }
+
+ dst += _surface.pitch;
+ }
+}
+
+// A half-high sparse block
+void CoktelDecoder::renderBlockSparse2Y(const byte *src, Common::Rect &rect) {
+ warning("renderBlockSparse2Y");
+
+ Common::Rect srcRect = rect;
+
+ rect.clip(_surface.w, _surface.h);
+
+ byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+ for (int i = 0; i < rect.height(); i += 2) {
+ byte *dstRow = dst;
+ int16 pixWritten = 0;
+
+ while (pixWritten < srcRect.width()) {
+ int16 pixCount = *src++;
+
+ if (pixCount & 0x80) { // Data
+ int16 copyCount;
+
+ pixCount = MIN((pixCount & 0x7F) + 1, srcRect.width() - pixWritten);
+ copyCount = CLIP<int16>(rect.width() - pixWritten, 0, pixCount);
+ memcpy(dstRow , src, pixCount);
+ memcpy(dstRow + _surface.pitch, src, pixCount);
+
+ pixWritten += pixCount;
+ dstRow += pixCount;
+ src += pixCount;
+ } else { // "Hole"
+ pixWritten += pixCount + 1;
+ dstRow += pixCount + 1;
+ }
+
+ }
+
+ dst += _surface.pitch;
+ }
+}
+
+void CoktelDecoder::renderBlockRLE(const byte *src, Common::Rect &rect) {
+ Common::Rect srcRect = rect;
+
+ rect.clip(_surface.w, _surface.h);
+
+ byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+ for (int i = 0; i < rect.height(); i++) {
+ byte *dstRow = dst;
+ int16 pixWritten = 0;
+
+ while (pixWritten < srcRect.width()) {
+ int16 pixCount = *src++;
+
+ if (pixCount & 0x80) {
+ int16 copyCount;
+
+ pixCount = MIN((pixCount & 0x7F) + 1, srcRect.width() - pixWritten);
+ copyCount = CLIP<int16>(rect.width() - pixWritten, 0, pixCount);
+
+ if (*src != 0xFF) { // Normal copy
+
+ memcpy(dstRow, src, copyCount);
+ dstRow += copyCount;
+ src += pixCount;
+ } else
+ deRLE(dstRow, src, copyCount, pixCount);
+
+ pixWritten += pixCount;
+ } else { // "Hole"
+ int16 copyCount = CLIP<int16>(rect.width() - pixWritten, 0, pixCount + 1);
+
+ dstRow += copyCount;
+ pixWritten += pixCount + 1;
+ }
+
+ }
+
+ dst += _surface.pitch;
+ }
+}
+
+Common::Rational CoktelDecoder::getFrameRate() const {
+ return _frameRate;
+}
+
+uint32 CoktelDecoder::getTimeToNextFrame() const {
+ // If there is no audio, just return the static time between
+ // frames without any elaborate sync calculation. This is
+ // needed for the gob engine, since it has a lot of control
+ // between the videos and often plays just few frames out of
+ // the middle of a long video.
+
+ if (!hasSound())
+ return Common::Rational(1000, _frameRate).toInt();
+
+ // If there /is/ audio, we do need to keep video and audio
+ // in sync, though.
+
+ return FixedRateVideoDecoder::getTimeToNextFrame();
+}
+
+inline void CoktelDecoder::unsignedToSigned(byte *buffer, int length) {
+ while (length-- > 0) *buffer++ ^= 0x80;
+}
+
+
+PreIMDDecoder::PreIMDDecoder(uint16 width, uint16 height,
+ Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : CoktelDecoder(mixer, soundType),
+ _stream(0), _videoBuffer(0), _videoBufferSize(0) {
+
+ _width = width;
+ _height = height;
+}
+
+PreIMDDecoder::~PreIMDDecoder() {
+ close();
+}
+
+bool PreIMDDecoder::seek(int32 frame, int whence, bool restart) {
+ if (!evaluateSeekFrame(frame, whence))
+ return false;
+
+ if (frame == _curFrame)
+ // Nothing to do
+ return true;
+
+ // Run through the frames
+ _curFrame = -1;
+ _stream->seek(2);
+ while (_curFrame != frame) {
+ uint16 frameSize = _stream->readUint16LE();
+
+ _stream->skip(frameSize + 2);
+
+ _curFrame++;
+ }
+
+ return true;
+}
+
+bool PreIMDDecoder::load(Common::SeekableReadStream *stream) {
+ // Since PreIMDs don't have any width and height values stored,
+ // we need them to be specified in the constructor
+ assert((_width > 0) && (_height > 0));
+
+ close();
+
+ _stream = stream;
+
+ _stream->seek(0);
+
+ _frameCount = _stream->readUint16LE();
+
+ _videoBufferSize = _width * _height;
+ _videoBuffer = new byte[_videoBufferSize];
+
+ memset(_videoBuffer, 0, _videoBufferSize);
+
+ return true;
+}
+
+void PreIMDDecoder::close() {
+ reset();
+
+ CoktelDecoder::close();
+
+ delete _stream;
+
+ delete[] _videoBuffer;
+
+ _stream = 0;
+
+ _videoBuffer = 0;
+ _videoBufferSize = 0;
+}
+
+bool PreIMDDecoder::isVideoLoaded() const {
+ return _stream != 0;
+}
+
+Surface *PreIMDDecoder::decodeNextFrame() {
+ if (!isVideoLoaded() || endOfVideo())
+ return 0;
+
+ createSurface();
+
+ processFrame();
+ renderFrame();
+
+ if (_curFrame == 0)
+ _startTime = g_system->getMillis();
+
+ return &_surface;
+}
+
+void PreIMDDecoder::processFrame() {
+ uint16 frameSize = _stream->readUint16LE();
+
+ uint32 nextFramePos = _stream->pos() + frameSize + 2;
+
+ byte cmd;
+
+ cmd = _stream->readByte();
+ frameSize--;
+
+ if (cmd == 0) {
+ // Palette. Ignored by Fascination, though.
+
+ // NOTE: If we ever find another game using this format,
+ // palettes may need to be evaluated.
+
+ _stream->skip(768);
+
+ frameSize -= 769;
+
+ cmd = _stream->readByte();
+ }
+
+ if (cmd != 2) {
+ // Partial frame data
+
+ uint32 fSize = frameSize;
+ uint32 vidSize = _videoBufferSize;
+
+ byte *vidBuffer = _videoBuffer;
+
+ while ((fSize > 0) && (vidSize > 0)) {
+ uint32 n = _stream->readByte();
+ fSize--;
+
+ if ((n & 0x80) != 0) {
+ // Data
+
+ n = MIN<uint32>((n & 0x7F) + 1, MIN(fSize, vidSize));
+
+ _stream->read(vidBuffer, n);
+
+ vidBuffer += n;
+ vidSize -= n;
+ fSize -= n;
+
+ } else {
+ // Skip
+
+ n = MIN<uint32>(n + 1, vidSize);
+
+ vidBuffer += n;
+ vidSize -= n;
+ }
+ }
+
+ } else {
+ // Full direct frame
+
+ uint32 vidSize = MIN<uint32>(_videoBufferSize, frameSize);
+
+ _stream->read(_videoBuffer, vidSize);
+ }
+
+ _stream->seek(nextFramePos);
+
+ _curFrame++;
+}
+
+// Just a simple blit
+void PreIMDDecoder::renderFrame() {
+ _dirtyRects.clear();
+
+ uint16 w = CLIP<int32>(_surface.w - _x, 0, _width);
+ uint16 h = CLIP<int32>(_surface.h - _y, 0, _height);
+
+ const byte *src = _videoBuffer;
+ byte *dst = (byte *)_surface.pixels + (_y * _surface.pitch) + _x;
+
+ uint32 frameDataSize = _videoBufferSize;
+
+ while (h-- > 0) {
+ uint32 n = MIN<uint32>(w, frameDataSize);
+
+ memcpy(dst, src, n);
+
+ src += _width;
+ dst += _surface.pitch;
+
+ frameDataSize -= n;
+ }
+
+ _dirtyRects.push_back(Common::Rect(_x, _y, _x + _width, _y + _height));
+}
+
+PixelFormat PreIMDDecoder::getPixelFormat() const {
+ return PixelFormat::createFormatCLUT8();
+}
+
+
+IMDDecoder::IMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : CoktelDecoder(mixer, soundType),
+ _stream(0), _version(0), _stdX(-1), _stdY(-1), _stdWidth(-1), _stdHeight(-1),
+ _flags(0), _firstFramePos(0), _framePos(0), _frameCoords(0),
+ _frameData(0), _frameDataSize(0), _frameDataLen(0),
+ _videoBuffer(0), _videoBufferSize(0),
+ _soundFlags(0), _soundFreq(0), _soundSliceSize(0), _soundSlicesCount(0) {
+
+}
+
+IMDDecoder::~IMDDecoder() {
+ close();
+}
+
+bool IMDDecoder::seek(int32 frame, int whence, bool restart) {
+ if (!evaluateSeekFrame(frame, whence))
+ return false;
+
+ if (frame == _curFrame)
+ // Nothing to do
+ return true;
+
+ // Try every possible way to find a file offset to that frame
+ uint32 framePos = 0;
+ if (frame == -1) {
+ // First frame, we know that position
+
+ framePos = _firstFramePos;
+
+ } else if (frame == 0) {
+ // Second frame, can be calculated from the first frame's position
+
+ framePos = _firstFramePos;
+ _stream->seek(framePos);
+ framePos += _stream->readUint16LE() + 4;
+
+ } else if (_framePos) {
+ // If we have an array of frame positions, use that
+
+ framePos = _framePos[frame + 1];
+
+ } else if (restart && (_soundStage == kSoundNone)) {
+ // If we are asked to restart the video if necessary and have no
+ // audio to worry about, restart the video and run through the frames
+
+ _curFrame = 0;
+ _stream->seek(_firstFramePos);
+
+ for (int i = ((frame > _curFrame) ? _curFrame : 0); i <= frame; i++)
+ processFrame();
+
+ return true;
+
+ } else {
+ // Not possible
+
+ warning("IMDDecoder::seek(): Frame %d is not directly accessible", frame + 1);
+ return false;
+ }
+
+ // Seek
+ _stream->seek(framePos);
+ _curFrame = frame;
+
+ return true;
+}
+
+void IMDDecoder::setXY(uint16 x, uint16 y) {
+ // Adjusting the standard coordinates
+ if (_stdX != -1) {
+ if (x != 0xFFFF)
+ _stdX = _stdX - _x + x;
+ if (y != 0xFFFF)
+ _stdY = _stdY - _y + y;
+ }
+
+ // Going through the coordinate table as well
+ if (_frameCoords) {
+ for (uint32 i = 0; i < _frameCount; i++) {
+ if (_frameCoords[i].left != -1) {
+ if (x != 0xFFFF) {
+ _frameCoords[i].left = _frameCoords[i].left - _x + x;
+ _frameCoords[i].right = _frameCoords[i].right - _x + x;
+ }
+ if (y != 0xFFFF) {
+ _frameCoords[i].top = _frameCoords[i].top - _y + y;
+ _frameCoords[i].bottom = _frameCoords[i].bottom - _y + y;
+ }
+ }
+ }
+ }
+
+ if (x != 0xFFFF)
+ _x = x;
+ if (y != 0xFFFF)
+ _y = y;
+}
+
+bool IMDDecoder::load(Common::SeekableReadStream *stream) {
+ close();
+
+ _stream = stream;
+
+ uint16 handle;
+
+ handle = _stream->readUint16LE();
+ _version = _stream->readByte();
+
+ // Version checking
+ if ((handle != 0) || (_version < 2)) {
+ warning("IMDDecoder::load(): Version incorrect (%d, 0x%X)", handle, _version);
+ close();
+ return false;
+ }
+
+ // Rest header
+ _features = _stream->readByte();
+ _frameCount = _stream->readUint16LE();
+ _defaultX = _stream->readSint16LE();
+ _defaultY = _stream->readSint16LE();
+ _width = _stream->readSint16LE();
+ _height = _stream->readSint16LE();
+ _flags = _stream->readUint16LE();
+ _firstFramePos = _stream->readUint16LE();
+
+ _x = _defaultX;
+ _y = _defaultY;
+
+ // IMDs always have video
+ _features |= kFeaturesVideo;
+ // IMDs always have palettes
+ _features |= kFeaturesPalette;
+
+ // Palette
+ for (int i = 0; i < 768; i++)
+ _palette[i] = _stream->readByte() << 2;
+
+ _paletteDirty = true;
+
+ if (!loadCoordinates()) {
+ close();
+ return false;
+ }
+
+ uint32 framePosPos, frameCoordsPos;
+ if (!loadFrameTableOffsets(framePosPos, frameCoordsPos)) {
+ close();
+ return false;
+ }
+
+ if (!assessAudioProperties()) {
+ close();
+ return false;
+ }
+
+ if (!assessVideoProperties()) {
+ close();
+ return false;
+ }
+
+ if (!loadFrameTables(framePosPos, frameCoordsPos)) {
+ close();
+ return false;
+ }
+
+ // Seek to the first frame
+ _stream->seek(_firstFramePos);
+
+ return true;
+}
+
+bool IMDDecoder::loadCoordinates() {
+ // Standard coordinates
+ if (_version >= 3) {
+ uint16 count = _stream->readUint16LE();
+ if (count > 1) {
+ warning("IMDDecoder::loadCoordinates(): More than one standard coordinate quad found (%d)", count);
+ return false;
+ }
+
+ if (count != 0) {
+ _stdX = _stream->readSint16LE();
+ _stdY = _stream->readSint16LE();
+ _stdWidth = _stream->readSint16LE();
+ _stdHeight = _stream->readSint16LE();
+ _features |= kFeaturesStdCoords;
+ } else
+ _stdX = _stdY = _stdWidth = _stdHeight = -1;
+
+ } else
+ _stdX = _stdY = _stdWidth = _stdHeight = -1;
+
+ return true;
+}
+
+bool IMDDecoder::loadFrameTableOffsets(uint32 &framePosPos, uint32 &frameCoordsPos) {
+ framePosPos = 0;
+ frameCoordsPos = 0;
+
+ // Frame positions
+ if (_version >= 4) {
+ framePosPos = _stream->readUint32LE();
+ if (framePosPos != 0) {
+ _framePos = new uint32[_frameCount];
+ _features |= kFeaturesFramePos;
+ }
+ }
+
+ // Frame coordinates
+ if (_features & kFeaturesFrameCoords)
+ frameCoordsPos = _stream->readUint32LE();
+
+ return true;
+}
+
+bool IMDDecoder::assessVideoProperties() {
+ // Sizes of the frame data and extra video buffer
+ if (_features & kFeaturesDataSize) {
+ _frameDataSize = _stream->readUint16LE();
+ if (_frameDataSize == 0) {
+ _frameDataSize = _stream->readUint32LE();
+ _videoBufferSize = _stream->readUint32LE();
+ } else
+ _videoBufferSize = _stream->readUint16LE();
+ } else {
+ _frameDataSize = _width * _height + 500;
+ if (!(_flags & 0x100) || (_flags & 0x1000))
+ _videoBufferSize = _frameDataSize;
+ }
+
+ // Allocating working memory
+ _frameData = new byte[_frameDataSize + 500];
+ memset(_frameData, 0, _frameDataSize + 500);
+
+ _videoBuffer = new byte[_videoBufferSize + 500];
+ memset(_videoBuffer, 0, _videoBufferSize + 500);
+
+ return true;
+}
+
+bool IMDDecoder::assessAudioProperties() {
+ if (_features & kFeaturesSound) {
+ _soundFreq = _stream->readSint16LE();
+ _soundSliceSize = _stream->readSint16LE();
+ _soundSlicesCount = _stream->readSint16LE();
+
+ if (_soundFreq < 0)
+ _soundFreq = -_soundFreq;
+
+ if (_soundSlicesCount < 0)
+ _soundSlicesCount = -_soundSlicesCount - 1;
+
+ if (_soundSlicesCount > 40) {
+ warning("IMDDecoder::assessAudioProperties(): More than 40 sound slices found (%d)", _soundSlicesCount);
+ return false;
+ }
+
+ _frameRate = Common::Rational(_soundFreq, _soundSliceSize);
+
+ _hasSound = true;
+ _soundEnabled = true;
+ _soundStage = kSoundLoaded;
+
+ _audioStream = Audio::makeQueuingAudioStream(_soundFreq, false);
+ }
+
+ return true;
+}
+
+bool IMDDecoder::loadFrameTables(uint32 framePosPos, uint32 frameCoordsPos) {
+ // Positions table
+ if (_framePos) {
+ _stream->seek(framePosPos);
+ for (uint32 i = 0; i < _frameCount; i++)
+ _framePos[i] = _stream->readUint32LE();
+ }
+
+ // Coordinates table
+ if (_features & kFeaturesFrameCoords) {
+ _stream->seek(frameCoordsPos);
+ _frameCoords = new Coord[_frameCount];
+ assert(_frameCoords);
+ for (uint32 i = 0; i < _frameCount; i++) {
+ _frameCoords[i].left = _stream->readSint16LE();
+ _frameCoords[i].top = _stream->readSint16LE();
+ _frameCoords[i].right = _stream->readSint16LE();
+ _frameCoords[i].bottom = _stream->readSint16LE();
+ }
+ }
+
+ return true;
+}
+
+void IMDDecoder::close() {
+ reset();
+
+ CoktelDecoder::close();
+
+ delete _stream;
+
+ delete[] _framePos;
+ delete[] _frameCoords;
+
+ delete[] _frameData;
+
+ delete[] _videoBuffer;
+
+ _stream = 0;
+
+ _version = 0;
+
+ _stdX = -1;
+ _stdY = -1;
+ _stdWidth = -1;
+ _stdHeight = -1;
+
+ _flags = 0;
+
+ _firstFramePos = 0;
+ _framePos = 0;
+ _frameCoords = 0;
+
+ _frameData = 0;
+ _frameDataSize = 0;
+ _frameDataLen = 0;
+
+ _videoBuffer = 0;
+ _videoBufferSize = 0;
+
+ _soundFlags = 0;
+ _soundFreq = 0;
+ _soundSliceSize = 0;
+ _soundSlicesCount = 0;
+
+ _hasSound = false;
+ _soundEnabled = false;
+ _soundStage = kSoundNone;
+}
+
+bool IMDDecoder::isVideoLoaded() const {
+ return _stream != 0;
+}
+
+Surface *IMDDecoder::decodeNextFrame() {
+ if (!isVideoLoaded() || endOfVideo())
+ return 0;
+
+ createSurface();
+
+ processFrame();
+
+ if (_curFrame == 0)
+ _startTime = g_system->getMillis();
+
+ return &_surface;
+}
+
+void IMDDecoder::processFrame() {
+ _curFrame++;
+
+ _dirtyRects.clear();
+
+ _paletteDirty = false;
+
+ uint32 cmd = 0;
+ bool hasNextCmd = false;
+ bool startSound = false;
+
+ do {
+ cmd = _stream->readUint16LE();
+
+ if ((cmd & kCommandBreakMask) == kCommandBreak) {
+ // Flow control
+
+ if (cmd == kCommandBreak) {
+ _stream->skip(2);
+ cmd = _stream->readUint16LE();
+ }
+
+ // Break
+ if (cmd == kCommandBreakSkip0) {
+ continue;
+ } else if (cmd == kCommandBreakSkip16) {
+ cmd = _stream->readUint16LE();
+ _stream->skip(cmd);
+ continue;
+ } else if (cmd == kCommandBreakSkip32) {
+ cmd = _stream->readUint32LE();
+ _stream->skip(cmd);
+ continue;
+ }
+ }
+
+ // Audio
+ if (cmd == kCommandNextSound) {
+
+ nextSoundSlice(hasNextCmd);
+ cmd = _stream->readUint16LE();
+
+ } else if (cmd == kCommandStartSound) {
+
+ startSound = initialSoundSlice(hasNextCmd);
+ cmd = _stream->readUint16LE();
+
+ } else
+ emptySoundSlice(hasNextCmd);
+
+ // Set palette
+ if (cmd == kCommandPalette) {
+ _stream->skip(2);
+
+ _paletteDirty = true;
+
+ for (int i = 0; i < 768; i++)
+ _palette[i] = _stream->readByte() << 2;
+
+ cmd = _stream->readUint16LE();
+ }
+
+ hasNextCmd = false;
+
+ if (cmd == kCommandJump) {
+ // Jump to frame
+
+ int16 frame = _stream->readSint16LE();
+ if (_framePos) {
+ _curFrame = frame - 1;
+ _stream->seek(_framePos[frame]);
+
+ hasNextCmd = true;
+ }
+
+ } else if (cmd == kCommandVideoData) {
+
+ _frameDataLen = _stream->readUint32LE() + 2;
+ _stream->read(_frameData, _frameDataLen);
+
+ Common::Rect rect = calcFrameCoords(_curFrame);
+
+ if (renderFrame(rect))
+ _dirtyRects.push_back(rect);
+
+ } else if (cmd != 0) {
+
+ _frameDataLen = cmd + 2;
+ _stream->read(_frameData, _frameDataLen);
+
+ Common::Rect rect = calcFrameCoords(_curFrame);
+
+ if (renderFrame(rect))
+ _dirtyRects.push_back(rect);
+
+ }
+
+ } while (hasNextCmd);
+
+ // Start the audio stream if necessary
+ if (startSound && _soundEnabled) {
+ _mixer->playStream(_soundType, &_audioHandle, _audioStream);
+ _soundStage = kSoundPlaying;
+ }
+
+ // End the audio stream if necessary
+ if ((_curFrame >= (int32)(_frameCount - 1)) && (_soundStage == kSoundPlaying)) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ _audioStream = 0;
+ _soundStage = kSoundNone;
+ }
+
+}
+
+Common::Rect IMDDecoder::calcFrameCoords(uint32 frame) {
+ Common::Rect rect;
+
+ if (frame == 0) {
+ // First frame is always a full "keyframe"
+
+ rect.left = _x;
+ rect.top = _y;
+ rect.right = _x + _width;
+ rect.bottom = _y + _height;
+ } else if (_frameCoords && ((_frameCoords[frame].left != -1))) {
+ // We have frame coordinates for that frame
+
+ rect.left = _frameCoords[frame].left;
+ rect.top = _frameCoords[frame].top;
+ rect.right = _frameCoords[frame].right + 1;
+ rect.bottom = _frameCoords[frame].bottom + 1;
+ } else if (_stdX != -1) {
+ // We have standard coordinates
+
+ rect.left = _stdX;
+ rect.top = _stdY;
+ rect.right = _stdX + _stdWidth;
+ rect.bottom = _stdY + _stdHeight;
+ } else {
+ // Otherwise, it must be a full "keyframe"
+
+ rect.left = _x;
+ rect.top = _y;
+ rect.right = _x + _width;
+ rect.bottom = _y + _height;
+ }
+
+ return rect;
+}
+
+bool IMDDecoder::renderFrame(Common::Rect &rect) {
+ if (!rect.isValidRect())
+ // Invalid rendering area
+ return false;
+
+ // Clip the rendering area to the video's visible area
+ rect.clip(Common::Rect(_x, _y, _x + _width, _y + _height));
+ if (!rect.isValidRect() || rect.isEmpty())
+ // Result is empty => nothing to do
+ return false;
+
+ byte *dataPtr = _frameData;
+
+ uint8 type = *dataPtr++;
+
+ if (type & 0x10) {
+ // Palette data
+
+ // One byte index
+ int index = *dataPtr++;
+
+ int count = MIN((255 - index) * 3, 48);
+ for (int i = 0; i < count; i++)
+ _palette[index * 3 + i] = dataPtr[i] << 2;
+
+ dataPtr += 48;
+ type ^= 0x10;
+
+ _paletteDirty = true;
+ }
+
+ if (type & 0x80) {
+ // Frame data is compressed
+
+ type &= 0x7F;
+
+ if ((type == 2) && (rect.width() == _surface.w) && (_x == 0)) {
+ // Directly uncompress onto the video surface
+ deLZ77((byte *)_surface.pixels + (_y * _surface.pitch), dataPtr);
+ return true;
+ }
+
+ deLZ77(_videoBuffer, dataPtr);
+
+ dataPtr = _videoBuffer;
+ }
+
+ // Evaluate the block type
+ if (type == 0x01)
+ renderBlockSparse (dataPtr, rect);
+ else if (type == 0x02)
+ renderBlockWhole (dataPtr, rect);
+ else if (type == 0x42)
+ renderBlockWhole4X (dataPtr, rect);
+ else if ((type & 0x0F) == 0x02)
+ renderBlockWhole2Y (dataPtr, rect);
+ else
+ renderBlockSparse2Y(dataPtr, rect);
+
+ return true;
+}
+
+void IMDDecoder::nextSoundSlice(bool hasNextCmd) {
+ if (hasNextCmd || !_soundEnabled) {
+ // Skip sound
+
+ _stream->skip(_soundSliceSize);
+ return;
+ }
+
+ // Read, convert, queue
+
+ byte *soundBuf = (byte *)malloc(_soundSliceSize);
+
+ _stream->read(soundBuf, _soundSliceSize);
+ unsignedToSigned(soundBuf, _soundSliceSize);
+
+ _audioStream->queueBuffer(soundBuf, _soundSliceSize, DisposeAfterUse::YES, 0);
+}
+
+bool IMDDecoder::initialSoundSlice(bool hasNextCmd) {
+ int dataLength = _soundSliceSize * _soundSlicesCount;
+
+ if (hasNextCmd || !_soundEnabled) {
+ // Skip sound
+
+ _stream->skip(dataLength);
+ return false;
+ }
+
+ // Read, convert, queue
+
+ byte *soundBuf = (byte *)malloc(dataLength);
+
+ _stream->read(soundBuf, dataLength);
+ unsignedToSigned(soundBuf, dataLength);
+
+ _audioStream->queueBuffer(soundBuf, dataLength, DisposeAfterUse::YES, 0);
+
+ return _soundStage == kSoundLoaded;
+}
+
+void IMDDecoder::emptySoundSlice(bool hasNextCmd) {
+ if (hasNextCmd || !_soundEnabled)
+ return;
+
+ // Create an empty sound buffer and queue it
+
+ byte *soundBuf = (byte *)malloc(_soundSliceSize);
+
+ memset(soundBuf, 0, _soundSliceSize);
+
+ _audioStream->queueBuffer(soundBuf, _soundSliceSize, DisposeAfterUse::YES, 0);
+}
+
+PixelFormat IMDDecoder::getPixelFormat() const {
+ return PixelFormat::createFormatCLUT8();
+}
+
+
+VMDDecoder::File::File() {
+ offset = 0;
+ size = 0;
+ realSize = 0;
+}
+
+
+VMDDecoder::Part::Part() {
+ type = kPartTypeSeparator;
+ field_1 = 0;
+ field_E = 0;
+ size = 0;
+ left = 0;
+ top = 0;
+ right = 0;
+ bottom = 0;
+ id = 0;
+ flags = 0;
+}
+
+
+VMDDecoder::Frame::Frame() {
+ parts = 0;
+ offset = 0;
+}
+
+VMDDecoder::Frame::~Frame() {
+ delete[] parts;
+}
+
+
+const uint16 VMDDecoder::_tableDPCM[128] = {
+ 0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080,
+ 0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120,
+ 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0,
+ 0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230,
+ 0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280,
+ 0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0,
+ 0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320,
+ 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370,
+ 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0,
+ 0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480,
+ 0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700,
+ 0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00,
+ 0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
+};
+
+const int32 VMDDecoder::_tableADPCM[] = {
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 16, 17, 19, 21, 23, 25, 28, 31,
+ 34, 37, 41, 45, 50, 55, 60, 66,
+ 73, 80, 88, 97, 107, 118, 130, 143,
+ 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658,
+ 724, 796, 876, 963, 1060, 1166, 1282, 1411,
+ 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
+ 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
+ 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
+ 32767, 0
+};
+
+const int32 VMDDecoder::_tableADPCMStep[] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+};
+
+VMDDecoder::VMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : CoktelDecoder(mixer, soundType),
+ _stream(0), _version(0), _flags(0), _frameInfoOffset(0), _partsPerFrame(0), _frames(0),
+ _soundFlags(0), _soundFreq(0), _soundSliceSize(0), _soundSlicesCount(0),
+ _soundBytesPerSample(0), _soundStereo(0), _soundHeaderSize(0), _soundDataSize(0),
+ _audioFormat(kAudioFormat8bitRaw), _hasVideo(false), _videoCodec(0),
+ _blitMode(0), _bytesPerPixel(0), _firstFramePos(0),
+ _frameData(0), _frameDataSize(0), _frameDataLen(0),
+ _videoBuffer(0), _videoBufferSize(0), _externalCodec(false), _codec(0),
+ _subtitle(-1) {
+
+}
+
+VMDDecoder::~VMDDecoder() {
+ close();
+}
+
+bool VMDDecoder::seek(int32 frame, int whence, bool restart) {
+ if (!evaluateSeekFrame(frame, whence))
+ return false;
+
+ if (frame == _curFrame)
+ // Nothing to do
+ return true;
+
+ // Restart sound
+ if (_hasSound && (frame == -1) && (_soundStage == kSoundNone) && !_audioStream) {
+ _soundStage = kSoundLoaded;
+ _audioStream = Audio::makeQueuingAudioStream(_soundFreq, _soundStereo != 0);
+ }
+
+ // Seek
+ _stream->seek(_frames[frame + 1].offset);
+ _curFrame = frame;
+
+ _subtitle = -1;
+
+ return true;
+}
+
+void VMDDecoder::setXY(uint16 x, uint16 y) {
+ for (uint32 i = 0; i < _frameCount; i++) {
+ for (int j = 0; j < _partsPerFrame; j++) {
+
+ if (_frames[i].parts[j].type == kPartTypeVideo) {
+ if (x != 0xFFFF) {
+ _frames[i].parts[j].left = _frames[i].parts[j].left - _x + x;
+ _frames[i].parts[j].right = _frames[i].parts[j].right - _x + x;
+ }
+ if (y != 0xFFFF) {
+ _frames[i].parts[j].top = _frames[i].parts[j].top - _y + y;
+ _frames[i].parts[j].bottom = _frames[i].parts[j].bottom - _y + y;
+ }
+ }
+
+ }
+ }
+
+ if (x != 0xFFFF)
+ _x = x;
+ if (y != 0xFFFF)
+ _y = y;
+}
+
+bool VMDDecoder::load(Common::SeekableReadStream *stream) {
+ close();
+
+ _stream = stream;
+
+ _stream->seek(0);
+
+ uint16 headerLength;
+ uint16 handle;
+
+ headerLength = _stream->readUint16LE();
+ handle = _stream->readUint16LE();
+ _version = _stream->readUint16LE();
+
+ // Version checking
+ if (headerLength == 50) {
+ // Newer version, used in Addy 5 upwards
+ warning("VMDDecoder::load(): TODO: Addy 5 videos");
+ } else if (headerLength == 814) {
+ // Old version
+ _features |= kFeaturesPalette;
+ } else {
+ warning("VMDDecoder::load(): Version incorrect (%d, %d, %d)", headerLength, handle, _version);
+ close();
+ return false;
+ }
+
+ _frameCount = _stream->readUint16LE();
+
+ _defaultX = _stream->readSint16LE();
+ _defaultY = _stream->readSint16LE();
+ _width = _stream->readSint16LE();
+ _height = _stream->readSint16LE();
+
+ _x = _defaultX;
+ _y = _defaultY;
+
+ if ((_width != 0) && (_height != 0)) {
+
+ _hasVideo = true;
+ _features |= kFeaturesVideo;
+
+ } else
+ _hasVideo = false;
+
+ _bytesPerPixel = 1;
+ if (_version & 4)
+ _bytesPerPixel = handle + 1;
+
+ if (_bytesPerPixel != 1) {
+ warning("TODO: _bytesPerPixel = %d", _bytesPerPixel);
+ close();
+ return false;
+ }
+
+ if (_bytesPerPixel > 3) {
+ warning("VMDDecoder::load(): Requested %d bytes per pixel (%d, %d, %d)",
+ _bytesPerPixel, headerLength, handle, _version);
+ close();
+ return false;
+ }
+
+ _flags = _stream->readUint16LE();
+
+ _partsPerFrame = _stream->readUint16LE();
+ _firstFramePos = _stream->readUint32LE();
+
+ _videoCodec = _stream->readUint32BE();
+
+ if (_features & kFeaturesPalette) {
+ for (int i = 0; i < 768; i++)
+ _palette[i] = _stream->readByte() << 2;
+
+ _paletteDirty = true;
+ }
+
+ _frameDataSize = _stream->readUint32LE();
+ _videoBufferSize = _stream->readUint32LE();
+
+ if (_hasVideo) {
+ if (!assessVideoProperties()) {
+ close();
+ return false;
+ }
+ }
+
+ _soundFreq = _stream->readSint16LE();
+ _soundSliceSize = _stream->readSint16LE();
+ _soundSlicesCount = _stream->readSint16LE();
+ _soundFlags = _stream->readUint16LE();
+
+ _hasSound = (_soundFreq != 0);
+
+ if (_hasSound) {
+ if (!assessAudioProperties()) {
+ close();
+ return false;
+ }
+ } else
+ _frameRate = 12;
+
+ _frameInfoOffset = _stream->readUint32LE();
+
+ int numFiles;
+ if (!readFrameTable(numFiles)) {
+ close();
+ return false;
+ }
+
+ _stream->seek(_firstFramePos);
+
+ if (numFiles == 0)
+ return true;
+
+ _files.reserve(numFiles);
+ if (!readFiles()) {
+ close();
+ return false;
+ }
+
+ _stream->seek(_firstFramePos);
+ return true;
+}
+
+bool VMDDecoder::assessVideoProperties() {
+ if ((_version & 2) && !(_version & 8)) {
+ _externalCodec = true;
+ _frameDataSize = _videoBufferSize = 0;
+ } else
+ _externalCodec = false;
+
+ if (_externalCodec) {
+ if (_videoCodec == kVideoCodecIndeo3) {
+#ifdef USE_INDEO3
+ _codec = new Indeo3Decoder(_width, _height);
+#else
+ warning("VMDDecoder::assessVideoProperties(): Indeo3 decoder not compiled in");
+#endif
+ } else {
+ warning("VMDDecoder::assessVideoProperties(): Unknown video codec FourCC \"%s\"",
+ tag2str(_videoCodec));
+ return false;
+ }
+ }
+
+ if (_externalCodec)
+ _blitMode = 0;
+ else if (_bytesPerPixel == 1)
+ _blitMode = 0;
+ else if ((_bytesPerPixel == 2) || (_bytesPerPixel == 3)) {
+ int n = (_flags & 0x80) ? 2 : 3;
+
+ _blitMode = n - 1;
+ _bytesPerPixel = n;
+ }
+
+ if (_hasVideo) {
+ if ((_frameDataSize == 0) || (_frameDataSize > 1048576))
+ _frameDataSize = _width * _height + 1000;
+ if ((_videoBufferSize == 0) || (_videoBufferSize > 1048576))
+ _videoBufferSize = _frameDataSize;
+
+ _frameData = new byte[_frameDataSize];
+ memset(_frameData, 0, _frameDataSize);
+
+ _videoBuffer = new byte[_videoBufferSize];
+ memset(_videoBuffer, 0, _videoBufferSize);
+ }
+
+ return true;
+}
+
+bool VMDDecoder::assessAudioProperties() {
+ bool supportedFormat = true;
+
+ _features |= kFeaturesSound;
+
+ _soundStereo = (_soundFlags & 0x8000) ? 1 : ((_soundFlags & 0x200) ? 2 : 0);
+
+ if (_soundSliceSize < 0) {
+ _soundBytesPerSample = 2;
+ _soundSliceSize = -_soundSliceSize;
+
+ if (_soundFlags & 0x10) {
+ _audioFormat = kAudioFormat16bitADPCM;
+ _soundHeaderSize = 3;
+ _soundDataSize = _soundSliceSize >> 1;
+
+ if (_soundStereo > 0)
+ supportedFormat = false;
+
+ } else {
+ _audioFormat = kAudioFormat16bitDPCM;
+ _soundHeaderSize = 1;
+ _soundDataSize = _soundSliceSize;
+
+ if (_soundStereo == 1) {
+ supportedFormat = false;
+ } else if (_soundStereo == 2) {
+ _soundDataSize = 2 * _soundDataSize + 2;
+ _soundHeaderSize = 4;
+ }
+
+ }
+ } else {
+ _soundBytesPerSample = 1;
+ _audioFormat = kAudioFormat8bitRaw;
+ _soundHeaderSize = 0;
+ _soundDataSize = _soundSliceSize;
+
+ if (_soundStereo > 0)
+ supportedFormat = false;
+ }
+
+ if (!supportedFormat) {
+ warning("VMDDecoder::assessAudioProperties(): Unsupported audio format: %d bits, encoding %d, stereo %d",
+ _soundBytesPerSample * 8, _audioFormat, _soundStereo);
+ return false;
+ }
+
+ _frameRate = Common::Rational(_soundFreq, _soundSliceSize);
+
+ _hasSound = true;
+ _soundEnabled = true;
+ _soundStage = kSoundLoaded;
+
+ _audioStream = Audio::makeQueuingAudioStream(_soundFreq, _soundStereo != 0);
+
+ return true;
+}
+
+bool VMDDecoder::readFrameTable(int &numFiles) {
+ numFiles = 0;
+
+ _stream->seek(_frameInfoOffset);
+ _frames = new Frame[_frameCount];
+ for (uint16 i = 0; i < _frameCount; i++) {
+ _frames[i].parts = new Part[_partsPerFrame];
+ _stream->skip(2); // Unknown
+ _frames[i].offset = _stream->readUint32LE();
+ }
+
+ for (uint16 i = 0; i < _frameCount; i++) {
+ bool separator = false;
+
+ for (uint16 j = 0; j < _partsPerFrame; j++) {
+
+ _frames[i].parts[j].type = (PartType) _stream->readByte();
+ _frames[i].parts[j].field_1 = _stream->readByte();
+ _frames[i].parts[j].size = _stream->readUint32LE();
+
+ if (_frames[i].parts[j].type == kPartTypeAudio) {
+
+ _frames[i].parts[j].flags = _stream->readByte();
+ _stream->skip(9); // Unknown
+
+ } else if (_frames[i].parts[j].type == kPartTypeVideo) {
+
+ _frames[i].parts[j].left = _stream->readUint16LE();
+ _frames[i].parts[j].top = _stream->readUint16LE();
+ _frames[i].parts[j].right = _stream->readUint16LE();
+ _frames[i].parts[j].bottom = _stream->readUint16LE();
+ _frames[i].parts[j].field_E = _stream->readByte();
+ _frames[i].parts[j].flags = _stream->readByte();
+
+ } else if (_frames[i].parts[j].type == kPartTypeSubtitle) {
+ _frames[i].parts[j].id = _stream->readUint16LE();
+ // Speech text file name
+ _stream->skip(8);
+ } else if (_frames[i].parts[j].type == kPartTypeFile) {
+ if (!separator)
+ numFiles++;
+ _stream->skip(10);
+ } else if (_frames[i].parts[j].type == kPartTypeSeparator) {
+ separator = true;
+ _stream->skip(10);
+ } else {
+ // Unknown type
+ _stream->skip(10);
+ }
+
+ }
+ }
+
+ return true;
+}
+
+bool VMDDecoder::readFiles() {
+ uint32 ssize = _stream->size();
+ for (uint16 i = 0; i < _frameCount; i++) {
+ _stream->seek(_frames[i].offset);
+
+ for (uint16 j = 0; j < _partsPerFrame; j++) {
+ if (_frames[i].parts[j].type == kPartTypeSeparator)
+ break;
+
+ if (_frames[i].parts[j].type == kPartTypeFile) {
+ File file;;
+
+ file.offset = _stream->pos() + 20;
+ file.size = _frames[i].parts[j].size;
+ file.realSize = _stream->readUint32LE();
+
+ char name[16];
+
+ _stream->read(name, 16);
+ name[15] = '\0';
+
+ file.name = name;
+
+ _stream->skip(_frames[i].parts[j].size - 20);
+
+ if ((((uint32) file.realSize) >= ssize) || (file.name == ""))
+ continue;
+
+ _files.push_back(file);
+
+ } else
+ _stream->skip(_frames[i].parts[j].size);
+ }
+ }
+
+ return true;
+}
+
+void VMDDecoder::close() {
+ reset();
+
+ CoktelDecoder::close();
+
+ delete _stream;
+
+ delete[] _frames;
+
+ delete[] _frameData;
+ delete[] _videoBuffer;
+
+ delete _codec;
+
+ _files.clear();
+
+
+ _stream = 0;
+
+ _version = 0;
+ _flags = 0;
+
+ _frameInfoOffset = 0;
+ _partsPerFrame = 0;
+ _frames = 0;
+
+ _soundFlags = 0;
+ _soundFreq = 0;
+ _soundSliceSize = 0;
+ _soundSlicesCount = 0;
+ _soundBytesPerSample = 0;
+ _soundStereo = 0;
+ _soundHeaderSize = 0;
+ _soundDataSize = 0;
+ _audioFormat = kAudioFormat8bitRaw;
+
+ _hasVideo = false;
+ _videoCodec = 0;
+ _blitMode = 0;
+ _bytesPerPixel = 0;
+
+ _firstFramePos = 0;
+
+ _frameData = 0;
+ _frameDataSize = 0;
+ _frameDataLen = 0;
+
+ _videoBuffer = 0;
+ _videoBufferSize = 0;
+
+ _externalCodec = false;
+ _codec = 0;
+}
+
+bool VMDDecoder::isVideoLoaded() const {
+ return _stream != 0;
+}
+
+Surface *VMDDecoder::decodeNextFrame() {
+ if (!isVideoLoaded() || endOfVideo())
+ return 0;
+
+ createSurface();
+
+ processFrame();
+
+ if (_curFrame == 0)
+ _startTime = g_system->getMillis();
+
+ return &_surface;
+}
+
+void VMDDecoder::processFrame() {
+ _curFrame++;
+
+ _dirtyRects.clear();
+
+ _paletteDirty = false;
+ _subtitle = -1;
+
+ bool startSound = false;
+
+ for (uint16 i = 0; i < _partsPerFrame; i++) {
+ uint32 pos = _stream->pos();
+
+ Part &part = _frames[_curFrame].parts[i];
+
+ if (part.type == kPartTypeAudio) {
+
+ if (part.flags == 1) {
+ // Next sound slice data
+
+ if (_soundEnabled) {
+ filledSoundSlice(part.size);
+
+ if (_soundStage == kSoundLoaded)
+ startSound = true;
+
+ } else
+ _stream->skip(part.size);
+
+ } else if (part.flags == 2) {
+ // Initial sound data (all slices)
+
+ if (_soundEnabled) {
+ uint32 mask = _stream->readUint32LE();
+ filledSoundSlices(part.size - 4, mask);
+
+ if (_soundStage == kSoundLoaded)
+ startSound = true;
+
+ } else
+ _stream->skip(part.size);
+
+ } else if (part.flags == 3) {
+ // Empty sound slice
+
+ if (_soundEnabled) {
+ emptySoundSlice(_soundDataSize * _soundBytesPerSample);
+
+ if (_soundStage == kSoundLoaded)
+ startSound = true;
+ }
+
+ _stream->skip(part.size);
+ } else if (part.flags == 4) {
+ warning("VMDDecoder::processFrame(): TODO: Addy 5 sound type 4 (%d)", part.size);
+ disableSound();
+ _stream->skip(part.size);
+ } else {
+ warning("VMDDecoder::processFrame(): Unknown sound type %d", part.flags);
+ _stream->skip(part.size);
+ }
+
+ _stream->seek(pos + part.size);
+
+ } else if ((part.type == kPartTypeVideo) && !_hasVideo) {
+
+ warning("VMDDecoder::processFrame(): Header claims there's no video, but video found (%d)", part.size);
+ _stream->skip(part.size);
+
+ } else if ((part.type == kPartTypeVideo) && _hasVideo) {
+
+ uint32 size = part.size;
+
+ // New palette
+ if (part.flags & 2) {
+ uint8 index = _stream->readByte();
+ uint8 count = _stream->readByte();
+
+ for (int j = 0; j < ((count + 1) * 3); j++)
+ _palette[index * 3 + j] = _stream->readByte() << 2;
+
+ _stream->skip((255 - count) * 3);
+
+ _paletteDirty = true;
+
+ size -= (768 + 2);
+ }
+
+ _stream->read(_frameData, size);
+ _frameDataLen = size;
+
+ Common::Rect rect(part.left, part.top, part.right + 1, part.bottom + 1);
+ if (renderFrame(rect))
+ _dirtyRects.push_back(rect);
+
+ } else if (part.type == kPartTypeSeparator) {
+
+ // Ignore
+
+ } else if (part.type == kPartTypeFile) {
+
+ // Ignore
+ _stream->skip(part.size);
+
+ } else if (part.type == kPartType4) {
+
+ // Unknown, ignore
+ _stream->skip(part.size);
+
+ } else if (part.type == kPartTypeSubtitle) {
+
+ _subtitle = part.id;
+ _stream->skip(part.size);
+
+ } else {
+
+ warning("VMDDecoder::processFrame(): Unknown frame part type %d, size %d (%d of %d)",
+ part.type, part.size, i + 1, _partsPerFrame);
+
+ }
+ }
+
+ if (startSound && _soundEnabled) {
+ if (_hasSound && _audioStream) {
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_audioHandle, _audioStream);
+ _soundStage = kSoundPlaying;
+ } else
+ _soundStage = kSoundNone;
+ }
+
+ if (((uint32)_curFrame == (_frameCount - 1)) && (_soundStage == 2)) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ _audioStream = 0;
+ _soundStage = kSoundNone;
+ }
+}
+
+bool VMDDecoder::renderFrame(Common::Rect &rect) {
+ if (!rect.isValidRect())
+ // Invalid rendering area
+ return false;
+
+ // Clip the rendering area to the video's visible area
+ rect.clip(Common::Rect(_x, _y, _x + _width, _y + _height));
+ if (!rect.isValidRect() || rect.isEmpty())
+ // Result is empty => nothing to do
+ return false;
+
+ if (_externalCodec) {
+ // TODO
+ warning("_external codec");
+ return false;
+ }
+
+ if (_blitMode > 0) {
+ // TODO
+ warning("_blitMode == %d", _blitMode);
+ return false;
+ }
+
+ byte *dataPtr = _frameData;
+
+ uint8 type = *dataPtr++;
+
+ if (type & 0x80) {
+ // Frame data is compressed
+
+ type &= 0x7F;
+
+ if ((type == 2) && (rect.width() == _surface.w) && (_x == 0)) {
+ // Directly uncompress onto the video surface
+ deLZ77((byte *)_surface.pixels + (_y * _surface.pitch), dataPtr);
+ return true;
+ }
+
+ deLZ77(_videoBuffer, dataPtr);
+
+ dataPtr = _videoBuffer;
+ }
+
+ // Evaluate the block type
+ if (type == 0x01)
+ renderBlockSparse (dataPtr, rect);
+ else if (type == 0x02)
+ renderBlockWhole (dataPtr, rect);
+ else if (type == 0x03)
+ renderBlockRLE (dataPtr, rect);
+ else if (type == 0x42)
+ renderBlockWhole4X (dataPtr, rect);
+ else if ((type & 0x0F) == 0x02)
+ renderBlockWhole2Y (dataPtr, rect);
+ else
+ renderBlockSparse2Y(dataPtr, rect);
+
+ return true;
+}
+
+void VMDDecoder::emptySoundSlice(uint32 size) {
+ byte *sound = soundEmpty(size);
+
+ if (sound) {
+ uint32 flags = 0;
+ flags |= (_soundBytesPerSample == 2) ? Audio::FLAG_16BITS : 0;
+ flags |= (_soundStereo > 0) ? Audio::FLAG_STEREO : 0;
+
+ _audioStream->queueBuffer(sound, size, DisposeAfterUse::YES, flags);
+ }
+}
+
+void VMDDecoder::filledSoundSlice(uint32 size) {
+ byte *sound = 0;
+ if (_audioFormat == kAudioFormat8bitRaw)
+ sound = sound8bitRaw(size);
+ else if (_audioFormat == kAudioFormat16bitDPCM)
+ sound = sound16bitDPCM(size);
+ else if (_audioFormat == kAudioFormat16bitADPCM)
+ sound = sound16bitADPCM(size);
+
+ if (sound) {
+ uint32 flags = 0;
+ flags |= (_soundBytesPerSample == 2) ? Audio::FLAG_16BITS : 0;
+ flags |= (_soundStereo > 0) ? Audio::FLAG_STEREO : 0;
+
+ _audioStream->queueBuffer(sound, size, DisposeAfterUse::YES, flags);
+ }
+}
+
+void VMDDecoder::filledSoundSlices(uint32 size, uint32 mask) {
+ bool fillInfo[32];
+
+ uint8 max;
+ uint8 n = evaluateMask(mask, fillInfo, max);
+
+ int32 extraSize;
+
+ extraSize = size - n * _soundDataSize;
+
+ if (_soundSlicesCount > 32)
+ extraSize -= (_soundSlicesCount - 32) * _soundDataSize;
+
+ if (n > 0)
+ extraSize /= n;
+
+ for (uint8 i = 0; i < max; i++)
+ if (fillInfo[i])
+ filledSoundSlice(_soundDataSize + extraSize);
+ else
+ emptySoundSlice(_soundDataSize * _soundBytesPerSample);
+
+ if (_soundSlicesCount > 32)
+ filledSoundSlice((_soundSlicesCount - 32) * _soundDataSize + _soundHeaderSize);
+}
+
+uint8 VMDDecoder::evaluateMask(uint32 mask, bool *fillInfo, uint8 &max) {
+ max = MIN<int>(_soundSlicesCount - 1, 31);
+
+ uint8 n = 0;
+ for (int i = 0; i < max; i++) {
+
+ if (!(mask & 1)) {
+ n++;
+ *fillInfo++ = true;
+ } else
+ *fillInfo++ = false;
+
+ mask >>= 1;
+ }
+
+ return n;
+}
+
+byte *VMDDecoder::soundEmpty(uint32 &size) {
+ if (!_audioStream)
+ return 0;
+
+ byte *soundBuf = (byte *)malloc(size);
+ memset(soundBuf, 0, size);
+
+ return soundBuf;
+}
+
+byte *VMDDecoder::sound8bitRaw(uint32 &size) {
+ if (!_audioStream) {
+ _stream->skip(size);
+ return 0;
+ }
+
+ byte *soundBuf = (byte *)malloc(size);
+ _stream->read(soundBuf, size);
+ unsignedToSigned(soundBuf, size);
+
+ return soundBuf;
+}
+
+byte *VMDDecoder::sound16bitDPCM(uint32 &size) {
+ if (!_audioStream) {
+ _stream->skip(size);
+ return 0;
+ }
+
+ int32 init[2];
+
+ init[0] = _stream->readSint16LE();
+ size -= 2;
+
+ if (_soundStereo > 0) {
+ init[1] = _stream->readSint16LE();
+ size -= 2;
+ }
+
+ byte *data = new byte[size];
+ byte *sound = 0;
+
+ if (_stream->read(data, size) == size)
+ sound = deDPCM(data, size, init);
+
+ delete[] data;
+
+ return sound;
+}
+
+byte *VMDDecoder::sound16bitADPCM(uint32 &size) {
+ if (!_audioStream) {
+ _stream->skip(size);
+ return 0;
+ }
+
+ int32 init = _stream->readSint16LE();
+ size -= 2;
+
+ int32 index = _stream->readByte();
+ size--;
+
+ byte *data = new byte[size];
+ byte *sound = 0;
+
+ if (_stream->read(data, size) == size)
+ sound = deADPCM(data, size, init, index);
+
+ delete[] data;
+
+ return sound;
+}
+
+byte *VMDDecoder::deDPCM(const byte *data, uint32 &size, int32 init[2]) {
+ if (!data || (size == 0))
+ return 0;
+
+ int channels = (_soundStereo > 0) ? 2 : 1;
+
+ uint32 inSize = size;
+ uint32 outSize = size + channels;
+
+ int16 *out = (int16 *)malloc(outSize * 2);
+ byte *sound = (byte *) out;
+
+ int channel = 0;
+
+ for (int i = 0; i < channels; i++) {
+ *out++ = TO_BE_16(init[channel]);
+
+ channel = (channel + 1) % channels;
+ }
+
+ while (inSize-- > 0) {
+ if (*data & 0x80)
+ init[channel] -= _tableDPCM[*data++ & 0x7F];
+ else
+ init[channel] += _tableDPCM[*data++];
+
+ init[channel] = CLIP<int32>(init[channel], -32768, 32767);
+ *out++ = TO_BE_16(init[channel]);
+
+ channel = (channel + 1) % channels;
+ }
+
+ size = outSize * 2;
+ return sound;
+}
+
+// Yet another IMA ADPCM variant
+byte *VMDDecoder::deADPCM(const byte *data, uint32 &size, int32 init, int32 index) {
+ if (!data || (size == 0))
+ return 0;
+
+ uint32 outSize = size * 2;
+
+ int16 *out = (int16 *)malloc(outSize * 2);
+ byte *sound = (byte *) out;
+
+ index = CLIP<int32>(index, 0, 88);
+
+ int32 predictor = _tableADPCM[index];
+
+ uint32 dataByte = 0;
+ bool newByte = true;
+
+ size *= 2;
+ while (size -- > 0) {
+ byte code = 0;
+
+ if (newByte) {
+ dataByte = *data++;
+ code = (dataByte >> 4) & 0xF;
+ } else
+ code = dataByte & 0xF;
+
+ newByte = !newByte;
+
+ index += _tableADPCMStep[code];
+ index = CLIP<int32>(index, 0, 88);
+
+ int32 value = predictor / 8;
+
+ if (code & 4)
+ value += predictor;
+ if (code & 2)
+ value += predictor / 2;
+ if (code & 1)
+ value += predictor / 4;
+
+ if (code & 8)
+ init -= value;
+ else
+ init += value;
+
+ init = CLIP<int32>(init, -32768, 32767);
+
+ predictor = _tableADPCM[index];
+
+ *out++ = TO_BE_16(init);
+ }
+
+ size = outSize * 2;
+ return sound;
+}
+
+PixelFormat VMDDecoder::getPixelFormat() const {
+ return PixelFormat::createFormatCLUT8();
+}
+
+bool VMDDecoder::getPartCoords(int16 frame, PartType type, int16 &x, int16 &y, int16 &width, int16 &height) {
+ if (frame >= ((int32) _frameCount))
+ return false;
+
+ Frame &f = _frames[frame];
+
+ // Look for a part matching the requested type, stopping at a separator
+ Part *part = 0;
+ for (int i = 0; i < _partsPerFrame; i++) {
+ Part &p = f.parts[i];
+
+ if ((p.type == kPartTypeSeparator) || (p.type == type)) {
+ part = &p;
+ break;
+ }
+ }
+
+ if (!part)
+ return false;
+
+ x = part->left;
+ y = part->top;
+ width = part->right - part->left + 1;
+ height = part->bottom - part->top + 1;
+
+ return true;
+}
+
+bool VMDDecoder::getFrameCoords(int16 frame, int16 &x, int16 &y, int16 &width, int16 &height) {
+ return getPartCoords(frame, kPartTypeVideo, x, y, width, height);
+}
+
+bool VMDDecoder::hasEmbeddedFiles() const {
+ return !_files.empty();
+}
+
+bool VMDDecoder::hasEmbeddedFile(const Common::String &fileName) const {
+ for (Common::Array<File>::const_iterator file = _files.begin(); file != _files.end(); ++file)
+ if (!file->name.compareToIgnoreCase(fileName))
+ return true;
+
+ return false;
+}
+
+Common::MemoryReadStream *VMDDecoder::getEmbeddedFile(const Common::String &fileName) const {
+ const File *file = 0;
+
+ for (Common::Array<File>::const_iterator it = _files.begin(); it != _files.end(); ++it)
+ if (!it->name.compareToIgnoreCase(fileName)) {
+ file = &*it;
+ break;
+ }
+
+ if (!file)
+ return 0;
+
+ if ((file->size - 20) != file->realSize) {
+ warning("VMDDecoder::getEmbeddedFile(): Sizes for \"%s\" differ! (%d, %d)",
+ fileName.c_str(), (file->size - 20), file->realSize);
+ return 0;
+ }
+
+ if (!_stream->seek(file->offset)) {
+ warning("VMDDecoder::getEmbeddedFile(): Can't seek to offset %d to (file \"%s\")",
+ file->offset, fileName.c_str());
+ return 0;
+ }
+
+ byte *data = (byte *) malloc(file->realSize);
+ if (_stream->read(data, file->realSize) != file->realSize) {
+ free(data);
+ warning("VMDDecoder::getEmbeddedFile(): Couldn't read %d bytes (file \"%s\")",
+ file->realSize, fileName.c_str());
+ }
+
+ Common::MemoryReadStream *stream =
+ new Common::MemoryReadStream(data, file->realSize, DisposeAfterUse::YES);
+
+ return stream;
+}
+
+int32 VMDDecoder::getSubtitleIndex() const {
+ return _subtitle;
+}
+
+} // End of namespace Graphics
+
+#endif // GRAPHICS_VIDEO_COKTELDECODER_H
diff --git a/graphics/video/coktel_decoder.h b/graphics/video/coktel_decoder.h
new file mode 100644
index 0000000000..97be9df44b
--- /dev/null
+++ b/graphics/video/coktel_decoder.h
@@ -0,0 +1,505 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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$
+ *
+ */
+
+// Currently, only GOB and SCI32 games play IMDs and VMDs, so skip compiling if GOB and SCI32 is disabled.
+#if !(defined(ENABLE_GOB) || defined(ENABLE_SCI32) || defined(DYNAMIC_MODULES))
+
+// Do not compile the CoktelDecoder code
+
+#else
+
+#ifndef GRAPHICS_VIDEO_COKTELDECODER_H
+#define GRAPHICS_VIDEO_COKTELDECODER_H
+
+#include "common/list.h"
+#include "common/array.h"
+#include "common/rect.h"
+
+#include "graphics/video/video_decoder.h"
+
+#include "sound/mixer.h"
+
+namespace Audio {
+ class QueuingAudioStream;
+}
+
+namespace Graphics {
+
+class Codec;
+
+class CoktelDecoder : public FixedRateVideoDecoder {
+public:
+ struct State {
+ /** Set accordingly to what was done. */
+ uint32 flags;
+ /** The id of the spoken words. */
+ uint16 speechId;
+
+ State();
+ };
+
+ CoktelDecoder(Audio::Mixer *mixer,
+ Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
+ ~CoktelDecoder();
+
+ virtual bool seek(int32 frame, int whence = SEEK_SET, bool restart = false) = 0;
+
+ /** Draw directly onto the specified video memory. */
+ void setSurfaceMemory(void *mem, uint16 width, uint16 height, uint8 bpp);
+ /** Reset the video memory. */
+ void setSurfaceMemory();
+
+ const Surface *getSurface() const;
+
+ /** Draw the video starting at this position within the video memory. */
+ virtual void setXY(uint16 x, uint16 y);
+ /** Draw the video at the default position. */
+ void setXY();
+
+ /** Override the video's frame rate. */
+ void setFrameRate(Common::Rational frameRate);
+
+ /** Get the video's default X position. */
+ uint16 getDefaultX() const;
+ /** Get the video's default Y position. */
+ uint16 getDefaultY() const;
+
+ /** Return a list of rectangles that changed in the last frame. */
+ const Common::List<Common::Rect> &getDirtyRects() const;
+
+ bool hasPalette() const;
+
+ bool hasSound() const;
+ bool isSoundEnabled() const;
+ bool isSoundPlaying() const;
+
+ void enableSound();
+ void disableSound();
+
+ /** Return the coordinates of the specified frame. */
+ virtual bool getFrameCoords(int16 frame, int16 &x, int16 &y, int16 &width, int16 &height);
+
+ /** Return whether that video has any embedded files. */
+ virtual bool hasEmbeddedFiles() const;
+
+ /** Return whether that embedded file exists. */
+ virtual bool hasEmbeddedFile(const Common::String &fileName) const;
+
+ /** Return that embedded file. */
+ virtual Common::MemoryReadStream *getEmbeddedFile(const Common::String &fileName) const;
+
+ /** Return the current subtitle index. */
+ virtual int32 getSubtitleIndex() const;
+
+
+ // VideoDecoder interface
+
+ void close();
+
+ uint16 getWidth() const;
+ uint16 getHeight() const;
+
+ uint32 getFrameCount() const;
+
+ byte *getPalette();
+ bool hasDirtyPalette() const;
+
+
+ // FixedRateVideoDecoder interface
+
+ uint32 getTimeToNextFrame() const;
+
+protected:
+ enum SoundStage {
+ kSoundNone = 0, ///< No sound.
+ kSoundLoaded = 1, ///< Sound loaded.
+ kSoundPlaying = 2 ///< Sound is playing.
+ };
+
+ enum Features {
+ kFeaturesNone = 0x0000,
+ kFeaturesPalette = 0x0008, ///< Has an own palette.
+ kFeaturesDataSize = 0x0020, ///< Suggests a data size.
+ kFeaturesSound = 0x0040, ///< Has sound.
+ kFeaturesFrameCoords = 0x0080, ///< Has specific frame coordinates.
+ kFeaturesStdCoords = 0x0100, ///< Has general standard coordinates.
+ kFeaturesFramePos = 0x0200, ///< Has a frame positions table.
+ kFeaturesVideo = 0x0400 ///< Has video.
+ };
+
+ Audio::Mixer *_mixer;
+ Audio::Mixer::SoundType _soundType;
+
+ uint16 _width;
+ uint16 _height;
+
+ uint16 _x;
+ uint16 _y;
+
+ uint16 _defaultX;
+ uint16 _defaultY;
+
+ uint32 _features;
+
+ uint32 _frameCount;
+
+ byte _palette[768];
+ bool _paletteDirty;
+
+ bool _ownSurface;
+ Surface _surface;
+
+ Common::List<Common::Rect> _dirtyRects;
+
+ Common::Rational _frameRate;
+
+ // Current sound state
+ bool _hasSound;
+ bool _soundEnabled;
+ SoundStage _soundStage;
+
+ Audio::QueuingAudioStream *_audioStream;
+ Audio::SoundHandle _audioHandle;
+
+ bool evaluateSeekFrame(int32 &frame, int whence) const;
+
+ // Surface management
+ bool hasSurface();
+ void createSurface();
+ void freeSurface();
+
+ // Decompression
+ void deLZ77(byte *dest, byte *src);
+ void deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen);
+
+ // Block rendering
+ void renderBlockWhole (const byte *src, Common::Rect &rect);
+ void renderBlockWhole4X (const byte *src, Common::Rect &rect);
+ void renderBlockWhole2Y (const byte *src, Common::Rect &rect);
+ void renderBlockSparse (const byte *src, Common::Rect &rect);
+ void renderBlockSparse2Y(const byte *src, Common::Rect &rect);
+ void renderBlockRLE (const byte *src, Common::Rect &rect);
+
+ // Sound helper functions
+ inline void unsignedToSigned(byte *buffer, int length);
+
+
+ // FixedRateVideoDecoder interface
+
+ Common::Rational getFrameRate() const;
+};
+
+class PreIMDDecoder : public CoktelDecoder {
+public:
+ PreIMDDecoder(uint16 width, uint16 height, Audio::Mixer *mixer,
+ Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
+ ~PreIMDDecoder();
+
+ bool seek(int32 frame, int whence = SEEK_SET, bool restart = false);
+
+
+ // VideoDecoder interface
+
+ bool load(Common::SeekableReadStream *stream);
+ void close();
+
+ bool isVideoLoaded() const;
+
+ Surface *decodeNextFrame();
+
+ PixelFormat getPixelFormat() const;
+
+private:
+ Common::SeekableReadStream *_stream;
+
+ // Buffer for processed frame data
+ byte *_videoBuffer;
+ uint32 _videoBufferSize;
+
+ // Frame decoding
+ void processFrame();
+ void renderFrame();
+};
+
+class IMDDecoder : public CoktelDecoder {
+public:
+ IMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
+ ~IMDDecoder();
+
+ bool seek(int32 frame, int whence = SEEK_SET, bool restart = false);
+
+ void setXY(uint16 x, uint16 y);
+
+
+ // VideoDecoder interface
+
+ bool load(Common::SeekableReadStream *stream);
+ void close();
+
+ bool isVideoLoaded() const;
+
+ Surface *decodeNextFrame();
+
+ PixelFormat getPixelFormat() const;
+
+private:
+ enum Command {
+ kCommandNextSound = 0xFF00,
+ kCommandStartSound = 0xFF01,
+
+ kCommandBreak = 0xFFF0,
+ kCommandBreakSkip0 = 0xFFF1,
+ kCommandBreakSkip16 = 0xFFF2,
+ kCommandBreakSkip32 = 0xFFF3,
+ kCommandBreakMask = 0xFFF8,
+
+ kCommandPalette = 0xFFF4,
+ kCommandVideoData = 0xFFFC,
+
+ kCommandJump = 0xFFFD
+ };
+
+ struct Coord {
+ int16 left;
+ int16 top;
+ int16 right;
+ int16 bottom;
+ };
+
+ Common::SeekableReadStream *_stream;
+
+ byte _version;
+
+ // Standard coordinates gives by the header
+ int16 _stdX;
+ int16 _stdY;
+ int16 _stdWidth;
+ int16 _stdHeight;
+
+ uint32 _flags;
+
+ uint32 _firstFramePos; ///< Position of the first frame's data within the stream.
+ uint32 *_framePos; ///< Positions of all frames.
+ Coord *_frameCoords; ///< Coordinates of all frames.
+
+ // Buffer for raw frame data
+ byte *_frameData;
+ uint32 _frameDataSize;
+ uint32 _frameDataLen;
+
+ // Buffer for processed frame data
+ byte *_videoBuffer;
+ uint32 _videoBufferSize;
+
+ // Sound properties
+ uint16 _soundFlags;
+ int16 _soundFreq;
+ int16 _soundSliceSize;
+ int16 _soundSlicesCount;
+
+ // Loading helper functions
+ bool loadCoordinates();
+ bool loadFrameTableOffsets(uint32 &framePosPos, uint32 &frameCoordsPos);
+ bool assessVideoProperties();
+ bool assessAudioProperties();
+ bool loadFrameTables(uint32 framePosPos, uint32 frameCoordsPos);
+
+ // Frame decoding
+ void processFrame();
+ Common::Rect calcFrameCoords(uint32 frame);
+
+ // Video
+ bool renderFrame(Common::Rect &rect);
+
+ // Sound
+ void nextSoundSlice(bool hasNextCmd);
+ bool initialSoundSlice(bool hasNextCmd);
+ void emptySoundSlice(bool hasNextCmd);
+};
+
+class VMDDecoder : public CoktelDecoder {
+public:
+ VMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
+ ~VMDDecoder();
+
+ bool seek(int32 frame, int whence = SEEK_SET, bool restart = false);
+
+ void setXY(uint16 x, uint16 y);
+
+ bool getFrameCoords(int16 frame, int16 &x, int16 &y, int16 &width, int16 &height);
+
+ bool hasEmbeddedFiles() const;
+ bool hasEmbeddedFile(const Common::String &fileName) const;
+ Common::MemoryReadStream *getEmbeddedFile(const Common::String &fileName) const;
+
+ int32 getSubtitleIndex() const;
+
+
+ // VideoDecoder interface
+
+ bool load(Common::SeekableReadStream *stream);
+ void close();
+
+ bool isVideoLoaded() const;
+
+ Surface *decodeNextFrame();
+
+ PixelFormat getPixelFormat() const;
+
+private:
+ enum PartType {
+ kPartTypeSeparator = 0,
+ kPartTypeAudio = 1,
+ kPartTypeVideo = 2,
+ kPartTypeFile = 3,
+ kPartType4 = 4,
+ kPartTypeSubtitle = 5
+ };
+
+ enum AudioFormat {
+ kAudioFormat8bitRaw = 0,
+ kAudioFormat16bitDPCM = 1,
+ kAudioFormat16bitADPCM = 2
+ };
+
+ struct File {
+ Common::String name;
+
+ uint32 offset;
+ uint32 size;
+ uint32 realSize;
+
+ File();
+ };
+
+ struct Part {
+ PartType type;
+ byte field_1;
+ byte field_E;
+ uint32 size;
+ int16 left;
+ int16 top;
+ int16 right;
+ int16 bottom;
+ uint16 id;
+ byte flags;
+
+ Part();
+ };
+
+ struct Frame {
+ uint32 offset;
+ Part *parts;
+
+ Frame();
+ ~Frame();
+ };
+
+ // Tables for the audio decompressors
+ static const uint16 _tableDPCM[128];
+ static const int32 _tableADPCM[];
+ static const int32 _tableADPCMStep[];
+
+ Common::SeekableReadStream *_stream;
+
+ byte _version;
+ uint32 _flags;
+
+ uint32 _frameInfoOffset;
+ uint16 _partsPerFrame;
+ Frame *_frames;
+
+ Common::Array<File> _files;
+
+ // Sound properties
+ uint16 _soundFlags;
+ int16 _soundFreq;
+ int16 _soundSliceSize;
+ int16 _soundSlicesCount;
+ byte _soundBytesPerSample;
+ byte _soundStereo; // (0: mono, 1: old-style stereo, 2: new-style stereo)
+ uint32 _soundHeaderSize;
+ uint32 _soundDataSize;
+ AudioFormat _audioFormat;
+
+ // Video properties
+ bool _hasVideo;
+ uint32 _videoCodec;
+ byte _blitMode;
+ byte _bytesPerPixel;
+
+ uint32 _firstFramePos; ///< Position of the first frame's data within the stream.
+
+ // Buffer for raw frame data
+ byte *_frameData;
+ uint32 _frameDataSize;
+ uint32 _frameDataLen;
+
+ // Buffer for processed frame data
+ byte *_videoBuffer;
+ uint32 _videoBufferSize;
+
+ bool _externalCodec;
+ Codec *_codec;
+
+ int32 _subtitle;
+
+ // Loading helper functions
+ bool assessVideoProperties();
+ bool assessAudioProperties();
+ bool readFrameTable(int &numFiles);
+ bool readFiles();
+
+ // Frame decoding
+ void processFrame();
+
+ // Video
+ bool renderFrame(Common::Rect &rect);
+
+ // Sound
+ void emptySoundSlice (uint32 size);
+ void filledSoundSlice (uint32 size);
+ void filledSoundSlices(uint32 size, uint32 mask);
+
+ uint8 evaluateMask(uint32 mask, bool *fillInfo, uint8 &max);
+
+ // Generating sound slices
+ byte *soundEmpty (uint32 &size);
+ byte *sound8bitRaw (uint32 &size);
+ byte *sound16bitDPCM (uint32 &size);
+ byte *sound16bitADPCM(uint32 &size);
+
+ // Sound decompression
+ byte *deDPCM (const byte *data, uint32 &size, int32 init[2]);
+ byte *deADPCM(const byte *data, uint32 &size, int32 init, int32 index);
+
+ bool getPartCoords(int16 frame, PartType type, int16 &x, int16 &y, int16 &width, int16 &height);
+};
+
+} // End of namespace Graphics
+
+#endif // GRAPHICS_VIDEO_COKTELDECODER_H
+
+#endif // Engine and dynamic plugins guard
diff --git a/graphics/video/dxa_decoder.cpp b/graphics/video/dxa_decoder.cpp
index 3f26012f5e..5066e8cf37 100644
--- a/graphics/video/dxa_decoder.cpp
+++ b/graphics/video/dxa_decoder.cpp
@@ -66,10 +66,10 @@ DXADecoder::~DXADecoder() {
close();
}
-bool DXADecoder::load(Common::SeekableReadStream &stream) {
+bool DXADecoder::load(Common::SeekableReadStream *stream) {
close();
- _fileStream = &stream;
+ _fileStream = stream;
uint32 tag = _fileStream->readUint32BE();
assert(tag == MKID_BE('DEXA'));
diff --git a/graphics/video/dxa_decoder.h b/graphics/video/dxa_decoder.h
index 0312828195..eb4426dbbc 100644
--- a/graphics/video/dxa_decoder.h
+++ b/graphics/video/dxa_decoder.h
@@ -43,9 +43,9 @@ public:
DXADecoder();
virtual ~DXADecoder();
- bool load(Common::SeekableReadStream &stream);
+ bool load(Common::SeekableReadStream *stream);
void close();
-
+
bool isVideoLoaded() const { return _fileStream != 0; }
uint16 getWidth() const { return _width; }
uint16 getHeight() const { return _height; }
diff --git a/graphics/video/flic_decoder.cpp b/graphics/video/flic_decoder.cpp
index bb5b4f219b..843d3ee093 100644
--- a/graphics/video/flic_decoder.cpp
+++ b/graphics/video/flic_decoder.cpp
@@ -41,10 +41,10 @@ FlicDecoder::~FlicDecoder() {
close();
}
-bool FlicDecoder::load(Common::SeekableReadStream &stream) {
+bool FlicDecoder::load(Common::SeekableReadStream *stream) {
close();
- _fileStream = &stream;
+ _fileStream = stream;
/* uint32 frameSize = */ _fileStream->readUint32LE();
uint16 frameType = _fileStream->readUint16LE();
@@ -57,7 +57,7 @@ bool FlicDecoder::load(Common::SeekableReadStream &stream) {
return false;
}
-
+
_frameCount = _fileStream->readUint16LE();
uint16 width = _fileStream->readUint16LE();
uint16 height = _fileStream->readUint16LE();
@@ -71,9 +71,8 @@ bool FlicDecoder::load(Common::SeekableReadStream &stream) {
_fileStream->readUint16LE(); // flags
// Note: The normal delay is a 32-bit integer (dword), whereas the overriden delay is a 16-bit integer (word)
- // frameDelay is the FLIC "speed", in milliseconds. Our frameDelay is calculated in 1/100 ms, so we convert it here
- uint32 frameDelay = 100 * _fileStream->readUint32LE();
- _frameRate = 100 * 1000 / frameDelay;
+ // the frame delay is the FLIC "speed", in milliseconds.
+ _frameRate = Common::Rational(1000, _fileStream->readUint32LE());
_fileStream->seek(80);
_offsetFrame1 = _fileStream->readUint32LE();
@@ -209,10 +208,10 @@ Surface *FlicDecoder::decodeNextFrame() {
chunkCount = _fileStream->readUint16LE();
// Note: The overriden delay is a 16-bit integer (word), whereas the normal delay is a 32-bit integer (dword)
- // frameDelay is the FLIC "speed", in milliseconds. Our frameDelay is calculated in 1/100 ms, so we convert it here
+ // the frame delay is the FLIC "speed", in milliseconds.
uint16 newFrameDelay = _fileStream->readUint16LE(); // "speed", in milliseconds
if (newFrameDelay > 0)
- _frameRate = 1000 / newFrameDelay;
+ _frameRate = Common::Rational(1000, newFrameDelay);
_fileStream->readUint16LE(); // reserved, always 0
uint16 newWidth = _fileStream->readUint16LE();
@@ -265,11 +264,8 @@ Surface *FlicDecoder::decodeNextFrame() {
delete[] data;
}
}
-
- _curFrame++;
- if (_curFrame == 0)
- _startTime = g_system->getMillis();
+ _curFrame++;
// If we just processed the ring frame, set the next frame
if (_curFrame == (int32)_frameCount) {
@@ -277,6 +273,9 @@ Surface *FlicDecoder::decodeNextFrame() {
_fileStream->seek(_offsetFrame2);
}
+ if (_curFrame == 0)
+ _startTime = g_system->getMillis();
+
return _surface;
}
diff --git a/graphics/video/flic_decoder.h b/graphics/video/flic_decoder.h
index 60d68889a2..bba1403c22 100644
--- a/graphics/video/flic_decoder.h
+++ b/graphics/video/flic_decoder.h
@@ -51,7 +51,7 @@ public:
* Load a video file
* @param stream the stream to load
*/
- bool load(Common::SeekableReadStream &stream);
+ bool load(Common::SeekableReadStream *stream);
void close();
/**
@@ -72,7 +72,7 @@ public:
void copyDirtyRectsToBuffer(uint8 *dst, uint pitch);
byte *getPalette() { _paletteChanged = false; return _palette; }
- bool hasDirtyPalette() { return _paletteChanged; }
+ bool hasDirtyPalette() const { return _paletteChanged; }
void reset();
protected:
@@ -91,7 +91,7 @@ private:
Common::SeekableReadStream *_fileStream;
Surface *_surface;
uint32 _frameCount;
- uint32 _frameRate;
+ Common::Rational _frameRate;
Common::List<Common::Rect> _dirtyRects;
};
diff --git a/graphics/video/mpeg_player.cpp b/graphics/video/mpeg_player.cpp
index f237f76eed..ea1fa4ec1c 100644
--- a/graphics/video/mpeg_player.cpp
+++ b/graphics/video/mpeg_player.cpp
@@ -23,6 +23,69 @@
*
*/
+// The YUV to RGB conversion code is derived from SDL's YUV overlay code, which
+// in turn appears to be derived from mpeg_play. The following copyright
+// notices have been included in accordance with the original license. Please
+// note that the term "software" in this context only applies to the
+// buildLookup() and plotYUV*() functions below.
+
+// Copyright (c) 1995 The Regents of the University of California.
+// All rights reserved.
+//
+// Permission to use, copy, modify, and distribute this software and its
+// documentation for any purpose, without fee, and without written agreement is
+// hereby granted, provided that the above copyright notice and the following
+// two paragraphs appear in all copies of this software.
+//
+// IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+// OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+// CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+// ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+// PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+// Copyright (c) 1995 Erik Corry
+// All rights reserved.
+//
+// Permission to use, copy, modify, and distribute this software and its
+// documentation for any purpose, without fee, and without written agreement is
+// hereby granted, provided that the above copyright notice and the following
+// two paragraphs appear in all copies of this software.
+//
+// IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
+// THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
+// BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
+// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+// Portions of this software Copyright (c) 1995 Brown University.
+// All rights reserved.
+//
+// Permission to use, copy, modify, and distribute this software and its
+// documentation for any purpose, without fee, and without written agreement
+// is hereby granted, provided that the above copyright notice and the
+// following two paragraphs appear in all copies of this software.
+//
+// IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
+// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+// OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
+// UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
+// BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
+// SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
#include "graphics/video/mpeg_player.h"
#include "common/file.h"
#include "common/system.h"
@@ -284,69 +347,6 @@ void BaseAnimationState::buildLookup(int p, int lines) {
#else
-// The YUV to RGB conversion code is derived from SDL's YUV overlay code, which
-// in turn appears to be derived from mpeg_play. The following copyright
-// notices have been included in accordance with the original license. Please
-// note that the term "software" in this context only applies to the two
-// functions buildLookup() and plotYUV() below.
-
-// Copyright (c) 1995 The Regents of the University of California.
-// All rights reserved.
-//
-// Permission to use, copy, modify, and distribute this software and its
-// documentation for any purpose, without fee, and without written agreement is
-// hereby granted, provided that the above copyright notice and the following
-// two paragraphs appear in all copies of this software.
-//
-// IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
-// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
-// OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
-// CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
-// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
-// ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
-// PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-
-// Copyright (c) 1995 Erik Corry
-// All rights reserved.
-//
-// Permission to use, copy, modify, and distribute this software and its
-// documentation for any purpose, without fee, and without written agreement is
-// hereby granted, provided that the above copyright notice and the following
-// two paragraphs appear in all copies of this software.
-//
-// IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
-// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
-// THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
-// OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-// PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
-// BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
-// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-
-// Portions of this software Copyright (c) 1995 Brown University.
-// All rights reserved.
-//
-// Permission to use, copy, modify, and distribute this software and its
-// documentation for any purpose, without fee, and without written agreement
-// is hereby granted, provided that the above copyright notice and the
-// following two paragraphs appear in all copies of this software.
-//
-// IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
-// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
-// OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
-// UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-// PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
-// BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
-// SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-
void BaseAnimationState::buildLookup() {
// Do we already have lookup tables for this bit format?
Graphics::PixelFormat format = _sys->getOverlayFormat();
diff --git a/graphics/video/mpeg_player.h b/graphics/video/mpeg_player.h
index 70754fb5ed..4dedf12f57 100644
--- a/graphics/video/mpeg_player.h
+++ b/graphics/video/mpeg_player.h
@@ -52,10 +52,8 @@
typedef signed long int32_t;
typedef unsigned long uint32_t;
#endif
-#elif !defined(PALMOS_MODE)
-# include <inttypes.h>
#else
-# include <stdint.h>
+# include <inttypes.h>
#endif
extern "C" {
diff --git a/graphics/video/qt_decoder.cpp b/graphics/video/qt_decoder.cpp
new file mode 100644
index 0000000000..470441dab8
--- /dev/null
+++ b/graphics/video/qt_decoder.cpp
@@ -0,0 +1,1326 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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$
+ *
+ */
+
+//
+// Heavily based on ffmpeg code.
+//
+// Copyright (c) 2001 Fabrice Bellard.
+// First version by Francois Revol revol@free.fr
+// Seek function by Gael Chardon gael.dev@4now.net
+//
+
+#include "graphics/video/qt_decoder.h"
+
+#include "common/debug.h"
+#include "common/endian.h"
+#include "common/macresman.h"
+#include "common/util.h"
+#include "common/zlib.h"
+
+// Audio codecs
+#include "sound/decoders/adpcm.h"
+#include "sound/decoders/raw.h"
+#include "graphics/video/codecs/qdm2.h"
+
+// Video codecs
+#include "graphics/video/codecs/cinepak.h"
+#include "graphics/video/codecs/mjpeg.h"
+#include "graphics/video/codecs/qtrle.h"
+#include "graphics/video/codecs/rpza.h"
+#include "graphics/video/codecs/smc.h"
+
+namespace Graphics {
+
+////////////////////////////////////////////
+// QuickTimeDecoder
+////////////////////////////////////////////
+
+QuickTimeDecoder::QuickTimeDecoder() : VideoDecoder() {
+ _audStream = NULL;
+ _beginOffset = 0;
+ _videoCodec = NULL;
+ _curFrame = -1;
+ _startTime = _nextFrameStartTime = 0;
+ _audHandle = Audio::SoundHandle();
+ _numStreams = 0;
+ _fd = 0;
+ _scaledSurface = 0;
+ _dirtyPalette = false;
+ _resFork = new Common::MacResManager();
+
+ initParseTable();
+}
+
+QuickTimeDecoder::~QuickTimeDecoder() {
+ close();
+ delete _resFork;
+}
+
+uint16 QuickTimeDecoder::getWidth() const {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ return _streams[_videoStreamIndex]->width / getScaleMode();
+}
+
+uint16 QuickTimeDecoder::getHeight() const {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ return _streams[_videoStreamIndex]->height / getScaleMode();
+}
+
+uint32 QuickTimeDecoder::getFrameCount() const {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ return _streams[_videoStreamIndex]->nb_frames;
+}
+
+byte QuickTimeDecoder::getBitsPerPixel() {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ return _streams[_videoStreamIndex]->bits_per_sample & 0x1F;
+}
+
+uint32 QuickTimeDecoder::getCodecTag() {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ return _streams[_videoStreamIndex]->codec_tag;
+}
+
+ScaleMode QuickTimeDecoder::getScaleMode() const {
+ if (_videoStreamIndex < 0)
+ return kScaleNormal;
+
+ return (ScaleMode)(_scaleMode * _streams[_videoStreamIndex]->scaleMode);
+}
+
+uint32 QuickTimeDecoder::getFrameDuration() {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ uint32 curFrameIndex = 0;
+ for (int32 i = 0; i < _streams[_videoStreamIndex]->stts_count; i++) {
+ curFrameIndex += _streams[_videoStreamIndex]->stts_data[i].count;
+ if ((uint32)_curFrame < curFrameIndex) {
+ // Ok, now we have what duration this frame has.
+ return _streams[_videoStreamIndex]->stts_data[i].duration;
+ }
+ }
+
+ // This should never occur
+ error ("Cannot find duration for frame %d", _curFrame);
+ return 0;
+}
+
+PixelFormat QuickTimeDecoder::getPixelFormat() const {
+ if (!_videoCodec)
+ return PixelFormat::createFormatCLUT8();
+
+ return _videoCodec->getPixelFormat();
+}
+
+void QuickTimeDecoder::rewind() {
+ VideoDecoder::reset();
+ _nextFrameStartTime = 0;
+
+ // Restart the audio too
+ stopAudio();
+ if (_audioStreamIndex >= 0) {
+ _curAudioChunk = 0;
+ _audStream = Audio::makeQueuingAudioStream(_streams[_audioStreamIndex]->sample_rate, _streams[_audioStreamIndex]->channels == 2);
+ }
+ startAudio();
+}
+
+Codec *QuickTimeDecoder::createCodec(uint32 codecTag, byte bitsPerPixel) {
+ if (codecTag == MKID_BE('cvid')) {
+ // Cinepak: As used by most Myst and all Riven videos as well as some Myst ME videos. "The Chief" videos also use this.
+ return new CinepakDecoder();
+ } else if (codecTag == MKID_BE('rpza')) {
+ // Apple Video ("Road Pizza"): Used by some Myst videos.
+ return new RPZADecoder(getWidth(), getHeight());
+ } else if (codecTag == MKID_BE('rle ')) {
+ // QuickTime RLE: Used by some Myst ME videos.
+ return new QTRLEDecoder(getWidth(), getHeight(), bitsPerPixel);
+ } else if (codecTag == MKID_BE('smc ')) {
+ // Apple SMC: Used by some Myst videos.
+ return new SMCDecoder(getWidth(), getHeight());
+ } else if (codecTag == MKID_BE('SVQ1')) {
+ // Sorenson Video 1: Used by some Myst ME videos.
+ warning ("Sorenson Video 1 not yet supported");
+ } else if (codecTag == MKID_BE('SVQ3')) {
+ // Sorenson Video 3: Used by some Myst ME videos.
+ warning ("Sorenson Video 3 not yet supported");
+ } else if (codecTag == MKID_BE('jpeg')) {
+ // Motion JPEG: Used by some Myst ME 10th Anniversary videos.
+ return new JPEGDecoder();
+ } else if (codecTag == MKID_BE('QkBk')) {
+ // CDToons: Used by most of the Broderbund games. This is an unknown format so far.
+ warning ("CDToons not yet supported");
+ } else {
+ warning ("Unsupported codec \'%s\'", tag2str(codecTag));
+ }
+
+ return NULL;
+}
+
+void QuickTimeDecoder::startAudio() {
+ if (_audStream) { // No audio/audio not supported
+ updateAudioBuffer();
+ g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audHandle, _audStream);
+ }
+}
+
+void QuickTimeDecoder::stopAudio() {
+ if (_audStream) {
+ g_system->getMixer()->stopHandle(_audHandle);
+ _audStream = NULL; // the mixer automatically frees the stream
+ }
+}
+
+void QuickTimeDecoder::pauseVideoIntern(bool pause) {
+ if (_audStream)
+ g_system->getMixer()->pauseHandle(_audHandle, pause);
+}
+
+Surface *QuickTimeDecoder::decodeNextFrame() {
+ if (!_videoCodec || _curFrame >= (int32)getFrameCount() - 1)
+ return NULL;
+
+ if (_startTime == 0)
+ _startTime = g_system->getMillis();
+
+ _curFrame++;
+ _nextFrameStartTime += getFrameDuration();
+
+ Common::SeekableReadStream *frameData = getNextFramePacket();
+
+ if (frameData) {
+ Surface *frame = _videoCodec->decodeImage(frameData);
+ delete frameData;
+ return scaleSurface(frame);
+ }
+
+ return NULL;
+}
+
+Surface *QuickTimeDecoder::scaleSurface(Surface *frame) {
+ if (getScaleMode() == kScaleNormal)
+ return frame;
+
+ assert(_scaledSurface);
+
+ for (uint32 j = 0; j < _scaledSurface->h; j++)
+ for (uint32 k = 0; k < _scaledSurface->w; k++)
+ memcpy(_scaledSurface->getBasePtr(k, j), frame->getBasePtr(k * getScaleMode(), j * getScaleMode()), frame->bytesPerPixel);
+
+ return _scaledSurface;
+}
+
+bool QuickTimeDecoder::endOfVideo() const {
+ return (!_audStream || _audStream->endOfData()) && (!_videoCodec || VideoDecoder::endOfVideo());
+}
+
+uint32 QuickTimeDecoder::getElapsedTime() const {
+ if (_audStream)
+ return g_system->getMixer()->getSoundElapsedTime(_audHandle);
+
+ return g_system->getMillis() - _startTime;
+}
+
+uint32 QuickTimeDecoder::getTimeToNextFrame() const {
+ if (endOfVideo() || _curFrame < 0)
+ return 0;
+
+ // Convert from the QuickTime rate base to 1000
+ uint32 nextFrameStartTime = _nextFrameStartTime * 1000 / _streams[_videoStreamIndex]->time_scale;
+ uint32 elapsedTime = getElapsedTime();
+
+ if (nextFrameStartTime <= elapsedTime)
+ return 0;
+
+ return nextFrameStartTime - elapsedTime;
+}
+
+bool QuickTimeDecoder::loadFile(const Common::String &filename) {
+ if (!_resFork->open(filename) || !_resFork->hasDataFork())
+ return false;
+
+ _foundMOOV = _foundMDAT = false;
+ _numStreams = 0;
+ _partial = 0;
+ _videoStreamIndex = _audioStreamIndex = -1;
+ _startTime = 0;
+
+ MOVatom atom = { 0, 0, 0xffffffff };
+
+ if (_resFork->hasResFork()) {
+ // Search for a 'moov' resource
+ Common::MacResIDArray idArray = _resFork->getResIDArray(MKID_BE('moov'));
+
+ if (!idArray.empty())
+ _fd = _resFork->getResource(MKID_BE('moov'), idArray[0]);
+
+ if (_fd) {
+ atom.size = _fd->size();
+ if (readDefault(atom) < 0 || !_foundMOOV)
+ return false;
+ }
+ delete _fd;
+
+ atom.type = 0;
+ atom.offset = 0;
+ atom.size = 0xffffffff;
+ }
+
+ _fd = _resFork->getDataFork();
+
+ if (readDefault(atom) < 0 || !_foundMOOV || !_foundMDAT)
+ return false;
+
+ init();
+ return true;
+}
+
+bool QuickTimeDecoder::load(Common::SeekableReadStream *stream) {
+ _fd = stream;
+ _foundMOOV = _foundMDAT = false;
+ _numStreams = 0;
+ _partial = 0;
+ _videoStreamIndex = _audioStreamIndex = -1;
+ _startTime = 0;
+
+ MOVatom atom = { 0, 0, 0xffffffff };
+
+ if (readDefault(atom) < 0 || !_foundMOOV || !_foundMDAT) {
+ _fd = 0;
+ return false;
+ }
+
+ init();
+ return true;
+}
+
+void QuickTimeDecoder::init() {
+ // some cleanup : make sure we are on the mdat atom
+ if((uint32)_fd->pos() != _mdatOffset)
+ _fd->seek(_mdatOffset, SEEK_SET);
+
+ for (uint32 i = 0; i < _numStreams;) {
+ if (_streams[i]->codec_type == CODEC_TYPE_MOV_OTHER) {// not audio, not video, delete
+ delete _streams[i];
+ for (uint32 j = i + 1; j < _numStreams; j++)
+ _streams[j - 1] = _streams[j];
+ _numStreams--;
+ } else
+ i++;
+ }
+
+ for (uint32 i = 0; i < _numStreams; i++) {
+ MOVStreamContext *sc = _streams[i];
+
+ if (!sc->time_rate)
+ sc->time_rate = 1;
+
+ if (!sc->time_scale)
+ sc->time_scale = _timeScale;
+
+ sc->duration /= sc->time_rate;
+
+ sc->ffindex = i;
+ sc->is_ff_stream = 1;
+
+ if (sc->codec_type == CODEC_TYPE_VIDEO && _videoStreamIndex < 0)
+ _videoStreamIndex = i;
+ else if (sc->codec_type == CODEC_TYPE_AUDIO && _audioStreamIndex < 0)
+ _audioStreamIndex = i;
+ }
+
+ if (_audioStreamIndex >= 0 && checkAudioCodecSupport(_streams[_audioStreamIndex]->codec_tag)) {
+ _audStream = Audio::makeQueuingAudioStream(_streams[_audioStreamIndex]->sample_rate, _streams[_audioStreamIndex]->channels == 2);
+ _curAudioChunk = 0;
+
+ // Make sure the bits per sample transfers to the sample size
+ if (_streams[_audioStreamIndex]->codec_tag == MKID_BE('raw ') || _streams[_audioStreamIndex]->codec_tag == MKID_BE('twos'))
+ _streams[_audioStreamIndex]->sample_size = (_streams[_audioStreamIndex]->bits_per_sample / 8) * _streams[_audioStreamIndex]->channels;
+
+ startAudio();
+ }
+
+ if (_videoStreamIndex >= 0) {
+ _videoCodec = createCodec(getCodecTag(), getBitsPerPixel());
+
+ if (getScaleMode() != kScaleNormal) {
+ // We have to initialize the scaled surface
+ _scaledSurface = new Surface();
+ _scaledSurface->create(getWidth(), getHeight(), getPixelFormat().bytesPerPixel);
+ }
+ }
+}
+
+void QuickTimeDecoder::initParseTable() {
+ static const ParseTable p[] = {
+ { &QuickTimeDecoder::readDefault, MKID_BE('dinf') },
+ { &QuickTimeDecoder::readLeaf, MKID_BE('dref') },
+ { &QuickTimeDecoder::readDefault, MKID_BE('edts') },
+ { &QuickTimeDecoder::readELST, MKID_BE('elst') },
+ { &QuickTimeDecoder::readHDLR, MKID_BE('hdlr') },
+ { &QuickTimeDecoder::readMDAT, MKID_BE('mdat') },
+ { &QuickTimeDecoder::readMDHD, MKID_BE('mdhd') },
+ { &QuickTimeDecoder::readDefault, MKID_BE('mdia') },
+ { &QuickTimeDecoder::readDefault, MKID_BE('minf') },
+ { &QuickTimeDecoder::readMOOV, MKID_BE('moov') },
+ { &QuickTimeDecoder::readMVHD, MKID_BE('mvhd') },
+ { &QuickTimeDecoder::readLeaf, MKID_BE('smhd') },
+ { &QuickTimeDecoder::readDefault, MKID_BE('stbl') },
+ { &QuickTimeDecoder::readSTCO, MKID_BE('stco') },
+ { &QuickTimeDecoder::readSTSC, MKID_BE('stsc') },
+ { &QuickTimeDecoder::readSTSD, MKID_BE('stsd') },
+ { &QuickTimeDecoder::readSTSS, MKID_BE('stss') },
+ { &QuickTimeDecoder::readSTSZ, MKID_BE('stsz') },
+ { &QuickTimeDecoder::readSTTS, MKID_BE('stts') },
+ { &QuickTimeDecoder::readTKHD, MKID_BE('tkhd') },
+ { &QuickTimeDecoder::readTRAK, MKID_BE('trak') },
+ { &QuickTimeDecoder::readLeaf, MKID_BE('udta') },
+ { &QuickTimeDecoder::readLeaf, MKID_BE('vmhd') },
+ { &QuickTimeDecoder::readCMOV, MKID_BE('cmov') },
+ { &QuickTimeDecoder::readWAVE, MKID_BE('wave') },
+ { 0, 0 }
+ };
+
+ _parseTable = p;
+}
+
+int QuickTimeDecoder::readDefault(MOVatom atom) {
+ uint32 total_size = 0;
+ MOVatom a;
+ int err = 0;
+
+ a.offset = atom.offset;
+
+ while(((total_size + 8) < atom.size) && !_fd->eos() && _fd->pos() < _fd->size() && !err) {
+ a.size = atom.size;
+ a.type = 0;
+
+ if (atom.size >= 8) {
+ a.size = _fd->readUint32BE();
+ a.type = _fd->readUint32BE();
+
+ // Some QuickTime videos with resource forks have mdat chunks
+ // that are of size 0. Adjust it so it's the correct size.
+ if (a.type == MKID_BE('mdat') && a.size == 0)
+ a.size = _fd->size();
+ }
+
+ total_size += 8;
+ a.offset += 8;
+ debug(4, "type: %08x %.4s sz: %x %x %x", a.type, tag2str(a.type), a.size, atom.size, total_size);
+
+ if (a.size == 1) { // 64 bit extended size
+ warning("64 bit extended size is not supported in QuickTime");
+ return -1;
+ }
+
+ if (a.size == 0) {
+ a.size = atom.size - total_size;
+ if (a.size <= 8)
+ break;
+ }
+
+ uint32 i = 0;
+
+ for (; _parseTable[i].type != 0 && _parseTable[i].type != a.type; i++)
+ // empty;
+
+ if (a.size < 8)
+ break;
+
+ a.size -= 8;
+
+ if (_parseTable[i].type == 0) { // skip leaf atoms data
+ debug(0, ">>> Skipped [%s]", tag2str(a.type));
+
+ _fd->seek(a.size, SEEK_CUR);
+ } else {
+ uint32 start_pos = _fd->pos();
+ err = (this->*_parseTable[i].func)(a);
+
+ uint32 left = a.size - _fd->pos() + start_pos;
+
+ if (left > 0) // skip garbage at atom end
+ _fd->seek(left, SEEK_CUR);
+ }
+
+ a.offset += a.size;
+ total_size += a.size;
+ }
+
+ if (!err && total_size < atom.size)
+ _fd->seek(atom.size - total_size, SEEK_SET);
+
+ return err;
+}
+
+int QuickTimeDecoder::readLeaf(MOVatom atom) {
+ if (atom.size > 1)
+ _fd->seek(atom.size, SEEK_SET);
+
+ return 0;
+}
+
+int QuickTimeDecoder::readMOOV(MOVatom atom) {
+ if (readDefault(atom) < 0)
+ return -1;
+
+ // we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat'
+ // so we don't parse the whole file if over a network
+ _foundMOOV = true;
+
+ if(_foundMDAT)
+ return 1; // found both, just go
+
+ return 0; // now go for mdat
+}
+
+int QuickTimeDecoder::readCMOV(MOVatom atom) {
+#ifdef USE_ZLIB
+ // Read in the dcom atom
+ _fd->readUint32BE();
+ if (_fd->readUint32BE() != MKID_BE('dcom'))
+ return -1;
+ if (_fd->readUint32BE() != MKID_BE('zlib')) {
+ warning("Unknown cmov compression type");
+ return -1;
+ }
+
+ // Read in the cmvd atom
+ uint32 compressedSize = _fd->readUint32BE() - 12;
+ if (_fd->readUint32BE() != MKID_BE('cmvd'))
+ return -1;
+ uint32 uncompressedSize = _fd->readUint32BE();
+
+ // Read in data
+ byte *compressedData = (byte *)malloc(compressedSize);
+ _fd->read(compressedData, compressedSize);
+
+ // Create uncompressed stream
+ byte *uncompressedData = (byte *)malloc(uncompressedSize);
+
+ // Uncompress the data
+ unsigned long dstLen = uncompressedSize;
+ if (!Common::uncompress(uncompressedData, &dstLen, compressedData, compressedSize)) {
+ warning ("Could not uncompress cmov chunk");
+ free(compressedData);
+ free(uncompressedData);
+ return -1;
+ }
+
+ // Load data into a new MemoryReadStream and assign _fd to be that
+ Common::SeekableReadStream *oldStream = _fd;
+ _fd = new Common::MemoryReadStream(uncompressedData, uncompressedSize, DisposeAfterUse::YES);
+
+ // Read the contents of the uncompressed data
+ MOVatom a = { MKID_BE('moov'), 0, uncompressedSize };
+ int err = readDefault(a);
+
+ // Assign the file handle back to the original handle
+ free(compressedData);
+ delete _fd;
+ _fd = oldStream;
+
+ return err;
+#else
+ warning ("zlib not found, cannot read QuickTime cmov atom");
+ return -1;
+#endif
+}
+
+int QuickTimeDecoder::readMVHD(MOVatom atom) {
+ byte version = _fd->readByte(); // version
+ _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
+
+ if (version == 1) {
+ warning("QuickTime version 1");
+ _fd->readUint32BE(); _fd->readUint32BE();
+ _fd->readUint32BE(); _fd->readUint32BE();
+ } else {
+ _fd->readUint32BE(); // creation time
+ _fd->readUint32BE(); // modification time
+ }
+
+ _timeScale = _fd->readUint32BE(); // time scale
+ debug(0, "time scale = %i\n", _timeScale);
+
+ // duration
+ _duration = (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE();
+ _fd->readUint32BE(); // preferred scale
+
+ _fd->readUint16BE(); // preferred volume
+
+ _fd->seek(10, SEEK_CUR); // reserved
+
+ // We only need two values from the movie display matrix. Most of the values are just
+ // skipped. xMod and yMod are 16:16 fixed point numbers, the last part of the 3x3 matrix
+ // is 2:30.
+ uint32 xMod = _fd->readUint32BE();
+ _fd->skip(12);
+ uint32 yMod = _fd->readUint32BE();
+ _fd->skip(16);
+
+ if (xMod != yMod)
+ error("X and Y resolution modifiers differ");
+
+ if (xMod == 0x8000)
+ _scaleMode = kScaleHalf;
+ else if (xMod == 0x4000)
+ _scaleMode = kScaleQuarter;
+ else
+ _scaleMode = kScaleNormal;
+
+ debug(1, "readMVHD(): scaleMode = %d", (int)_scaleMode);
+
+ _fd->readUint32BE(); // preview time
+ _fd->readUint32BE(); // preview duration
+ _fd->readUint32BE(); // poster time
+ _fd->readUint32BE(); // selection time
+ _fd->readUint32BE(); // selection duration
+ _fd->readUint32BE(); // current time
+ _fd->readUint32BE(); // next track ID
+
+ return 0;
+}
+
+int QuickTimeDecoder::readTRAK(MOVatom atom) {
+ MOVStreamContext *sc = new MOVStreamContext();
+
+ if (!sc)
+ return -1;
+
+ sc->sample_to_chunk_index = -1;
+ sc->codec_type = CODEC_TYPE_MOV_OTHER;
+ sc->start_time = 0; // XXX: check
+ _streams[_numStreams++] = sc;
+
+ return readDefault(atom);
+}
+
+// this atom contains actual media data
+int QuickTimeDecoder::readMDAT(MOVatom atom) {
+ if (atom.size == 0) // wrong one (MP4)
+ return 0;
+
+ _foundMDAT = true;
+
+ _mdatOffset = atom.offset;
+ _mdatSize = atom.size;
+
+ if (_foundMOOV)
+ return 1; // found both, just go
+
+ _fd->seek(atom.size, SEEK_CUR);
+
+ return 0; // now go for moov
+}
+
+int QuickTimeDecoder::readTKHD(MOVatom atom) {
+ MOVStreamContext *st = _streams[_numStreams - 1];
+ byte version = _fd->readByte();
+
+ _fd->readByte(); _fd->readByte();
+ _fd->readByte(); // flags
+ //
+ //MOV_TRACK_ENABLED 0x0001
+ //MOV_TRACK_IN_MOVIE 0x0002
+ //MOV_TRACK_IN_PREVIEW 0x0004
+ //MOV_TRACK_IN_POSTER 0x0008
+ //
+
+ if (version == 1) {
+ _fd->readUint32BE(); _fd->readUint32BE();
+ _fd->readUint32BE(); _fd->readUint32BE();
+ } else {
+ _fd->readUint32BE(); // creation time
+ _fd->readUint32BE(); // modification time
+ }
+
+ /* st->id = */_fd->readUint32BE(); // track id (NOT 0 !)
+ _fd->readUint32BE(); // reserved
+ //st->start_time = 0; // check
+ (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE(); // highlevel (considering edits) duration in movie timebase
+ _fd->readUint32BE(); // reserved
+ _fd->readUint32BE(); // reserved
+
+ _fd->readUint16BE(); // layer
+ _fd->readUint16BE(); // alternate group
+ _fd->readUint16BE(); // volume
+ _fd->readUint16BE(); // reserved
+
+ // We only need the two values from the displacement matrix for a track.
+ // See readMVHD() for more information.
+ uint32 xMod = _fd->readUint32BE();
+ _fd->skip(12);
+ uint32 yMod = _fd->readUint32BE();
+ _fd->skip(16);
+
+ if (xMod != yMod)
+ error("X and Y resolution modifiers differ");
+
+ if (xMod == 0x8000)
+ st->scaleMode = kScaleHalf;
+ else if (xMod == 0x4000)
+ st->scaleMode = kScaleQuarter;
+ else
+ st->scaleMode = kScaleNormal;
+
+ debug(1, "readTKHD(): scaleMode = %d", (int)_scaleMode);
+
+ // these are fixed-point, 16:16
+ // uint32 tkWidth = _fd->readUint32BE() >> 16; // track width
+ // uint32 tkHeight = _fd->readUint32BE() >> 16; // track height
+
+ return 0;
+}
+
+// edit list atom
+int QuickTimeDecoder::readELST(MOVatom atom) {
+ _fd->readByte(); // version
+ _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
+ uint32 editCount = _streams[_numStreams - 1]->edit_count = _fd->readUint32BE(); // entries
+
+ for (uint32 i = 0; i < editCount; i++){
+ _fd->readUint32BE(); // Track duration
+ _fd->readUint32BE(); // Media time
+ _fd->readUint32BE(); // Media rate
+ }
+
+ debug(0, "track[%i].edit_count = %i", _numStreams - 1, _streams[_numStreams - 1]->edit_count);
+
+ if (editCount != 1)
+ warning("Multiple edit list entries. Things may go awry");
+
+ return 0;
+}
+
+int QuickTimeDecoder::readHDLR(MOVatom atom) {
+ MOVStreamContext *st = _streams[_numStreams - 1];
+
+ _fd->readByte(); // version
+ _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
+
+ // component type
+ uint32 ctype = _fd->readUint32LE();
+ uint32 type = _fd->readUint32BE(); // component subtype
+
+ debug(0, "ctype= %s (0x%08lx)", tag2str(ctype), (long)ctype);
+ debug(0, "stype= %s", tag2str(type));
+
+ if(ctype == MKID_BE('mhlr')) // MOV
+ debug(0, "MOV detected");
+ else if(ctype == 0) {
+ warning("MP4 streams are not supported");
+ return -1;
+ }
+
+ if (type == MKID_BE('vide'))
+ st->codec_type = CODEC_TYPE_VIDEO;
+ else if (type == MKID_BE('soun'))
+ st->codec_type = CODEC_TYPE_AUDIO;
+
+ _fd->readUint32BE(); // component manufacture
+ _fd->readUint32BE(); // component flags
+ _fd->readUint32BE(); // component flags mask
+
+ if (atom.size <= 24)
+ return 0; // nothing left to read
+
+ // .mov: PASCAL string
+ byte len = _fd->readByte();
+ _fd->seek(len, SEEK_CUR);
+
+ _fd->seek(atom.size - (_fd->pos() - atom.offset), SEEK_CUR);
+
+ return 0;
+}
+
+int QuickTimeDecoder::readMDHD(MOVatom atom) {
+ MOVStreamContext *st = _streams[_numStreams - 1];
+ byte version = _fd->readByte();
+
+ if (version > 1)
+ return 1; // unsupported
+
+ _fd->readByte(); _fd->readByte();
+ _fd->readByte(); // flags
+
+ if (version == 1) {
+ _fd->readUint32BE(); _fd->readUint32BE();
+ _fd->readUint32BE(); _fd->readUint32BE();
+ } else {
+ _fd->readUint32BE(); // creation time
+ _fd->readUint32BE(); // modification time
+ }
+
+ st->time_scale = _fd->readUint32BE();
+ st->duration = (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE(); // duration
+
+ _fd->readUint16BE(); // language
+ _fd->readUint16BE(); // quality
+
+ return 0;
+}
+
+int QuickTimeDecoder::readSTSD(MOVatom atom) {
+ MOVStreamContext *st = _streams[_numStreams - 1];
+
+ _fd->readByte(); // version
+ _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
+
+ uint32 entries = _fd->readUint32BE();
+
+ while (entries--) { //Parsing Sample description table
+ MOVatom a = { 0, 0, 0 };
+ uint32 start_pos = _fd->pos();
+ int size = _fd->readUint32BE(); // size
+ uint32 format = _fd->readUint32BE(); // data format
+
+ _fd->readUint32BE(); // reserved
+ _fd->readUint16BE(); // reserved
+ _fd->readUint16BE(); // index
+
+ debug(0, "size=%d 4CC= %s codec_type=%d", size, tag2str(format), st->codec_type);
+ st->codec_tag = format;
+
+ if (st->codec_type == CODEC_TYPE_VIDEO) {
+ debug(0, "Video Codec FourCC: \'%s\'", tag2str(format));
+
+ _fd->readUint16BE(); // version
+ _fd->readUint16BE(); // revision level
+ _fd->readUint32BE(); // vendor
+ _fd->readUint32BE(); // temporal quality
+ _fd->readUint32BE(); // spacial quality
+
+ st->width = _fd->readUint16BE(); // width
+ st->height = _fd->readUint16BE(); // height
+
+ _fd->readUint32BE(); // horiz resolution
+ _fd->readUint32BE(); // vert resolution
+ _fd->readUint32BE(); // data size, always 0
+ uint16 frames_per_sample = _fd->readUint16BE(); // frames per samples
+
+ debug(0, "frames/samples = %d", frames_per_sample);
+
+ byte codec_name[32];
+ _fd->read(codec_name, 32); // codec name, pascal string (FIXME: true for mp4?)
+ if (codec_name[0] <= 31) {
+ memcpy(st->codec_name, &codec_name[1], codec_name[0]);
+ st->codec_name[codec_name[0]] = 0;
+ }
+
+ st->bits_per_sample = _fd->readUint16BE(); // depth
+ st->color_table_id = _fd->readUint16BE(); // colortable id
+
+// These are set in mov_read_stts and might already be set!
+// st->codec->time_base.den = 25;
+// st->codec->time_base.num = 1;
+
+
+ // figure out the palette situation
+ byte colorDepth = st->bits_per_sample & 0x1F;
+ bool colorGreyscale = (st->bits_per_sample & 0x20) != 0;
+
+ debug(0, "color depth: %d", colorDepth);
+
+ // if the depth is 2, 4, or 8 bpp, file is palettized
+ if (colorDepth == 2 || colorDepth == 4 || colorDepth == 8) {
+ _dirtyPalette = true;
+
+ if (colorGreyscale) {
+ debug(0, "Greyscale palette");
+
+ // compute the greyscale palette
+ uint16 colorCount = 1 << colorDepth;
+ int16 colorIndex = 255;
+ byte colorDec = 256 / (colorCount - 1);
+ for (byte j = 0; j < colorCount; j++) {
+ _palette[j * 3] = _palette[j * 3 + 1] = _palette[j * 3 + 2] = colorIndex;
+ colorIndex -= colorDec;
+ if (colorIndex < 0)
+ colorIndex = 0;
+ }
+ } else if (st->color_table_id & 0x08) {
+ // if flag bit 3 is set, use the default palette
+ //uint16 colorCount = 1 << colorDepth;
+
+ warning("Predefined palette! %dbpp", colorDepth);
+#if 0
+ byte *color_table;
+ byte r, g, b;
+
+ if (colorDepth == 2)
+ color_table = ff_qt_default_palette_4;
+ else if (colorDepth == 4)
+ color_table = ff_qt_default_palette_16;
+ else
+ color_table = ff_qt_default_palette_256;
+
+ for (byte j = 0; j < color_count; j++) {
+ r = color_table[j * 4 + 0];
+ g = color_table[j * 4 + 1];
+ b = color_table[j * 4 + 2];
+ _palette_control.palette[j] = (r << 16) | (g << 8) | (b);
+ }
+#endif
+
+ } else {
+ debug(0, "Palette from file");
+
+ // load the palette from the file
+ uint32 colorStart = _fd->readUint32BE();
+ /* uint16 colorCount = */ _fd->readUint16BE();
+ uint16 colorEnd = _fd->readUint16BE();
+ for (uint32 j = colorStart; j <= colorEnd; j++) {
+ // each R, G, or B component is 16 bits;
+ // only use the top 8 bits; skip alpha bytes
+ // up front
+ _fd->readByte();
+ _fd->readByte();
+ _palette[j * 3] = _fd->readByte();
+ _fd->readByte();
+ _palette[j * 3 + 1] = _fd->readByte();
+ _fd->readByte();
+ _palette[j * 3 + 2] = _fd->readByte();
+ _fd->readByte();
+ }
+ }
+ st->palettized = true;
+ } else
+ st->palettized = false;
+ } else if (st->codec_type == CODEC_TYPE_AUDIO) {
+ debug(0, "Audio Codec FourCC: \'%s\'", tag2str(format));
+
+ st->stsd_version = _fd->readUint16BE();
+ _fd->readUint16BE(); // revision level
+ _fd->readUint32BE(); // vendor
+
+ st->channels = _fd->readUint16BE(); // channel count
+ st->bits_per_sample = _fd->readUint16BE(); // sample size
+ // do we need to force to 16 for AMR ?
+
+ // handle specific s8 codec
+ _fd->readUint16BE(); // compression id = 0
+ _fd->readUint16BE(); // packet size = 0
+
+ st->sample_rate = (_fd->readUint32BE() >> 16);
+
+ debug(0, "stsd version =%d", st->stsd_version);
+ if (st->stsd_version == 0) {
+ // Not used, except in special cases. See below.
+ st->samples_per_frame = st->bytes_per_frame = 0;
+ } else if (st->stsd_version == 1) {
+ // Read QT version 1 fields. In version 0 these dont exist.
+ st->samples_per_frame = _fd->readUint32BE();
+ debug(0, "stsd samples_per_frame =%d", st->samples_per_frame);
+ _fd->readUint32BE(); // bytes per packet
+ st->bytes_per_frame = _fd->readUint32BE();
+ debug(0, "stsd bytes_per_frame =%d", st->bytes_per_frame);
+ _fd->readUint32BE(); // bytes per sample
+ } else {
+ warning("Unsupported QuickTime STSD audio version %d", st->stsd_version);
+ return 1;
+ }
+
+ // Version 0 videos (such as the Riven ones) don't have this set,
+ // but we need it later on. Add it in here.
+ if (format == MKID_BE('ima4')) {
+ st->samples_per_frame = 64;
+ st->bytes_per_frame = 34 * st->channels;
+ }
+ } else {
+ // other codec type, just skip (rtp, mp4s, tmcd ...)
+ _fd->seek(size - (_fd->pos() - start_pos), SEEK_CUR);
+ }
+
+ // this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...)
+ a.size = size - (_fd->pos() - start_pos);
+ if (a.size > 8)
+ readDefault(a);
+ else if (a.size > 0)
+ _fd->seek(a.size, SEEK_CUR);
+ }
+
+ if (st->codec_type == CODEC_TYPE_AUDIO && st->sample_rate == 0 && st->time_scale > 1)
+ st->sample_rate= st->time_scale;
+
+ return 0;
+}
+
+int QuickTimeDecoder::readSTSC(MOVatom atom) {
+ MOVStreamContext *st = _streams[_numStreams - 1];
+
+ _fd->readByte(); // version
+ _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
+
+ st->sample_to_chunk_sz = _fd->readUint32BE();
+
+ debug(0, "track[%i].stsc.entries = %i", _numStreams - 1, st->sample_to_chunk_sz);
+
+ st->sample_to_chunk = new MOVstsc[st->sample_to_chunk_sz];
+
+ if (!st->sample_to_chunk)
+ return -1;
+
+ for (uint32 i = 0; i < st->sample_to_chunk_sz; i++) {
+ st->sample_to_chunk[i].first = _fd->readUint32BE();
+ st->sample_to_chunk[i].count = _fd->readUint32BE();
+ st->sample_to_chunk[i].id = _fd->readUint32BE();
+ //printf ("Sample to Chunk[%d]: First = %d, Count = %d\n", i, st->sample_to_chunk[i].first, st->sample_to_chunk[i].count);
+ }
+
+ return 0;
+}
+
+int QuickTimeDecoder::readSTSS(MOVatom atom) {
+ MOVStreamContext *st = _streams[_numStreams - 1];
+
+ _fd->readByte(); // version
+ _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
+
+ st->keyframe_count = _fd->readUint32BE();
+
+ debug(0, "keyframe_count = %d", st->keyframe_count);
+
+ st->keyframes = new uint32[st->keyframe_count];
+
+ if (!st->keyframes)
+ return -1;
+
+ for (uint32 i = 0; i < st->keyframe_count; i++) {
+ st->keyframes[i] = _fd->readUint32BE();
+ debug(6, "keyframes[%d] = %d", i, st->keyframes[i]);
+
+ }
+ return 0;
+}
+
+int QuickTimeDecoder::readSTSZ(MOVatom atom) {
+ MOVStreamContext *st = _streams[_numStreams - 1];
+
+ _fd->readByte(); // version
+ _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
+
+ st->sample_size = _fd->readUint32BE();
+ st->sample_count = _fd->readUint32BE();
+
+ debug(5, "sample_size = %d sample_count = %d", st->sample_size, st->sample_count);
+
+ if (st->sample_size)
+ return 0; // there isn't any table following
+
+ st->sample_sizes = new uint32[st->sample_count];
+
+ if (!st->sample_sizes)
+ return -1;
+
+ for(uint32 i = 0; i < st->sample_count; i++) {
+ st->sample_sizes[i] = _fd->readUint32BE();
+ debug(6, "sample_sizes[%d] = %d", i, st->sample_sizes[i]);
+ }
+
+ return 0;
+}
+
+static uint32 ff_gcd(uint32 a, uint32 b) {
+ if(b) return ff_gcd(b, a%b);
+ else return a;
+}
+
+int QuickTimeDecoder::readSTTS(MOVatom atom) {
+ MOVStreamContext *st = _streams[_numStreams - 1];
+ uint32 duration = 0;
+ uint32 total_sample_count = 0;
+
+ _fd->readByte(); // version
+ _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
+
+ st->stts_count = _fd->readUint32BE();
+ st->stts_data = new MOVstts[st->stts_count];
+
+ debug(0, "track[%i].stts.entries = %i", _numStreams - 1, st->stts_count);
+
+ st->time_rate = 0;
+
+ for (int32 i = 0; i < st->stts_count; i++) {
+ int sample_duration;
+ int sample_count;
+
+ sample_count = _fd->readUint32BE();
+ sample_duration = _fd->readUint32BE();
+ st->stts_data[i].count = sample_count;
+ st->stts_data[i].duration = sample_duration;
+
+ st->time_rate = ff_gcd(st->time_rate, sample_duration);
+
+ debug(0, "sample_count=%d, sample_duration=%d", sample_count, sample_duration);
+
+ duration += sample_duration * sample_count;
+ total_sample_count += sample_count;
+ }
+
+ st->nb_frames = total_sample_count;
+
+ if (duration)
+ st->duration = duration;
+
+ return 0;
+}
+
+int QuickTimeDecoder::readSTCO(MOVatom atom) {
+ MOVStreamContext *st = _streams[_numStreams - 1];
+
+ _fd->readByte(); // version
+ _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
+
+ st->chunk_count = _fd->readUint32BE();
+ st->chunk_offsets = new uint32[st->chunk_count];
+
+ if (!st->chunk_offsets)
+ return -1;
+
+ for (uint32 i = 0; i < st->chunk_count; i++) {
+ // WORKAROUND/HACK: The offsets in Riven videos (ones inside the Mohawk archives themselves)
+ // have offsets relative to the archive and not the video. This is quite nasty. We subtract
+ // the initial offset of the stream to get the correct value inside of the stream.
+ st->chunk_offsets[i] = _fd->readUint32BE() - _beginOffset;
+ }
+
+ for (uint32 i = 0; i < _numStreams; i++) {
+ MOVStreamContext *sc2 = _streams[i];
+
+ if(sc2 && sc2->chunk_offsets){
+ uint32 first = sc2->chunk_offsets[0];
+ uint32 last = sc2->chunk_offsets[sc2->chunk_count - 1];
+
+ if(first >= st->chunk_offsets[st->chunk_count - 1] || last <= st->chunk_offsets[0])
+ _ni = 1;
+ }
+ }
+
+ return 0;
+}
+
+int QuickTimeDecoder::readWAVE(MOVatom atom) {
+ if (_numStreams < 1)
+ return 0;
+
+ MOVStreamContext *st = _streams[_numStreams - 1];
+
+ if (atom.size > (1 << 30))
+ return -1;
+
+ if (st->codec_tag == MKID_BE('QDM2')) // Read extradata for QDM2
+ st->extradata = _fd->readStream(atom.size - 8);
+ else if (atom.size > 8)
+ return readDefault(atom);
+ else
+ _fd->skip(atom.size);
+
+ return 0;
+}
+
+void QuickTimeDecoder::close() {
+ stopAudio();
+
+ delete _videoCodec; _videoCodec = 0;
+
+ for (uint32 i = 0; i < _numStreams; i++)
+ delete _streams[i];
+
+ delete _fd;
+ _fd = 0;
+
+ if (_scaledSurface) {
+ _scaledSurface->free();
+ delete _scaledSurface;
+ _scaledSurface = 0;
+ }
+
+ // The audio stream is deleted automatically
+ _audStream = NULL;
+
+ VideoDecoder::reset();
+}
+
+Common::SeekableReadStream *QuickTimeDecoder::getNextFramePacket() {
+ if (_videoStreamIndex < 0)
+ return NULL;
+
+ // First, we have to track down which chunk holds the sample and which sample in the chunk contains the frame we are looking for.
+ int32 totalSampleCount = 0;
+ int32 sampleInChunk = 0;
+ int32 actualChunk = -1;
+
+ for (uint32 i = 0; i < _streams[_videoStreamIndex]->chunk_count; i++) {
+ int32 sampleToChunkIndex = -1;
+
+ for (uint32 j = 0; j < _streams[_videoStreamIndex]->sample_to_chunk_sz; j++)
+ if (i >= _streams[_videoStreamIndex]->sample_to_chunk[j].first - 1)
+ sampleToChunkIndex = j;
+
+ if (sampleToChunkIndex < 0)
+ error("This chunk (%d) is imaginary", sampleToChunkIndex);
+
+ totalSampleCount += _streams[_videoStreamIndex]->sample_to_chunk[sampleToChunkIndex].count;
+
+ if (totalSampleCount > getCurFrame()) {
+ actualChunk = i;
+ sampleInChunk = _streams[_videoStreamIndex]->sample_to_chunk[sampleToChunkIndex].count - totalSampleCount + getCurFrame();
+ break;
+ }
+ }
+
+ if (actualChunk < 0) {
+ warning ("Could not find data for frame %d", getCurFrame());
+ return NULL;
+ }
+
+ // Next seek to that frame
+ _fd->seek(_streams[_videoStreamIndex]->chunk_offsets[actualChunk]);
+
+ // Then, if the chunk holds more than one frame, seek to where the frame we want is located
+ for (int32 i = getCurFrame() - sampleInChunk; i < getCurFrame(); i++) {
+ if (_streams[_videoStreamIndex]->sample_size != 0)
+ _fd->skip(_streams[_videoStreamIndex]->sample_size);
+ else
+ _fd->skip(_streams[_videoStreamIndex]->sample_sizes[i]);
+ }
+
+ // Finally, read in the raw data for the frame
+ //printf ("Frame Data[%d]: Offset = %d, Size = %d\n", getCurFrame(), _fd->pos(), _streams[_videoStreamIndex]->sample_sizes[getCurFrame()]);
+
+ if (_streams[_videoStreamIndex]->sample_size != 0)
+ return _fd->readStream(_streams[_videoStreamIndex]->sample_size);
+
+ return _fd->readStream(_streams[_videoStreamIndex]->sample_sizes[getCurFrame()]);
+}
+
+bool QuickTimeDecoder::checkAudioCodecSupport(uint32 tag) {
+ // Check if the codec is a supported codec
+ if (tag == MKID_BE('twos') || tag == MKID_BE('raw ') || tag == MKID_BE('ima4'))
+ return true;
+
+#ifdef GRAPHICS_QDM2_H
+ if (tag == MKID_BE('QDM2'))
+ return true;
+#endif
+
+ warning("Audio Codec Not Supported: \'%s\'", tag2str(tag));
+
+ return false;
+}
+
+Audio::AudioStream *QuickTimeDecoder::createAudioStream(Common::SeekableReadStream *stream) {
+ if (!stream || _audioStreamIndex < 0)
+ return NULL;
+
+ if (_streams[_audioStreamIndex]->codec_tag == MKID_BE('twos') || _streams[_audioStreamIndex]->codec_tag == MKID_BE('raw ')) {
+ // Fortunately, most of the audio used in Myst videos is raw...
+ uint16 flags = 0;
+ if (_streams[_audioStreamIndex]->codec_tag == MKID_BE('raw '))
+ flags |= Audio::FLAG_UNSIGNED;
+ if (_streams[_audioStreamIndex]->channels == 2)
+ flags |= Audio::FLAG_STEREO;
+ if (_streams[_audioStreamIndex]->bits_per_sample == 16)
+ flags |= Audio::FLAG_16BITS;
+ uint32 dataSize = stream->size();
+ byte *data = (byte *)malloc(dataSize);
+ stream->read(data, dataSize);
+ delete stream;
+ return Audio::makeRawStream(data, dataSize, _streams[_audioStreamIndex]->sample_rate, flags);
+ } else if (_streams[_audioStreamIndex]->codec_tag == MKID_BE('ima4')) {
+ // Riven uses this codec (as do some Myst ME videos)
+ return Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMApple, _streams[_audioStreamIndex]->sample_rate, _streams[_audioStreamIndex]->channels, 34);
+#ifdef GRAPHICS_QDM2_H
+ } else if (_streams[_audioStreamIndex]->codec_tag == MKID_BE('QDM2')) {
+ // Several Myst ME videos use this codec
+ return makeQDM2Stream(stream, _streams[_audioStreamIndex]->extradata);
+#endif
+ }
+
+ error("Unsupported audio codec");
+
+ return NULL;
+}
+
+void QuickTimeDecoder::updateAudioBuffer() {
+ if (!_audStream)
+ return;
+
+ // Keep three streams in buffer so that if/when the first two end, it goes right into the next
+ for (; _audStream->numQueuedStreams() < 3 && _curAudioChunk < _streams[_audioStreamIndex]->chunk_count; _curAudioChunk++) {
+ Common::MemoryWriteStreamDynamic *wStream = new Common::MemoryWriteStreamDynamic();
+
+ _fd->seek(_streams[_audioStreamIndex]->chunk_offsets[_curAudioChunk]);
+
+ // First, we have to get the sample count
+ uint32 sampleCount = 0;
+ for (uint32 j = 0; j < _streams[_audioStreamIndex]->sample_to_chunk_sz; j++)
+ if (_curAudioChunk >= (_streams[_audioStreamIndex]->sample_to_chunk[j].first - 1))
+ sampleCount = _streams[_audioStreamIndex]->sample_to_chunk[j].count;
+ assert(sampleCount);
+
+ // Then calculate the right sizes
+ while (sampleCount > 0) {
+ uint32 samples = 0, size = 0;
+
+ if (_streams[_audioStreamIndex]->samples_per_frame >= 160) {
+ samples = _streams[_audioStreamIndex]->samples_per_frame;
+ size = _streams[_audioStreamIndex]->bytes_per_frame;
+ } else if (_streams[_audioStreamIndex]->samples_per_frame > 1) {
+ samples = MIN<uint32>((1024 / _streams[_audioStreamIndex]->samples_per_frame) * _streams[_audioStreamIndex]->samples_per_frame, sampleCount);
+ size = (samples / _streams[_audioStreamIndex]->samples_per_frame) * _streams[_audioStreamIndex]->bytes_per_frame;
+ } else {
+ samples = MIN<uint32>(1024, sampleCount);
+ size = samples * _streams[_audioStreamIndex]->sample_size;
+ }
+
+ // Now, we read in the data for this data and output it
+ byte *data = (byte *)malloc(size);
+ _fd->read(data, size);
+ wStream->write(data, size);
+ free(data);
+ sampleCount -= samples;
+ }
+
+ // Now queue the buffer
+ _audStream->queueAudioStream(createAudioStream(new Common::MemoryReadStream(wStream->getData(), wStream->size(), DisposeAfterUse::YES)));
+ delete wStream;
+ }
+}
+
+} // End of namespace Graphics
diff --git a/graphics/video/qt_decoder.h b/graphics/video/qt_decoder.h
new file mode 100644
index 0000000000..196d4c02cb
--- /dev/null
+++ b/graphics/video/qt_decoder.h
@@ -0,0 +1,289 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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$
+ *
+ */
+
+//
+// Heavily based on ffmpeg code.
+//
+// Copyright (c) 2001 Fabrice Bellard.
+// First version by Francois Revol revol@free.fr
+// Seek function by Gael Chardon gael.dev@4now.net
+//
+
+#ifndef GRAPHICS_QT_DECODER_H
+#define GRAPHICS_QT_DECODER_H
+
+#include "common/scummsys.h"
+#include "common/queue.h"
+
+#include "graphics/video/video_decoder.h"
+#include "graphics/video/codecs/codec.h"
+
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+
+namespace Common {
+ class File;
+ class MacResManager;
+}
+
+namespace Graphics {
+
+enum ScaleMode {
+ kScaleNormal = 1,
+ kScaleHalf = 2,
+ kScaleQuarter = 4
+};
+
+class QuickTimeDecoder : public RewindableVideoDecoder {
+public:
+ QuickTimeDecoder();
+ virtual ~QuickTimeDecoder();
+
+ /**
+ * Returns the width of the video
+ * @return the width of the video
+ */
+ uint16 getWidth() const;
+
+ /**
+ * Returns the height of the video
+ * @return the height of the video
+ */
+ uint16 getHeight() const;
+
+ /**
+ * Returns the amount of frames in the video
+ * @return the amount of frames in the video
+ */
+ uint32 getFrameCount() const;
+
+ /**
+ * Load a video file
+ * @param filename the filename to load
+ */
+ bool loadFile(const Common::String &filename);
+
+ /**
+ * Load a QuickTime video file from a SeekableReadStream
+ * @param stream the stream to load
+ */
+ bool load(Common::SeekableReadStream *stream);
+
+ /**
+ * Close a QuickTime encoded video file
+ */
+ void close();
+
+ /**
+ * Returns the palette of the video
+ * @return the palette of the video
+ */
+ byte *getPalette() { _dirtyPalette = false; return _palette; }
+ bool hasDirtyPalette() const { return _dirtyPalette; }
+
+ /**
+ * Set the beginning offset of the video so we can modify the offsets in the stco
+ * atom of videos inside the Mohawk archives
+ * @param the beginning offset of the video
+ */
+ void setChunkBeginOffset(uint32 offset) { _beginOffset = offset; }
+
+ bool isVideoLoaded() const { return _fd != 0; }
+ Surface *decodeNextFrame();
+ bool endOfVideo() const;
+ uint32 getElapsedTime() const;
+ uint32 getTimeToNextFrame() const;
+ PixelFormat getPixelFormat() const;
+
+ // RewindableVideoDecoder API
+ void rewind();
+
+ // TODO: This audio function need to be removed from the public and/or added to
+ // the VideoDecoder API directly. I plan on replacing this function with something
+ // that can figure out how much audio is needed instead of constantly keeping two
+ // chunks in memory.
+ void updateAudioBuffer();
+
+protected:
+ // This is the file handle from which data is read from. It can be the actual file handle or a decompressed stream.
+ Common::SeekableReadStream *_fd;
+
+ struct MOVatom {
+ uint32 type;
+ uint32 offset;
+ uint32 size;
+ };
+
+ struct ParseTable {
+ int (QuickTimeDecoder::*func)(MOVatom atom);
+ uint32 type;
+ };
+
+ struct MOVstts {
+ int count;
+ int duration;
+ };
+
+ struct MOVstsc {
+ uint32 first;
+ uint32 count;
+ uint32 id;
+ };
+
+ enum CodecType {
+ CODEC_TYPE_MOV_OTHER,
+ CODEC_TYPE_VIDEO,
+ CODEC_TYPE_AUDIO
+ };
+
+ struct MOVStreamContext {
+ MOVStreamContext() { memset(this, 0, sizeof(MOVStreamContext)); }
+ ~MOVStreamContext() {
+ delete[] chunk_offsets;
+ delete[] stts_data;
+ delete[] ctts_data;
+ delete[] sample_to_chunk;
+ delete[] sample_sizes;
+ delete[] keyframes;
+ delete extradata;
+ }
+
+ int ffindex; /* the ffmpeg stream id */
+ int is_ff_stream; /* Is this stream presented to ffmpeg ? i.e. is this an audio or video stream ? */
+ uint32 next_chunk;
+ uint32 chunk_count;
+ uint32 *chunk_offsets;
+ int stts_count;
+ MOVstts *stts_data;
+ int ctts_count;
+ MOVstts *ctts_data;
+ int edit_count; /* number of 'edit' (elst atom) */
+ uint32 sample_to_chunk_sz;
+ MOVstsc *sample_to_chunk;
+ int32 sample_to_chunk_index;
+ int sample_to_time_index;
+ uint32 sample_to_time_sample;
+ uint32 sample_to_time_time;
+ int sample_to_ctime_index;
+ int sample_to_ctime_sample;
+ uint32 sample_size;
+ uint32 sample_count;
+ uint32 *sample_sizes;
+ uint32 keyframe_count;
+ uint32 *keyframes;
+ int32 time_scale;
+ int time_rate;
+ uint32 current_sample;
+ uint32 left_in_chunk; /* how many samples before next chunk */
+
+ uint16 width;
+ uint16 height;
+ int codec_type;
+ uint32 codec_tag;
+ char codec_name[32];
+ uint16 bits_per_sample;
+ uint16 color_table_id;
+ bool palettized;
+ Common::SeekableReadStream *extradata;
+
+ uint16 stsd_version;
+ uint16 channels;
+ uint16 sample_rate;
+ uint32 samples_per_frame;
+ uint32 bytes_per_frame;
+
+ uint32 nb_frames;
+ uint32 duration;
+ uint32 start_time;
+ ScaleMode scaleMode;
+ };
+
+ const ParseTable *_parseTable;
+ bool _foundMOOV;
+ bool _foundMDAT;
+ uint32 _timeScale;
+ uint32 _duration;
+ uint32 _mdatOffset;
+ uint32 _mdatSize;
+ MOVStreamContext *_partial;
+ uint32 _numStreams;
+ int _ni;
+ ScaleMode _scaleMode;
+ MOVStreamContext *_streams[20];
+ byte _palette[256 * 3];
+ bool _dirtyPalette;
+ uint32 _beginOffset;
+ Common::MacResManager *_resFork;
+
+ void initParseTable();
+ Audio::AudioStream *createAudioStream(Common::SeekableReadStream *stream);
+ bool checkAudioCodecSupport(uint32 tag);
+ Common::SeekableReadStream *getNextFramePacket();
+ uint32 getFrameDuration();
+ uint32 getCodecTag();
+ byte getBitsPerPixel();
+ void init();
+
+ Audio::QueuingAudioStream *_audStream;
+ void startAudio();
+ void stopAudio();
+ int8 _audioStreamIndex;
+ uint _curAudioChunk;
+ Audio::SoundHandle _audHandle;
+
+ Codec *createCodec(uint32 codecTag, byte bitsPerPixel);
+ Codec *_videoCodec;
+ uint32 _nextFrameStartTime;
+ int8 _videoStreamIndex;
+
+ Surface *_scaledSurface;
+ Surface *scaleSurface(Surface *frame);
+ ScaleMode getScaleMode() const;
+
+ void pauseVideoIntern(bool pause);
+
+ int readDefault(MOVatom atom);
+ int readLeaf(MOVatom atom);
+ int readELST(MOVatom atom);
+ int readHDLR(MOVatom atom);
+ int readMDAT(MOVatom atom);
+ int readMDHD(MOVatom atom);
+ int readMOOV(MOVatom atom);
+ int readMVHD(MOVatom atom);
+ int readTKHD(MOVatom atom);
+ int readTRAK(MOVatom atom);
+ int readSTCO(MOVatom atom);
+ int readSTSC(MOVatom atom);
+ int readSTSD(MOVatom atom);
+ int readSTSS(MOVatom atom);
+ int readSTSZ(MOVatom atom);
+ int readSTTS(MOVatom atom);
+ int readCMOV(MOVatom atom);
+ int readWAVE(MOVatom atom);
+};
+
+} // End of namespace Graphics
+
+#endif
diff --git a/graphics/video/smk_decoder.cpp b/graphics/video/smk_decoder.cpp
index 3f200b5971..4d03305cce 100644
--- a/graphics/video/smk_decoder.cpp
+++ b/graphics/video/smk_decoder.cpp
@@ -25,7 +25,7 @@
// Based on http://wiki.multimedia.cx/index.php?title=Smacker
// and the FFmpeg Smacker decoder (libavcodec/smacker.c), revision 16143
-// http://svn.ffmpeg.org/ffmpeg/trunk/libavcodec/smacker.c?revision=16143&view=markup
+// http://git.ffmpeg.org/?p=ffmpeg;a=blob;f=libavcodec/smacker.c;hb=b8437a00a2f14d4a437346455d624241d726128e
#include "graphics/video/smk_decoder.h"
@@ -361,16 +361,16 @@ SmackerDecoder::~SmackerDecoder() {
}
uint32 SmackerDecoder::getElapsedTime() const {
- if (_audioStream)
+ if (_audioStream && _audioStarted)
return _mixer->getSoundElapsedTime(_audioHandle);
return VideoDecoder::getElapsedTime();
}
-bool SmackerDecoder::load(Common::SeekableReadStream &stream) {
+bool SmackerDecoder::load(Common::SeekableReadStream *stream) {
close();
- _fileStream = &stream;
+ _fileStream = stream;
// Seek to the first frame
_header.signature = _fileStream->readUint32BE();
diff --git a/graphics/video/smk_decoder.h b/graphics/video/smk_decoder.h
index 6bf671f318..43bb84a4f8 100644
--- a/graphics/video/smk_decoder.h
+++ b/graphics/video/smk_decoder.h
@@ -57,7 +57,7 @@ public:
Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType);
virtual ~SmackerDecoder();
- bool load(Common::SeekableReadStream &stream);
+ bool load(Common::SeekableReadStream *stream);
void close();
bool isVideoLoaded() const { return _fileStream != 0; }
diff --git a/graphics/video/video_decoder.cpp b/graphics/video/video_decoder.cpp
index fe4a5848f3..081f47bf78 100644
--- a/graphics/video/video_decoder.cpp
+++ b/graphics/video/video_decoder.cpp
@@ -42,7 +42,7 @@ bool VideoDecoder::loadFile(const Common::String &filename) {
return false;
}
- return load(*file);
+ return load(file);
}
uint32 VideoDecoder::getElapsedTime() const {
@@ -64,7 +64,7 @@ void VideoDecoder::setSystemPalette() {
delete[] sysPalette;
}
-bool VideoDecoder::needsUpdate() const {
+bool VideoDecoder::needsUpdate() const {
return !endOfVideo() && getTimeToNextFrame() == 0;
}
@@ -81,9 +81,14 @@ bool VideoDecoder::endOfVideo() const {
void VideoDecoder::pauseVideo(bool pause) {
if (pause) {
_pauseLevel++;
- } else {
- assert(_pauseLevel); // We can't go negative
+
+ // We can't go negative
+ } else if (_pauseLevel) {
_pauseLevel--;
+
+ // Do nothing
+ } else {
+ return;
}
if (_pauseLevel == 1 && pause) {
diff --git a/graphics/video/video_decoder.h b/graphics/video/video_decoder.h
index d96545d2c1..a398a62009 100644
--- a/graphics/video/video_decoder.h
+++ b/graphics/video/video_decoder.h
@@ -93,7 +93,7 @@ public:
* Load a video file
* @param stream the stream to load
*/
- virtual bool load(Common::SeekableReadStream &stream) = 0;
+ virtual bool load(Common::SeekableReadStream *stream) = 0;
/**
* Close a video file
diff --git a/gui/EditTextWidget.cpp b/gui/EditTextWidget.cpp
index 658ac21117..7079453173 100644
--- a/gui/EditTextWidget.cpp
+++ b/gui/EditTextWidget.cpp
@@ -30,16 +30,16 @@
namespace GUI {
-EditTextWidget::EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text, uint32 cmd)
- : EditableWidget(boss, x, y - 1, w, h + 2, cmd) {
+EditTextWidget::EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text, const char *tooltip, uint32 cmd)
+ : EditableWidget(boss, x, y - 1, w, h + 2, tooltip, cmd) {
setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE);
_type = kEditTextWidget;
setEditString(text);
}
-EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String &text, uint32 cmd)
- : EditableWidget(boss, name, cmd) {
+EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String &text, const char *tooltip, uint32 cmd)
+ : EditableWidget(boss, name, tooltip, cmd) {
setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE);
_type = kEditTextWidget;
diff --git a/gui/EditTextWidget.h b/gui/EditTextWidget.h
index 5a5823cfb1..9c4ef03648 100644
--- a/gui/EditTextWidget.h
+++ b/gui/EditTextWidget.h
@@ -41,8 +41,8 @@ protected:
int _rightPadding;
public:
- EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text, uint32 cmd = 0);
- EditTextWidget(GuiObject *boss, const String &name, const String &text, uint32 cmd = 0);
+ EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text, const char *tooltip = 0, uint32 cmd = 0);
+ EditTextWidget(GuiObject *boss, const String &name, const String &text, const char *tooltp = 0, uint32 cmd = 0);
void setEditString(const String &str);
diff --git a/gui/GuiManager.cpp b/gui/GuiManager.cpp
index 99fb3be4dc..bbd7718d71 100644
--- a/gui/GuiManager.cpp
+++ b/gui/GuiManager.cpp
@@ -27,6 +27,8 @@
#include "common/util.h"
#include "common/config-manager.h"
#include "common/algorithm.h"
+#include "common/timer.h"
+#include "common/translation.h"
#include "backends/keymapper/keymapper.h"
@@ -43,12 +45,13 @@ namespace GUI {
enum {
kDoubleClickDelay = 500, // milliseconds
- kCursorAnimateDelay = 250
+ kCursorAnimateDelay = 250,
+ kTooltipDelay = 1250
};
// Constructor
-GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled),
- _stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0) {
+GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled), _tooltipCheck(false),
+ _stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0) {
_theme = 0;
_useStdCursor = false;
@@ -74,10 +77,13 @@ GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled),
error("Failed to load any GUI theme, aborting");
}
}
+
+ _tooltip = 0;
}
GuiManager::~GuiManager() {
delete _theme;
+ delete _tooltip;
}
#ifdef ENABLE_KEYMAPPER
@@ -94,27 +100,28 @@ void GuiManager::initKeymap() {
Action *act;
Keymap *guiMap = new Keymap("gui");
- act = new Action(guiMap, "CLOS", "Close", kGenericActionType, kStartKeyType);
+ act = new Action(guiMap, "CLOS", _("Close"), kGenericActionType, kStartKeyType);
act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0));
- act = new Action(guiMap, "CLIK", "Mouse click");
+ act = new Action(guiMap, "CLIK", _("Mouse click"));
act->addLeftClickEvent();
- act = new Action(guiMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType);
+ act = new Action(guiMap, "VIRT", _("Display keyboard"), kVirtualKeyboardActionType);
act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0));
- act = new Action(guiMap, "REMP", "Remap keys", kKeyRemapActionType);
+ act = new Action(guiMap, "REMP", _("Remap keys"), kKeyRemapActionType);
act->addKeyEvent(KeyState(KEYCODE_F8, ASCII_F8, 0));
mapper->addGlobalKeymap(guiMap);
}
#endif
-bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx) {
+bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx, bool forced) {
// If we are asked to reload the currently active theme, just do nothing
// FIXME: Actually, why? It might be desirable at times to force a theme reload...
- if (_theme && id == _theme->getThemeId() && gfx == _theme->getGraphicsMode())
- return true;
+ if (!forced)
+ if (_theme && id == _theme->getThemeId() && gfx == _theme->getGraphicsMode())
+ return true;
ThemeEngine *newTheme = 0;
@@ -242,6 +249,9 @@ void GuiManager::runLoop() {
redraw();
}
+ _lastMousePosition.x = _lastMousePosition.y = -1;
+ _lastMousePosition.time = 0;
+
Common::EventManager *eventMan = _system->getEventManager();
uint32 lastRedraw = 0;
const uint32 waitTime = 1000 / 45;
@@ -276,6 +286,8 @@ void GuiManager::runLoop() {
}
Common::Event event;
+
+ bool eventTookplace = false;
while (eventMan->pollEvent(event)) {
// The top dialog can change during the event loop. In that case, flush all the
@@ -298,16 +310,28 @@ void GuiManager::runLoop() {
switch (event.type) {
case Common::EVENT_KEYDOWN:
activeDialog->handleKeyDown(event.kbd);
+ eventTookplace = true;
break;
case Common::EVENT_KEYUP:
activeDialog->handleKeyUp(event.kbd);
+ eventTookplace = true;
break;
case Common::EVENT_MOUSEMOVE:
activeDialog->handleMouseMoved(mouse.x, mouse.y, 0);
+
+ if (mouse.x != _lastMousePosition.x || mouse.y != _lastMousePosition.y) {
+ _lastMousePosition.x = mouse.x;
+ _lastMousePosition.y = mouse.y;
+ _lastMousePosition.time = _system->getMillis();
+ }
+
+ _tooltipCheck = true;
+ eventTookplace = true;
break;
// We don't distinguish between mousebuttons (for now at least)
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_RBUTTONDOWN:
+ eventTookplace = true;
button = (event.type == Common::EVENT_LBUTTONDOWN ? 1 : 2);
time = _system->getMillis();
if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay)
@@ -324,18 +348,22 @@ void GuiManager::runLoop() {
break;
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
+ eventTookplace = true;
button = (event.type == Common::EVENT_LBUTTONUP ? 1 : 2);
activeDialog->handleMouseUp(mouse.x, mouse.y, button, _lastClick.count);
break;
case Common::EVENT_WHEELUP:
+ eventTookplace = true;
activeDialog->handleMouseWheel(mouse.x, mouse.y, -1);
break;
case Common::EVENT_WHEELDOWN:
+ eventTookplace = true;
activeDialog->handleMouseWheel(mouse.x, mouse.y, 1);
break;
case Common::EVENT_QUIT:
return;
case Common::EVENT_SCREEN_CHANGED:
+ eventTookplace = true;
screenChange();
break;
default:
@@ -343,6 +371,18 @@ void GuiManager::runLoop() {
}
}
+ if (_tooltipCheck && _lastMousePosition.time + kTooltipDelay < _system->getMillis()) {
+ if (_tooltip == 0)
+ _tooltip = new Tooltip();
+
+ _tooltipCheck = false;
+ _tooltip->tooltipModal(_lastMousePosition.x, _lastMousePosition.y);
+ }
+
+ if (eventTookplace && _tooltip) {
+ _tooltip->mustClose();
+ }
+
// Delay for a moment
_system->delayMillis(10);
}
diff --git a/gui/GuiManager.h b/gui/GuiManager.h
index 892d1aa3ac..ee1351dc9b 100644
--- a/gui/GuiManager.h
+++ b/gui/GuiManager.h
@@ -33,6 +33,7 @@
#include "graphics/font.h"
#include "gui/widget.h"
+#include "gui/Tooltip.h"
#include "gui/ThemeEngine.h"
class OSystem;
@@ -60,6 +61,7 @@ typedef Common::FixedStack<Dialog *> DialogStack;
*/
class GuiManager : public Common::Singleton<GuiManager> {
friend class Dialog;
+ friend class Tooltip;
friend class Common::Singleton<SingletonBaseType>;
GuiManager();
~GuiManager();
@@ -71,7 +73,7 @@ public:
bool isActive() const { return ! _dialogStack.empty(); }
- bool loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled);
+ bool loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled, bool force = false);
ThemeEngine *theme() { return _theme; }
ThemeEval *xmlEval() { return _theme->getEvaluator(); }
@@ -91,6 +93,7 @@ public:
* @return true if the a screen change indeed occurred, false otherwise
*/
bool checkScreenChange();
+
protected:
enum RedrawStatus {
kRedrawDisabled = 0,
@@ -114,12 +117,15 @@ protected:
bool _useStdCursor;
+ Tooltip *_tooltip;
+ bool _tooltipCheck;
+
// position and time of last mouse click (used to detect double clicks)
struct {
- int16 x, y; // Position of mouse when the click occured
+ int16 x, y; // Position of mouse when the click occurred
uint32 time; // Time
int count; // How often was it already pressed?
- } _lastClick;
+ } _lastClick, _lastMousePosition;
// mouse cursor state
int _cursorAnimateCounter;
diff --git a/gui/KeysDialog.cpp b/gui/KeysDialog.cpp
index b80dd200bb..897dd8c741 100644
--- a/gui/KeysDialog.cpp
+++ b/gui/KeysDialog.cpp
@@ -25,6 +25,7 @@
#include "gui/KeysDialog.h"
#include "gui/Actions.h"
+#include "common/translation.h"
#include <SDL_keyboard.h>
#ifdef _WIN32_WCE
@@ -40,15 +41,15 @@ enum {
KeysDialog::KeysDialog(const Common::String &title)
: GUI::Dialog("KeysDialog") {
- new ButtonWidget(this, "KeysDialog.Map", "Map", kMapCmd, 0);
- new ButtonWidget(this, "KeysDialog.Ok", "OK", kOKCmd, 0);
- new ButtonWidget(this, "KeysDialog.Cancel", "Cancel", kCloseCmd, 0);
+ new ButtonWidget(this, "KeysDialog.Map", _("Map"), 0, kMapCmd);
+ new ButtonWidget(this, "KeysDialog.Ok", _("OK"), 0, kOKCmd);
+ new ButtonWidget(this, "KeysDialog.Cancel", _("Cancel"), 0, kCloseCmd);
_actionsList = new ListWidget(this, "KeysDialog.List");
_actionsList->setNumberingMode(kListNumberingZero);
_actionTitle = new StaticTextWidget(this, "KeysDialog.Action", title);
- _keyMapping = new StaticTextWidget(this, "KeysDialog.Mapping", "Select an action and click 'Map'");
+ _keyMapping = new StaticTextWidget(this, "KeysDialog.Mapping", _("Select an action and click 'Map'"));
_actionTitle->setFlags(WIDGET_CLEARBG);
_keyMapping->setFlags(WIDGET_CLEARBG);
@@ -79,9 +80,9 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
key = key - Common::ASCII_F1 + SDLK_F1;
#endif
if (key != 0)
- sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey)key));
+ sprintf(selection, _("Associated key : %s"), SDL_GetKeyName((SDLKey)key));
else
- sprintf(selection, "Associated key : none");
+ sprintf(selection, _("Associated key : none"));
_keyMapping->setLabel(selection);
_keyMapping->draw();
@@ -89,7 +90,7 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
break;
case kMapCmd:
if (_actionsList->getSelected() < 0) {
- _actionTitle->setLabel("Please select an action");
+ _actionTitle->setLabel(_("Please select an action"));
} else {
char selection[100];
@@ -101,11 +102,11 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
key = key - Common::ASCII_F1 + SDLK_F1;
#endif
if (key != 0)
- sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey)key));
+ sprintf(selection, _("Associated key : %s"), SDL_GetKeyName((SDLKey)key));
else
- sprintf(selection, "Associated key : none");
+ sprintf(selection, _("Associated key : none"));
- _actionTitle->setLabel("Press the key to associate");
+ _actionTitle->setLabel(_("Press the key to associate"));
_keyMapping->setLabel(selection);
_keyMapping->draw();
Actions::Instance()->beginMapping(true);
@@ -140,11 +141,11 @@ void KeysDialog::handleKeyUp(Common::KeyState state) {
Actions::Instance()->setMapping((ActionType)_actionSelected, state.ascii);
if (state.ascii != 0)
- sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey) state.keycode));
+ sprintf(selection, _("Associated key : %s"), SDL_GetKeyName((SDLKey) state.keycode));
else
- sprintf(selection, "Associated key : none");
+ sprintf(selection, _("Associated key : none"));
- _actionTitle->setLabel("Choose an action to map");
+ _actionTitle->setLabel(_("Choose an action to map"));
_keyMapping->setLabel(selection);
_keyMapping->draw();
_actionTitle->draw();
diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp
index ad6c7e0c3a..4447b62244 100644
--- a/gui/ListWidget.cpp
+++ b/gui/ListWidget.cpp
@@ -36,8 +36,8 @@
namespace GUI {
-ListWidget::ListWidget(GuiObject *boss, const String &name, uint32 cmd)
- : EditableWidget(boss, name), _cmd(cmd) {
+ListWidget::ListWidget(Dialog *boss, const String &name, const char *tooltip, uint32 cmd)
+ : EditableWidget(boss, name, tooltip), _cmd(cmd) {
_scrollBar = NULL;
_textWidth = NULL;
@@ -68,8 +68,8 @@ ListWidget::ListWidget(GuiObject *boss, const String &name, uint32 cmd)
_editColor = ThemeEngine::kFontColorNormal;
}
-ListWidget::ListWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd)
- : EditableWidget(boss, x, y, w, h), _cmd(cmd) {
+ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd)
+ : EditableWidget(boss, x, y, w, h, tooltip), _cmd(cmd) {
_scrollBar = NULL;
_textWidth = NULL;
@@ -439,11 +439,6 @@ bool ListWidget::handleKeyDown(Common::KeyState state) {
_scrollBar->draw();
}
-#if !defined(PALMOS_MODE)
- // not done on PalmOS because keyboard is emulated and keyup is not generated
- _currentKeyDown = state.keycode;
-#endif
-
return handled;
}
@@ -472,6 +467,10 @@ void ListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
if (_currentPos != (int)data) {
_currentPos = data;
draw();
+
+ // Scrollbar actions cause list focus (which triggers a redraw)
+ // NOTE: ListWidget's boss is always GUI::Dialog
+ ((GUI::Dialog *)_boss)->setFocusWidget(this);
}
break;
}
diff --git a/gui/ListWidget.h b/gui/ListWidget.h
index 02f2c22e7c..3858fa6de2 100644
--- a/gui/ListWidget.h
+++ b/gui/ListWidget.h
@@ -87,8 +87,8 @@ protected:
ThemeEngine::FontColor _editColor;
public:
- ListWidget(GuiObject *boss, const String &name, uint32 cmd = 0);
- ListWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd = 0);
+ ListWidget(Dialog *boss, const String &name, const char *tooltip = 0, uint32 cmd = 0);
+ ListWidget(Dialog *boss, int x, int y, int w, int h, const char *tooltip = 0, uint32 cmd = 0);
virtual ~ListWidget();
virtual Widget *findWidget(int x, int y);
diff --git a/gui/PopUpWidget.cpp b/gui/PopUpWidget.cpp
index 7463399e0b..1bd9cc5063 100644
--- a/gui/PopUpWidget.cpp
+++ b/gui/PopUpWidget.cpp
@@ -378,8 +378,8 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) {
// PopUpWidget
//
-PopUpWidget::PopUpWidget(GuiObject *boss, const String &name)
- : Widget(boss, name), CommandSender(boss) {
+PopUpWidget::PopUpWidget(GuiObject *boss, const String &name, const char *tooltip)
+ : Widget(boss, name, tooltip), CommandSender(boss) {
setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_IGNORE_DRAG);
_type = kPopUpWidget;
diff --git a/gui/PopUpWidget.h b/gui/PopUpWidget.h
index bd1d3b3918..f2c1728b52 100644
--- a/gui/PopUpWidget.h
+++ b/gui/PopUpWidget.h
@@ -59,13 +59,14 @@ protected:
int _rightPadding;
public:
- PopUpWidget(GuiObject *boss, const String &name);
+ PopUpWidget(GuiObject *boss, const String &name, const char *tooltip = 0);
void handleMouseDown(int x, int y, int button, int clickCount);
void handleMouseWheel(int x, int y, int direction);
void appendEntry(const String &entry, uint32 tag = (uint32)-1);
void clearEntries();
+ int numEntries() { return _entries.size(); }
/** Select the entry at the given index. */
void setSelected(int item);
diff --git a/gui/ScrollBarWidget.cpp b/gui/ScrollBarWidget.cpp
index f6b36b3aa0..f4aaa8ffc9 100644
--- a/gui/ScrollBarWidget.cpp
+++ b/gui/ScrollBarWidget.cpp
@@ -26,6 +26,8 @@
#include "gui/dialog.h"
#include "gui/GuiManager.h"
+#include "common/timer.h"
+
namespace GUI {
#define UP_DOWN_BOX_HEIGHT (_w+1)
@@ -47,6 +49,28 @@ ScrollBarWidget::ScrollBarWidget(GuiObject *boss, int x, int y, int w, int h)
_currentPos = 0;
}
+static void upArrowRepeater(void *ref) {
+ ScrollBarWidget *sb = (ScrollBarWidget *)ref;
+ int old_pos = sb->_currentPos;
+
+ sb->_currentPos -= 3;
+ sb->checkBounds(old_pos);
+
+ g_system->getTimerManager()->removeTimerProc(&upArrowRepeater);
+ g_system->getTimerManager()->installTimerProc(&upArrowRepeater, 1000000/10, ref);
+}
+
+static void downArrowRepeater(void *ref) {
+ ScrollBarWidget *sb = (ScrollBarWidget *)ref;
+ int old_pos = sb->_currentPos;
+
+ sb->_currentPos += 3;
+ sb->checkBounds(old_pos);
+
+ g_system->getTimerManager()->removeTimerProc(&downArrowRepeater);
+ g_system->getTimerManager()->installTimerProc(&downArrowRepeater, 1000000/10, ref);
+}
+
void ScrollBarWidget::handleMouseDown(int x, int y, int button, int clickCount) {
int old_pos = _currentPos;
@@ -58,10 +82,12 @@ void ScrollBarWidget::handleMouseDown(int x, int y, int button, int clickCount)
// Up arrow
_currentPos--;
_draggingPart = kUpArrowPart;
+ g_system->getTimerManager()->installTimerProc(&upArrowRepeater, 1000000/2, this);
} else if (y >= _h - UP_DOWN_BOX_HEIGHT) {
// Down arrow
_currentPos++;
_draggingPart = kDownArrowPart;
+ g_system->getTimerManager()->installTimerProc(&downArrowRepeater, 1000000/2, this);
} else if (y < _sliderPos) {
_currentPos -= _entriesPerPage - 1;
} else if (y >= _sliderPos + _sliderHeight) {
@@ -77,6 +103,9 @@ void ScrollBarWidget::handleMouseDown(int x, int y, int button, int clickCount)
void ScrollBarWidget::handleMouseUp(int x, int y, int button, int clickCount) {
_draggingPart = kNoPart;
+
+ g_system->getTimerManager()->removeTimerProc(&upArrowRepeater);
+ g_system->getTimerManager()->removeTimerProc(&downArrowRepeater);
}
void ScrollBarWidget::handleMouseWheel(int x, int y, int direction) {
diff --git a/gui/ScrollBarWidget.h b/gui/ScrollBarWidget.h
index 9379736f05..dd2b702686 100644
--- a/gui/ScrollBarWidget.h
+++ b/gui/ScrollBarWidget.h
@@ -73,9 +73,10 @@ public:
// should these accessors force a redraw?
void recalc();
+ void checkBounds(int old_pos);
+
protected:
void drawWidget();
- void checkBounds(int old_pos);
};
} // End of namespace GUI
diff --git a/gui/TabWidget.cpp b/gui/TabWidget.cpp
index 3eb45297f3..ca409e50ab 100644
--- a/gui/TabWidget.cpp
+++ b/gui/TabWidget.cpp
@@ -37,12 +37,12 @@ enum {
};
TabWidget::TabWidget(GuiObject *boss, int x, int y, int w, int h)
- : Widget(boss, x, y, w, h) {
+ : Widget(boss, x, y, w, h), _bodyBackgroundType(GUI::ThemeEngine::kDialogBackgroundDefault) {
init();
}
TabWidget::TabWidget(GuiObject *boss, const String &name)
- : Widget(boss, name) {
+ : Widget(boss, name), _bodyBackgroundType(GUI::ThemeEngine::kDialogBackgroundDefault) {
init();
}
@@ -56,15 +56,20 @@ void TabWidget::init() {
_tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height");
_titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top");
- _butRP = g_gui.xmlEval()->getVar("Globals.TabWidget.navButtonPadding.Right", 0);
+ _bodyTP = g_gui.xmlEval()->getVar("Globals.TabWidget.Body.Padding.Top");
+ _bodyBP = g_gui.xmlEval()->getVar("Globals.TabWidget.Body.Padding.Bottom");
+ _bodyLP = g_gui.xmlEval()->getVar("Globals.TabWidget.Body.Padding.Left");
+ _bodyRP = g_gui.xmlEval()->getVar("Globals.TabWidget.Body.Padding.Right");
+
+ _butRP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButtonPadding.Right", 0);
_butTP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Padding.Top", 0);
_butW = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Width", 10);
_butH = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Height", 10);
int x = _w - _butRP - _butW * 2 - 2;
int y = _butTP - _tabHeight;
- _navLeft = new ButtonWidget(this, x, y, _butW, _butH, "<", kCmdLeft, 0);
- _navRight = new ButtonWidget(this, x + _butW + 2, y, _butW, _butH, ">", kCmdRight, 0);
+ _navLeft = new ButtonWidget(this, x, y, _butW, _butH, "<", 0, kCmdLeft);
+ _navRight = new ButtonWidget(this, x + _butW + 2, y, _butW, _butH, ">", 0, kCmdRight);
}
TabWidget::~TabWidget() {
@@ -279,11 +284,14 @@ void TabWidget::drawWidget() {
for (int i = _firstVisibleTab; i < (int)_tabs.size(); ++i) {
tabs.push_back(_tabs[i].title);
}
+ g_gui.theme()->drawDialogBackground(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP), _bodyBackgroundType);
+
g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad);
}
void TabWidget::draw() {
Widget::draw();
+
if (_tabWidth * _tabs.size() > _w) {
_navLeft->draw();
_navRight->draw();
diff --git a/gui/TabWidget.h b/gui/TabWidget.h
index 81544c2de7..e7b8733d8f 100644
--- a/gui/TabWidget.h
+++ b/gui/TabWidget.h
@@ -46,6 +46,9 @@ protected:
int _tabWidth;
int _tabHeight;
+ int _bodyRP, _bodyTP, _bodyLP, _bodyBP;
+ ThemeEngine::DialogBackground _bodyBackgroundType;
+
int _titleVPad;
int _butRP, _butTP, _butW, _butH;
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index b472ad0535..3a50b2c69c 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -30,6 +30,7 @@
#include "common/fs.h"
#include "common/unzip.h"
#include "common/tokenizer.h"
+#include "common/translation.h"
#include "graphics/colormasks.h"
#include "graphics/cursorman.h"
@@ -43,10 +44,6 @@
#include "gui/ThemeEval.h"
#include "gui/ThemeParser.h"
-#if defined(MACOSX) || defined(IPHONE)
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-
#define GUI_ENABLE_BUILTIN_THEME
namespace GUI {
@@ -168,6 +165,7 @@ static const DrawDataInfo kDrawDataDefaults[] = {
{kDDMainDialogBackground, "mainmenu_bg", true, kDDNone},
{kDDSpecialColorBackground, "special_bg", true, kDDNone},
{kDDPlainColorBackground, "plain_bg", true, kDDNone},
+ {kDDTooltipBackground, "tooltip_bg", true, kDDNone},
{kDDDefaultBackground, "default_bg", true, kDDNone},
{kDDTextSelectionBackground, "text_selection", false, kDDNone},
{kDDTextSelectionFocusBackground, "text_selection_focus", false, kDDNone},
@@ -189,6 +187,10 @@ static const DrawDataInfo kDrawDataDefaults[] = {
{kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone},
{kDDCheckboxSelected, "checkbox_selected", false, kDDCheckboxDefault},
+ {kDDRadiobuttonDefault, "radiobutton_default", true, kDDNone},
+ {kDDRadiobuttonDisabled, "radiobutton_disabled", true, kDDNone},
+ {kDDRadiobuttonSelected, "radiobutton_selected", false, kDDRadiobuttonDefault},
+
{kDDTabActive, "tab_active", false, kDDTabInactive},
{kDDTabInactive, "tab_inactive", true, kDDNone},
{kDDTabBackground, "tab_background", true, kDDNone},
@@ -329,10 +331,10 @@ ThemeEngine::~ThemeEngine() {
* Rendering mode management
*********************************************************/
const ThemeEngine::Renderer ThemeEngine::_rendererModes[] = {
- { "Disabled GFX", "none", kGfxDisabled },
- { "Standard Renderer (16bpp)", "normal_16bpp", kGfxStandard16bit },
+ { _s("Disabled GFX"), "none", kGfxDisabled },
+ { _s("Standard Renderer (16bpp)"), "normal_16bpp", kGfxStandard16bit },
#ifndef DISABLE_FANCY_THEMES
- { "Antialiased Renderer (16bpp)", "aa_16bpp", kGfxAntialias16bit }
+ { _s("Antialiased Renderer (16bpp)"), "aa_16bpp", kGfxAntialias16bit }
#endif
};
@@ -391,20 +393,23 @@ bool ThemeEngine::init() {
// Try to create a Common::Archive with the files of the theme.
if (!_themeArchive && !_themeFile.empty()) {
Common::FSNode node(_themeFile);
- if (node.getName().hasSuffix(".zip") && !node.isDirectory()) {
-#ifdef USE_ZLIB
- Common::Archive *zipArchive = Common::makeZipArchive(node);
-
- if (!zipArchive) {
- warning("Failed to open Zip archive '%s'.", node.getPath().c_str());
- }
- _themeArchive = zipArchive;
-#else
- warning("Trying to load theme '%s' in a Zip archive without zLib support", _themeFile.c_str());
- return false;
-#endif
- } else if (node.isDirectory()) {
+ if (node.isDirectory()) {
_themeArchive = new Common::FSDirectory(node);
+ } else if (_themeFile.hasSuffix(".zip")) {
+ // TODO: Also use "node" directly?
+ // Look for the zip file via SearchMan
+ Common::ArchiveMemberPtr member = SearchMan.getMember(_themeFile);
+ if (member) {
+ _themeArchive = Common::makeZipArchive(member->createReadStream());
+ if (!_themeArchive) {
+ warning("Failed to open Zip archive '%s'.", member->getDisplayName().c_str());
+ }
+ } else {
+ _themeArchive = Common::makeZipArchive(node);
+ if (!_themeArchive) {
+ warning("Failed to open Zip archive '%s'.", node.getPath().c_str());
+ }
+ }
}
}
@@ -563,10 +568,17 @@ bool ThemeEngine::addFont(TextData textId, const Common::String &file) {
if (file == "default") {
_texts[textId]->_fontPtr = _font;
} else {
- _texts[textId]->_fontPtr = FontMan.getFontByName(file);
+ Common::String localized = genLocalizedFontFilename(file.c_str());
+ // Try built-in fonts
+ _texts[textId]->_fontPtr = FontMan.getFontByName(localized);
if (!_texts[textId]->_fontPtr) {
- _texts[textId]->_fontPtr = loadFont(file);
+ // First try to load localized font
+ _texts[textId]->_fontPtr = loadFont(localized);
+
+ // Fallback to non-localized font
+ if (!_texts[textId]->_fontPtr)
+ _texts[textId]->_fontPtr = loadFont(file);
if (!_texts[textId]->_fontPtr)
error("Couldn't load font '%s'", file.c_str());
@@ -884,6 +896,32 @@ void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str,
queueDDText(getTextData(dd), getTextColor(dd), r2, str, false, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV);
}
+void ThemeEngine::drawRadiobutton(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ Common::Rect r2 = r;
+ DrawData dd = kDDRadiobuttonDefault;
+
+ if (checked)
+ dd = kDDRadiobuttonSelected;
+
+ if (state == kStateDisabled)
+ dd = kDDRadiobuttonDisabled;
+
+ const int checkBoxSize = MIN((int)r.height(), getFontHeight());
+
+ r2.bottom = r2.top + checkBoxSize;
+ r2.right = r2.left + checkBoxSize;
+
+ queueDD(dd, r2);
+
+ r2.left = r2.right + checkBoxSize;
+ r2.right = r.right;
+
+ queueDDText(getTextData(dd), getTextColor(dd), r2, str, false, false, _widgets[kDDRadiobuttonDefault]->_textAlignH, _widgets[dd]->_textAlignV);
+}
+
void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) {
if (!ready())
return;
@@ -947,6 +985,10 @@ void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground b
queueDD(kDDPlainColorBackground, r);
break;
+ case kDialogBackgroundTooltip:
+ queueDD(kDDTooltipBackground, r);
+ break;
+
case kDialogBackgroundDefault:
queueDD(kDDDefaultBackground, r);
break;
@@ -1025,12 +1067,16 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co
if (i == active)
continue;
+ if (r.left + i * tabWidth > r.right || r.left + (i + 1) * tabWidth > r.right)
+ continue;
+
Common::Rect tabRect(r.left + i * tabWidth, r.top, r.left + (i + 1) * tabWidth, r.top + tabHeight);
queueDD(kDDTabInactive, tabRect);
queueDDText(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
}
- if (active >= 0) {
+ if (active >= 0 &&
+ (r.left + active * tabWidth < r.right) && (r.left + (active + 1) * tabWidth < r.right)) {
Common::Rect tabRect(r.left + active * tabWidth, r.top, r.left + (active + 1) * tabWidth, r.top + tabHeight);
const uint16 tabLeft = active * tabWidth;
const uint16 tabRight = MAX(r.right - tabRect.right, 0);
@@ -1039,7 +1085,7 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co
}
}
-void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color) {
+void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore) {
if (!ready())
return;
@@ -1090,13 +1136,7 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid
return;
}
- TextData textId = kTextDataNone;
- if (font == kFontStyleNormal)
- textId = kTextDataNormalFont;
- else
- textId = kTextDataDefault;
-
- bool restore = true;
+ TextData textId = fontStyleToData(font);
switch (inverted) {
case kTextInversion:
@@ -1138,7 +1178,69 @@ void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) {
_screen.vLine(r.right, r.top, r.bottom, 0xFFFF);
}
+ThemeEngine::StoredState *ThemeEngine::storeState(const Common::Rect &r) {
+ StoredState *state = new StoredState;
+ byte *dst;
+ byte *src;
+
+ state->r.top = r.top;
+ state->r.bottom = r.bottom;
+ state->r.left = r.left;
+ state->r.right = r.right;
+
+ state->r.clip(_screen.w, _screen.h);
+
+ state->screen.create(state->r.width(), state->r.height(), _screen.bytesPerPixel);
+ state->backBuffer.create(state->r.width(), state->r.height(), _backBuffer.bytesPerPixel);
+
+ src = (byte *)_screen.getBasePtr(state->r.left, state->r.top);
+ dst = (byte *)state->screen.getBasePtr(0, 0);
+
+ for (int i = state->r.height(); i > 0; i--) {
+ memcpy(dst, src, state->r.width() * _screen.bytesPerPixel);
+ src += _screen.pitch;
+ dst += state->screen.pitch;
+ }
+
+ src = (byte *)_backBuffer.getBasePtr(state->r.left, state->r.top);
+ dst = (byte *)state->backBuffer.getBasePtr(0, 0);
+
+ for (int i = state->r.height(); i > 0; i--) {
+ memcpy(dst, src, state->r.width() * _backBuffer.bytesPerPixel);
+ src += _backBuffer.pitch;
+ dst += state->backBuffer.pitch;
+ }
+
+ return state;
+}
+void ThemeEngine::restoreState(StoredState *state) {
+ byte *dst;
+ byte *src;
+
+ if (!state)
+ return;
+
+ src = (byte *)state->screen.getBasePtr(0, 0);
+ dst = (byte *)_screen.getBasePtr(state->r.left, state->r.top);
+
+ for (int i = state->r.height(); i > 0; i--) {
+ memcpy(dst, src, state->r.width() * _screen.bytesPerPixel);
+ src += state->screen.pitch;
+ dst += _screen.pitch;
+ }
+
+ src = (byte *)state->backBuffer.getBasePtr(0, 0);
+ dst = (byte *)_backBuffer.getBasePtr(state->r.left, state->r.top);
+
+ for (int i = state->r.height(); i > 0; i--) {
+ memcpy(dst, src, state->r.width() * _backBuffer.bytesPerPixel);
+ src += state->backBuffer.pitch;
+ dst += _backBuffer.pitch;
+ }
+
+ addDirtyRect(state->r);
+}
/**********************************************************
* Screen/overlay management
@@ -1349,6 +1451,20 @@ const Graphics::Font *ThemeEngine::loadFontFromArchive(const Common::String &fil
if (_themeArchive)
stream = _themeArchive->createReadStreamForMember(filename);
if (stream) {
+ font = Graphics::NewFont::loadFont(*stream);
+ delete stream;
+ }
+
+ return font;
+}
+
+const Graphics::Font *ThemeEngine::loadCachedFontFromArchive(const Common::String &filename) {
+ Common::SeekableReadStream *stream = 0;
+ const Graphics::Font *font = 0;
+
+ if (_themeArchive)
+ stream = _themeArchive->createReadStreamForMember(filename);
+ if (stream) {
font = Graphics::NewFont::loadFromCache(*stream);
delete stream;
}
@@ -1362,13 +1478,14 @@ const Graphics::Font *ThemeEngine::loadFont(const Common::String &filename) {
Common::File fontFile;
if (!cacheFilename.empty()) {
- if (fontFile.open(cacheFilename))
+ if (fontFile.open(cacheFilename)) {
font = Graphics::NewFont::loadFromCache(fontFile);
+ }
if (font)
return font;
- if ((font = loadFontFromArchive(cacheFilename)))
+ if ((font = loadCachedFontFromArchive(cacheFilename)))
return font;
}
@@ -1383,7 +1500,7 @@ const Graphics::Font *ThemeEngine::loadFont(const Common::String &filename) {
if (font) {
if (!cacheFilename.empty()) {
- if (!Graphics::NewFont::cacheFontData(*(const Graphics::NewFont*)font, cacheFilename)) {
+ if (!Graphics::NewFont::cacheFontData(*(const Graphics::NewFont *)font, cacheFilename)) {
warning("Couldn't create cache file for font '%s'", filename.c_str());
}
}
@@ -1408,6 +1525,34 @@ Common::String ThemeEngine::genCacheFilename(const char *filename) {
return Common::String();
}
+Common::String ThemeEngine::genLocalizedFontFilename(const char *filename) {
+#ifndef USE_TRANSLATION
+ return Common::String(filename);
+#else
+
+ Common::String result;
+ bool pointPassed = false;
+
+ for (const char *p = filename; *p != 0; p++) {
+ if (!pointPassed) {
+ if (*p != '.') {
+ result += *p;
+ } else {
+ result += "-";
+ result += TransMan.getCurrentCharset();
+ result += *p;
+
+ pointPassed = true;
+ }
+ } else {
+ result += *p;
+ }
+ }
+
+ return result;
+#endif
+}
+
/**********************************************************
* Static Theme XML functions
@@ -1436,12 +1581,33 @@ bool ThemeEngine::themeConfigParseHeader(Common::String header, Common::String &
return tok.empty();
}
+bool ThemeEngine::themeConfigUsable(const Common::ArchiveMember &member, Common::String &themeName) {
+ Common::File stream;
+ bool foundHeader = false;
+
+ if (member.getName().hasSuffix(".zip")) {
+ Common::Archive *zipArchive = Common::makeZipArchive(member.createReadStream());
+
+ if (zipArchive && zipArchive->hasFile("THEMERC")) {
+ stream.open("THEMERC", *zipArchive);
+ }
+
+ delete zipArchive;
+ }
+
+ if (stream.isOpen()) {
+ Common::String stxHeader = stream.readLine();
+ foundHeader = themeConfigParseHeader(stxHeader, themeName);
+ }
+
+ return foundHeader;
+}
+
bool ThemeEngine::themeConfigUsable(const Common::FSNode &node, Common::String &themeName) {
Common::File stream;
bool foundHeader = false;
if (node.getName().hasSuffix(".zip") && !node.isDirectory()) {
-#ifdef USE_ZLIB
Common::Archive *zipArchive = Common::makeZipArchive(node);
if (zipArchive && zipArchive->hasFile("THEMERC")) {
// Open THEMERC from the ZIP file.
@@ -1454,7 +1620,6 @@ bool ThemeEngine::themeConfigUsable(const Common::FSNode &node, Common::String &
// reference to zipArchive anywhere. This could change if we
// ever modify ZipArchive::createReadStreamForMember.
delete zipArchive;
-#endif
} else if (node.isDirectory()) {
Common::FSNode headerfile = node.getChild("THEMERC");
if (!headerfile.exists() || !headerfile.isReadable() || headerfile.isDirectory())
@@ -1493,26 +1658,7 @@ void ThemeEngine::listUsableThemes(Common::List<ThemeDescriptor> &list) {
if (ConfMan.hasKey("themepath"))
listUsableThemes(Common::FSNode(ConfMan.get("themepath")), list);
-#ifdef DATA_PATH
- listUsableThemes(Common::FSNode(DATA_PATH), list);
-#endif
-
-#if defined(MACOSX) || defined(IPHONE)
- CFURLRef resourceUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
- if (resourceUrl) {
- char buf[256];
- if (CFURLGetFileSystemRepresentation(resourceUrl, true, (UInt8 *)buf, 256)) {
- Common::FSNode resourcePath(buf);
- listUsableThemes(resourcePath, list);
- }
- CFRelease(resourceUrl);
- }
-#endif
-
- if (ConfMan.hasKey("extrapath"))
- listUsableThemes(Common::FSNode(ConfMan.get("extrapath")), list);
-
- listUsableThemes(Common::FSNode("."), list, 1);
+ listUsableThemes(SearchMan, list);
// Now we need to strip all duplicates
// TODO: It might not be the best idea to strip duplicates. The user might
@@ -1531,6 +1677,32 @@ void ThemeEngine::listUsableThemes(Common::List<ThemeDescriptor> &list) {
output.clear();
}
+void ThemeEngine::listUsableThemes(Common::Archive &archive, Common::List<ThemeDescriptor> &list) {
+ ThemeDescriptor td;
+
+ Common::ArchiveMemberList fileList;
+ archive.listMatchingMembers(fileList, "*.zip");
+ for (Common::ArchiveMemberList::iterator i = fileList.begin();
+ i != fileList.end(); ++i) {
+ td.name.clear();
+ if (themeConfigUsable(**i, td.name)) {
+ td.filename = (*i)->getName();
+ td.id = (*i)->getDisplayName();
+
+ // If the name of the node object also contains
+ // the ".zip" suffix, we will strip it.
+ if (td.id.hasSuffix(".zip")) {
+ for (int j = 0; j < 4; ++j)
+ td.id.deleteLastChar();
+ }
+
+ list.push_back(td);
+ }
+ }
+
+ fileList.clear();
+}
+
void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth) {
if (!node.exists() || !node.isReadable() || !node.isDirectory())
return;
@@ -1550,7 +1722,6 @@ void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<Them
}
Common::FSList fileList;
-#ifdef USE_ZLIB
// Check all files. We need this to find all themes inside ZIP archives.
if (!node.getChildren(fileList, Common::FSNode::kListFilesOnly))
return;
@@ -1577,7 +1748,6 @@ void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<Them
}
fileList.clear();
-#endif
// Check if we exceeded the given recursion depth
if (depth - 1 == -1)
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 2da1c3a014..73181b74a6 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -61,6 +61,7 @@ enum DrawData {
kDDMainDialogBackground,
kDDSpecialColorBackground,
kDDPlainColorBackground,
+ kDDTooltipBackground,
kDDDefaultBackground,
kDDTextSelectionBackground,
kDDTextSelectionFocusBackground,
@@ -82,6 +83,10 @@ enum DrawData {
kDDCheckboxDisabled,
kDDCheckboxSelected,
+ kDDRadiobuttonDefault,
+ kDDRadiobuttonDisabled,
+ kDDRadiobuttonSelected,
+
kDDTabActive,
kDDTabInactive,
kDDTabBackground,
@@ -108,6 +113,7 @@ enum TextData {
kTextDataDefault = 0,
kTextDataButton,
kTextDataNormalFont,
+ kTextDataTooltip,
kTextDataMAX
};
@@ -157,6 +163,7 @@ public:
kDialogBackgroundMain,
kDialogBackgroundSpecial,
kDialogBackgroundPlain,
+ kDialogBackgroundTooltip,
kDialogBackgroundDefault
};
@@ -173,7 +180,7 @@ public:
enum TextInversionState {
kTextInversionNone, ///< Indicates that the text should not be drawn inverted
kTextInversion, ///< Indicates that the text should be drawn inverted, but not focused
- kTextInversionFocus ///< Indicates thte the test should be drawn inverted, and focused
+ kTextInversionFocus ///< Indicates that the text should be drawn inverted, and focused
};
enum ScrollbarState {
@@ -192,6 +199,7 @@ public:
kFontStyleFixedNormal = 3, ///< Fixed size font.
kFontStyleFixedBold = 4, ///< Fixed size bold font.
kFontStyleFixedItalic = 5, ///< Fixed size italic font.
+ kFontStyleTooltip = 6, ///< Tiny console font
kFontStyleMax
};
@@ -255,6 +263,17 @@ public:
void enable();
void disable();
+ struct StoredState {
+ Common::Rect r;
+ Graphics::Surface screen;
+ Graphics::Surface backBuffer;
+
+ StoredState() {}
+ };
+
+ StoredState *storeState(const Common::Rect &r);
+ void restoreState(StoredState *state);
+
/**
* Implementation of the GUI::Theme API. Called when a
* new dialog is opened. Note that the boolean parameter
@@ -280,6 +299,8 @@ public:
TextData fontStyleToData(FontStyle font) const {
if (font == kFontStyleNormal)
return kTextDataNormalFont;
+ if (font == kFontStyleTooltip)
+ return kTextDataTooltip;
return kTextDataDefault;
}
@@ -312,6 +333,9 @@ public:
void drawCheckbox(const Common::Rect &r, const Common::String &str,
bool checked, WidgetStateInfo state = kStateEnabled);
+ void drawRadiobutton(const Common::Rect &r, const Common::String &str,
+ bool checked, WidgetStateInfo state = kStateEnabled);
+
void drawTab(const Common::Rect &r, int tabHeight, int tabWidth,
const Common::Array<Common::String> &tabs, int active, uint16 hints,
int titleVPad, WidgetStateInfo state = kStateEnabled);
@@ -329,7 +353,7 @@ public:
void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled);
- void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal);
+ void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true);
void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal);
@@ -516,7 +540,9 @@ protected:
const Graphics::Font *loadFont(const Common::String &filename);
const Graphics::Font *loadFontFromArchive(const Common::String &filename);
+ const Graphics::Font *loadCachedFontFromArchive(const Common::String &filename);
Common::String genCacheFilename(const char *filename);
+ Common::String genLocalizedFontFilename(const char *filename);
/**
* Actual Dirty Screen handling function.
@@ -560,11 +586,13 @@ public:
static void listUsableThemes(Common::List<ThemeDescriptor> &list);
private:
static bool themeConfigUsable(const Common::FSNode &node, Common::String &themeName);
+ static bool themeConfigUsable(const Common::ArchiveMember &member, Common::String &themeName);
static bool themeConfigParseHeader(Common::String header, Common::String &themeName);
static Common::String getThemeFile(const Common::String &id);
static Common::String getThemeId(const Common::String &filename);
static void listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth = -1);
+ static void listUsableThemes(Common::Archive &archive, Common::List<ThemeDescriptor> &list);
protected:
OSystem *_system; /** Global system object. */
diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp
index e22d440bd9..c809447cbd 100644
--- a/gui/ThemeParser.cpp
+++ b/gui/ThemeParser.cpp
@@ -42,7 +42,8 @@ struct TextDataInfo {
static const TextDataInfo kTextDataDefaults[] = {
{ kTextDataDefault, "text_default" },
{ kTextDataButton, "text_button" },
- { kTextDataNormalFont, "text_normal" }
+ { kTextDataNormalFont, "text_normal" },
+ { kTextDataTooltip, "tooltip_normal" }
};
@@ -364,10 +365,8 @@ bool ThemeParser::parserCallback_drawdata(ParserNode *node) {
if (_theme->addDrawData(node->values["id"], cached) == false)
return parserError("Error adding Draw Data set: Invalid DrawData name.");
- if (_defaultStepLocal) {
- delete _defaultStepLocal;
- _defaultStepLocal = 0;
- }
+ delete _defaultStepLocal;
+ _defaultStepLocal = 0;
return true;
}
diff --git a/gui/Tooltip.cpp b/gui/Tooltip.cpp
new file mode 100644
index 0000000000..64c34688df
--- /dev/null
+++ b/gui/Tooltip.cpp
@@ -0,0 +1,101 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/util.h"
+#include "graphics/fontman.h"
+#include "gui/widget.h"
+#include "gui/dialog.h"
+#include "gui/GuiManager.h"
+
+#include "gui/Tooltip.h"
+#include "gui/ThemeEval.h"
+
+namespace GUI {
+
+
+Tooltip::Tooltip() :
+ Dialog(-1, -1, -1, -1), _maxWidth(-1) {
+
+ _backgroundType = GUI::ThemeEngine::kDialogBackgroundTooltip;
+}
+
+void Tooltip::mustClose() {
+ if (isVisible())
+ Dialog::close();
+}
+
+bool Tooltip::tooltipModal(int x, int y) {
+ Widget *wdg;
+
+ if (!g_gui.getTopDialog())
+ return false;
+
+ wdg = g_gui.getTopDialog()->findWidget(x, y);
+
+ if (!wdg || !wdg->getTooltip())
+ return false;
+
+ if (_maxWidth == -1) {
+ _maxWidth = g_gui.xmlEval()->getVar("Globals.Tooltip.MaxWidth", 100);
+ _xdelta = g_gui.xmlEval()->getVar("Globals.Tooltip.XDelta", 0);
+ _ydelta = g_gui.xmlEval()->getVar("Globals.Tooltip.YDelta", 0);
+ }
+
+ const Graphics::Font *tooltipFont = g_gui.theme()->getFont(ThemeEngine::kFontStyleTooltip);
+
+ _wrappedLines.clear();
+ _w = tooltipFont->wordWrapText(wdg->getTooltip(), _maxWidth - 4, _wrappedLines);
+ _h = (tooltipFont->getFontHeight() + 2) * _wrappedLines.size();
+
+ _x = MIN<int16>(g_gui.getTopDialog()->_x + x + _xdelta, g_gui.getWidth() - _w - 3);
+ _y = MIN<int16>(g_gui.getTopDialog()->_y + y + _ydelta, g_gui.getHeight() - _h - 3);
+
+ open();
+ g_gui.runLoop();
+
+ return true;
+}
+
+void Tooltip::drawDialog() {
+ int num = 0;
+ int h = g_gui.theme()->getFontHeight(ThemeEngine::kFontStyleTooltip) + 2;
+
+ Dialog::drawDialog();
+
+ for (Common::StringArray::const_iterator i = _wrappedLines.begin(); i != _wrappedLines.end(); ++i, ++num) {
+ g_gui.theme()->drawText(
+ Common::Rect(_x + 1, _y + 1 + num * h, _x + 1 +_w, _y + 1+ (num + 1) * h), *i,
+ ThemeEngine::kStateEnabled,
+ Graphics::kTextAlignLeft,
+ ThemeEngine::kTextInversionNone,
+ 0,
+ false,
+ ThemeEngine::kFontStyleTooltip,
+ ThemeEngine::kFontColorNormal,
+ false
+ );
+ }
+}
+
+}
diff --git a/backends/platform/PalmOS/Src/init_sony.h b/gui/Tooltip.h
index 86224283f6..60f3cf3a19 100644
--- a/backends/platform/PalmOS/Src/init_sony.h
+++ b/gui/Tooltip.h
@@ -8,33 +8,43 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public 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 INIT_SONY_H
-#define INIT_SONY_H
+#ifndef GUI_TOOLTIP_H
+#define GUI_TOOLTIP_H
+
+#include "gui/dialog.h"
-#define SONY_PORTRAIT 1
-#define SONY_LANDSCAPE 2
+namespace GUI {
-UInt16 SilkInit(UInt32 *retVersion);
-void SilkRelease(UInt16 slkRefNum);
+class Tooltip : public Dialog {
+public:
+ Tooltip();
+ ~Tooltip() {}
+
+ void drawDialog();
+ bool tooltipModal(int x, int y);
+ void mustClose();
-UInt16 SonyHRInit(UInt32 depth);
-void SonyHRRelease(UInt16 HRrefNum);
+protected:
+ Common::String _text;
+ int _maxWidth;
+ int _xdelta, _ydelta;
-UInt8 SonyScreenSize(UInt16 HRrefNum, Coord *stdw, Coord *stdh, Coord *fullw, Coord *fullh);
+ Common::StringArray _wrappedLines;
+};
+}
#endif
diff --git a/gui/about.cpp b/gui/about.cpp
index 74851caf94..ea326eb71e 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -27,6 +27,7 @@
#include "base/version.h"
#include "common/events.h"
#include "common/system.h"
+#include "common/translation.h"
#include "common/util.h"
#include "gui/about.h"
#include "gui/GuiManager.h"
@@ -113,22 +114,25 @@ AboutDialog::AboutDialog()
version += gScummVMVersion;
_lines.push_back(version);
- Common::String date("C2""(built on ");
- date += gScummVMBuildDate;
- date += ')';
- _lines.push_back(date);
+ Common::String date = Common::String::printf(_("(built on %s)"), gScummVMBuildDate);
+ _lines.push_back("C2" + date);
for (i = 0; i < ARRAYSIZE(copyright_text); i++)
addLine(copyright_text[i]);
- addLine("C1""Features compiled in:");
- Common::String features("C0");
- features += gScummVMFeatures;
+ Common::String features("C1");
+ features += _("Features compiled in:");
addLine(features.c_str());
+ Common::String featureList("C0");
+ featureList += gScummVMFeatures;
+ addLine(featureList.c_str());
_lines.push_back("");
- addLine("C1""Available engines:");
+ Common::String engines("C1");
+ engines += _("Available engines:");
+ addLine(engines.c_str());
+
const EnginePlugin::List &plugins = EngineMan.getPlugins();
EnginePlugin::List::const_iterator iter = plugins.begin();
for (; iter != plugins.end(); ++iter) {
diff --git a/gui/browser.cpp b/gui/browser.cpp
index c090742988..0d95e5397b 100644
--- a/gui/browser.cpp
+++ b/gui/browser.cpp
@@ -30,6 +30,8 @@
#include "common/system.h"
#include "common/algorithm.h"
+#include "common/translation.h"
+
namespace GUI {
enum {
@@ -64,9 +66,9 @@ BrowserDialog::BrowserDialog(const char *title, bool dirBrowser)
_backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain;
// Buttons
- new ButtonWidget(this, "Browser.Up", "Go up", kGoUpCmd, 0);
- new ButtonWidget(this, "Browser.Cancel", "Cancel", kCloseCmd, 0);
- new ButtonWidget(this, "Browser.Choose", "Choose", kChooseCmd, 0);
+ new ButtonWidget(this, "Browser.Up", _("Go up"), _("Go to previous directory level"), kGoUpCmd);
+ new ButtonWidget(this, "Browser.Cancel", _("Cancel"), 0, kCloseCmd);
+ new ButtonWidget(this, "Browser.Choose", _("Choose"), 0, kChooseCmd);
}
void BrowserDialog::open() {
diff --git a/gui/chooser.cpp b/gui/chooser.cpp
index 0155bb2afb..a7b453c957 100644
--- a/gui/chooser.cpp
+++ b/gui/chooser.cpp
@@ -23,6 +23,7 @@
*/
#include "common/system.h"
+#include "common/translation.h"
#include "gui/chooser.h"
#include "gui/GuiManager.h"
#include "gui/ListWidget.h"
@@ -45,8 +46,8 @@ ChooserDialog::ChooserDialog(const String &title, String dialogId)
_list->setEditable(false);
// Buttons
- new ButtonWidget(this, dialogId + ".Cancel", "Cancel", kCloseCmd, 0);
- _chooseButton = new ButtonWidget(this, dialogId + ".Choose", "Choose", kChooseCmd, 0);
+ new ButtonWidget(this, dialogId + ".Cancel", _("Cancel"), 0, kCloseCmd);
+ _chooseButton = new ButtonWidget(this, dialogId + ".Choose", _("Choose"), 0, kChooseCmd);
_chooseButton->setEnabled(false);
}
diff --git a/gui/console.cpp b/gui/console.cpp
index 37d3bd6aa5..a53e97888b 100644
--- a/gui/console.cpp
+++ b/gui/console.cpp
@@ -156,7 +156,9 @@ void ConsoleDialog::open() {
_slideMode = kDownSlideMode;
Dialog::open();
- if (_promptStartPos == -1) {
+ if ((_promptStartPos == -1) || (_currentPos > _promptEndPos)) {
+ // we print a prompt, if this is the first time we are called or if the
+ // engine wrote onto us since the last call
print(PROMPT);
_promptStartPos = _promptEndPos = _currentPos;
}
@@ -667,11 +669,7 @@ int ConsoleDialog::printf(const char *format, ...) {
}
int ConsoleDialog::vprintf(const char *format, va_list argptr) {
-#ifdef PALMOS_MODE
- char buf[256];
-#else
char buf[2048];
-#endif
#if defined(WIN32)
int count = _vsnprintf(buf, sizeof(buf), format, argptr);
diff --git a/gui/credits.h b/gui/credits.h
index 4bf3e429b0..bd4ecffc9b 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -189,6 +189,9 @@ static const char *credits[] = {
"",
"",
"C1""Backend Teams",
+"C1""Android",
+"C0""Angus Lees",
+"",
"C1""Dreamcast",
"C0""Marcus Comstedt",
"",
@@ -210,9 +213,6 @@ static const char *credits[] = {
"C1""Nintendo DS",
"C0""Neil Millstone",
"",
-"C1""PalmOS",
-"C0""Chris Apers",
-"",
"C1""PocketPC / WinCE",
"C0""Nicolas Bacca",
"C2""(retired)",
@@ -283,6 +283,8 @@ static const char *credits[] = {
"C2""Wiki editor",
"",
"C1""Retired Team Members",
+"C0""Chris Apers",
+"C2""Former PalmOS porter",
"C0""Ralph Brorsen",
"C2""Help with GUI implementation",
"C0""Jamieson Christian",
@@ -360,6 +362,35 @@ static const char *credits[] = {
"C0""Johannes Schickel",
"",
"",
+"C1""Translations",
+"C0""Thierry Crozat",
+"C2""Translation Lead",
+"C1""Catalan",
+"C0""Jordi Vilalta Prat",
+"",
+"C1""French",
+"C0""Thierry Crozat",
+"",
+"C1""German",
+"C0""Simon Sawatzki",
+"C0""Lothar Serra Mari",
+"",
+"C1""Hungarian",
+"C0""Alex Bevilacqua",
+"",
+"C1""Italian",
+"C0""Matteo Angelino",
+"",
+"C1""Russian",
+"C0""Eugene Sandulenko",
+"",
+"C1""Spanish",
+"C0""Tom\341s Maidagan",
+"",
+"C1""Ukrainian",
+"C0""Lubomyr Lisen",
+"",
+"",
"C1""Websites (design)",
"C0""Dob\363 Bal\341zs",
"C2""Website design",
@@ -476,7 +507,7 @@ static const char *credits[] = {
"C0""Rune Orsval",
"C2""Configuration file editor",
"C0""Rickard Lind",
-"C2""MT32->GM MIDI mapping magic, sound research",
+"C2""MT-32->GM MIDI mapping magic, sound research",
"C0""Rink Springer",
"C2""Port to the DOS platform, several bug fixes",
"C0""Robey Pointer",
diff --git a/gui/debugger.cpp b/gui/debugger.cpp
index 13dc02452d..9bd3b35915 100644
--- a/gui/debugger.cpp
+++ b/gui/debugger.cpp
@@ -39,9 +39,8 @@
namespace GUI {
Debugger::Debugger() {
- _frame_countdown = 0;
- _detach_now = false;
- _isAttached = false;
+ _frameCountdown = 0;
+ _isActive = false;
_errStr = NULL;
_firstTime = true;
#ifndef USE_TEXT_CONSOLE
@@ -50,6 +49,10 @@ Debugger::Debugger() {
_debuggerDialog->setCompletionCallback(debuggerCompletionCallback, this);
#endif
+ // Register variables
+ DVar_Register("debug_countdown", &_frameCountdown, DVAR_INT, 0);
+
+ // Register commands
//DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
DCmd_Register("exit", WRAP_METHOD(Debugger, Cmd_Exit));
DCmd_Register("quit", WRAP_METHOD(Debugger, Cmd_Exit));
@@ -84,40 +87,32 @@ int Debugger::DebugPrintf(const char *format, ...) {
}
void Debugger::attach(const char *entry) {
-
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
- if (entry) {
- _errStr = strdup(entry);
- }
+ // Set error string (if any)
+ free(_errStr);
+ _errStr = entry ? strdup(entry) : 0;
- _frame_countdown = 1;
- _detach_now = false;
- _isAttached = true;
+ // Reset frame countdown (i.e. attach immediately)
+ _frameCountdown = 1;
}
void Debugger::detach() {
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
-
- _detach_now = false;
- _isAttached = false;
}
// Temporary execution handler
void Debugger::onFrame() {
- if (_frame_countdown == 0)
- return;
- --_frame_countdown;
-
- if (!_frame_countdown) {
-
- preEnter();
- enter();
- postEnter();
-
- // Detach if we're finished with the debugger
- if (_detach_now)
- detach();
+ // Count down until 0 is reached
+ if (_frameCountdown > 0) {
+ --_frameCountdown;
+ if (_frameCountdown == 0) {
+ _isActive = true;
+ preEnter();
+ enter();
+ postEnter();
+ _isActive = false;
+ }
}
}
@@ -250,8 +245,8 @@ bool Debugger::parseCommand(const char *inputOrig) {
} else {
int element = atoi(chr+1);
int32 *var = *(int32 **)_dvars[i].variable;
- if (element >= _dvars[i].optional) {
- DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].optional);
+ if (element >= _dvars[i].arraySize) {
+ DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].arraySize);
} else {
var[element] = atoi(param[1]);
DebugPrintf("(int)%s = %d\n", param[0], var[element]);
@@ -281,8 +276,8 @@ bool Debugger::parseCommand(const char *inputOrig) {
} else {
int element = atoi(chr+1);
const int32 *var = *(const int32 **)_dvars[i].variable;
- if (element >= _dvars[i].optional) {
- DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].optional);
+ if (element >= _dvars[i].arraySize) {
+ DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].arraySize);
} else {
DebugPrintf("(int)%s = %d\n", param[0], var[element]);
}
@@ -383,7 +378,7 @@ char *Debugger::readlineComplete(const char *input, int state) {
#endif
// Variable registration function
-void Debugger::DVar_Register(const Common::String &varname, void *pointer, int type, int optional) {
+void Debugger::DVar_Register(const Common::String &varname, void *pointer, VarType type, int arraySize) {
// TODO: Filter out duplicates
// TODO: Sort this list? Then we can do binary search later on when doing lookups.
assert(pointer);
@@ -392,7 +387,7 @@ void Debugger::DVar_Register(const Common::String &varname, void *pointer, int t
tmp.name = varname;
tmp.type = type;
tmp.variable = pointer;
- tmp.optional = optional;
+ tmp.arraySize = arraySize;
_dvars.push_back(tmp);
}
@@ -406,7 +401,7 @@ void Debugger::DCmd_Register(const Common::String &cmdname, Debuglet *debuglet)
// Detach ("exit") the debugger
bool Debugger::Cmd_Exit(int argc, const char **argv) {
- _detach_now = true;
+ detach();
return false;
}
diff --git a/gui/debugger.h b/gui/debugger.h
index 07fdddb808..6f06befdf1 100644
--- a/gui/debugger.h
+++ b/gui/debugger.h
@@ -43,20 +43,46 @@ public:
int DebugPrintf(const char *format, ...);
+ /**
+ * The onFrame() method should be invoked by the engine at regular
+ * intervals (usually once per main loop iteration) whenever the
+ * debugger is attached.
+ * This will open up the console and accept user input if certain
+ * preconditions are met, such as the frame countdown having
+ * reached zero.
+ *
+ * Subclasses can override this to e.g. check for breakpoints being
+ * triggered.
+ */
virtual void onFrame();
+ /**
+ * 'Attach' the debugger. This ensures that the next time onFrame()
+ * is invoked, the debugger will activate and accept user input.
+ */
virtual void attach(const char *entry = 0);
- bool isAttached() const { return _isAttached; }
+
+ /**
+ * Return true if the debugger is currently active (i.e. executing
+ * a command or waiting for use input).
+ */
+ bool isActive() const { return _isActive; }
protected:
typedef Common::Functor2<int, const char **, bool> Debuglet;
- // Convenience macro for registering a method of a debugger class
- // as the current command.
+ /**
+ * Convenience macro that makes it either to register a method
+ * of a debugger subclass as a command.
+ * Usage example:
+ * DCmd_Register("COMMAND", WRAP_METHOD(MyDebugger, MyCmd));
+ * would register the method MyDebugger::MyCmd(int, const char **)
+ * under the command name "COMMAND".
+ */
#define WRAP_METHOD(cls, method) \
new Common::Functor2Mem<int, const char **, bool, cls>(this, &cls::method)
- enum {
+ enum VarType {
DVAR_BYTE,
DVAR_INT,
DVAR_BOOL,
@@ -67,50 +93,100 @@ protected:
struct DVar {
Common::String name;
void *variable;
- int type;
- int optional;
+ VarType type;
+ int arraySize;
};
- int _frame_countdown;
- bool _detach_now;
+
+ /**
+ * Register a variable with the debugger. This allows the user to read and modify
+ * this variable.
+ * @param varname the identifier with which the user may access the variable
+ * @param variable pointer to the actual storage of the variable
+ * @param type the type of the variable (byte, int, bool, ...)
+ * @paral arraySize for type DVAR_INTARRAY this specifies the size of the array
+ *
+ * @todo replace this single method by type safe variants.
+ */
+ void DVar_Register(const Common::String &varname, void *variable, VarType type, int arraySize);
+ void DCmd_Register(const Common::String &cmdname, Debuglet *debuglet);
+
private:
+ /**
+ * The frame countdown specifies a number of frames that must pass
+ * until the console will show up. This value is decremented by one
+ * each time onFrame() is called, until it reaches 0, at which point
+ * onFrame() will open the console and handle input into it.
+ *
+ * The user can modify this value using the debug_countdown command.
+ *
+ * Note: The console must be in *attached* state, otherwise, it
+ * won't show up (and the countdown won't count down either).
+ */
+ uint _frameCountdown;
+
Common::Array<DVar> _dvars;
typedef Common::HashMap<Common::String, Common::SharedPtr<Debuglet>, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> CommandsMap;
CommandsMap _cmds;
- bool _isAttached;
+ /**
+ * True if the debugger is currently active (i.e. executing
+ * a command or waiting for use input).
+ */
+ bool _isActive;
+
char *_errStr;
+
+ /**
+ * Initially true, set to false when Debugger::enter is called
+ * the first time. We use this flag to show a greeting message
+ * to the user once, when he opens the debugger for the first
+ * time.
+ */
bool _firstTime;
+
#ifndef USE_TEXT_CONSOLE
GUI::ConsoleDialog *_debuggerDialog;
#endif
protected:
- // Hook for subclasses: Called just before enter() is run
+ /**
+ * Hook for subclasses which is called just before enter() is run.
+ * A typical usage example is pausing music and sound effects.
+ */
virtual void preEnter() {}
- // Hook for subclasses: Called just after enter() was run
+ /**
+ * Hook for subclasses which is called just after enter() was run.
+ * A typical usage example is resuming music and sound effects.
+ */
virtual void postEnter() {}
- // Hook for subclasses: Process the given command line.
- // Should return true if and only if argv[0] is a known command and was
- // handled, false otherwise.
- virtual bool handleCommand(int argc, const char **argv, bool &keepRunning);
-
+ /**
+ * Subclasses should invoke the detach() method in their Cmd_FOO methods
+ * if that command will resume execution of the program (as opposed to
+ * executing, say, a "single step through code" command).
+ *
+ * This currently only hides the virtual keyboard, if any.
+ */
+ void detach();
private:
- void detach();
void enter();
bool parseCommand(const char *input);
bool tabComplete(const char *input, Common::String &completion) const;
-protected:
- void DVar_Register(const Common::String &varname, void *pointer, int type, int optional);
- void DCmd_Register(const Common::String &cmdname, Debuglet *debuglet);
+ /**
+ * Process the given command line.
+ * Returns true if and only if argv[0] is a known command and was
+ * handled, false otherwise.
+ */
+ virtual bool handleCommand(int argc, const char **argv, bool &keepRunning);
+protected:
bool Cmd_Exit(int argc, const char **argv);
bool Cmd_Help(int argc, const char **argv);
bool Cmd_DebugFlagsList(int argc, const char **argv);
diff --git a/gui/dialog.cpp b/gui/dialog.cpp
index 5e3a9a1927..e20b181c83 100644
--- a/gui/dialog.cpp
+++ b/gui/dialog.cpp
@@ -171,7 +171,7 @@ void Dialog::handleMouseDown(int x, int y, int button, int clickCount) {
if (w && !(w->getFlags() & WIDGET_IGNORE_DRAG))
_dragWidget = w;
- // If the click occured inside a widget which is not the currently
+ // If the click occurred inside a widget which is not the currently
// focused one, change the focus to that widget.
if (w && w != _focusedWidget && w->wantsFocus()) {
setFocusWidget(w);
diff --git a/gui/dialog.h b/gui/dialog.h
index 5008f272ba..1845786044 100644
--- a/gui/dialog.h
+++ b/gui/dialog.h
@@ -44,6 +44,7 @@ enum {
class Dialog : public GuiObject {
friend class GuiManager;
+ friend class Tooltip;
protected:
Widget *_mouseWidget;
Widget *_focusedWidget;
diff --git a/gui/editable.cpp b/gui/editable.cpp
index 723384ed44..92faad5bb3 100644
--- a/gui/editable.cpp
+++ b/gui/editable.cpp
@@ -28,13 +28,13 @@
namespace GUI {
-EditableWidget::EditableWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd)
- : Widget(boss, x, y, w, h), CommandSender(boss), _cmd(cmd) {
+EditableWidget::EditableWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd)
+ : Widget(boss, x, y, w, h, tooltip), CommandSender(boss), _cmd(cmd) {
init();
}
-EditableWidget::EditableWidget(GuiObject *boss, const String &name, uint32 cmd)
- : Widget(boss, name), CommandSender(boss), _cmd(cmd) {
+EditableWidget::EditableWidget(GuiObject *boss, const String &name, const char *tooltip, uint32 cmd)
+ : Widget(boss, name, tooltip), CommandSender(boss), _cmd(cmd) {
init();
}
diff --git a/gui/editable.h b/gui/editable.h
index 00cb3431a5..8ff5298511 100644
--- a/gui/editable.h
+++ b/gui/editable.h
@@ -55,8 +55,8 @@ protected:
ThemeEngine::FontStyle _font;
public:
- EditableWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd = 0);
- EditableWidget(GuiObject *boss, const String &name, uint32 cmd = 0);
+ EditableWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0, uint32 cmd = 0);
+ EditableWidget(GuiObject *boss, const String &name, const char *tooltip = 0, uint32 cmd = 0);
virtual ~EditableWidget();
void init();
diff --git a/gui/error.cpp b/gui/error.cpp
index fbe09c5a02..3332eb533a 100644
--- a/gui/error.cpp
+++ b/gui/error.cpp
@@ -27,6 +27,8 @@
#include "gui/message.h"
#include "gui/error.h"
+#include "common/translation.h"
+
namespace GUI {
void displayErrorDialog(const char *text) {
@@ -37,7 +39,7 @@ void displayErrorDialog(const char *text) {
void displayErrorDialog(Common::Error error, const char *extraText) {
Common::String errorText(extraText);
errorText += " ";
- errorText += Common::errorToString(error);
+ errorText += _(Common::errorToString(error));
GUI::MessageDialog alert(errorText);
alert.runModal();
}
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 732286c2a0..bc5debd9cd 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -30,6 +30,7 @@
#include "common/util.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "common/translation.h"
#include "gui/about.h"
#include "gui/browser.h"
@@ -71,6 +72,7 @@ enum {
kCmdGlobalGraphicsOverride = 'OGFX',
kCmdGlobalAudioOverride = 'OSFX',
kCmdGlobalMIDIOverride = 'OMID',
+ kCmdGlobalMT32Override = 'OM32',
kCmdGlobalVolumeOverride = 'OVOL',
kCmdChooseSoundFontCmd = 'chsf',
@@ -87,8 +89,8 @@ enum {
*/
class DomainEditTextWidget : public EditTextWidget {
public:
- DomainEditTextWidget(GuiObject *boss, const String &name, const String &text)
- : EditTextWidget(boss, name, text) {
+ DomainEditTextWidget(GuiObject *boss, const String &name, const String &text, const char *tooltip = 0)
+ : EditTextWidget(boss, name, text, tooltip) {
}
protected:
@@ -143,6 +145,7 @@ protected:
CheckboxWidget *_globalGraphicsOverride;
CheckboxWidget *_globalAudioOverride;
CheckboxWidget *_globalMIDIOverride;
+ CheckboxWidget *_globalMT32Override;
CheckboxWidget *_globalVolumeOverride;
};
@@ -166,30 +169,31 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
//
// 1) The game tab
//
- tab->addTab("Game");
+ tab->addTab(_("Game"));
// GUI: Label & edit widget for the game ID
- new StaticTextWidget(tab, "GameOptions_Game.Id", "ID:");
- _domainWidget = new DomainEditTextWidget(tab, "GameOptions_Game.Domain", _domain);
+ new StaticTextWidget(tab, "GameOptions_Game.Id", _("ID:"), _("Short game identifier used for referring to savegames and running the game from the command line"));
+ _domainWidget = new DomainEditTextWidget(tab, "GameOptions_Game.Domain", _domain, _("Short game identifier used for referring to savegames and running the game from the command line"));
// GUI: Label & edit widget for the description
- new StaticTextWidget(tab, "GameOptions_Game.Name", "Name:");
- _descriptionWidget = new EditTextWidget(tab, "GameOptions_Game.Desc", description);
+ new StaticTextWidget(tab, "GameOptions_Game.Name", _("Name:"), _("Full title of the game"));
+ _descriptionWidget = new EditTextWidget(tab, "GameOptions_Game.Desc", description, _("Full title of the game"));
// Language popup
- _langPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.LangPopupDesc", "Language:");
- _langPopUp = new PopUpWidget(tab, "GameOptions_Game.LangPopup");
- _langPopUp->appendEntry("<default>");
- _langPopUp->appendEntry("");
+ _langPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.LangPopupDesc", _("Language:"), _("Language of the game. This will not turn your Spanish game version into English"));
+ _langPopUp = new PopUpWidget(tab, "GameOptions_Game.LangPopup", _("Language of the game. This will not turn your Spanish game version into English"));
+ _langPopUp->appendEntry(_("<default>"), 0);
+ _langPopUp->appendEntry("", 0);
const Common::LanguageDescription *l = Common::g_languages;
for (; l->code; ++l) {
- _langPopUp->appendEntry(l->description, l->id);
+ if (checkGameGUIOptionLanguage(l->id, _guioptionsString))
+ _langPopUp->appendEntry(l->description, l->id);
}
// Platform popup
- _platformPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.PlatformPopupDesc", "Platform:");
- _platformPopUp = new PopUpWidget(tab, "GameOptions_Game.PlatformPopup");
- _platformPopUp->appendEntry("<default>");
+ _platformPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.PlatformPopupDesc", _("Platform:"), _("Platform the game was originally designed for"));
+ _platformPopUp = new PopUpWidget(tab, "GameOptions_Game.PlatformPopup", _("Platform the game was originally designed for"));
+ _platformPopUp->appendEntry(_("<default>"));
_platformPopUp->appendEntry("");
const Common::PlatformDescription *p = Common::g_platforms;
for (; p->code; ++p) {
@@ -197,39 +201,39 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
}
//
- // 3) The graphics tab
+ // 2) The graphics tab
//
- _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX");
+ _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX"));
- _globalGraphicsOverride = new CheckboxWidget(tab, "GameOptions_Graphics.EnableTabCheckbox", "Override global graphic settings", kCmdGlobalGraphicsOverride, 0);
+ _globalGraphicsOverride = new CheckboxWidget(tab, "GameOptions_Graphics.EnableTabCheckbox", _("Override global graphic settings"), 0, kCmdGlobalGraphicsOverride);
addGraphicControls(tab, "GameOptions_Graphics.");
//
- // 4) The audio tab
+ // 3) The audio tab
//
- tab->addTab("Audio");
+ tab->addTab(_("Audio"));
- _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", "Override global audio settings", kCmdGlobalAudioOverride, 0);
+ _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", _("Override global audio settings"), 0, kCmdGlobalAudioOverride);
addAudioControls(tab, "GameOptions_Audio.");
addSubtitleControls(tab, "GameOptions_Audio.");
//
- // 5) The volume tab
+ // 4) The volume tab
//
- tab->addTab("Volume");
+ tab->addTab(_("Volume"));
- _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", "Override global volume settings", kCmdGlobalVolumeOverride, 0);
+ _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", _("Override global volume settings"), 0, kCmdGlobalVolumeOverride);
addVolumeControls(tab, "GameOptions_Volume.");
//
- // 6) The MIDI tab
+ // 5) The MIDI tab
//
- tab->addTab("MIDI");
+ tab->addTab(_("MIDI"));
- _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", "Override global MIDI settings", kCmdGlobalMIDIOverride, 0);
+ _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", _("Override global MIDI settings"), 0, kCmdGlobalMIDIOverride);
if (_guioptions & Common::GUIO_NOMIDI)
_globalMIDIOverride->setEnabled(false);
@@ -237,32 +241,44 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
addMIDIControls(tab, "GameOptions_MIDI.");
//
- // 2) The 'Path' tab
+ // 6) The MT-32 tab
//
- tab->addTab("Paths");
+ tab->addTab(_("MT-32"));
+
+ _globalMT32Override = new CheckboxWidget(tab, "GameOptions_MT32.EnableTabCheckbox", _("Override global MT-32 settings"), 0, kCmdGlobalMT32Override);
+
+ //if (_guioptions & Common::GUIO_NOMIDI)
+ // _globalMT32Override->setEnabled(false);
+
+ addMT32Controls(tab, "GameOptions_MT32.");
+
+ //
+ // 7) The Paths tab
+ //
+ tab->addTab(_("Paths"));
// These buttons have to be extra wide, or the text will be truncated
// in the small version of the GUI.
// GUI: Button + Label for the game path
- new ButtonWidget(tab, "GameOptions_Paths.Gamepath", "Game Path:", kCmdGameBrowser, 0);
+ new ButtonWidget(tab, "GameOptions_Paths.Gamepath", _("Game Path:"), 0, kCmdGameBrowser);
_gamePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.GamepathText", gamePath);
// GUI: Button + Label for the additional path
- new ButtonWidget(tab, "GameOptions_Paths.Extrapath", "Extra Path:", kCmdExtraBrowser, 0);
- _extraPathWidget = new StaticTextWidget(tab, "GameOptions_Paths.ExtrapathText", extraPath);
+ new ButtonWidget(tab, "GameOptions_Paths.Extrapath", _("Extra Path:"), _("Specifies path to additional data used the game"), kCmdExtraBrowser);
+ _extraPathWidget = new StaticTextWidget(tab, "GameOptions_Paths.ExtrapathText", extraPath, _("Specifies path to additional data used the game"));
// GUI: Button + Label for the save path
- new ButtonWidget(tab, "GameOptions_Paths.Savepath", "Save Path:", kCmdSaveBrowser, 0);
- _savePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.SavepathText", savePath);
+ new ButtonWidget(tab, "GameOptions_Paths.Savepath", _("Save Path:"), _("Specifies where your savegames are put"), kCmdSaveBrowser);
+ _savePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.SavepathText", savePath, _("Specifies where your savegames are put"));
// Activate the first tab
tab->setActiveTab(0);
_tabWidget = tab;
// Add OK & Cancel buttons
- new ButtonWidget(this, "GameOptions.Cancel", "Cancel", kCloseCmd, 0);
- new ButtonWidget(this, "GameOptions.Ok", "OK", kOKCmd, 0);
+ new ButtonWidget(this, "GameOptions.Cancel", _("Cancel"), 0, kCloseCmd);
+ new ButtonWidget(this, "GameOptions.Ok", _("OK"), 0, kOKCmd);
}
void EditGameDialog::open() {
@@ -270,12 +286,12 @@ void EditGameDialog::open() {
String extraPath(ConfMan.get("extrapath", _domain));
if (extraPath.empty() || !ConfMan.hasKey("extrapath", _domain)) {
- _extraPathWidget->setLabel("None");
+ _extraPathWidget->setLabel(_("None"));
}
String savePath(ConfMan.get("savepath", _domain));
if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) {
- _savePathWidget->setLabel("Default");
+ _savePathWidget->setLabel(_("Default"));
}
int sel, i;
@@ -303,24 +319,25 @@ void EditGameDialog::open() {
e = ConfMan.hasKey("soundfont", _domain) ||
ConfMan.hasKey("multi_midi", _domain) ||
- ConfMan.hasKey("native_mt32", _domain) ||
- ConfMan.hasKey("enable_gs", _domain) ||
ConfMan.hasKey("midi_gain", _domain);
_globalMIDIOverride->setState(e);
+ e = ConfMan.hasKey("native_mt32", _domain) ||
+ ConfMan.hasKey("enable_gs", _domain);
+ _globalMT32Override->setState(e);
+
// TODO: game path
- const Common::LanguageDescription *l = Common::g_languages;
const Common::Language lang = Common::parseLanguage(ConfMan.get("language", _domain));
- sel = 0;
if (ConfMan.hasKey("language", _domain)) {
- for (i = 0; l->code; ++l, ++i) {
- if (lang == l->id)
- sel = i + 2;
- }
+ _langPopUp->setSelectedTag(lang);
+ }
+
+ if (_langPopUp->numEntries() <= 3) { // If only one language is avaliable
+ _langPopUpDesc->setEnabled(false);
+ _langPopUp->setEnabled(false);
}
- _langPopUp->setSelected(sel);
const Common::PlatformDescription *p = Common::g_platforms;
@@ -349,11 +366,11 @@ void EditGameDialog::close() {
ConfMan.set("path", gamePath, _domain);
String extraPath(_extraPathWidget->getLabel());
- if (!extraPath.empty() && (extraPath != "None"))
+ if (!extraPath.empty() && (extraPath != _("None")))
ConfMan.set("extrapath", extraPath, _domain);
String savePath(_savePathWidget->getLabel());
- if (!savePath.empty() && (savePath != "Default"))
+ if (!savePath.empty() && (savePath != _("Default")))
ConfMan.set("savepath", savePath, _domain);
Common::Platform platform = (Common::Platform)_platformPopUp->getSelectedTag();
@@ -382,19 +399,23 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
setMIDISettingsState(data != 0);
draw();
break;
+ case kCmdGlobalMT32Override:
+ setMT32SettingsState(data != 0);
+ draw();
+ break;
case kCmdGlobalVolumeOverride:
setVolumeSettingsState(data != 0);
draw();
break;
case kCmdChooseSoundFontCmd: {
- BrowserDialog browser("Select SoundFont", false);
+ BrowserDialog browser(_("Select SoundFont"), false);
if (browser.runModal() > 0) {
// User made this choice...
Common::FSNode file(browser.getResult());
_soundFont->setLabel(file.getPath());
- if (!file.getPath().empty() && (file.getPath() != "None"))
+ if (!file.getPath().empty() && (file.getPath() != _("None")))
_soundFontClearButton->setEnabled(true);
else
_soundFontClearButton->setEnabled(false);
@@ -406,7 +427,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
// Change path for the game
case kCmdGameBrowser: {
- BrowserDialog browser("Select directory with game data", true);
+ BrowserDialog browser(_("Select directory with game data"), true);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode dir(browser.getResult());
@@ -424,7 +445,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
// Change path for extra game data (eg, using sword cutscenes when playing via CD)
case kCmdExtraBrowser: {
- BrowserDialog browser("Select additional game directory", true);
+ BrowserDialog browser(_("Select additional game directory"), true);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode dir(browser.getResult());
@@ -436,7 +457,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
}
// Change path for stored save game (perm and temp) data
case kCmdSaveBrowser: {
- BrowserDialog browser("Select directory for saved games", true);
+ BrowserDialog browser(_("Select directory for saved games"), true);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode dir(browser.getResult());
@@ -455,7 +476,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
|| newDomain.hasPrefix("_")
|| newDomain == ConfigManager::kApplicationDomain
|| ConfMan.hasGameDomain(newDomain)) {
- MessageDialog alert("This game ID is already taken. Please choose another one.");
+ MessageDialog alert(_("This game ID is already taken. Please choose another one."));
alert.runModal();
return;
}
@@ -496,39 +517,39 @@ LauncherDialog::LauncherDialog()
new StaticTextWidget(this, "Launcher.Version", gScummVMFullVersion);
#endif
- new ButtonWidget(this, "Launcher.QuitButton", "Quit", kQuitCmd, 'Q');
- new ButtonWidget(this, "Launcher.AboutButton", "About...", kAboutCmd, 'B');
- new ButtonWidget(this, "Launcher.OptionsButton", "Options...", kOptionsCmd, 'O');
+ new ButtonWidget(this, "Launcher.QuitButton", _("~Q~uit"), _("Quit ScummVM"), kQuitCmd);
+ new ButtonWidget(this, "Launcher.AboutButton", _("A~b~out..."), _("About ScummVM"), kAboutCmd);
+ new ButtonWidget(this, "Launcher.OptionsButton", _("~O~ptions..."), _("Change global ScummVM options"), kOptionsCmd);
_startButton =
- new ButtonWidget(this, "Launcher.StartButton", "Start", kStartCmd, 'S');
+ new ButtonWidget(this, "Launcher.StartButton", _("~S~tart"), _("Start selected game"), kStartCmd);
_loadButton =
- new ButtonWidget(this, "Launcher.LoadGameButton", "Load...", kLoadGameCmd, 'L');
+ new ButtonWidget(this, "Launcher.LoadGameButton", _("~L~oad..."), _("Load savegame for selected game"), kLoadGameCmd);
// Above the lowest button rows: two more buttons (directly below the list box)
_addButton =
- new ButtonWidget(this, "Launcher.AddGameButton", "Add Game...", kAddGameCmd, 'A');
+ new ButtonWidget(this, "Launcher.AddGameButton", _("~A~dd Game..."), _("Hold Shift for Mass Add"), kAddGameCmd);
_editButton =
- new ButtonWidget(this, "Launcher.EditGameButton", "Edit Game...", kEditGameCmd, 'E');
+ new ButtonWidget(this, "Launcher.EditGameButton", _("~E~dit Game..."), _("Change game options"), kEditGameCmd);
_removeButton =
- new ButtonWidget(this, "Launcher.RemoveGameButton", "Remove Game", kRemoveGameCmd, 'R');
+ new ButtonWidget(this, "Launcher.RemoveGameButton", _("~R~emove Game"), _("Remove game from the list. The game data files stay intact"), kRemoveGameCmd);
// Search box
_searchDesc = 0;
#ifndef DISABLE_FANCY_THEMES
_searchPic = 0;
if (g_gui.xmlEval()->getVar("Globals.ShowSearchPic") == 1 && g_gui.theme()->supportsImages()) {
- _searchPic = new GraphicsWidget(this, "Launcher.SearchPic");
+ _searchPic = new GraphicsWidget(this, "Launcher.SearchPic", _("Search in game list"));
_searchPic->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSearch));
} else
#endif
- _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", "Search:");
+ _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", _("Search:"));
- _searchWidget = new EditTextWidget(this, "Launcher.Search", _search, kSearchCmd);
- _searchClearButton = new ButtonWidget(this, "Launcher.SearchClearButton", "C", kSearchClearCmd, 0);
+ _searchWidget = new EditTextWidget(this, "Launcher.Search", _search, 0, kSearchCmd);
+ _searchClearButton = new ButtonWidget(this, "Launcher.SearchClearButton", "C", _("Clear value"), kSearchClearCmd);
// Add list with game titles
- _list = new ListWidget(this, "Launcher.GameList", kListSearchCmd);
+ _list = new ListWidget(this, "Launcher.GameList", 0, kListSearchCmd);
_list->setEditable(false);
_list->setNumberingMode(kListNumberingOff);
@@ -544,10 +565,10 @@ LauncherDialog::LauncherDialog()
updateButtons();
// Create file browser dialog
- _browser = new BrowserDialog("Select directory with game data", true);
+ _browser = new BrowserDialog(_("Select directory with game data"), true);
// Create Load dialog
- _loadDialog = new SaveLoadChooser("Load game:", "Load");
+ _loadDialog = new SaveLoadChooser(_("Load game:"), _("Load"));
}
void LauncherDialog::selectTarget(const String &target) {
@@ -619,8 +640,12 @@ void LauncherDialog::updateListing() {
description = g.description();
}
- if (description.empty())
- description = "Unknown (target " + iter->_key + ", gameid " + gameid + ")";
+ if (description.empty()) {
+ char tmp[200];
+
+ snprintf(tmp, 200, "Unknown (target %s, gameid %s)", iter->_key.c_str(), gameid.c_str());
+ description = tmp;
+ }
if (!gameid.empty() && !description.empty()) {
// Insert the game into the launcher list
@@ -652,8 +677,8 @@ void LauncherDialog::addGame() {
const bool massAdd = (modifiers & Common::KBD_SHIFT) != 0;
if (massAdd) {
- MessageDialog alert("Do you really want to run the mass game detector? "
- "This could potentially add a huge number of games.", "Yes", "No");
+ MessageDialog alert(_("Do you really want to run the mass game detector? "
+ "This could potentially add a huge number of games."), _("Yes"), _("No"));
if (alert.runModal() == GUI::kMessageOK && _browser->runModal() > 0) {
MassAddDialog massAddDlg(_browser->getResult());
@@ -700,7 +725,7 @@ void LauncherDialog::addGame() {
Common::FSNode dir(_browser->getResult());
Common::FSList files;
if (!dir.getChildren(files, Common::FSNode::kListAll)) {
- MessageDialog alert("ScummVM couldn't open the specified directory!");
+ MessageDialog alert(_("ScummVM couldn't open the specified directory!"));
alert.runModal();
return;
}
@@ -712,7 +737,7 @@ void LauncherDialog::addGame() {
int idx;
if (candidates.empty()) {
// No game was found in the specified directory
- MessageDialog alert("ScummVM could not find any game in the specified directory!");
+ MessageDialog alert(_("ScummVM could not find any game in the specified directory!"));
alert.runModal();
idx = -1;
@@ -726,7 +751,7 @@ void LauncherDialog::addGame() {
for (idx = 0; idx < (int)candidates.size(); idx++)
list.push_back(candidates[idx].description());
- ChooserDialog dialog("Pick the game:");
+ ChooserDialog dialog(_("Pick the game:"));
dialog.setList(list);
idx = dialog.runModal();
}
@@ -802,7 +827,7 @@ Common::String addGameToConf(const GameDescriptor &result) {
}
void LauncherDialog::removeGame(int item) {
- MessageDialog alert("Do you really want to remove this game configuration?", "Yes", "No");
+ MessageDialog alert(_("Do you really want to remove this game configuration?"), _("Yes"), _("No"));
if (alert.runModal() == GUI::kMessageOK) {
// Remove the currently selected game from the list
@@ -870,11 +895,11 @@ void LauncherDialog::loadGame(int item) {
}
} else {
MessageDialog dialog
- ("This game does not support loading games from the launcher.", "OK");
+ (_("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");
+ MessageDialog dialog(_("ScummVM could not find any engine capable of running the selected game!"), _("OK"));
dialog.runModal();
}
}
@@ -986,8 +1011,8 @@ void LauncherDialog::updateButtons() {
int modifiers = g_system->getEventManager()->getModifierState();
const bool massAdd = (modifiers & Common::KBD_SHIFT) != 0;
const char *newAddButtonLabel = massAdd
- ? "Mass Add..."
- : "Add Game...";
+ ? _("Mass Add...")
+ : _("Add Game...");
if (_addButton->getLabel() != newAddButtonLabel)
_addButton->setLabel(newAddButtonLabel);
@@ -1034,7 +1059,7 @@ void LauncherDialog::reflowLayout() {
}
} else {
if (!_searchDesc)
- _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", "Search:");
+ _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", _("Search:"));
if (_searchPic) {
removeWidget(_searchPic);
diff --git a/gui/massadd.cpp b/gui/massadd.cpp
index 266226161a..7a597085c5 100644
--- a/gui/massadd.cpp
+++ b/gui/massadd.cpp
@@ -27,6 +27,7 @@
#include "common/events.h"
#include "common/func.h"
#include "common/config-manager.h"
+#include "common/translation.h"
#include "gui/launcher.h" // For addGameToConf()
#include "gui/massadd.h"
@@ -75,10 +76,10 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir)
// new StaticTextWidget(this, "massadddialog_caption", "Mass Add Dialog");
_dirProgressText = new StaticTextWidget(this, "MassAdd.DirProgressText",
- "... progress ...");
+ _("... progress ..."));
_gameProgressText = new StaticTextWidget(this, "MassAdd.GameProgressText",
- "... progress ...");
+ _("... progress ..."));
_dirProgressText->setAlign(Graphics::kTextAlignCenter);
_gameProgressText->setAlign(Graphics::kTextAlignCenter);
@@ -88,10 +89,10 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir)
_list->setNumberingMode(kListNumberingOff);
_list->setList(l);
- _okButton = new ButtonWidget(this, "MassAdd.Ok", "OK", kOkCmd, Common::ASCII_RETURN);
+ _okButton = new ButtonWidget(this, "MassAdd.Ok", _("OK"), 0, kOkCmd, Common::ASCII_RETURN);
_okButton->setEnabled(false);
- new ButtonWidget(this, "MassAdd.Cancel", "Cancel", kCancelCmd, Common::ASCII_ESCAPE);
+ new ButtonWidget(this, "MassAdd.Cancel", _("Cancel"), 0, kCancelCmd, Common::ASCII_ESCAPE);
// Build a map from all configured game paths to the targets using them
const Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
@@ -240,17 +241,17 @@ void MassAddDialog::handleTickle() {
// Enable the OK button
_okButton->setEnabled(true);
- snprintf(buf, sizeof(buf), "Scan complete!");
+ snprintf(buf, sizeof(buf), "%s", _("Scan complete!"));
_dirProgressText->setLabel(buf);
- snprintf(buf, sizeof(buf), "Discovered %d new games.", _games.size());
+ snprintf(buf, sizeof(buf), _("Discovered %d new games."), _games.size());
_gameProgressText->setLabel(buf);
} else {
- snprintf(buf, sizeof(buf), "Scanned %d directories ...", _dirsScanned);
+ snprintf(buf, sizeof(buf), _("Scanned %d directories ..."), _dirsScanned);
_dirProgressText->setLabel(buf);
- snprintf(buf, sizeof(buf), "Discovered %d new games ...", _games.size());
+ snprintf(buf, sizeof(buf), _("Discovered %d new games ..."), _games.size());
_gameProgressText->setLabel(buf);
}
diff --git a/gui/message.cpp b/gui/message.cpp
index 12ac3123a4..6406976569 100644
--- a/gui/message.cpp
+++ b/gui/message.cpp
@@ -89,10 +89,10 @@ MessageDialog::MessageDialog(const Common::String &message, const char *defaultB
}
if (defaultButton)
- new ButtonWidget(this, okButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, defaultButton, kOkCmd, Common::ASCII_RETURN); // Confirm dialog
+ new ButtonWidget(this, okButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, defaultButton, 0, kOkCmd, Common::ASCII_RETURN); // Confirm dialog
if (altButton)
- new ButtonWidget(this, cancelButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, altButton, kCancelCmd, Common::ASCII_ESCAPE); // Cancel dialog
+ new ButtonWidget(this, cancelButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, altButton, 0, kCancelCmd, Common::ASCII_ESCAPE); // Cancel dialog
}
void MessageDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
diff --git a/gui/module.mk b/gui/module.mk
index 9bf1a08d4b..72b5fa18f3 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -25,6 +25,7 @@ MODULE_OBJS := \
ThemeEval.o \
ThemeLayout.o \
ThemeParser.o \
+ Tooltip.o \
widget.o
ifdef MACOSX
diff --git a/gui/options.cpp b/gui/options.cpp
index 212e90f9f0..072b20b393 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -35,10 +35,12 @@
#include "common/fs.h"
#include "common/config-manager.h"
#include "common/system.h"
+#include "common/translation.h"
#include "graphics/scaler.h"
#include "sound/mididrv.h"
+#include "sound/musicplugin.h"
#include "sound/mixer.h"
#include "sound/fmopl.h"
@@ -61,15 +63,21 @@ enum {
kChooseThemeCmd = 'chtf'
};
+enum {
+ kSubtitlesSpeech,
+ kSubtitlesSubs,
+ kSubtitlesBoth
+};
+
#ifdef SMALL_SCREEN_DEVICE
enum {
kChooseKeyMappingCmd = 'chma'
};
#endif
-static const char *savePeriodLabels[] = { "Never", "every 5 mins", "every 10 mins", "every 15 mins", "every 30 mins", 0 };
+static const char *savePeriodLabels[] = { _s("Never"), _s("every 5 mins"), _s("every 10 mins"), _s("every 15 mins"), _s("every 30 mins"), 0 };
static const int savePeriodValues[] = { 0, 5 * 60, 10 * 60, 15 * 60, 30 * 60, -1 };
-static const char *outputRateLabels[] = { "<default>", "8 kHz", "11kHz", "22 kHz", "44 kHz", "48 kHz", 0 };
+static const char *outputRateLabels[] = { _s("<default>"), _s("8 kHz"), _s("11kHz"), _s("22 kHz"), _s("44 kHz"), _s("48 kHz"), 0 };
static const int outputRateValues[] = { 0, 8000, 11025, 22050, 44100, 48000, -1 };
@@ -84,18 +92,6 @@ OptionsDialog::OptionsDialog(const Common::String &domain, const Common::String
init();
}
-const char *OptionsDialog::_subModeDesc[] = {
- "Speech Only",
- "Speech and Subtitles",
- "Subtitles Only"
-};
-
-const char *OptionsDialog::_lowresSubModeDesc[] = {
- "Speech Only",
- "Speech & Subs",
- "Subtitles Only"
-};
-
void OptionsDialog::init() {
_enableGraphicSettings = false;
_gfxPopUp = 0;
@@ -107,8 +103,11 @@ void OptionsDialog::init() {
_oplPopUp = 0;
_outputRatePopUp = 0;
_enableMIDISettings = false;
+ _gmDevicePopUp = 0;
_multiMidiCheckbox = 0;
+ _enableMT32Settings = false;
_mt32Checkbox = 0;
+ _mt32DevicePopUp = 0;
_enableGSCheckbox = 0;
_enableVolumeSettings = false;
_musicVolumeDesc = 0;
@@ -122,15 +121,20 @@ void OptionsDialog::init() {
_speechVolumeLabel = 0;
_muteCheckbox = 0;
_subToggleDesc = 0;
- _subToggleButton = 0;
+ _subToggleGroup = 0;
+ _subToggleSubOnly = 0;
+ _subToggleSpeechOnly = 0;
+ _subToggleSubBoth = 0;
_subSpeedDesc = 0;
_subSpeedSlider = 0;
_subSpeedLabel = 0;
// Retrieve game GUI options
_guioptions = 0;
- if (ConfMan.hasKey("guioptions", _domain))
- _guioptions = parseGameGUIOptions(ConfMan.get("guioptions", _domain));
+ if (ConfMan.hasKey("guioptions", _domain)) {
+ _guioptionsString = ConfMan.get("guioptions", _domain);
+ _guioptions = parseGameGUIOptions(_guioptionsString);
+ }
}
void OptionsDialog::open() {
@@ -141,8 +145,10 @@ void OptionsDialog::open() {
// Retrieve game GUI options
_guioptions = 0;
- if (ConfMan.hasKey("guioptions", _domain))
- _guioptions = parseGameGUIOptions(ConfMan.get("guioptions", _domain));
+ if (ConfMan.hasKey("guioptions", _domain)) {
+ _guioptionsString = ConfMan.get("guioptions", _domain);
+ _guioptions = parseGameGUIOptions(_guioptionsString);
+ }
// Graphic options
if (_fullscreenCheckbox) {
@@ -189,11 +195,8 @@ void OptionsDialog::open() {
}
// Audio options
- if (_midiPopUp) {
- // Music driver
- MidiDriverType id = MidiDriver::parseMusicDriver(ConfMan.get("music_driver", _domain));
- _midiPopUp->setSelectedTag(id);
- }
+ if (!loadMusicDeviceSetting(_midiPopUp, "music_driver"))
+ _midiPopUp->setSelected(0);
if (_oplPopUp) {
OPL::Config::DriverId id = MAX<OPL::Config::DriverId>(OPL::Config::parse(ConfMan.get("opl_driver", _domain)), 0);
@@ -210,19 +213,21 @@ void OptionsDialog::open() {
}
if (_multiMidiCheckbox) {
+ if (!loadMusicDeviceSetting(_gmDevicePopUp, "gm_device")) {
+ if (_domain.equals(Common::ConfigManager::kApplicationDomain)) {
+ if (!loadMusicDeviceSetting(_gmDevicePopUp, Common::String(), MT_GM))
+ _gmDevicePopUp->setSelected(0);
+ } else {
+ _gmDevicePopUp->setSelected(0);
+ }
+ }
// Multi midi setting
_multiMidiCheckbox->setState(ConfMan.getBool("multi_midi", _domain));
- // Native mt32 setting
- _mt32Checkbox->setState(ConfMan.getBool("native_mt32", _domain));
-
- // GS extensions setting
- _enableGSCheckbox->setState(ConfMan.getBool("enable_gs", _domain));
-
Common::String soundFont(ConfMan.get("soundfont", _domain));
if (soundFont.empty() || !ConfMan.hasKey("soundfont", _domain)) {
- _soundFont->setLabel("None");
+ _soundFont->setLabel(_("None"));
_soundFontClearButton->setEnabled(false);
} else {
_soundFont->setLabel(soundFont);
@@ -237,6 +242,24 @@ void OptionsDialog::open() {
_midiGainLabel->setLabel(buf);
}
+ // MT-32 options
+ if (_mt32DevicePopUp) {
+ if (!loadMusicDeviceSetting(_mt32DevicePopUp, "mt32_device")) {
+ if (_domain.equals(Common::ConfigManager::kApplicationDomain)) {
+ if (!loadMusicDeviceSetting(_mt32DevicePopUp, Common::String(), MT_MT32))
+ _mt32DevicePopUp->setSelected(0);
+ } else {
+ _mt32DevicePopUp->setSelected(0);
+ }
+ }
+
+ // Native mt32 setting
+ _mt32Checkbox->setState(ConfMan.getBool("native_mt32", _domain));
+
+ // GS extensions setting
+ _enableGSCheckbox->setState(ConfMan.getBool("enable_gs", _domain));
+ }
+
// Volume options
if (_musicVolumeSlider) {
int vol;
@@ -263,11 +286,12 @@ void OptionsDialog::open() {
}
// Subtitle options
- if (_subToggleButton) {
- int speed; int sliderMaxValue = _subSpeedSlider->getMaxValue();
+ if (_subToggleGroup) {
+ int speed;
+ int sliderMaxValue = _subSpeedSlider->getMaxValue();
- _subMode = getSubtitleMode(ConfMan.getBool("subtitles", _domain), ConfMan.getBool("speech_mute", _domain));
- _subToggleButton->setLabel(_subModeDesc[_subMode]);
+ int subMode = getSubtitleMode(ConfMan.getBool("subtitles", _domain), ConfMan.getBool("speech_mute", _domain));
+ _subToggleGroup->setValue(subMode);
// Engines that reuse the subtitle speed widget set their own max value.
// Scale the config value accordingly (see addSubtitleControls)
@@ -331,13 +355,7 @@ void OptionsDialog::close() {
// Audio options
if (_midiPopUp) {
if (_enableAudioSettings) {
- const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers();
- while (md->name && md->id != (int)_midiPopUp->getSelectedTag())
- md++;
- if (md->name)
- ConfMan.set("music_driver", md->name, _domain);
- else
- ConfMan.removeKey("music_driver", _domain);
+ saveMusicDeviceSetting(_midiPopUp, "music_driver");
} else {
ConfMan.removeKey("music_driver", _domain);
}
@@ -372,41 +390,53 @@ void OptionsDialog::close() {
// MIDI options
if (_multiMidiCheckbox) {
if (_enableMIDISettings) {
+ saveMusicDeviceSetting(_gmDevicePopUp, "gm_device");
+
ConfMan.setBool("multi_midi", _multiMidiCheckbox->getState(), _domain);
- ConfMan.setBool("native_mt32", _mt32Checkbox->getState(), _domain);
- ConfMan.setBool("enable_gs", _enableGSCheckbox->getState(), _domain);
ConfMan.setInt("midi_gain", _midiGainSlider->getValue(), _domain);
Common::String soundFont(_soundFont->getLabel());
- if (!soundFont.empty() && (soundFont != "None"))
+ if (!soundFont.empty() && (soundFont != _("None")))
ConfMan.set("soundfont", soundFont, _domain);
else
ConfMan.removeKey("soundfont", _domain);
} else {
+ ConfMan.removeKey("gm_device", _domain);
ConfMan.removeKey("multi_midi", _domain);
- ConfMan.removeKey("native_mt32", _domain);
- ConfMan.removeKey("enable_gs", _domain);
ConfMan.removeKey("midi_gain", _domain);
ConfMan.removeKey("soundfont", _domain);
}
}
+ // MT-32 options
+ if (_mt32DevicePopUp) {
+ if (_enableMT32Settings) {
+ saveMusicDeviceSetting(_mt32DevicePopUp, "mt32_device");
+ ConfMan.setBool("native_mt32", _mt32Checkbox->getState(), _domain);
+ ConfMan.setBool("enable_gs", _enableGSCheckbox->getState(), _domain);
+ } else {
+ ConfMan.removeKey("mt32_device", _domain);
+ ConfMan.removeKey("native_mt32", _domain);
+ ConfMan.removeKey("enable_gs", _domain);
+ }
+ }
+
// Subtitle options
- if (_subToggleButton) {
+ if (_subToggleGroup) {
if (_enableSubtitleSettings) {
bool subtitles, speech_mute;
int talkspeed;
int sliderMaxValue = _subSpeedSlider->getMaxValue();
- switch (_subMode) {
- case 0:
+ switch (_subToggleGroup->getValue()) {
+ case kSubtitlesSpeech:
subtitles = speech_mute = false;
break;
- case 1:
+ case kSubtitlesBoth:
subtitles = true;
speech_mute = false;
break;
- case 2:
+ case kSubtitlesSubs:
default:
subtitles = speech_mute = true;
break;
@@ -459,24 +489,12 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
// 'true' because if control is disabled then event do not pass
setVolumeSettingsState(true);
break;
- case kSubtitleToggle:
- if (_subMode < 2)
- _subMode++;
- else
- _subMode = 0;
-
- _subToggleButton->setLabel(g_system->getOverlayWidth() > 320 ? _subModeDesc[_subMode] : _lowresSubModeDesc[_subMode]);
- _subToggleButton->draw();
- _subSpeedDesc->draw();
- _subSpeedSlider->draw();
- _subSpeedLabel->draw();
- break;
case kSubtitleSpeedChanged:
_subSpeedLabel->setValue(_subSpeedSlider->getValue());
_subSpeedLabel->draw();
break;
case kClearSoundFontCmd:
- _soundFont->setLabel("None");
+ _soundFont->setLabel(_("None"));
_soundFontClearButton->setEnabled(false);
draw();
break;
@@ -504,11 +522,20 @@ void OptionsDialog::setGraphicSettingsState(bool enabled) {
void OptionsDialog::setAudioSettingsState(bool enabled) {
_enableAudioSettings = enabled;
-
_midiPopUpDesc->setEnabled(enabled);
_midiPopUp->setEnabled(enabled);
- _oplPopUpDesc->setEnabled(enabled);
- _oplPopUp->setEnabled(enabled);
+
+ uint32 allFlags = MidiDriver::musicType2GUIO((uint32)-1);
+
+ if (_domain != Common::ConfigManager::kApplicationDomain && // global dialog
+ (_guioptions & allFlags) && // No flags are specified
+ !(_guioptions & Common::GUIO_MIDIADLIB)) {
+ _oplPopUpDesc->setEnabled(false);
+ _oplPopUp->setEnabled(false);
+ } else {
+ _oplPopUpDesc->setEnabled(enabled);
+ _oplPopUp->setEnabled(enabled);
+ }
_outputRatePopUpDesc->setEnabled(enabled);
_outputRatePopUp->setEnabled(enabled);
}
@@ -517,24 +544,35 @@ void OptionsDialog::setMIDISettingsState(bool enabled) {
if (_guioptions & Common::GUIO_NOMIDI)
enabled = false;
+ _gmDevicePopUpDesc->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
+ _gmDevicePopUp->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
+
_enableMIDISettings = enabled;
_soundFontButton->setEnabled(enabled);
_soundFont->setEnabled(enabled);
- if (enabled && !_soundFont->getLabel().empty() && (_soundFont->getLabel() != "None"))
+ if (enabled && !_soundFont->getLabel().empty() && (_soundFont->getLabel() != _("None")))
_soundFontClearButton->setEnabled(enabled);
else
_soundFontClearButton->setEnabled(false);
_multiMidiCheckbox->setEnabled(enabled);
- _mt32Checkbox->setEnabled(enabled);
- _enableGSCheckbox->setEnabled(enabled);
_midiGainDesc->setEnabled(enabled);
_midiGainSlider->setEnabled(enabled);
_midiGainLabel->setEnabled(enabled);
}
+void OptionsDialog::setMT32SettingsState(bool enabled) {
+ _enableMT32Settings = enabled;
+
+ _mt32DevicePopUpDesc->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
+ _mt32DevicePopUp->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
+
+ _mt32Checkbox->setEnabled(enabled);
+ _enableGSCheckbox->setEnabled(enabled);
+}
+
void OptionsDialog::setVolumeSettingsState(bool enabled) {
bool ena;
@@ -575,7 +613,7 @@ void OptionsDialog::setSubtitleSettingsState(bool enabled) {
if ((_guioptions & Common::GUIO_NOSUBTITLES) || (_guioptions & Common::GUIO_NOSPEECH))
ena = false;
- _subToggleButton->setEnabled(ena);
+ _subToggleGroup->setEnabled(ena);
_subToggleDesc->setEnabled(ena);
ena = enabled;
@@ -591,87 +629,115 @@ void OptionsDialog::addGraphicControls(GuiObject *boss, const Common::String &pr
const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes();
// The GFX mode popup
- _gfxPopUpDesc = new StaticTextWidget(boss, prefix + "grModePopupDesc", "Graphics mode:");
+ _gfxPopUpDesc = new StaticTextWidget(boss, prefix + "grModePopupDesc", _("Graphics mode:"));
_gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup");
- _gfxPopUp->appendEntry("<default>");
+ _gfxPopUp->appendEntry(_("<default>"));
_gfxPopUp->appendEntry("");
while (gm->name) {
- _gfxPopUp->appendEntry(gm->description, gm->id);
+ _gfxPopUp->appendEntry(_(gm->description), gm->id);
gm++;
}
// RenderMode popup
- _renderModePopUpDesc = new StaticTextWidget(boss, prefix + "grRenderPopupDesc", "Render mode:");
- _renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup");
- _renderModePopUp->appendEntry("<default>", Common::kRenderDefault);
+ _renderModePopUpDesc = new StaticTextWidget(boss, prefix + "grRenderPopupDesc", _("Render mode:"), _("Special dithering modes supported by some games"));
+ _renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup", _("Special dithering modes supported by some games"));
+ _renderModePopUp->appendEntry(_("<default>"), Common::kRenderDefault);
_renderModePopUp->appendEntry("");
const Common::RenderModeDescription *rm = Common::g_renderModes;
for (; rm->code; ++rm) {
- _renderModePopUp->appendEntry(rm->description, rm->id);
+ _renderModePopUp->appendEntry(_(rm->description), rm->id);
}
// Fullscreen checkbox
- _fullscreenCheckbox = new CheckboxWidget(boss, prefix + "grFullscreenCheckbox", "Fullscreen mode", 0, 0);
+ _fullscreenCheckbox = new CheckboxWidget(boss, prefix + "grFullscreenCheckbox", _("Fullscreen mode"));
// Aspect ratio checkbox
- _aspectCheckbox = new CheckboxWidget(boss, prefix + "grAspectCheckbox", "Aspect ratio correction", 0, 0);
+ _aspectCheckbox = new CheckboxWidget(boss, prefix + "grAspectCheckbox", _("Aspect ratio correction"), _("Correct aspect ratio for 320x200 games"));
_enableGraphicSettings = true;
}
void OptionsDialog::addAudioControls(GuiObject *boss, const Common::String &prefix) {
// The MIDI mode popup & a label
- _midiPopUpDesc = new StaticTextWidget(boss, prefix + "auMidiPopupDesc", "Music driver:");
- _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup");
+ _midiPopUpDesc = new StaticTextWidget(boss, prefix + "auMidiPopupDesc", _domain == Common::ConfigManager::kApplicationDomain ? _("Preferred Device:") : _("Music Device:"), _domain == Common::ConfigManager::kApplicationDomain ? _("Specifies preferred sound device or sound card emulator") : _("Specifies output sound device or sound card emulator"));
+ _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup", _("Specifies output sound device or sound card emulator"));
// Populate it
- const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers();
- while (md->name) {
- _midiPopUp->appendEntry(md->description, md->id);
- md++;
+ uint32 allFlags = MidiDriver::musicType2GUIO((uint32)-1);
+
+ const MusicPlugin::List p = MusicMan.getPlugins();
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) {
+ MusicDevices i = (**m)->getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
+ const uint32 deviceGuiOption = MidiDriver::musicType2GUIO(d->getMusicType());
+
+ if ((_domain == Common::ConfigManager::kApplicationDomain && d->getMusicType() != MT_TOWNS) // global dialog - skip useless FM-Towns option there
+ || (_domain != Common::ConfigManager::kApplicationDomain && !(_guioptions & allFlags)) // No flags are specified
+ || (_guioptions & deviceGuiOption) // flag is present
+ // HACK/FIXME: For now we have to show GM devices, even when the game only has GUIO_MIDIMT32 set,
+ // else we would not show for example external devices connected via ALSA, since they are always
+ // marked as General MIDI device.
+ || (deviceGuiOption == Common::GUIO_MIDIGM && (_guioptions & Common::GUIO_MIDIMT32))
+ || d->getMusicDriverId() == "auto" || d->getMusicDriverId() == "null") // always add default and null device
+ _midiPopUp->appendEntry(d->getCompleteName(), d->getHandle());
+ }
}
// The OPL emulator popup & a label
- _oplPopUpDesc = new StaticTextWidget(boss, prefix + "auOPLPopupDesc", "AdLib emulator:");
- _oplPopUp = new PopUpWidget(boss, prefix + "auOPLPopup");
+ _oplPopUpDesc = new StaticTextWidget(boss, prefix + "auOPLPopupDesc", _("AdLib emulator:"), _("AdLib is used for music in many games"));
+ _oplPopUp = new PopUpWidget(boss, prefix + "auOPLPopup", _("AdLib is used for music in many games"));
// Populate it
const OPL::Config::EmulatorDescription *ed = OPL::Config::getAvailable();
while (ed->name) {
- _oplPopUp->appendEntry(ed->description, ed->id);
+ _oplPopUp->appendEntry(_(ed->description), ed->id);
++ed;
}
// Sample rate settings
- _outputRatePopUpDesc = new StaticTextWidget(boss, prefix + "auSampleRatePopupDesc", "Output rate:");
- _outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup");
+ _outputRatePopUpDesc = new StaticTextWidget(boss, prefix + "auSampleRatePopupDesc", _("Output rate:"), _("Higher value specifies better sound quality but may be not supported by your soundcard"));
+ _outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup", _("Higher value specifies better sound quality but may be not supported by your soundcard"));
for (int i = 0; outputRateLabels[i]; i++) {
- _outputRatePopUp->appendEntry(outputRateLabels[i], outputRateValues[i]);
+ _outputRatePopUp->appendEntry(_(outputRateLabels[i]), outputRateValues[i]);
}
_enableAudioSettings = true;
}
void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefix) {
- // SoundFont
- _soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", "SoundFont:", kChooseSoundFontCmd, 0);
- _soundFont = new StaticTextWidget(boss, prefix + "mcFontPath", "None");
- _soundFontClearButton = new ButtonWidget(boss, prefix + "mcFontClearButton", "C", kClearSoundFontCmd, 0);
+ _gmDevicePopUpDesc = new StaticTextWidget(boss, prefix + "auPrefGmPopupDesc", _("GM Device:"), _("Specifies default sound device for General MIDI output"));
+ _gmDevicePopUp = new PopUpWidget(boss, prefix + "auPrefGmPopup");
+
+ // Populate
+ const MusicPlugin::List p = MusicMan.getPlugins();
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) {
+ MusicDevices i = (**m)->getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
+ if (d->getMusicType() >= MT_GM || d->getMusicDriverId() == "auto") {
+ if (d->getMusicType() != MT_MT32)
+ _gmDevicePopUp->appendEntry(d->getCompleteName(), d->getHandle());
+ }
+ }
+ }
- // Multi midi setting
- _multiMidiCheckbox = new CheckboxWidget(boss, prefix + "mcMixedCheckbox", "Mixed AdLib/MIDI mode", 0, 0);
+ if (!_domain.equals(Common::ConfigManager::kApplicationDomain)) {
+ _gmDevicePopUpDesc->setEnabled(false);
+ _gmDevicePopUp->setEnabled(false);
+ }
- // Native mt32 setting
- _mt32Checkbox = new CheckboxWidget(boss, prefix + "mcMt32Checkbox", "True Roland MT-32 (disable GM emulation)", 0, 0);
+ // SoundFont
+ _soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _("SoundFont:"), _("SoundFont is supported by some audio cards, Fluidsynth and Timidity"), kChooseSoundFontCmd);
+ _soundFont = new StaticTextWidget(boss, prefix + "mcFontPath", _("None"), _("SoundFont is supported by some audio cards, Fluidsynth and Timidity"));
+ _soundFontClearButton = new ButtonWidget(boss, prefix + "mcFontClearButton", "C", _("Clear value"), kClearSoundFontCmd);
- // GS Extensions setting
- _enableGSCheckbox = new CheckboxWidget(boss, prefix + "mcGSCheckbox", "Enable Roland GS Mode", 0, 0);
+ // Multi midi setting
+ _multiMidiCheckbox = new CheckboxWidget(boss, prefix + "mcMixedCheckbox", _("Mixed AdLib/MIDI mode"), _("Use both MIDI and AdLib sound generation"));
// MIDI gain setting (FluidSynth uses this)
- _midiGainDesc = new StaticTextWidget(boss, prefix + "mcMidiGainText", "MIDI gain:");
- _midiGainSlider = new SliderWidget(boss, prefix + "mcMidiGainSlider", kMidiGainChanged);
+ _midiGainDesc = new StaticTextWidget(boss, prefix + "mcMidiGainText", _("MIDI gain:"));
+ _midiGainSlider = new SliderWidget(boss, prefix + "mcMidiGainSlider", 0, kMidiGainChanged);
_midiGainSlider->setMinValue(0);
_midiGainSlider->setMaxValue(1000);
_midiGainLabel = new StaticTextWidget(boss, prefix + "mcMidiGainLabel", "1.00");
@@ -679,16 +745,57 @@ void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefi
_enableMIDISettings = true;
}
+void OptionsDialog::addMT32Controls(GuiObject *boss, const Common::String &prefix) {
+ _mt32DevicePopUpDesc = new StaticTextWidget(boss, prefix + "auPrefMt32PopupDesc", _("MT-32 Device:"), _("Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"));
+ _mt32DevicePopUp = new PopUpWidget(boss, prefix + "auPrefMt32Popup");
+
+ // Native mt32 setting
+ _mt32Checkbox = new CheckboxWidget(boss, prefix + "mcMt32Checkbox", _("True Roland MT-32 (disable GM emulation)"), _("Check if you want to use your real hardware Roland-compatible sound device connected to your computer"));
+
+ // GS Extensions setting
+ _enableGSCheckbox = new CheckboxWidget(boss, prefix + "mcGSCheckbox", _("Enable Roland GS Mode"), _("Turns off General MIDI mapping for games with Roland MT-32 soundtrack"));
+
+ const MusicPlugin::List p = MusicMan.getPlugins();
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) {
+ MusicDevices i = (**m)->getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
+ if (d->getMusicType() >= MT_GM || d->getMusicDriverId() == "auto") {
+ _mt32DevicePopUp->appendEntry(d->getCompleteName(), d->getHandle());
+ }
+ }
+ }
+
+ if (!_domain.equals(Common::ConfigManager::kApplicationDomain)) {
+ _mt32DevicePopUpDesc->setEnabled(false);
+ _mt32DevicePopUp->setEnabled(false);
+ }
+
+ _enableMIDISettings = true;
+}
+
// The function has an extra slider range parameter, since both the launcher and SCUMM engine
// make use of the widgets. The launcher range is 0-255. SCUMM's 0-9
void OptionsDialog::addSubtitleControls(GuiObject *boss, const Common::String &prefix, int maxSliderVal) {
- _subToggleDesc = new StaticTextWidget(boss, prefix + "subToggleDesc", "Text and Speech:");
- _subToggleButton = new ButtonWidget(boss, prefix + "subToggleButton", "", kSubtitleToggle, 0);
+ _subToggleDesc = new StaticTextWidget(boss, prefix + "subToggleDesc", _("Text and Speech:"));
+
+ if (g_system->getOverlayWidth() > 320) {
+ _subToggleGroup = new RadiobuttonGroup(boss, kSubtitleToggle);
+
+ _subToggleSpeechOnly = new RadiobuttonWidget(boss, prefix + "subToggleSpeechOnly", _subToggleGroup, kSubtitlesSpeech, _("Speech"));
+ _subToggleSubOnly = new RadiobuttonWidget(boss, prefix + "subToggleSubOnly", _subToggleGroup, kSubtitlesSubs, _("Subtitles"));
+ _subToggleSubBoth = new RadiobuttonWidget(boss, prefix + "subToggleSubBoth", _subToggleGroup, kSubtitlesBoth, _("Both"));
+ } else {
+ _subToggleGroup = new RadiobuttonGroup(boss, kSubtitleToggle);
+
+ _subToggleSpeechOnly = new RadiobuttonWidget(boss, prefix + "subToggleSpeechOnly", _subToggleGroup, kSubtitlesSpeech, _("Spch"), _("Speech"));
+ _subToggleSubOnly = new RadiobuttonWidget(boss, prefix + "subToggleSubOnly", _subToggleGroup, kSubtitlesSubs, _("Subs"), _("Subtitles"));
+ _subToggleSubBoth = new RadiobuttonWidget(boss, prefix + "subToggleSubBoth", _subToggleGroup, kSubtitlesBoth, _("Both"), _("Show subtitles and play speech"));
+ }
// Subtitle speed
- _subSpeedDesc = new StaticTextWidget(boss, prefix + "subSubtitleSpeedDesc", "Subtitle speed:");
- _subSpeedSlider = new SliderWidget(boss, prefix + "subSubtitleSpeedSlider", kSubtitleSpeedChanged);
+ _subSpeedDesc = new StaticTextWidget(boss, prefix + "subSubtitleSpeedDesc", _("Subtitle speed:"));
+ _subSpeedSlider = new SliderWidget(boss, prefix + "subSubtitleSpeedSlider", 0, kSubtitleSpeedChanged);
_subSpeedLabel = new StaticTextWidget(boss, prefix + "subSubtitleSpeedLabel", "100%");
_subSpeedSlider->setMinValue(0); _subSpeedSlider->setMaxValue(maxSliderVal);
_subSpeedLabel->setFlags(WIDGET_CLEARBG);
@@ -699,25 +806,25 @@ void OptionsDialog::addSubtitleControls(GuiObject *boss, const Common::String &p
void OptionsDialog::addVolumeControls(GuiObject *boss, const Common::String &prefix) {
// Volume controllers
- _musicVolumeDesc = new StaticTextWidget(boss, prefix + "vcMusicText", "Music volume:");
- _musicVolumeSlider = new SliderWidget(boss, prefix + "vcMusicSlider", kMusicVolumeChanged);
+ _musicVolumeDesc = new StaticTextWidget(boss, prefix + "vcMusicText", _("Music volume:"));
+ _musicVolumeSlider = new SliderWidget(boss, prefix + "vcMusicSlider", 0, kMusicVolumeChanged);
_musicVolumeLabel = new StaticTextWidget(boss, prefix + "vcMusicLabel", "100%");
_musicVolumeSlider->setMinValue(0);
_musicVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume);
_musicVolumeLabel->setFlags(WIDGET_CLEARBG);
- _muteCheckbox = new CheckboxWidget(boss, prefix + "vcMuteCheckbox", "Mute All", kMuteAllChanged, 0);
+ _muteCheckbox = new CheckboxWidget(boss, prefix + "vcMuteCheckbox", _("Mute All"), 0, kMuteAllChanged);
- _sfxVolumeDesc = new StaticTextWidget(boss, prefix + "vcSfxText", "SFX volume:");
- _sfxVolumeSlider = new SliderWidget(boss, prefix + "vcSfxSlider", kSfxVolumeChanged);
+ _sfxVolumeDesc = new StaticTextWidget(boss, prefix + "vcSfxText", _("SFX volume:"), _("Special sound effects volume"));
+ _sfxVolumeSlider = new SliderWidget(boss, prefix + "vcSfxSlider", _("Special sound effects volume"), kSfxVolumeChanged);
_sfxVolumeLabel = new StaticTextWidget(boss, prefix + "vcSfxLabel", "100%");
_sfxVolumeSlider->setMinValue(0);
_sfxVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume);
_sfxVolumeLabel->setFlags(WIDGET_CLEARBG);
- _speechVolumeDesc = new StaticTextWidget(boss, prefix + "vcSpeechText" , "Speech volume:");
- _speechVolumeSlider = new SliderWidget(boss, prefix + "vcSpeechSlider", kSpeechVolumeChanged);
+ _speechVolumeDesc = new StaticTextWidget(boss, prefix + "vcSpeechText" , _("Speech volume:"));
+ _speechVolumeSlider = new SliderWidget(boss, prefix + "vcSpeechSlider", 0, kSpeechVolumeChanged);
_speechVolumeLabel = new StaticTextWidget(boss, prefix + "vcSpeechLabel", "100%");
_speechVolumeSlider->setMinValue(0);
_speechVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume);
@@ -726,26 +833,69 @@ void OptionsDialog::addVolumeControls(GuiObject *boss, const Common::String &pre
_enableVolumeSettings = true;
}
+bool OptionsDialog::loadMusicDeviceSetting(PopUpWidget *popup, Common::String setting, MusicType preferredType) {
+ if (!popup || !popup->isEnabled())
+ return true;
+
+ if (_domain != Common::ConfigManager::kApplicationDomain || ConfMan.hasKey(setting, _domain) || preferredType) {
+ const Common::String drv = ConfMan.get(setting, (_domain != Common::ConfigManager::kApplicationDomain && !ConfMan.hasKey(setting, _domain)) ? Common::ConfigManager::kApplicationDomain : _domain);
+ const MusicPlugin::List p = MusicMan.getPlugins();
+
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) {
+ MusicDevices i = (**m)->getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
+ if (setting.empty() ? (preferredType == d->getMusicType()) : (drv == d->getCompleteId())) {
+ popup->setSelectedTag(d->getHandle());
+ return popup->getSelected() == -1 ? false : true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+void OptionsDialog::saveMusicDeviceSetting(PopUpWidget *popup, Common::String setting) {
+ if (!popup || !_enableAudioSettings)
+ return;
+
+ const MusicPlugin::List p = MusicMan.getPlugins();
+ bool found = false;
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end() && !found; ++m) {
+ MusicDevices i = (**m)->getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
+ if (d->getHandle() == popup->getSelectedTag()) {
+ ConfMan.set(setting, d->getCompleteId(), _domain);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ ConfMan.removeKey(setting, _domain);
+}
+
int OptionsDialog::getSubtitleMode(bool subtitles, bool speech_mute) {
if (_guioptions & Common::GUIO_NOSUBTITLES)
- return 0; // Speech only
+ return kSubtitlesSpeech; // Speech only
if (_guioptions & Common::GUIO_NOSPEECH)
- return 2; // Subtitles only
+ return kSubtitlesSubs; // Subtitles only
if (!subtitles && !speech_mute) // Speech only
- return 0;
+ return kSubtitlesSpeech;
else if (subtitles && !speech_mute) // Speech and subtitles
- return 1;
+ return kSubtitlesBoth;
else if (subtitles && speech_mute) // Subtitles only
- return 2;
+ return kSubtitlesSubs;
else
warning("Wrong configuration: Both subtitles and speech are off. Assuming subtitles only");
- return 2;
+ return kSubtitlesSubs;
}
void OptionsDialog::reflowLayout() {
if (_graphicsTabId != -1 && _tabWidget)
- _tabWidget->setTabTitle(_graphicsTabId, g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX");
+ _tabWidget->setTabTitle(_graphicsTabId, g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX"));
Dialog::reflowLayout();
}
@@ -762,17 +912,17 @@ GlobalOptionsDialog::GlobalOptionsDialog()
//
// 1) The graphics tab
//
- _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX");
+ _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX"));
addGraphicControls(tab, "GlobalOptions_Graphics.");
//
// 2) The audio tab
//
- tab->addTab("Audio");
+ tab->addTab(_("Audio"));
addAudioControls(tab, "GlobalOptions_Audio.");
addSubtitleControls(tab, "GlobalOptions_Audio.");
- tab->addTab("Volume");
+ tab->addTab(_("Volume"));
addVolumeControls(tab, "GlobalOptions_Volume.");
// TODO: cd drive setting
@@ -780,67 +930,104 @@ GlobalOptionsDialog::GlobalOptionsDialog()
//
// 3) The MIDI tab
//
- tab->addTab("MIDI");
+ tab->addTab(_("MIDI"));
addMIDIControls(tab, "GlobalOptions_MIDI.");
//
- // 4) The miscellaneous tab
+ // 4) The MT-32 tab
+ //
+ tab->addTab(_("MT-32"));
+ addMT32Controls(tab, "GlobalOptions_MT32.");
+
+ //
+ // 5) The Paths tab
//
- tab->addTab("Paths");
+ tab->addTab(_("Paths"));
#if !( defined(__DC__) || defined(__GP32__) )
// These two buttons have to be extra wide, or the text will be
// truncated in the small version of the GUI.
// Save game path
- new ButtonWidget(tab, "GlobalOptions_Paths.SaveButton", "Save Path: ", kChooseSaveDirCmd, 0);
- _savePath = new StaticTextWidget(tab, "GlobalOptions_Paths.SavePath", "/foo/bar");
+ new ButtonWidget(tab, "GlobalOptions_Paths.SaveButton", _("Save Path: "), _("Specifies where your savegames are put"), kChooseSaveDirCmd);
+ _savePath = new StaticTextWidget(tab, "GlobalOptions_Paths.SavePath", "/foo/bar", _("Specifies where your savegames are put"));
- new ButtonWidget(tab, "GlobalOptions_Paths.ThemeButton", "Theme Path:", kChooseThemeDirCmd, 0);
- _themePath = new StaticTextWidget(tab, "GlobalOptions_Paths.ThemePath", "None");
+ new ButtonWidget(tab, "GlobalOptions_Paths.ThemeButton", _("Theme Path:"), 0, kChooseThemeDirCmd);
+ _themePath = new StaticTextWidget(tab, "GlobalOptions_Paths.ThemePath", _("None"));
- new ButtonWidget(tab, "GlobalOptions_Paths.ExtraButton", "Extra Path:", kChooseExtraDirCmd, 0);
- _extraPath = new StaticTextWidget(tab, "GlobalOptions_Paths.ExtraPath", "None");
+ new ButtonWidget(tab, "GlobalOptions_Paths.ExtraButton", _("Extra Path:"), _("Specifies path to additional data used by all games or ScummVM"), kChooseExtraDirCmd);
+ _extraPath = new StaticTextWidget(tab, "GlobalOptions_Paths.ExtraPath", _("None"), _("Specifies path to additional data used by all games or ScummVM"));
#ifdef DYNAMIC_MODULES
- new ButtonWidget(tab, "GlobalOptions_Paths.PluginsButton", "Plugins Path:", kChoosePluginsDirCmd, 0);
- _pluginsPath = new StaticTextWidget(tab, "GlobalOptions_Paths.PluginsPath", "None");
+ new ButtonWidget(tab, "GlobalOptions_Paths.PluginsButton", _("Plugins Path:"), 0, kChoosePluginsDirCmd);
+ _pluginsPath = new StaticTextWidget(tab, "GlobalOptions_Paths.PluginsPath", _("None"));
#endif
#endif
- tab->addTab("Misc");
+ //
+ // 6) The miscellaneous tab
+ //
+ tab->addTab(_("Misc"));
- new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", "Theme:", kChooseThemeCmd, 0);
+ new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", _("Theme:"), 0, kChooseThemeCmd);
_curTheme = new StaticTextWidget(tab, "GlobalOptions_Misc.CurTheme", g_gui.theme()->getThemeName());
- _rendererPopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.RendererPopupDesc", "GUI Renderer:");
+ _rendererPopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.RendererPopupDesc", _("GUI Renderer:"));
_rendererPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.RendererPopup");
for (uint i = 1; i < GUI::ThemeEngine::_rendererModesSize; ++i)
- _rendererPopUp->appendEntry(GUI::ThemeEngine::_rendererModes[i].name, GUI::ThemeEngine::_rendererModes[i].mode);
+ _rendererPopUp->appendEntry(_(GUI::ThemeEngine::_rendererModes[i].name), GUI::ThemeEngine::_rendererModes[i].mode);
- _autosavePeriodPopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.AutosavePeriodPopupDesc", "Autosave:");
+ _autosavePeriodPopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.AutosavePeriodPopupDesc", _("Autosave:"));
_autosavePeriodPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.AutosavePeriodPopup");
for (int i = 0; savePeriodLabels[i]; i++) {
- _autosavePeriodPopUp->appendEntry(savePeriodLabels[i], savePeriodValues[i]);
+ _autosavePeriodPopUp->appendEntry(_(savePeriodLabels[i]), savePeriodValues[i]);
}
#ifdef SMALL_SCREEN_DEVICE
- new ButtonWidget(tab, "GlobalOptions_Misc.KeysButton", "Keys", kChooseKeyMappingCmd, 0);
+ new ButtonWidget(tab, "GlobalOptions_Misc.KeysButton", _("Keys"), 0, kChooseKeyMappingCmd);
#endif
// TODO: joystick setting
+#ifdef USE_TRANSLATION
+ _guiLanguagePopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.GuiLanguagePopupDesc", _("GUI Language:"), _("Language of ScummVM GUI"));
+ _guiLanguagePopUp = new PopUpWidget(tab, "GlobalOptions_Misc.GuiLanguagePopup");
+#ifdef USE_DETECTLANG
+ _guiLanguagePopUp->appendEntry(_("<default>"), Common::kTranslationAutodetectId);
+#endif // USE_DETECTLANG
+ _guiLanguagePopUp->appendEntry(_("English"), Common::kTranslationBuiltinId);
+ _guiLanguagePopUp->appendEntry("", 0);
+ Common::TLangArray languages = TransMan.getSupportedLanguageNames();
+ Common::TLangArray::iterator lang = languages.begin();
+ while (lang != languages.end()) {
+ _guiLanguagePopUp->appendEntry(lang->name, lang->id);
+ lang++;
+ }
+
+ // Select the currently configured language or default/English if
+ // nothing is specified.
+ if (ConfMan.hasKey("gui_language"))
+ _guiLanguagePopUp->setSelectedTag(TransMan.parseLanguage(ConfMan.get("gui_language")));
+ else
+#ifdef USE_DETECTLANG
+ _guiLanguagePopUp->setSelectedTag(Common::kTranslationAutodetectId);
+#else // !USE_DETECTLANG
+ _guiLanguagePopUp->setSelectedTag(Common::kTranslationBuiltinId);
+#endif // USE_DETECTLANG
+
+#endif // USE_TRANSLATION
+
// Activate the first tab
tab->setActiveTab(0);
_tabWidget = tab;
// Add OK & Cancel buttons
- new ButtonWidget(this, "GlobalOptions.Cancel", "Cancel", kCloseCmd, 0);
- new ButtonWidget(this, "GlobalOptions.Ok", "OK", kOKCmd, 0);
+ new ButtonWidget(this, "GlobalOptions.Cancel", _("Cancel"), 0, kCloseCmd);
+ new ButtonWidget(this, "GlobalOptions.Ok", _("OK"), 0, kOKCmd);
#ifdef SMALL_SCREEN_DEVICE
_keysDialog = new KeysDialog();
@@ -863,19 +1050,19 @@ void GlobalOptionsDialog::open() {
Common::String extraPath(ConfMan.get("extrapath", _domain));
if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) {
- _savePath->setLabel("None");
+ _savePath->setLabel(_("None"));
} else {
_savePath->setLabel(savePath);
}
if (themePath.empty() || !ConfMan.hasKey("themepath", _domain)) {
- _themePath->setLabel("None");
+ _themePath->setLabel(_("None"));
} else {
_themePath->setLabel(themePath);
}
if (extraPath.empty() || !ConfMan.hasKey("extrapath", _domain)) {
- _extraPath->setLabel("None");
+ _extraPath->setLabel(_("None"));
} else {
_extraPath->setLabel(extraPath);
}
@@ -883,7 +1070,7 @@ void GlobalOptionsDialog::open() {
#ifdef DYNAMIC_MODULES
Common::String pluginsPath(ConfMan.get("pluginspath", _domain));
if (pluginsPath.empty() || !ConfMan.hasKey("pluginspath", _domain)) {
- _pluginsPath->setLabel("None");
+ _pluginsPath->setLabel(_("None"));
} else {
_pluginsPath->setLabel(pluginsPath);
}
@@ -907,24 +1094,24 @@ void GlobalOptionsDialog::open() {
void GlobalOptionsDialog::close() {
if (getResult()) {
Common::String savePath(_savePath->getLabel());
- if (!savePath.empty() && (savePath != "None"))
+ if (!savePath.empty() && (savePath != _("None")))
ConfMan.set("savepath", savePath, _domain);
Common::String themePath(_themePath->getLabel());
- if (!themePath.empty() && (themePath != "None"))
+ if (!themePath.empty() && (themePath != _("None")))
ConfMan.set("themepath", themePath, _domain);
else
ConfMan.removeKey("themepath", _domain);
Common::String extraPath(_extraPath->getLabel());
- if (!extraPath.empty() && (extraPath != "None"))
+ if (!extraPath.empty() && (extraPath != _("None")))
ConfMan.set("extrapath", extraPath, _domain);
else
ConfMan.removeKey("extrapath", _domain);
#ifdef DYNAMIC_MODULES
Common::String pluginsPath(_pluginsPath->getLabel());
- if (!pluginsPath.empty() && (pluginsPath != "None"))
+ if (!pluginsPath.empty() && (pluginsPath != _("None")))
ConfMan.set("pluginspath", pluginsPath, _domain);
else
ConfMan.removeKey("pluginspath", _domain);
@@ -940,6 +1127,28 @@ void GlobalOptionsDialog::close() {
g_gui.loadNewTheme(g_gui.theme()->getThemeId(), selected);
ConfMan.set("gui_renderer", cfg, _domain);
}
+#ifdef USE_TRANSLATION
+ Common::String oldLang = ConfMan.get("gui_language");
+ int selLang = _guiLanguagePopUp->getSelectedTag();
+
+ ConfMan.set("gui_language", TransMan.getLangById(selLang));
+
+ Common::String newLang = ConfMan.get("gui_language").c_str();
+ if (newLang != oldLang) {
+#if 0
+ // Activate the selected language
+ TransMan.setLanguage(selLang);
+
+ // FIXME: Actually, any changes (including the theme change) should
+ // only become active *after* the options dialog has closed.
+ g_gui.loadNewTheme(g_gui.theme()->getThemeId(), ThemeEngine::kGfxDisabled, true);
+#else
+ MessageDialog error(_("You have to restart ScummVM to take the effect."));
+ error.runModal();
+#endif
+ }
+#endif // USE_TRANSLATION
+
}
OptionsDialog::close();
}
@@ -947,14 +1156,14 @@ void GlobalOptionsDialog::close() {
void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kChooseSaveDirCmd: {
- BrowserDialog browser("Select directory for savegames", true);
+ BrowserDialog browser(_("Select directory for savegames"), true);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode dir(browser.getResult());
if (dir.isWritable()) {
_savePath->setLabel(dir.getPath());
} else {
- MessageDialog error("The chosen directory cannot be written to. Please select another one.");
+ MessageDialog error(_("The chosen directory cannot be written to. Please select another one."));
error.runModal();
return;
}
@@ -963,7 +1172,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
break;
}
case kChooseThemeDirCmd: {
- BrowserDialog browser("Select directory for GUI themes", true);
+ BrowserDialog browser(_("Select directory for GUI themes"), true);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode dir(browser.getResult());
@@ -973,7 +1182,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
break;
}
case kChooseExtraDirCmd: {
- BrowserDialog browser("Select directory for extra files", true);
+ BrowserDialog browser(_("Select directory for extra files"), true);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode dir(browser.getResult());
@@ -984,7 +1193,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
}
#ifdef DYNAMIC_MODULES
case kChoosePluginsDirCmd: {
- BrowserDialog browser("Select directory for plugins", true);
+ BrowserDialog browser(_("Select directory for plugins"), true);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode dir(browser.getResult());
@@ -995,13 +1204,13 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
}
#endif
case kChooseSoundFontCmd: {
- BrowserDialog browser("Select SoundFont", false);
+ BrowserDialog browser(_("Select SoundFont"), false);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode file(browser.getResult());
_soundFont->setLabel(file.getPath());
- if (!file.getPath().empty() && (file.getPath() != "None"))
+ if (!file.getPath().empty() && (file.getPath() != _("None")))
_soundFontClearButton->setEnabled(true);
else
_soundFontClearButton->setEnabled(false);
diff --git a/gui/options.h b/gui/options.h
index 956f78c18f..c05f263d00 100644
--- a/gui/options.h
+++ b/gui/options.h
@@ -28,6 +28,7 @@
#include "gui/dialog.h"
#include "gui/TabWidget.h"
#include "common/str.h"
+#include "sound/musicplugin.h"
#ifdef SMALL_SCREEN_DEVICE
#include "gui/KeysDialog.h"
@@ -67,6 +68,7 @@ protected:
void addGraphicControls(GuiObject *boss, const Common::String &prefix);
void addAudioControls(GuiObject *boss, const Common::String &prefix);
void addMIDIControls(GuiObject *boss, const Common::String &prefix);
+ void addMT32Controls(GuiObject *boss, const Common::String &prefix);
void addVolumeControls(GuiObject *boss, const Common::String &prefix);
// The default value is the launcher's non-scaled talkspeed value. When SCUMM uses the widget,
// it uses its own scale
@@ -75,9 +77,13 @@ protected:
void setGraphicSettingsState(bool enabled);
void setAudioSettingsState(bool enabled);
void setMIDISettingsState(bool enabled);
+ void setMT32SettingsState(bool enabled);
void setVolumeSettingsState(bool enabled);
void setSubtitleSettingsState(bool enabled);
+ bool loadMusicDeviceSetting(PopUpWidget *popup, Common::String setting, MusicType preferredType = MT_AUTO);
+ void saveMusicDeviceSetting(PopUpWidget *popup, Common::String setting);
+
TabWidget *_tabWidget;
int _graphicsTabId;
@@ -104,25 +110,39 @@ private:
StaticTextWidget *_outputRatePopUpDesc;
PopUpWidget *_outputRatePopUp;
+ StaticTextWidget *_mt32DevicePopUpDesc;
+ PopUpWidget *_mt32DevicePopUp;
+ StaticTextWidget *_gmDevicePopUpDesc;
+ PopUpWidget *_gmDevicePopUp;
+
+
+
//
// MIDI controls
//
bool _enableMIDISettings;
CheckboxWidget *_multiMidiCheckbox;
- CheckboxWidget *_mt32Checkbox;
- CheckboxWidget *_enableGSCheckbox;
StaticTextWidget *_midiGainDesc;
SliderWidget *_midiGainSlider;
StaticTextWidget *_midiGainLabel;
//
+ // MT-32 controls
+ //
+ bool _enableMT32Settings;
+ CheckboxWidget *_mt32Checkbox;
+ CheckboxWidget *_enableGSCheckbox;
+
+ //
// Subtitle controls
//
int getSubtitleMode(bool subtitles, bool speech_mute);
bool _enableSubtitleSettings;
StaticTextWidget *_subToggleDesc;
- ButtonWidget *_subToggleButton;
- int _subMode;
+ RadiobuttonGroup *_subToggleGroup;
+ RadiobuttonWidget *_subToggleSubOnly;
+ RadiobuttonWidget *_subToggleSpeechOnly;
+ RadiobuttonWidget *_subToggleSubBoth;
static const char *_subModeDesc[];
static const char *_lowresSubModeDesc[];
StaticTextWidget *_subSpeedDesc;
@@ -153,6 +173,7 @@ protected:
// Game GUI options
//
uint32 _guioptions;
+ Common::String _guioptionsString;
};
@@ -184,6 +205,8 @@ protected:
PopUpWidget *_rendererPopUp;
StaticTextWidget *_autosavePeriodPopUpDesc;
PopUpWidget *_autosavePeriodPopUp;
+ StaticTextWidget *_guiLanguagePopUpDesc;
+ PopUpWidget *_guiLanguagePopUp;
};
} // End of namespace GUI
diff --git a/gui/saveload.cpp b/gui/saveload.cpp
index 8ec4dc4133..92cea00f30 100644
--- a/gui/saveload.cpp
+++ b/gui/saveload.cpp
@@ -23,6 +23,7 @@
*/
#include "common/config-manager.h"
+#include "common/translation.h"
#include "gui/ListWidget.h"
#include "gui/message.h"
@@ -56,16 +57,16 @@ SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel)
_gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10);
- _date = new StaticTextWidget(this, 0, 0, 10, 10, "No date saved", Graphics::kTextAlignCenter);
- _time = new StaticTextWidget(this, 0, 0, 10, 10, "No time saved", Graphics::kTextAlignCenter);
- _playtime = new StaticTextWidget(this, 0, 0, 10, 10, "No playtime saved", Graphics::kTextAlignCenter);
+ _date = new StaticTextWidget(this, 0, 0, 10, 10, _("No date saved"), Graphics::kTextAlignCenter);
+ _time = new StaticTextWidget(this, 0, 0, 10, 10, _("No time saved"), Graphics::kTextAlignCenter);
+ _playtime = new StaticTextWidget(this, 0, 0, 10, 10, _("No playtime saved"), Graphics::kTextAlignCenter);
// Buttons
- new GUI::ButtonWidget(this, "SaveLoadChooser.Cancel", "Cancel", kCloseCmd, 0);
- _chooseButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Choose", buttonLabel, kChooseCmd, 0);
+ new GUI::ButtonWidget(this, "SaveLoadChooser.Cancel", _("Cancel"), 0, kCloseCmd);
+ _chooseButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Choose", buttonLabel, 0, kChooseCmd);
_chooseButton->setEnabled(false);
- _deleteButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Delete", "Delete", kDelCmd, 0);
+ _deleteButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Delete", _("Delete"), 0, kDelCmd);
_deleteButton->setEnabled(false);
_delSupport = _metaInfoSupport = _thumbnailSupport = false;
@@ -152,8 +153,8 @@ void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 da
break;
case kDelCmd:
if (selItem >= 0 && _delSupport) {
- MessageDialog alert("Do you really want to delete this savegame?",
- "Delete", "Cancel");
+ 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()));
@@ -181,7 +182,7 @@ void SaveLoadChooser::reflowLayout() {
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 thumbH = kThumbnailHeight2;
int thumbX = x + (w >> 1) - (thumbW >> 1);
int thumbY = y + kLineHeight;
@@ -237,9 +238,9 @@ void SaveLoadChooser::updateSelection(bool redraw) {
bool startEditMode = _list->isEditable();
_gfxWidget->setGfx(-1, -1, _fillR, _fillG, _fillB);
- _date->setLabel("No date saved");
- _time->setLabel("No time saved");
- _playtime->setLabel("No playtime saved");
+ _date->setLabel(_("No date saved"));
+ _time->setLabel(_("No time saved"));
+ _playtime->setLabel(_("No playtime saved"));
if (selItem >= 0 && !_list->getSelectedString().empty() && _metaInfoSupport) {
SaveStateDescriptor desc = (*_plugin)->querySaveMetaInfos(_target.c_str(), atoi(_saveList[selItem].save_slot().c_str()));
@@ -261,15 +262,15 @@ void SaveLoadChooser::updateSelection(bool redraw) {
if (_saveDateSupport) {
if (desc.contains("save_date"))
- _date->setLabel("Date: " + desc.getVal("save_date"));
+ _date->setLabel(_("Date: ") + desc.getVal("save_date"));
if (desc.contains("save_time"))
- _time->setLabel("Time: " + desc.getVal("save_time"));
+ _time->setLabel(_("Time: ") + desc.getVal("save_time"));
}
if (_playTimeSupport) {
if (desc.contains("play_time"))
- _playtime->setLabel("Playtime: " + desc.getVal("play_time"));
+ _playtime->setLabel(_("Playtime: ") + desc.getVal("play_time"));
}
}
@@ -282,7 +283,7 @@ void SaveLoadChooser::updateSelection(bool redraw) {
if (startEditMode) {
_list->startEditMode();
- if (_chooseButton->isEnabled() && _list->getSelectedString() == "Untitled savestate" &&
+ if (_chooseButton->isEnabled() && _list->getSelectedString() == _("Untitled savestate") &&
_list->getSelectionColor() == ThemeEngine::kFontColorAlternate) {
_list->setEditString("");
_list->setEditColor(ThemeEngine::kFontColorNormal);
@@ -349,7 +350,7 @@ void SaveLoadChooser::updateSaveList() {
Common::String trimmedDescription = description;
trimmedDescription.trim();
if (trimmedDescription.empty()) {
- description = "Untitled savestate";
+ description = _("Untitled savestate");
colors.push_back(ThemeEngine::kFontColorAlternate);
} else {
colors.push_back(ThemeEngine::kFontColorNormal);
diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp
index 5d0e24394f..c8f732fe5f 100644
--- a/gui/themebrowser.cpp
+++ b/gui/themebrowser.cpp
@@ -26,6 +26,8 @@
#include "gui/ListWidget.h"
#include "gui/widget.h"
+#include "common/translation.h"
+
namespace GUI {
enum {
@@ -41,7 +43,7 @@ enum {
ThemeBrowser::ThemeBrowser() : Dialog("Browser") {
_fileList = 0;
- new StaticTextWidget(this, "Browser.Headline", "Select a Theme");
+ new StaticTextWidget(this, "Browser.Headline", _("Select a Theme"));
// Add file list
_fileList = new ListWidget(this, "Browser.List");
@@ -51,8 +53,8 @@ ThemeBrowser::ThemeBrowser() : Dialog("Browser") {
_backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain;
// Buttons
- new ButtonWidget(this, "Browser.Cancel", "Cancel", kCloseCmd, 0);
- new ButtonWidget(this, "Browser.Choose", "Choose", kChooseCmd, 0);
+ new ButtonWidget(this, "Browser.Cancel", _("Cancel"), 0, kCloseCmd);
+ new ButtonWidget(this, "Browser.Choose", _("Choose"), 0, kChooseCmd);
}
void ThemeBrowser::open() {
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 75c4fb73de..46ac4a1365 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -1,5 +1,5 @@
"<?xml version = '1.0'?>"
-"<layout_info resolution='320xY,256x240,Xx272'> "
+"<layout_info resolution='320xY,256x240,Xx272,Xx350'> "
"<globals> "
"<def var='Line.Height' value='12' /> "
"<def var='Font.Height' value='10' /> "
@@ -12,6 +12,9 @@
"<def var='KeyMapper.Spacing' value='5'/> "
"<def var='KeyMapper.LabelWidth' value='80'/> "
"<def var='KeyMapper.ButtonWidth' value='60'/> "
+"<def var='Tooltip.MaxWidth' value='70'/> "
+"<def var='Tooltip.XDelta' value='8'/> "
+"<def var='Tooltip.YDelta' value='8'/> "
"<widget name='Button' "
"size='72,16' "
"/> "
@@ -31,6 +34,9 @@
"<widget name='Checkbox' "
"size='-1,Globals.Line.Height' "
"/> "
+"<widget name='Radiobutton' "
+"size='-1,Globals.Line.Height' "
+"/> "
"<widget name='ListWidget' "
"padding='5,0,0,0' "
"/> "
@@ -50,17 +56,20 @@
"size='45,16' "
"padding='0,0,2,0' "
"/> "
+"<widget name='TabWidget.Body' "
+"padding='0,0,0,-8' "
+"/> "
"<widget name='TabWidget.NavButton' "
"size='32,18' "
-"padding='0,3,4,0' "
+"padding='0,0,1,0' "
"/> "
"</globals> "
"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='8,8,4,4'> "
+"<layout type='vertical' center='true' padding='6,6,2,2'> "
"<widget name='Version' "
"height='Globals.Line.Height' "
"/> "
-"<layout type='horizontal' spacing='5' padding='10,0,0,0'> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,0'> "
"<widget name='SearchDesc' "
"width='50' "
"height='Globals.Line.Height' "
@@ -77,7 +86,7 @@
"<space /> "
"</layout> "
"<widget name='GameList'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='LoadGameButton' "
"height='12' "
"/> "
@@ -91,7 +100,7 @@
"height='12' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='QuitButton' "
"height='12' "
"/> "
@@ -196,13 +205,18 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
-"<widget name='subToggleButton' "
-"width='128' "
-"height='Globals.Slider.Height' "
+"<widget name='subToggleSpeechOnly' "
+"type='Radiobutton' "
+"/> "
+"<widget name='subToggleSubOnly' "
+"type='Radiobutton' "
+"/> "
+"<widget name='subToggleSubBoth' "
+"type='Radiobutton' "
"/> "
"</layout> "
"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
@@ -263,6 +277,14 @@
"</dialog> "
"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='auPrefGmPopupDesc' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='auPrefGmPopup' "
+"type='PopUp' "
+"/> "
+"</layout> "
"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='mcFontButton' "
"type='Button' "
@@ -278,12 +300,6 @@
"<widget name='mcMixedCheckbox' "
"type='Checkbox' "
"/> "
-"<widget name='mcMt32Checkbox' "
-"type='Checkbox' "
-"/> "
-"<widget name='mcGSCheckbox' "
-"type='Checkbox' "
-"/> "
"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='mcMidiGainText' "
"type='OptionsLabel' "
@@ -298,6 +314,24 @@
"</layout> "
"</layout> "
"</dialog> "
+"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='auPrefMt32PopupDesc' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='auPrefMt32Popup' "
+"type='PopUp' "
+"/> "
+"</layout> "
+"<widget name='mcMt32Checkbox' "
+"type='Checkbox' "
+"/> "
+"<widget name='mcGSCheckbox' "
+"type='Checkbox' "
+"/> "
+"</layout> "
+"</dialog> "
"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
@@ -364,6 +398,16 @@
"type='PopUp' "
"/> "
"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='GuiLanguagePopupDesc' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
+"/> "
+"<widget name='GuiLanguagePopup' "
+"type='PopUp' "
+"/> "
+"</layout> "
"<widget name='KeysButton' "
"type='Button' "
"/> "
@@ -431,6 +475,14 @@
"<import layout='Dialog.GlobalOptions_MIDI' /> "
"</layout> "
"</dialog> "
+"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
+"/> "
+"<import layout='Dialog.GlobalOptions_MT32' /> "
+"</layout> "
+"</dialog> "
"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
@@ -513,7 +565,7 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,4,6' center='true'> "
+"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
"<widget name='Title' "
"width='160' "
"height='4' "
@@ -536,6 +588,10 @@
"width='120' "
"height='12' "
"/> "
+"<widget name='Help' "
+"width='120' "
+"height='12' "
+"/> "
"<widget name='About' "
"width='120' "
"height='12' "
@@ -555,42 +611,7 @@
"/> "
"</layout> "
"</dialog> "
-"<dialog name='ScummMain' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<widget name='Resume' "
-"width='Globals.Button.Width' "
-"height='14' "
-"/> "
-"<space size='2'/> "
-"<widget name='Load' "
-"width='Globals.Button.Width' "
-"height='14' "
-"/> "
-"<widget name='Save' "
-"width='Globals.Button.Width' "
-"height='14' "
-"/> "
-"<space size='2'/> "
-"<widget name='Options' "
-"width='Globals.Button.Width' "
-"height='14' "
-"/> "
-"<widget name='Help' "
-"width='Globals.Button.Width' "
-"height='14' "
-"/> "
-"<widget name='About' "
-"width='Globals.Button.Width' "
-"height='14' "
-"/> "
-"<space size='2'/> "
-"<widget name='Quit' "
-"width='Globals.Button.Width' "
-"height='14' "
-"/> "
-"</layout> "
-"</dialog> "
-"<dialog name='ScummConfig' overlays='screen_center'> "
+"<dialog name='GlobalConfig' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcMusicText' "
@@ -632,16 +653,26 @@
"width='80' "
"/> "
"</layout> "
-"<space size='4' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
-"<widget name='subToggleButton' "
-"width='128' "
-"height='Globals.Slider.Height' "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='subToggleSpeechOnly' "
+"type='Radiobutton' "
+"width='90' "
+"/> "
+"<widget name='subToggleSubOnly' "
+"type='Radiobutton' "
+"width='90' "
+"/> "
+"<widget name='subToggleSubBoth' "
+"type='Radiobutton' "
+"width='90' "
"/> "
"</layout> "
+"</layout> "
+"<space size='2' /> "
"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
@@ -653,7 +684,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<space size='20'/> "
+"<space size='16'/> "
"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
"<widget name='Keys' "
"type='Button' "
@@ -756,7 +787,7 @@
"</layout> "
"</dialog> "
"</layout_info> "
-"<layout_info resolution='-320xY,-256x240,-Xx272'> "
+"<layout_info resolution='-320xY,-256x240,-Xx272,-Xx350'> "
"<globals> "
"<def var='Line.Height' value='16' /> "
"<def var='Font.Height' value='16' /> "
@@ -769,6 +800,9 @@
"<def var='KeyMapper.Spacing' value='10'/> "
"<def var='KeyMapper.LabelWidth' value='100'/> "
"<def var='KeyMapper.ButtonWidth' value='80'/> "
+"<def var='Tooltip.MaxWidth' value='200'/> "
+"<def var='Tooltip.XDelta' value='16'/> "
+"<def var='Tooltip.YDelta' value='16'/> "
"<widget name='OptionsLabel' "
"size='110,Globals.Line.Height' "
"textalign='right' "
@@ -791,6 +825,9 @@
"<widget name='Checkbox' "
"size='-1,14' "
"/> "
+"<widget name='Radiobutton' "
+"size='-1,Globals.Line.Height' "
+"/> "
"<widget name='ListWidget' "
"padding='5,0,8,0' "
"/> "
@@ -810,6 +847,9 @@
"size='75,27' "
"padding='0,0,8,0' "
"/> "
+"<widget name='TabWidget.Body' "
+"padding='0,0,0,0' "
+"/> "
"<widget name='TabWidget.NavButton' "
"size='15,18' "
"padding='0,3,4,0' "
@@ -961,9 +1001,14 @@
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
-"<widget name='subToggleButton' "
-"width='150' "
-"height='Globals.Slider.Height' "
+"<widget name='subToggleSpeechOnly' "
+"type='Radiobutton' "
+"/> "
+"<widget name='subToggleSubOnly' "
+"type='Radiobutton' "
+"/> "
+"<widget name='subToggleSubBoth' "
+"type='Radiobutton' "
"/> "
"</layout> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
@@ -1026,6 +1071,14 @@
"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='auPrefGmPopupDesc' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='auPrefGmPopup' "
+"type='PopUp' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='mcFontButton' "
"type='Button' "
"/> "
@@ -1040,12 +1093,6 @@
"<widget name='mcMixedCheckbox' "
"type='Checkbox' "
"/> "
-"<widget name='mcMt32Checkbox' "
-"type='Checkbox' "
-"/> "
-"<widget name='mcGSCheckbox' "
-"type='Checkbox' "
-"/> "
"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='mcMidiGainText' "
"type='OptionsLabel' "
@@ -1060,6 +1107,24 @@
"</layout> "
"</layout> "
"</dialog> "
+"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='auPrefMt32PopupDesc' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='auPrefMt32Popup' "
+"type='PopUp' "
+"/> "
+"</layout> "
+"<widget name='mcMt32Checkbox' "
+"type='Checkbox' "
+"/> "
+"<widget name='mcGSCheckbox' "
+"type='Checkbox' "
+"/> "
+"</layout> "
+"</dialog> "
"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
@@ -1122,6 +1187,14 @@
"type='PopUp' "
"/> "
"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='GuiLanguagePopupDesc' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='GuiLanguagePopup' "
+"type='PopUp' "
+"/> "
+"</layout> "
"<widget name='KeysButton' "
"type='Button' "
"/> "
@@ -1189,6 +1262,14 @@
"<import layout='Dialog.GlobalOptions_MIDI' /> "
"</layout> "
"</dialog> "
+"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
+"/> "
+"<import layout='Dialog.GlobalOptions_MT32' /> "
+"</layout> "
+"</dialog> "
"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
@@ -1289,6 +1370,10 @@
"width='150' "
"height='Globals.Button.Height' "
"/> "
+"<widget name='Help' "
+"width='150' "
+"height='Globals.Button.Height' "
+"/> "
"<widget name='About' "
"width='150' "
"height='Globals.Button.Height' "
@@ -1304,35 +1389,7 @@
"/> "
"</layout> "
"</dialog> "
-"<dialog name='ScummMain' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<widget name='Resume' "
-"type='Button' "
-"/> "
-"<space size='15'/> "
-"<widget name='Load' "
-"type='Button' "
-"/> "
-"<widget name='Save' "
-"type='Button' "
-"/> "
-"<space size='15'/> "
-"<widget name='Options' "
-"type='Button' "
-"/> "
-"<widget name='Help' "
-"type='Button' "
-"/> "
-"<widget name='About' "
-"type='Button' "
-"/> "
-"<space size='15'/> "
-"<widget name='Quit' "
-"type='Button' "
-"/> "
-"</layout> "
-"</dialog> "
-"<dialog name='ScummConfig' overlays='screen_center'> "
+"<dialog name='GlobalConfig' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
"<layout type='horizontal' padding='0,0,0,0'> "
"<layout type='vertical' padding='0,0,0,0' center='true'> "
@@ -1382,9 +1439,17 @@
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
-"<widget name='subToggleButton' "
-"width='158' "
-"height='Globals.Slider.Height' "
+"<widget name='subToggleSpeechOnly' "
+"type='Radiobutton' "
+"width='100' "
+"/> "
+"<widget name='subToggleSubOnly' "
+"type='Radiobutton' "
+"width='100' "
+"/> "
+"<widget name='subToggleSubBoth' "
+"type='Radiobutton' "
+"width='100' "
"/> "
"</layout> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
@@ -1529,13 +1594,28 @@
"</palette> "
"<fonts> "
"<font id='text_default' "
-"file='default' "
+"file='helvb12.bdf' "
+"/> "
+"<font resolution='320xY,256x240' "
+"id='text_default' "
+"file='clR6x12.bdf' "
"/> "
"<font id='text_button' "
-"file='default' "
+"file='helvb12.bdf' "
+"/> "
+"<font resolution='320xY,256x240' "
+"id='text_button' "
+"file='clR6x12.bdf' "
"/> "
"<font id='text_normal' "
-"file='default' "
+"file='helvb12.bdf' "
+"/> "
+"<font resolution='320xY,256x240' "
+"id='text_normal' "
+"file='clR6x12.bdf' "
+"/> "
+"<font id='tooltip_normal' "
+"file='fixed5x8.bdf' "
"/> "
"<text_color id='color_normal' "
"color='green' "
@@ -1595,6 +1675,13 @@
"bevel='2' "
"/> "
"</drawdata> "
+"<drawdata id='tooltip_bg' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='foreground' "
+"fg_color='black' "
+"/> "
+"</drawdata> "
"<drawdata id='separator' cache='false'> "
"<drawstep func='square' "
"fill='foreground' "
@@ -1859,9 +1946,71 @@
"fill='none' "
"/> "
"</drawdata> "
+"<drawdata id='radiobutton_default' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='center' "
+"horizontal_align='left' "
+"/> "
+"<drawstep func='circle' "
+"width='7' "
+"height='7' "
+"radius='7' "
+"fill='background' "
+"bg_color='darkgrey' "
+"xpos='0' "
+"ypos='0' "
+"/> "
+"</drawdata> "
+"<drawdata id='radiobutton_selected' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='center' "
+"horizontal_align='left' "
+"/> "
+"<drawstep func='circle' "
+"width='7' "
+"height='7' "
+"radius='7' "
+"fg_color='darkgrey' "
+"fill='none' "
+"xpos='0' "
+"ypos='0' "
+"/> "
+"<drawstep func='circle' "
+"width='7' "
+"height='7' "
+"radius='5' "
+"fg_color='green' "
+"fill='foreground' "
+"xpos='2' "
+"ypos='2' "
+"/> "
+"</drawdata> "
+"<drawdata id='radiobutton_disabled' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal_disabled' "
+"vertical_align='center' "
+"horizontal_align='left' "
+"/> "
+"<drawstep func='circle' "
+"width='7' "
+"height='7' "
+"radius='7' "
+"bg_color='lightgrey' "
+"fill='background' "
+"xpos='0' "
+"ypos='0' "
+"/> "
+"</drawdata> "
"<drawdata id='widget_default' cache='false'> "
"<drawstep func='bevelsq' "
"bevel='2' "
"/> "
"</drawdata> "
+"<drawdata id='widget_small' cache='false'> "
+"<drawstep func='square' "
+"stroke='0' "
+"/> "
+"</drawdata> "
"</render_info> "
diff --git a/gui/themes/fonts/Arial.bdf b/gui/themes/fonts/Arial.bdf
new file mode 100644
index 0000000000..8c2d2f264a
--- /dev/null
+++ b/gui/themes/fonts/Arial.bdf
@@ -0,0 +1,1537 @@
+STARTFONT 2.1
+COMMENT
+COMMENT Converted from TrueType font "arial.ttf" by "ttf2bdf 2.8".
+COMMENT
+FONT -FreeType-Arial-Medium-R-Normal--12-120-75-75-P-57-ISO10646-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 14 13 -1 -3
+STARTPROPERTIES 19
+FOUNDRY "FreeType"
+FAMILY_NAME "Arial"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 57
+CHARSET_REGISTRY "ISO10646"
+CHARSET_ENCODING "1"
+FONT_ASCENT 11
+FONT_DESCENT 2
+COPYRIGHT "Typeface © The Monotype Corporation plc. Data © The Monotype Corporation plc/Type Solutions Inc. 1990-1992. All Rights Reserved"
+_TTF_FONTFILE "arial.ttf"
+_TTF_PSNAME "ArialMT"
+ENDPROPERTIES
+CHARS 96
+STARTCHAR 0020
+ENCODING 32
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR 0021
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 10 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR 0022
+ENCODING 34
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 3 1 7
+BITMAP
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR 0023
+ENCODING 35
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+12
+12
+14
+FF
+24
+24
+FF
+48
+48
+48
+ENDCHAR
+STARTCHAR 0024
+ENCODING 36
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 11 1 -1
+BITMAP
+70
+A8
+A0
+A0
+E0
+38
+28
+A8
+A8
+70
+20
+ENDCHAR
+STARTCHAR 0025
+ENCODING 37
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+6100
+9200
+9200
+9400
+6400
+0980
+0A40
+1240
+1240
+2180
+ENDCHAR
+STARTCHAR 0026
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 10 1 0
+BITMAP
+30
+48
+48
+48
+30
+60
+92
+8A
+8C
+73
+ENDCHAR
+STARTCHAR 0027
+ENCODING 39
+SWIDTH 160 0
+DWIDTH 2 0
+BBX 1 3 1 7
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR 0028
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 13 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR 0029
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 13 0 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR 002A
+ENCODING 42
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 5 4 0 6
+BITMAP
+20
+F8
+20
+50
+ENDCHAR
+STARTCHAR 002B
+ENCODING 43
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 7 1 1
+BITMAP
+10
+10
+10
+FE
+10
+10
+10
+ENDCHAR
+STARTCHAR 002C
+ENCODING 44
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 3 2 -2
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR 002D
+ENCODING 45
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 1 0 3
+BITMAP
+E0
+ENDCHAR
+STARTCHAR 002E
+ENCODING 46
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR 002F
+ENCODING 47
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+10
+10
+20
+20
+20
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0030
+ENCODING 48
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR 0031
+ENCODING 49
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 10 1 0
+BITMAP
+20
+60
+A0
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR 0032
+ENCODING 50
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+84
+04
+04
+04
+08
+10
+20
+40
+FC
+ENDCHAR
+STARTCHAR 0033
+ENCODING 51
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+84
+04
+04
+38
+04
+04
+04
+84
+78
+ENDCHAR
+STARTCHAR 0034
+ENCODING 52
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+08
+18
+18
+28
+28
+48
+48
+FC
+08
+08
+ENDCHAR
+STARTCHAR 0035
+ENCODING 53
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+7C
+40
+40
+80
+F8
+84
+04
+04
+84
+78
+ENDCHAR
+STARTCHAR 0036
+ENCODING 54
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+84
+80
+80
+B8
+C4
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR 0037
+ENCODING 55
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+FC
+08
+08
+10
+10
+20
+20
+40
+40
+40
+ENDCHAR
+STARTCHAR 0038
+ENCODING 56
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+84
+84
+84
+78
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR 0039
+ENCODING 57
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+84
+84
+84
+8C
+74
+04
+04
+88
+70
+ENDCHAR
+STARTCHAR 003A
+ENCODING 58
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 7 1 0
+BITMAP
+80
+00
+00
+00
+00
+00
+80
+ENDCHAR
+STARTCHAR 003B
+ENCODING 59
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 9 1 -2
+BITMAP
+80
+00
+00
+00
+00
+00
+80
+80
+80
+ENDCHAR
+STARTCHAR 003C
+ENCODING 60
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 7 1 1
+BITMAP
+04
+18
+60
+80
+60
+18
+04
+ENDCHAR
+STARTCHAR 003D
+ENCODING 61
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 4 0 3
+BITMAP
+FE
+00
+00
+FE
+ENDCHAR
+STARTCHAR 003E
+ENCODING 62
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 7 1 1
+BITMAP
+80
+60
+18
+04
+18
+60
+80
+ENDCHAR
+STARTCHAR 003F
+ENCODING 63
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+70
+88
+88
+08
+10
+20
+40
+40
+00
+40
+ENDCHAR
+STARTCHAR 0040
+ENCODING 64
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 12 13 0 -3
+BITMAP
+0F80
+3040
+4020
+4E90
+9190
+A090
+A110
+A120
+A320
+9DC0
+4010
+2060
+1F80
+ENDCHAR
+STARTCHAR 0041
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+0800
+1400
+1400
+3600
+2200
+2200
+7F00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR 0042
+ENCODING 66
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+FC
+82
+82
+82
+FC
+82
+82
+82
+82
+FC
+ENDCHAR
+STARTCHAR 0043
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+38
+44
+82
+80
+80
+80
+80
+82
+44
+38
+ENDCHAR
+STARTCHAR 0044
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+F8
+84
+82
+82
+82
+82
+82
+82
+84
+F8
+ENDCHAR
+STARTCHAR 0045
+ENCODING 69
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+FE
+80
+80
+80
+FE
+80
+80
+80
+80
+FE
+ENDCHAR
+STARTCHAR 0046
+ENCODING 70
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+FC
+80
+80
+80
+F8
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR 0047
+ENCODING 71
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3C
+42
+81
+80
+80
+8F
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR 0048
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+82
+82
+82
+82
+FE
+82
+82
+82
+82
+82
+ENDCHAR
+STARTCHAR 0049
+ENCODING 73
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 10 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR 004A
+ENCODING 74
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 10 0 0
+BITMAP
+08
+08
+08
+08
+08
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR 004B
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 10 1 0
+BITMAP
+81
+82
+84
+88
+90
+B0
+C8
+84
+82
+81
+ENDCHAR
+STARTCHAR 004C
+ENCODING 76
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR 004D
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+8080
+C180
+C180
+A280
+A280
+9680
+9480
+9480
+8880
+8880
+ENDCHAR
+STARTCHAR 004E
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+82
+C2
+A2
+A2
+92
+92
+8A
+8A
+86
+82
+ENDCHAR
+STARTCHAR 004F
+ENCODING 79
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3C
+42
+81
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR 0050
+ENCODING 80
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+FC
+82
+82
+82
+82
+FC
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR 0051
+ENCODING 81
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3C
+42
+81
+81
+81
+81
+81
+8D
+42
+3D
+ENDCHAR
+STARTCHAR 0052
+ENCODING 82
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+FC
+82
+82
+82
+82
+FC
+88
+84
+84
+82
+ENDCHAR
+STARTCHAR 0053
+ENCODING 83
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+7C
+82
+82
+80
+70
+0C
+02
+82
+82
+7C
+ENDCHAR
+STARTCHAR 0054
+ENCODING 84
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR 0055
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+82
+82
+82
+82
+82
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR 0056
+ENCODING 86
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+8080
+8080
+4100
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+ENDCHAR
+STARTCHAR 0057
+ENCODING 87
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 13 10 0 0
+BITMAP
+8208
+8508
+4510
+4510
+4510
+28A0
+28A0
+28A0
+1040
+1040
+ENDCHAR
+STARTCHAR 0058
+ENCODING 88
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+82
+44
+24
+28
+10
+10
+28
+28
+44
+82
+ENDCHAR
+STARTCHAR 0059
+ENCODING 89
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+82
+44
+44
+28
+28
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR 005A
+ENCODING 90
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+7E
+04
+08
+08
+10
+10
+20
+20
+40
+FE
+ENDCHAR
+STARTCHAR 005B
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 13 1 -3
+BITMAP
+C0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+C0
+ENDCHAR
+STARTCHAR 005C
+ENCODING 92
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+80
+80
+40
+40
+40
+20
+20
+20
+10
+10
+ENDCHAR
+STARTCHAR 005D
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 13 1 -3
+BITMAP
+C0
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+C0
+ENDCHAR
+STARTCHAR 005E
+ENCODING 94
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 5 5 0 4
+BITMAP
+20
+50
+50
+50
+88
+ENDCHAR
+STARTCHAR 005F
+ENCODING 95
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 1 0 -3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR 0060
+ENCODING 96
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 2 1 8
+BITMAP
+80
+40
+ENDCHAR
+STARTCHAR 0061
+ENCODING 97
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+08
+78
+88
+98
+68
+ENDCHAR
+STARTCHAR 0062
+ENCODING 98
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+80
+80
+80
+B0
+C8
+88
+88
+88
+C8
+B0
+ENDCHAR
+STARTCHAR 0063
+ENCODING 99
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+80
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR 0064
+ENCODING 100
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+08
+08
+08
+68
+98
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR 0065
+ENCODING 101
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR 0066
+ENCODING 102
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 4 10 0 0
+BITMAP
+30
+40
+40
+E0
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR 0067
+ENCODING 103
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR 0068
+ENCODING 104
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+80
+80
+80
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR 0069
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 10 1 0
+BITMAP
+80
+00
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR 006A
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 13 -1 -3
+BITMAP
+20
+00
+00
+20
+20
+20
+20
+20
+20
+20
+20
+20
+C0
+ENDCHAR
+STARTCHAR 006B
+ENCODING 107
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+80
+80
+80
+88
+90
+A0
+E0
+90
+90
+88
+ENDCHAR
+STARTCHAR 006C
+ENCODING 108
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 10 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR 006D
+ENCODING 109
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 7 1 0
+BITMAP
+B300
+CC80
+8880
+8880
+8880
+8880
+8880
+ENDCHAR
+STARTCHAR 006E
+ENCODING 110
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR 006F
+ENCODING 111
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 0070
+ENCODING 112
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+B0
+C8
+88
+88
+88
+C8
+B0
+80
+80
+80
+ENDCHAR
+STARTCHAR 0071
+ENCODING 113
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+68
+98
+88
+88
+88
+98
+68
+08
+08
+08
+ENDCHAR
+STARTCHAR 0072
+ENCODING 114
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+A0
+C0
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR 0073
+ENCODING 115
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+80
+70
+08
+88
+70
+ENDCHAR
+STARTCHAR 0074
+ENCODING 116
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 9 0 0
+BITMAP
+40
+40
+E0
+40
+40
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR 0075
+ENCODING 117
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR 0076
+ENCODING 118
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+88
+88
+50
+50
+50
+20
+20
+ENDCHAR
+STARTCHAR 0077
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 7 0 0
+BITMAP
+8880
+8C80
+5500
+5500
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR 0078
+ENCODING 120
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+88
+50
+50
+20
+50
+50
+88
+ENDCHAR
+STARTCHAR 0079
+ENCODING 121
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+50
+50
+50
+20
+20
+20
+20
+C0
+ENDCHAR
+STARTCHAR 007A
+ENCODING 122
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+F8
+10
+10
+20
+40
+40
+F8
+ENDCHAR
+STARTCHAR 007B
+ENCODING 123
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 13 0 -3
+BITMAP
+20
+40
+40
+40
+40
+40
+80
+40
+40
+40
+40
+40
+20
+ENDCHAR
+STARTCHAR 007C
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 12 1 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR 007D
+ENCODING 125
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 13 1 -3
+BITMAP
+80
+40
+40
+40
+40
+40
+20
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR 007E
+ENCODING 126
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 2 0 4
+BITMAP
+72
+9C
+ENDCHAR
+STARTCHAR 00A0
+ENCODING 160
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/Arial12.bdf b/gui/themes/fonts/Arial12.bdf
new file mode 100644
index 0000000000..ddca587007
--- /dev/null
+++ b/gui/themes/fonts/Arial12.bdf
@@ -0,0 +1,7119 @@
+STARTFONT 2.1
+COMMENT
+COMMENT Converted from TrueType font "arialbd.ttf" by "ttf2bdf 2.8".
+COMMENT
+FONT -FreeType-Arial-Bold-R-Normal--104-750-100-100-P-481-ISO10646-1
+SIZE 75 100 100
+FONTBOUNDINGBOX 105 104 -5 -24
+STARTPROPERTIES 19
+FOUNDRY "FreeType"
+FAMILY_NAME "Arial"
+WEIGHT_NAME "Bold"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 104
+POINT_SIZE 750
+RESOLUTION_X 100
+RESOLUTION_Y 100
+SPACING "P"
+AVERAGE_WIDTH 481
+CHARSET_REGISTRY "ISO10646"
+CHARSET_ENCODING "1"
+FONT_ASCENT 94
+FONT_DESCENT 22
+COPYRIGHT "Typeface © The Monotype Corporation plc. Data © The Monotype Corporation plc/Type Solutions Inc. 1990-1992. All Rights Reserved"
+_TTF_FONTFILE "arialbd.ttf"
+_TTF_PSNAME "Arial-BoldMT"
+ENDPROPERTIES
+CHARS 96
+STARTCHAR 0020
+ENCODING 32
+SWIDTH 268 0
+DWIDTH 28 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR 0021
+ENCODING 33
+SWIDTH 307 0
+DWIDTH 32 0
+BBX 14 75 9 0
+BITMAP
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+7FFC
+7FF8
+7FF8
+7FF8
+7FF8
+7FF8
+7FF8
+7FF8
+7FF8
+7FF8
+7FF8
+3FF8
+3FF8
+3FF0
+3FF0
+3FF0
+3FF0
+3FF0
+3FF0
+3FF0
+3FF0
+3FF0
+3FF0
+1FF0
+1FE0
+1FE0
+1FE0
+1FE0
+1FE0
+1FE0
+1FE0
+1FE0
+1FE0
+0000
+0000
+0000
+0000
+0000
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+ENDCHAR
+STARTCHAR 0022
+ENCODING 34
+SWIDTH 470 0
+DWIDTH 49 0
+BBX 38 27 5 48
+BITMAP
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+FFFC00FFFC
+7FF8007FF8
+7FF8007FF8
+7FF8007FF8
+7FF8007FF8
+7FF8007FF8
+7FF8007FF8
+3FF8003FF8
+3FF0003FF0
+3FF0003FF0
+3FF0003FF0
+3FF0003FF0
+ENDCHAR
+STARTCHAR 0023
+ENCODING 35
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 56 75 1 0
+BITMAP
+00001FFC003FF8
+00001FFC003FF8
+00003FFC007FF8
+00003FFC007FF8
+00003FF8007FF0
+00003FF8007FF0
+00003FF8007FF0
+00007FF800FFF0
+00007FF000FFE0
+00007FF000FFE0
+00007FF000FFE0
+00007FF000FFE0
+0000FFF001FFE0
+0000FFE001FFC0
+0000FFE001FFC0
+0000FFE001FFC0
+0001FFE003FFC0
+0001FFE003FFC0
+0001FFC003FF80
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+000FFF001FFE00
+000FFF001FFE00
+000FFE001FFC00
+000FFE001FFC00
+000FFE001FFC00
+001FFE003FFC00
+001FFC003FF800
+001FFC003FF800
+001FFC003FF800
+001FFC003FF800
+003FFC007FF800
+003FF8007FF000
+003FF8007FF000
+003FF8007FF000
+007FF800FFF000
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+01FFC003FF8000
+01FFC003FF8000
+01FFC003FF8000
+03FFC007FF8000
+03FF8007FF0000
+03FF8007FF0000
+03FF8007FF0000
+07FF800FFF0000
+07FF000FFE0000
+07FF000FFE0000
+07FF000FFE0000
+07FF000FFE0000
+0FFF001FFE0000
+0FFE001FFC0000
+0FFE001FFC0000
+0FFE001FFC0000
+0FFE001FFC0000
+1FFE003FFC0000
+1FFC003FF80000
+ENDCHAR
+STARTCHAR 0024
+ENCODING 36
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 50 90 3 -10
+BITMAP
+000007F0000000
+000007F0000000
+000007F0000000
+000007F0000000
+000007F0000000
+00003FFE000000
+0001FFFFE00000
+000FFFFFF80000
+001FFFFFFE0000
+007FFFFFFF0000
+00FFFFFFFFC000
+01FFFFFFFFE000
+03FFFFFFFFF000
+07FFFFFFFFF000
+07FFFFFFFFF800
+0FFFFFFFFFFC00
+0FFFF7F7FFFC00
+1FFFC7F1FFFE00
+1FFF87F0FFFE00
+1FFF07F07FFE00
+3FFF07F07FFF00
+3FFE07F03FFF00
+3FFE07F03FF800
+3FFE07F01C0000
+3FFE07F0000000
+3FFE07F0000000
+3FFE07F0000000
+3FFE07F0000000
+3FFF07F0000000
+3FFF07F0000000
+1FFF87F0000000
+1FFFC7F0000000
+1FFFF7F0000000
+1FFFFFF0000000
+0FFFFFF0000000
+0FFFFFF0000000
+07FFFFFF000000
+03FFFFFFE00000
+03FFFFFFF80000
+01FFFFFFFE0000
+00FFFFFFFF8000
+007FFFFFFFE000
+001FFFFFFFF000
+000FFFFFFFF800
+0003FFFFFFFC00
+0000FFFFFFFE00
+00001FFFFFFE00
+000007FFFFFF00
+000007FFFFFF00
+000007F7FFFF80
+000007F1FFFF80
+000007F07FFF80
+000007F03FFFC0
+000007F01FFFC0
+000007F00FFFC0
+000007F00FFFC0
+000007F007FFC0
+003807F007FFC0
+1FF807F007FFC0
+FFFC07F007FFC0
+FFFC07F007FFC0
+FFFE07F007FFC0
+7FFE07F00FFF80
+7FFF07F00FFF80
+7FFF87F01FFF80
+3FFF87F03FFF80
+3FFFE7F07FFF00
+3FFFF7F1FFFF00
+1FFFFFFFFFFE00
+1FFFFFFFFFFE00
+0FFFFFFFFFFC00
+07FFFFFFFFF800
+07FFFFFFFFF800
+03FFFFFFFFF000
+01FFFFFFFFE000
+00FFFFFFFF8000
+007FFFFFFF0000
+001FFFFFFC0000
+0007FFFFF00000
+0001FFFFC00000
+00003FFC000000
+000007F0000000
+000007F0000000
+000007F0000000
+000007F0000000
+000007F0000000
+000007F0000000
+000007F0000000
+000007F0000000
+000007F0000000
+ENDCHAR
+STARTCHAR 0025
+ENCODING 37
+SWIDTH 864 0
+DWIDTH 90 0
+BBX 81 79 4 -3
+BITMAP
+000FF000000001FFC00000
+007FFE00000003FF800000
+01FFFF80000003FF800000
+03FFFFC0000007FF000000
+07FFFFE0000007FF000000
+0FFFFFF000000FFE000000
+1FFFFFF800000FFE000000
+3FFFFFFC00001FFC000000
+3FFC3FFC00001FFC000000
+7FF81FFC00003FF8000000
+7FF00FFE00003FF8000000
+7FF00FFE00007FF0000000
+7FF00FFE00007FF0000000
+FFE007FE0000FFE0000000
+FFE007FF0000FFE0000000
+FFE007FF0001FFC0000000
+FFE007FF0001FFC0000000
+FFE007FF0003FF80000000
+FFE007FF0003FF80000000
+FFE007FF0007FF00000000
+FFE007FF0007FF00000000
+FFE007FF000FFE00000000
+FFE007FF000FFE00000000
+FFE007FF001FFC00000000
+FFE007FF001FFC00000000
+FFE007FE003FFC00000000
+7FF00FFE003FF800000000
+7FF00FFE007FF800000000
+7FF00FFE007FF000000000
+7FF81FFC007FF000000000
+3FFC3FFC00FFE000000000
+3FFFFFFC00FFE000000000
+1FFFFFF801FFC000000000
+0FFFFFF001FFC000000000
+0FFFFFE003FF8000000000
+03FFFFC003FF8000000000
+01FFFF8007FF0000000000
+007FFE0007FF0000000000
+000FF0000FFE0000000000
+000000000FFE0000000000
+000000001FFC0007F80000
+000000001FFC003FFF0000
+000000003FF800FFFFC000
+000000003FF801FFFFE000
+000000007FF003FFFFF000
+000000007FF007FFFFF800
+00000000FFE00FFFFFFC00
+00000000FFE01FFFFFFE00
+00000001FFC01FFE1FFE00
+00000001FFC03FFC0FFE00
+00000003FF803FF807FF00
+00000003FF803FF807FF00
+00000007FF003FF807FF00
+00000007FF007FF003FF00
+0000000FFE007FF003FF80
+0000000FFE007FF003FF80
+0000001FFC007FF003FF80
+0000001FFC007FF003FF80
+0000003FF8007FF003FF80
+0000003FF8007FF003FF80
+0000007FF0007FF003FF80
+0000007FF0007FF003FF80
+000000FFE0007FF003FF80
+000000FFE0007FF003FF80
+000001FFC0007FF003FF80
+000001FFC0007FF003FF00
+000003FF80003FF807FF00
+000003FF80003FF807FF00
+000007FF00003FF807FF00
+000007FF00003FFC0FFE00
+00000FFE00001FFE1FFE00
+00000FFE00001FFFFFFE00
+00001FFE00000FFFFFFC00
+00001FFC000007FFFFF800
+00003FFC000003FFFFF000
+00003FF8000001FFFFE000
+00003FF8000000FFFFC000
+00007FF00000003FFF0000
+00007FF000000007F80000
+ENDCHAR
+STARTCHAR 0026
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 75 0
+BBX 69 77 4 -1
+BITMAP
+000001FFE000000000
+00001FFFFE00000000
+00007FFFFFC0000000
+0001FFFFFFE0000000
+0003FFFFFFF8000000
+0007FFFFFFFC000000
+000FFFFFFFFE000000
+001FFFFFFFFF000000
+003FFFFFFFFF800000
+003FFFFFFFFF800000
+007FFFC07FFFC00000
+007FFF003FFFC00000
+00FFFE001FFFC00000
+00FFFC000FFFE00000
+00FFFC0007FFE00000
+00FFFC0007FFE00000
+00FFFC0007FFE00000
+00FFFC0007FFE00000
+00FFFE0007FFE00000
+00FFFE000FFFE00000
+007FFF001FFFC00000
+007FFF803FFFC00000
+003FFFC07FFFC00000
+003FFFE0FFFF800000
+001FFFF3FFFF000000
+001FFFFFFFFF000000
+000FFFFFFFFE000000
+0007FFFFFFFC000000
+0007FFFFFFF8000000
+0003FFFFFFE0000000
+0001FFFFFFC0000000
+0000FFFFFF00000000
+0001FFFFFE00000000
+0003FFFFF800000000
+000FFFFFF800000000
+001FFFFFFC00000000
+007FFFFFFC00000000
+00FFFFFFFE00000000
+01FFFFFFFF00000000
+03FFFFFFFF80100000
+07FFFFFFFFC01F0000
+0FFFFCFFFFC03FF800
+0FFFF07FFFE03FFF00
+1FFFE03FFFF07FFE00
+1FFFC03FFFF87FFE00
+3FFF801FFFFC7FFE00
+3FFF000FFFFEFFFC00
+7FFF0007FFFFFFFC00
+7FFE0003FFFFFFFC00
+7FFE0001FFFFFFF800
+FFFC0001FFFFFFF800
+FFFC0000FFFFFFF800
+FFFC00007FFFFFF000
+FFFC00003FFFFFF000
+FFFC00001FFFFFE000
+FFFC00000FFFFFE000
+FFFC00000FFFFFC000
+FFFE000007FFFFC000
+FFFE000003FFFFE000
+FFFF000007FFFFF000
+7FFF00001FFFFFF800
+7FFF80003FFFFFFE00
+7FFFE000FFFFFFFF00
+3FFFF807FFFFFFFFC0
+3FFFFFFFFFFFFFFFE0
+1FFFFFFFFFFFFFFFF8
+1FFFFFFFFFFFFFFFF0
+0FFFFFFFFFFFFFFFF0
+07FFFFFFFFFFFFFFE0
+03FFFFFFFFFE7FFFC0
+01FFFFFFFFFC1FFF80
+00FFFFFFFFF00FFF80
+007FFFFFFFE007FF00
+001FFFFFFF8003FE00
+0007FFFFFE0000FC00
+0001FFFFF800003C00
+00000FFF8000001800
+ENDCHAR
+STARTCHAR 0027
+ENCODING 39
+SWIDTH 240 0
+DWIDTH 25 0
+BBX 14 27 5 48
+BITMAP
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+7FF8
+7FF8
+7FF8
+7FF8
+7FF8
+7FF8
+3FF8
+3FF0
+3FF0
+3FF0
+3FF0
+ENDCHAR
+STARTCHAR 0028
+ENCODING 40
+SWIDTH 336 0
+DWIDTH 35 0
+BBX 25 96 5 -21
+BITMAP
+0000FF80
+0001FF00
+0003FF00
+0003FF00
+0007FE00
+000FFE00
+000FFC00
+001FFC00
+001FFC00
+003FF800
+003FF800
+007FF800
+007FF000
+00FFF000
+00FFF000
+01FFE000
+01FFE000
+03FFE000
+03FFC000
+07FFC000
+07FFC000
+07FF8000
+0FFF8000
+0FFF8000
+0FFF8000
+1FFF0000
+1FFF0000
+1FFF0000
+3FFF0000
+3FFF0000
+3FFE0000
+3FFE0000
+3FFE0000
+7FFE0000
+7FFE0000
+7FFE0000
+7FFE0000
+7FFC0000
+7FFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+7FFC0000
+7FFC0000
+7FFE0000
+7FFE0000
+7FFE0000
+7FFE0000
+7FFE0000
+3FFE0000
+3FFE0000
+3FFE0000
+3FFF0000
+1FFF0000
+1FFF0000
+1FFF0000
+0FFF0000
+0FFF8000
+0FFF8000
+07FF8000
+07FF8000
+07FFC000
+03FFC000
+03FFC000
+03FFC000
+01FFE000
+01FFE000
+00FFE000
+00FFF000
+007FF000
+007FF000
+003FF800
+003FF800
+001FF800
+001FFC00
+000FFC00
+000FFE00
+0007FE00
+0003FE00
+0003FF00
+0001FF00
+0000FF80
+ENDCHAR
+STARTCHAR 0029
+ENCODING 41
+SWIDTH 336 0
+DWIDTH 35 0
+BBX 25 96 5 -21
+BITMAP
+FF800000
+7FC00000
+7FE00000
+7FE00000
+3FF00000
+3FF80000
+1FF80000
+1FFC0000
+1FFC0000
+0FFE0000
+0FFE0000
+0FFF0000
+07FF0000
+07FF8000
+07FF8000
+03FFC000
+03FFC000
+03FFE000
+01FFE000
+01FFF000
+01FFF000
+00FFF000
+00FFF800
+00FFF800
+00FFF800
+007FFC00
+007FFC00
+007FFC00
+007FFE00
+007FFE00
+003FFE00
+003FFE00
+003FFE00
+003FFF00
+003FFF00
+003FFF00
+003FFF00
+003FFF00
+001FFF00
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF80
+001FFF00
+001FFF00
+001FFF00
+003FFF00
+003FFF00
+003FFF00
+003FFF00
+003FFE00
+003FFE00
+003FFE00
+007FFE00
+007FFC00
+007FFC00
+007FFC00
+007FFC00
+007FF800
+00FFF800
+00FFF800
+00FFF000
+00FFF000
+01FFF000
+01FFE000
+01FFE000
+01FFC000
+03FFC000
+03FFC000
+03FF8000
+07FF8000
+07FF0000
+07FF0000
+0FFE0000
+0FFE0000
+0FFC0000
+1FFC0000
+1FF80000
+3FF00000
+3FF00000
+7FE00000
+7FE00000
+7FC00000
+FF800000
+ENDCHAR
+STARTCHAR 002A
+ENCODING 42
+SWIDTH 384 0
+DWIDTH 40 0
+BBX 37 35 1 40
+BITMAP
+0003FE0000
+0003FE0000
+0003FE0000
+0003FE0000
+0003FE0000
+0003FE0000
+0003FE0000
+0003FC0000
+1801FC00C0
+1E01FC03C0
+1F81FC0FC0
+3FE1FC3FE0
+3FF9FCFFE0
+7FFFFFFFF0
+7FFFFFFFF0
+7FFFFFFFF0
+FFFFFFFFF8
+3FFFFFFFE0
+00FFFFFC00
+0007FF0000
+000FFF8000
+001FFFC000
+003FFFE000
+007FFFF000
+00FFDFF800
+01FF8FFC00
+03FF07FE00
+07FF07FF00
+0FFE03FF80
+1FFC01FFC0
+0FFC01FF80
+03F800FE00
+01F0007C00
+00F0007800
+0020002000
+ENDCHAR
+STARTCHAR 002B
+ENCODING 43
+SWIDTH 585 0
+DWIDTH 61 0
+BBX 51 51 4 11
+BITMAP
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+00001FFF000000
+ENDCHAR
+STARTCHAR 002C
+ENCODING 44
+SWIDTH 278 0
+DWIDTH 29 0
+BBX 15 31 6 -17
+BITMAP
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+00FE
+00FE
+00FE
+00FE
+01FC
+01FC
+03FC
+03F8
+07F8
+1FF0
+7FF0
+FFE0
+7FC0
+7F80
+3F00
+3C00
+1000
+ENDCHAR
+STARTCHAR 002D
+ENCODING 45
+SWIDTH 336 0
+DWIDTH 35 0
+BBX 29 13 5 20
+BITMAP
+FFFFFFF8
+FFFFFFF8
+FFFFFFF8
+FFFFFFF8
+FFFFFFF8
+FFFFFFF8
+FFFFFFF8
+FFFFFFF8
+FFFFFFF8
+FFFFFFF8
+FFFFFFF8
+FFFFFFF8
+FFFFFFF8
+ENDCHAR
+STARTCHAR 002E
+ENCODING 46
+SWIDTH 278 0
+DWIDTH 29 0
+BBX 14 14 7 0
+BITMAP
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+ENDCHAR
+STARTCHAR 002F
+ENCODING 47
+SWIDTH 278 0
+DWIDTH 29 0
+BBX 29 75 0 0
+BITMAP
+00003FF8
+00007FF8
+00007FF0
+00007FF0
+00007FF0
+0000FFF0
+0000FFE0
+0000FFE0
+0000FFE0
+0001FFE0
+0001FFE0
+0001FFC0
+0001FFC0
+0003FFC0
+0003FFC0
+0003FF80
+0003FF80
+0007FF80
+0007FF80
+0007FF00
+0007FF00
+0007FF00
+000FFF00
+000FFE00
+000FFE00
+000FFE00
+001FFE00
+001FFC00
+001FFC00
+001FFC00
+003FFC00
+003FF800
+003FF800
+003FF800
+007FF800
+007FF800
+007FF000
+007FF000
+00FFF000
+00FFF000
+00FFE000
+00FFE000
+01FFE000
+01FFE000
+01FFC000
+01FFC000
+01FFC000
+03FFC000
+03FF8000
+03FF8000
+03FF8000
+07FF8000
+07FF0000
+07FF0000
+07FF0000
+0FFF0000
+0FFE0000
+0FFE0000
+0FFE0000
+1FFE0000
+1FFE0000
+1FFC0000
+1FFC0000
+3FFC0000
+3FFC0000
+3FF80000
+3FF80000
+7FF80000
+7FF80000
+7FF00000
+7FF00000
+7FF00000
+FFF00000
+FFE00000
+FFE00000
+ENDCHAR
+STARTCHAR 0030
+ENCODING 48
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 49 76 4 -1
+BITMAP
+00001FFC000000
+0000FFFF800000
+0003FFFFE00000
+000FFFFFF80000
+003FFFFFFC0000
+007FFFFFFF0000
+00FFFFFFFF8000
+01FFFFFFFF8000
+01FFFFFFFFC000
+03FFFFFFFFE000
+07FFFFFFFFE000
+07FFFFFFFFF000
+0FFFFFFFFFF800
+0FFFF80FFFF800
+1FFFE003FFF800
+1FFFC001FFFC00
+1FFF8000FFFC00
+3FFF8000FFFC00
+3FFF00007FFE00
+3FFF00007FFE00
+3FFF00007FFE00
+7FFE00003FFE00
+7FFE00003FFF00
+7FFE00003FFF00
+7FFE00003FFF00
+7FFE00003FFF00
+7FFC00001FFF00
+7FFC00001FFF00
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF00
+7FFC00003FFF00
+7FFE00003FFF00
+7FFE00003FFF00
+7FFE00003FFF00
+7FFE00003FFF00
+7FFE00003FFF00
+3FFF00007FFE00
+3FFF00007FFE00
+3FFF00007FFE00
+3FFF8000FFFC00
+1FFF8000FFFC00
+1FFFC001FFFC00
+1FFFE003FFF800
+0FFFF80FFFF800
+0FFFFFFFFFF800
+07FFFFFFFFF000
+07FFFFFFFFF000
+03FFFFFFFFE000
+01FFFFFFFFC000
+01FFFFFFFFC000
+00FFFFFFFF8000
+007FFFFFFF0000
+001FFFFFFE0000
+000FFFFFF80000
+0003FFFFE00000
+0000FFFF800000
+00001FFC000000
+ENDCHAR
+STARTCHAR 0031
+ENCODING 49
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 32 75 8 0
+BITMAP
+00000FFF
+00000FFF
+00000FFF
+00001FFF
+00001FFF
+00003FFF
+00007FFF
+0000FFFF
+0000FFFF
+0001FFFF
+0003FFFF
+000FFFFF
+001FFFFF
+003FFFFF
+007FFFFF
+01FFFFFF
+07FFFFFF
+0FFFFFFF
+7FFFFFFF
+FFFFFFFF
+FFFFFFFF
+FFFFFFFF
+FFFFBFFF
+FFFF3FFF
+FFFE3FFF
+FFF83FFF
+FFF03FFF
+FFE03FFF
+FF803FFF
+FF003FFF
+FC003FFF
+F0003FFF
+80003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+00003FFF
+ENDCHAR
+STARTCHAR 0032
+ENCODING 50
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 49 75 4 0
+BITMAP
+000007FF000000
+00007FFFF00000
+0003FFFFFC0000
+000FFFFFFF0000
+001FFFFFFF8000
+007FFFFFFFC000
+00FFFFFFFFE000
+01FFFFFFFFF000
+01FFFFFFFFF800
+03FFFFFFFFFC00
+07FFFFFFFFFC00
+07FFFFFFFFFE00
+0FFFFFFFFFFE00
+0FFFFC07FFFF00
+0FFFF001FFFF00
+1FFFE000FFFF00
+1FFFC0007FFF80
+1FFFC0003FFF80
+1FFF80003FFF80
+3FFF80001FFF80
+3FFF00001FFF80
+3FFF00001FFF80
+3FFF00001FFF80
+001F00001FFF80
+000000001FFF80
+000000001FFF80
+000000003FFF00
+000000003FFF00
+000000003FFF00
+000000007FFE00
+000000007FFE00
+00000000FFFE00
+00000001FFFC00
+00000003FFFC00
+00000007FFF800
+00000007FFF800
+0000000FFFF000
+0000001FFFE000
+0000003FFFC000
+0000007FFFC000
+000000FFFF8000
+000001FFFF0000
+000007FFFE0000
+00000FFFFC0000
+00001FFFF80000
+00003FFFF00000
+00007FFFE00000
+0000FFFFC00000
+0001FFFF800000
+0003FFFF000000
+0007FFFE000000
+000FFFFC000000
+001FFFF8000000
+003FFFF0000000
+003FFFE0000000
+007FFF80000000
+00FFFF80000000
+01FFFF00000000
+03FFFE00000000
+03FFFC00000000
+07FFF800000000
+0FFFFFFFFFFF80
+0FFFFFFFFFFF80
+1FFFFFFFFFFF80
+1FFFFFFFFFFF80
+3FFFFFFFFFFF80
+3FFFFFFFFFFF80
+3FFFFFFFFFFF80
+7FFFFFFFFFFF80
+7FFFFFFFFFFF80
+7FFFFFFFFFFF80
+7FFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+ENDCHAR
+STARTCHAR 0033
+ENCODING 51
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 49 76 4 -1
+BITMAP
+00001FFC000000
+0000FFFF800000
+0007FFFFE00000
+000FFFFFF80000
+003FFFFFFE0000
+007FFFFFFF0000
+00FFFFFFFF8000
+01FFFFFFFFC000
+03FFFFFFFFC000
+03FFFFFFFFE000
+07FFFFFFFFF000
+07FFFFFFFFF000
+0FFFFFFFFFF800
+0FFFFC0FFFF800
+1FFFF007FFF800
+1FFFE003FFFC00
+1FFFC001FFFC00
+1FFF8000FFFC00
+3FFF8000FFFC00
+3FFF0000FFFC00
+03FF0000FFFC00
+00070000FFFC00
+00000000FFFC00
+00000001FFF800
+00000001FFF800
+00000003FFF800
+00000003FFF000
+0000000FFFE000
+0000003FFFE000
+000007FFFFC000
+000007FFFF8000
+000007FFFF0000
+000007FFFE0000
+000007FFF80000
+000007FFF00000
+000007FFFE0000
+000007FFFF8000
+00000FFFFFC000
+00000FFFFFE000
+00000FFFFFF000
+00000C07FFF800
+00000001FFFC00
+00000000FFFE00
+000000007FFE00
+000000007FFF00
+000000003FFF00
+000000003FFF00
+000000001FFF00
+000000001FFF80
+000000001FFF80
+000000001FFF80
+000000001FFF80
+003C00001FFF80
+3FFC00001FFF80
+FFFC00001FFF80
+FFFE00003FFF80
+FFFE00003FFF80
+7FFF00003FFF00
+7FFF00007FFF00
+7FFF8000FFFF00
+7FFFC001FFFF00
+3FFFE003FFFE00
+3FFFF80FFFFE00
+1FFFFFFFFFFC00
+1FFFFFFFFFFC00
+0FFFFFFFFFF800
+07FFFFFFFFF000
+07FFFFFFFFE000
+03FFFFFFFFC000
+01FFFFFFFF8000
+00FFFFFFFF0000
+003FFFFFFE0000
+001FFFFFFC0000
+0007FFFFF00000
+0001FFFF800000
+00001FFC000000
+ENDCHAR
+STARTCHAR 0034
+ENCODING 52
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 54 74 2 0
+BITMAP
+00000000FFF800
+00000000FFF800
+00000001FFF800
+00000003FFF800
+00000003FFF800
+00000007FFF800
+0000000FFFF800
+0000001FFFF800
+0000001FFFF800
+0000003FFFF800
+0000007FFFF800
+0000007FFFF800
+000000FFFFF800
+000001FFFFF800
+000003FFFFF800
+000003FFFFF800
+000007FFFFF800
+00000FFFFFF800
+00000FFFFFF800
+00001FFFFFF800
+00003FFFFFF800
+00007FFFFFF800
+00007FFDFFF800
+0000FFF9FFF800
+0001FFF9FFF800
+0001FFF1FFF800
+0003FFE1FFF800
+0007FFE1FFF800
+0007FFC1FFF800
+000FFF81FFF800
+001FFF01FFF800
+003FFF01FFF800
+003FFE01FFF800
+007FFC01FFF800
+00FFFC01FFF800
+00FFF801FFF800
+01FFF001FFF800
+03FFE001FFF800
+07FFE001FFF800
+07FFC001FFF800
+0FFF8001FFF800
+1FFF8001FFF800
+1FFF0001FFF800
+3FFE0001FFF800
+7FFC0001FFF800
+FFFC0001FFF800
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+00000001FFF800
+ENDCHAR
+STARTCHAR 0035
+ENCODING 53
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 50 75 4 -1
+BITMAP
+003FFFFFFFFE00
+003FFFFFFFFE00
+007FFFFFFFFE00
+007FFFFFFFFE00
+007FFFFFFFFE00
+007FFFFFFFFE00
+007FFFFFFFFE00
+007FFFFFFFFE00
+00FFFFFFFFFE00
+00FFFFFFFFFE00
+00FFFFFFFFFE00
+00FFFFFFFFFE00
+00FFFFFFFFFE00
+01FFFFFFFFFE00
+01FFF800000000
+01FFF800000000
+01FFF800000000
+01FFF800000000
+03FFF800000000
+03FFF000000000
+03FFF000000000
+03FFF000000000
+03FFF000000000
+07FFF000000000
+07FFE0FF800000
+07FFE7FFF00000
+07FFFFFFFC0000
+07FFFFFFFF0000
+0FFFFFFFFF8000
+0FFFFFFFFFC000
+0FFFFFFFFFE000
+0FFFFFFFFFF000
+0FFFFFFFFFF800
+1FFFFFFFFFFC00
+1FFFFFFFFFFC00
+1FFFFFFFFFFE00
+1FFFFFFFFFFE00
+1FFFF807FFFF00
+3FFFE001FFFF00
+3FFF8000FFFF80
+3FFF00007FFF80
+003E00003FFF80
+000000001FFF80
+000000001FFFC0
+000000001FFFC0
+000000000FFFC0
+000000000FFFC0
+000000000FFFC0
+000000000FFFC0
+000000000FFFC0
+000000000FFFC0
+007800000FFFC0
+7FF800000FFFC0
+FFFC00000FFFC0
+FFFC00001FFF80
+FFFC00001FFF80
+7FFE00003FFF80
+7FFE00003FFF80
+7FFF00007FFF00
+3FFF8000FFFF00
+3FFFE003FFFE00
+3FFFF80FFFFE00
+1FFFFFFFFFFC00
+1FFFFFFFFFFC00
+0FFFFFFFFFF800
+07FFFFFFFFF000
+07FFFFFFFFF000
+03FFFFFFFFE000
+01FFFFFFFFC000
+00FFFFFFFF8000
+003FFFFFFE0000
+001FFFFFFC0000
+0007FFFFF00000
+0001FFFFC00000
+00001FFC000000
+ENDCHAR
+STARTCHAR 0036
+ENCODING 54
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 49 76 4 -1
+BITMAP
+000007FE000000
+00003FFFE00000
+0001FFFFF80000
+0003FFFFFC0000
+000FFFFFFE0000
+001FFFFFFF8000
+003FFFFFFFC000
+007FFFFFFFC000
+00FFFFFFFFE000
+01FFFFFFFFF000
+03FFFFFFFFF000
+03FFFFFFFFF800
+07FFFFFFFFF800
+0FFFFC0FFFF800
+0FFFF003FFFC00
+0FFFC001FFFC00
+1FFF8000FFFC00
+1FFF8000FFFE00
+3FFF0000FFFE00
+3FFF00007FFE00
+3FFE00007C0000
+3FFE0000000000
+7FFE0000000000
+7FFC0000000000
+7FFC0000000000
+7FFC0000000000
+7FFC0000000000
+7FFC0000000000
+FFF803FE000000
+FFF81FFFE00000
+FFF87FFFF80000
+FFF8FFFFFE0000
+FFF9FFFFFF0000
+FFFBFFFFFF8000
+FFFFFFFFFFC000
+FFFFFFFFFFE000
+FFFFFFFFFFF000
+FFFFFFFFFFF800
+FFFFFFFFFFF800
+FFFFFFFFFFFC00
+FFFFFFFFFFFE00
+FFFFF80FFFFE00
+FFFFE003FFFE00
+FFFF8000FFFF00
+FFFF00007FFF00
+FFFE00007FFF00
+FFFE00003FFF80
+FFFE00003FFF80
+7FFC00001FFF80
+7FFC00001FFF80
+7FFC00001FFF80
+7FFC00001FFF80
+7FFC00001FFF80
+7FFC00001FFF80
+7FFC00001FFF80
+3FFE00001FFF80
+3FFE00003FFF80
+3FFE00003FFF00
+1FFF00003FFF00
+1FFF80007FFF00
+1FFFC000FFFF00
+0FFFE001FFFE00
+0FFFFC07FFFE00
+07FFFFFFFFFE00
+07FFFFFFFFFC00
+03FFFFFFFFF800
+01FFFFFFFFF800
+01FFFFFFFFF000
+00FFFFFFFFE000
+007FFFFFFFC000
+003FFFFFFF8000
+001FFFFFFF0000
+0007FFFFFC0000
+0001FFFFF80000
+00007FFFC00000
+00000FFE000000
+ENDCHAR
+STARTCHAR 0037
+ENCODING 55
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 49 74 4 0
+BITMAP
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF00
+FFFFFFFFFFFE00
+00000000FFFC00
+00000001FFF800
+00000001FFF000
+00000003FFE000
+00000007FFE000
+00000007FFC000
+0000000FFF8000
+0000001FFF8000
+0000001FFF0000
+0000003FFE0000
+0000007FFE0000
+0000007FFC0000
+000000FFFC0000
+000001FFF80000
+000001FFF00000
+000003FFF00000
+000003FFE00000
+000007FFE00000
+000007FFC00000
+00000FFFC00000
+00000FFF800000
+00001FFF800000
+00001FFF800000
+00003FFF000000
+00003FFF000000
+00003FFE000000
+00007FFE000000
+00007FFC000000
+0000FFFC000000
+0000FFFC000000
+0000FFF8000000
+0001FFF8000000
+0001FFF8000000
+0001FFF0000000
+0003FFF0000000
+0003FFF0000000
+0003FFF0000000
+0007FFE0000000
+0007FFE0000000
+0007FFE0000000
+0007FFE0000000
+000FFFC0000000
+000FFFC0000000
+000FFFC0000000
+000FFFC0000000
+000FFF80000000
+001FFF80000000
+001FFF80000000
+001FFF80000000
+001FFF80000000
+001FFF80000000
+001FFF00000000
+003FFF00000000
+003FFF00000000
+003FFF00000000
+003FFF00000000
+003FFF00000000
+003FFF00000000
+003FFF00000000
+003FFF00000000
+ENDCHAR
+STARTCHAR 0038
+ENCODING 56
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 49 76 4 -1
+BITMAP
+00001FFC000000
+0003FFFFC00000
+000FFFFFF80000
+003FFFFFFE0000
+007FFFFFFF0000
+00FFFFFFFF8000
+01FFFFFFFFC000
+03FFFFFFFFE000
+07FFFFFFFFF000
+0FFFFFFFFFF000
+0FFFFFFFFFF800
+1FFFFC0FFFFC00
+1FFFE003FFFC00
+1FFFC001FFFC00
+3FFF8000FFFE00
+3FFF8000FFFE00
+3FFF80007FFE00
+3FFF00007FFE00
+3FFF00007FFE00
+3FFF00007FFE00
+3FFF00007FFE00
+3FFF00007FFE00
+3FFF00007FFE00
+1FFF0000FFFC00
+1FFF8000FFFC00
+1FFF8000FFFC00
+0FFFC001FFF800
+0FFFE003FFF800
+07FFF80FFFF000
+03FFFFFFFFE000
+01FFFFFFFFC000
+00FFFFFFFF8000
+007FFFFFFF0000
+001FFFFFFC0000
+000FFFFFF80000
+003FFFFFFE0000
+00FFFFFFFF8000
+01FFFFFFFFC000
+03FFFFFFFFE000
+07FFFFFFFFF000
+0FFFF80FFFF800
+1FFFE003FFFC00
+1FFFC001FFFC00
+3FFF8000FFFE00
+3FFF00007FFE00
+7FFF00003FFF00
+7FFE00003FFF00
+7FFE00003FFF00
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFC00001FFF80
+FFFE00003FFF80
+7FFE00003FFF00
+7FFF00003FFF00
+7FFF00007FFF00
+7FFF8000FFFF00
+3FFFC001FFFE00
+3FFFE003FFFE00
+1FFFF80FFFFC00
+1FFFFFFFFFFC00
+0FFFFFFFFFF800
+07FFFFFFFFF000
+03FFFFFFFFE000
+01FFFFFFFFC000
+00FFFFFFFF8000
+007FFFFFFF0000
+001FFFFFFE0000
+0007FFFFF80000
+0001FFFFC00000
+00001FFE000000
+ENDCHAR
+STARTCHAR 0039
+ENCODING 57
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 49 76 4 -1
+BITMAP
+00003FF8000000
+0001FFFF000000
+000FFFFFC00000
+001FFFFFF00000
+007FFFFFF80000
+00FFFFFFFE0000
+01FFFFFFFF0000
+03FFFFFFFF8000
+07FFFFFFFFC000
+0FFFFFFFFFC000
+0FFFFFFFFFE000
+1FFFFFFFFFF000
+3FFFFFFFFFF000
+3FFFF01FFFF800
+3FFFC007FFF800
+7FFF8001FFFC00
+7FFF0000FFFC00
+7FFE00007FFC00
+7FFE00003FFE00
+FFFE00003FFE00
+FFFC00003FFE00
+FFFC00001FFE00
+FFFC00001FFF00
+FFFC00001FFF00
+FFFC00001FFF00
+FFFC00001FFF00
+FFFC00001FFF00
+FFFC00001FFF00
+FFFE00003FFF80
+FFFE00003FFF80
+7FFF00003FFF80
+7FFF00007FFF80
+7FFF8000FFFF80
+7FFFE003FFFF80
+3FFFF80FFFFF80
+3FFFFFFFFFFF80
+1FFFFFFFFFFF80
+1FFFFFFFFFFF80
+0FFFFFFFFFFF80
+07FFFFFFFFFF80
+03FFFFFFFFFF80
+01FFFFFFFFFF80
+00FFFFFFEFFF80
+007FFFFFCFFF80
+003FFFFF8FFF80
+000FFFFF0FFF80
+0003FFFC0FFF80
+00007FE00FFF00
+000000001FFF00
+000000001FFF00
+000000001FFF00
+000000001FFF00
+000000001FFF00
+000000003FFF00
+000000003FFE00
+001F00003FFE00
+3FFF00007FFE00
+3FFF80007FFC00
+3FFF8000FFFC00
+1FFF8000FFFC00
+1FFFC001FFF800
+1FFFE007FFF800
+1FFFF81FFFF000
+0FFFFFFFFFF000
+0FFFFFFFFFE000
+07FFFFFFFFE000
+07FFFFFFFFC000
+03FFFFFFFF8000
+03FFFFFFFF0000
+01FFFFFFFE0000
+00FFFFFFFC0000
+007FFFFFF80000
+003FFFFFE00000
+000FFFFFC00000
+0003FFFE000000
+00007FF0000000
+ENDCHAR
+STARTCHAR 003A
+ENCODING 58
+SWIDTH 326 0
+DWIDTH 34 0
+BBX 14 55 10 0
+BITMAP
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+ENDCHAR
+STARTCHAR 003B
+ENCODING 59
+SWIDTH 326 0
+DWIDTH 34 0
+BBX 15 72 9 -17
+BITMAP
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+7FFE
+00FE
+00FE
+00FE
+00FE
+01FC
+01FC
+03FC
+03F8
+07F8
+1FF0
+7FF0
+FFE0
+7FC0
+7F80
+3F00
+3C00
+1000
+ENDCHAR
+STARTCHAR 003C
+ENCODING 60
+SWIDTH 585 0
+DWIDTH 61 0
+BBX 51 57 4 8
+BITMAP
+00000000000020
+000000000000E0
+000000000007E0
+00000000001FE0
+00000000007FE0
+0000000003FFE0
+000000000FFFE0
+000000003FFFE0
+00000000FFFFE0
+00000007FFFFE0
+0000001FFFFFE0
+0000007FFFFFE0
+000003FFFFFFE0
+00000FFFFFFFC0
+00003FFFFFFE00
+0001FFFFFFF800
+0007FFFFFFE000
+001FFFFFFF0000
+007FFFFFFC0000
+03FFFFFFE00000
+0FFFFFFF800000
+3FFFFFFE000000
+FFFFFFF0000000
+FFFFFFC0000000
+FFFFFE00000000
+FFFFF800000000
+FFFFE000000000
+FFFF0000000000
+FFFE0000000000
+FFFF8000000000
+FFFFF000000000
+FFFFFC00000000
+FFFFFF00000000
+FFFFFFE0000000
+FFFFFFF8000000
+3FFFFFFE000000
+0FFFFFFFC00000
+01FFFFFFF00000
+007FFFFFFC0000
+001FFFFFFF8000
+0007FFFFFFE000
+0000FFFFFFF800
+00003FFFFFFF00
+00000FFFFFFFC0
+000003FFFFFFE0
+0000007FFFFFE0
+0000001FFFFFE0
+00000007FFFFE0
+00000000FFFFE0
+000000003FFFE0
+000000000FFFE0
+0000000003FFE0
+00000000007FE0
+00000000001FE0
+000000000007E0
+000000000000E0
+00000000000020
+ENDCHAR
+STARTCHAR 003D
+ENCODING 61
+SWIDTH 585 0
+DWIDTH 61 0
+BBX 52 35 4 20
+BITMAP
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+00000000000000
+00000000000000
+00000000000000
+00000000000000
+00000000000000
+00000000000000
+00000000000000
+00000000000000
+00000000000000
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+ENDCHAR
+STARTCHAR 003E
+ENCODING 62
+SWIDTH 585 0
+DWIDTH 61 0
+BBX 51 57 4 8
+BITMAP
+80000000000000
+E0000000000000
+FC000000000000
+FF000000000000
+FFC00000000000
+FFF80000000000
+FFFE0000000000
+FFFF8000000000
+FFFFE000000000
+FFFFFC00000000
+FFFFFF00000000
+FFFFFFC0000000
+FFFFFFF8000000
+7FFFFFFE000000
+0FFFFFFF800000
+03FFFFFFE00000
+00FFFFFFFC0000
+001FFFFFFF0000
+0007FFFFFFC000
+0001FFFFFFF800
+00003FFFFFFE00
+00000FFFFFFF80
+000003FFFFFFE0
+0000007FFFFFE0
+0000001FFFFFE0
+00000003FFFFE0
+00000000FFFFE0
+000000003FFFE0
+000000000FFFE0
+000000003FFFE0
+00000000FFFFE0
+00000007FFFFE0
+0000001FFFFFE0
+0000007FFFFFE0
+000003FFFFFFE0
+00000FFFFFFF80
+00003FFFFFFE00
+0001FFFFFFF000
+0007FFFFFFC000
+001FFFFFFF0000
+00FFFFFFFC0000
+03FFFFFFE00000
+1FFFFFFF800000
+7FFFFFFE000000
+FFFFFFF0000000
+FFFFFFC0000000
+FFFFFF00000000
+FFFFFC00000000
+FFFFE000000000
+FFFF8000000000
+FFFE0000000000
+FFF80000000000
+FFC00000000000
+FF000000000000
+FC000000000000
+E0000000000000
+80000000000000
+ENDCHAR
+STARTCHAR 003F
+ENCODING 63
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 54 76 5 0
+BITMAP
+000007FF800000
+0000FFFFFC0000
+0003FFFFFF0000
+000FFFFFFFC000
+003FFFFFFFF000
+007FFFFFFFF800
+01FFFFFFFFFE00
+03FFFFFFFFFF00
+07FFFFFFFFFF80
+0FFFFFFFFFFF80
+0FFFFFFFFFFFC0
+1FFFFF00FFFFE0
+3FFFF8001FFFF0
+3FFFE0000FFFF0
+7FFFC00007FFF8
+7FFF800003FFF8
+7FFF000001FFF8
+FFFF000001FFFC
+FFFE000000FFFC
+FFFE000000FFFC
+FFFC000000FFFC
+01FC000000FFFC
+0000000000FFFC
+0000000000FFFC
+0000000001FFFC
+0000000001FFFC
+0000000003FFF8
+0000000007FFF8
+000000000FFFF8
+000000001FFFF0
+000000003FFFF0
+000000007FFFE0
+00000000FFFFC0
+00000003FFFF80
+00000007FFFF00
+0000000FFFFE00
+0000001FFFFC00
+0000003FFFF800
+0000007FFFF000
+000000FFFFE000
+000001FFFFC000
+000003FFFF8000
+000007FFFF0000
+000007FFFE0000
+00000FFFF80000
+00000FFFF00000
+00000FFFF00000
+00000FFFE00000
+00001FFFC00000
+00001FFFC00000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00000000000000
+00000000000000
+00000000000000
+00000000000000
+00000000000000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+00001FFF800000
+ENDCHAR
+STARTCHAR 0040
+ENCODING 64
+SWIDTH 969 0
+DWIDTH 101 0
+BBX 97 100 3 -24
+BITMAP
+00000000001FFFE00000000000
+0000000003FFFFFF0000000000
+000000003FFFFFFFF000000000
+00000001FFFFFFFFFC00000000
+00000007FFFFFFFFFF80000000
+0000001FFFFFFFFFFFE0000000
+0000007FFFFFFFFFFFF0000000
+000001FFFFFFFFFFFFFC000000
+000007FFFFFFFFFFFFFE000000
+00000FFFFFFFFFFFFFFF800000
+00001FFFFFF0003FFFFFC00000
+00007FFFFE000001FFFFE00000
+0000FFFFE00000003FFFF00000
+0001FFFF800000000FFFF80000
+0003FFFE0000000003FFFC0000
+0007FFF80000000000FFFC0000
+000FFFE000000000007FFE0000
+000FFFC000000000003FFF0000
+001FFF8000000000000FFF0000
+003FFE00000000000007FF8000
+007FFC00007FC0000007FF8000
+007FF80003FFF80FFF83FFC000
+00FFF8001FFFFE0FFF81FFC000
+00FFF0003FFFFF1FFF80FFE000
+01FFE000FFFFFF9FFF00FFE000
+01FFC001FFFFFFDFFF007FF000
+03FF8003FFFFFFFFFF007FF000
+03FF8007FFFFFFFFFF003FF000
+07FF000FFFFFFFFFFF003FF800
+07FF001FFFF03FFFFE001FF800
+0FFE001FFFC00FFFFE001FF800
+0FFE003FFF0007FFFE001FF800
+1FFC007FFE0003FFFE001FF800
+1FFC007FFC0003FFFE000FFC00
+1FF800FFF80001FFFC000FFC00
+3FF800FFF80001FFFC000FFC00
+3FF801FFF00001FFFC000FFC00
+3FF001FFF00000FFFC000FFC00
+3FF003FFE00000FFFC000FFC00
+7FF003FFE00000FFF8000FFC00
+7FF007FFC00000FFF8000FFC00
+7FE007FFC00000FFF8000FFC00
+7FE007FFC00000FFF8000FFC00
+7FE00FFFC00000FFF8000FFC00
+FFE00FFF800000FFF0001FFC00
+FFE00FFF800000FFF0001FFC00
+FFC00FFF800000FFF0001FF800
+FFC00FFF800001FFF0001FF800
+FFC01FFF000001FFF0003FF800
+FFC01FFF000001FFE0003FF800
+FFC01FFF000001FFE0003FF000
+FFC01FFF000003FFE0007FF000
+FFC01FFF000003FFE0007FF000
+FFC01FFF000003FFE000FFE000
+FFC01FFF000003FFC000FFE000
+FFC01FFF000007FFC001FFC000
+FFC01FFF000007FFC003FFC000
+FFC01FFF00000FFFC003FF8000
+FFC01FFF00000FFFC007FF8000
+FFC01FFF80001FFF800FFF0000
+7FE00FFF80001FFF801FFF0000
+7FE00FFF80003FFF803FFE0000
+7FE00FFFC0007FFF80FFFC0000
+7FE00FFFC000FFFF81FFFC0000
+7FF007FFE001FFFFC7FFF80000
+3FF007FFF003FFFFFFFFF00000
+3FF003FFFC0FFFFFFFFFE00000
+3FF803FFFFFFFFFFFFFFC00000
+3FF801FFFFFFFFFFFFFF800000
+1FF800FFFFFFFFFFFFFF000000
+1FFC007FFFFFFFFFFFFC000000
+1FFC003FFFFFEFFFFFF8000000
+0FFE001FFFFF8FFFFFE0000000
+0FFF000FFFFF07FFFF80000000
+07FF0003FFFC03FFFC00000000
+07FF80003FE000FFC000000000
+03FFC00000000000000007FF80
+03FFC0000000000000000FFF00
+01FFE0000000000000001FFF00
+01FFF0000000000000003FFE00
+00FFF8000000000000007FFE00
+007FFC00000000000000FFFC00
+007FFF00000000000001FFF800
+003FFF80000000000007FFF000
+001FFFE000000000000FFFF000
+000FFFF800000000003FFFE000
+0007FFFE0000000000FFFFC000
+0003FFFFC000000007FFFF8000
+0001FFFFFC0000007FFFFF0000
+0000FFFFFFE0000FFFFFFE0000
+00007FFFFFFFFFFFFFFFF80000
+00001FFFFFFFFFFFFFFFF00000
+000007FFFFFFFFFFFFFFC00000
+000003FFFFFFFFFFFFFF800000
+000000FFFFFFFFFFFFFE000000
+0000001FFFFFFFFFFFF8000000
+00000007FFFFFFFFFFC0000000
+000000007FFFFFFFFE00000000
+0000000007FFFFFFE000000000
+00000000001FFFF80000000000
+ENDCHAR
+STARTCHAR 0041
+ENCODING 65
+SWIDTH 681 0
+DWIDTH 71 0
+BBX 71 75 0 0
+BITMAP
+0000000FFFE0000000
+0000000FFFE0000000
+0000001FFFF0000000
+0000001FFFF0000000
+0000003FFFF0000000
+0000003FFFF8000000
+0000003FFFF8000000
+0000007FFFF8000000
+0000007FFFFC000000
+0000007FFFFC000000
+000000FFFFFE000000
+000000FFFFFE000000
+000001FFFFFE000000
+000001FFFFFF000000
+000001FFFFFF000000
+000003FFFFFF800000
+000003FFFFFF800000
+000003FFFFFF800000
+000007FFEFFFC00000
+000007FFEFFFC00000
+00000FFFEFFFC00000
+00000FFFC7FFE00000
+00000FFFC7FFE00000
+00001FFFC3FFF00000
+00001FFF83FFF00000
+00001FFF83FFF00000
+00003FFF01FFF80000
+00003FFF01FFF80000
+00007FFF01FFF80000
+00007FFE00FFFC0000
+00007FFE00FFFC0000
+0000FFFE00FFFE0000
+0000FFFC007FFE0000
+0000FFFC007FFE0000
+0001FFFC003FFF0000
+0001FFF8003FFF0000
+0003FFF8003FFF0000
+0003FFF0001FFF8000
+0003FFF0001FFF8000
+0007FFF0001FFFC000
+0007FFE0000FFFC000
+0007FFE0000FFFC000
+000FFFE0000FFFE000
+000FFFC00007FFE000
+001FFFC00007FFE000
+001FFFFFFFFFFFF000
+001FFFFFFFFFFFF000
+003FFFFFFFFFFFF800
+003FFFFFFFFFFFF800
+003FFFFFFFFFFFF800
+007FFFFFFFFFFFFC00
+007FFFFFFFFFFFFC00
+00FFFFFFFFFFFFFC00
+00FFFFFFFFFFFFFE00
+00FFFFFFFFFFFFFE00
+01FFFFFFFFFFFFFF00
+01FFFFFFFFFFFFFF00
+01FFFFFFFFFFFFFF00
+03FFF80000003FFF80
+03FFF80000001FFF80
+07FFF00000001FFFC0
+07FFF00000001FFFC0
+07FFE00000000FFFC0
+0FFFE00000000FFFE0
+0FFFE00000000FFFE0
+0FFFC000000007FFE0
+1FFFC000000007FFF0
+1FFFC000000003FFF0
+3FFF8000000003FFF8
+3FFF8000000003FFF8
+3FFF8000000001FFF8
+7FFF0000000001FFFC
+7FFF0000000001FFFC
+7FFF0000000000FFFC
+FFFE0000000000FFFE
+ENDCHAR
+STARTCHAR 0042
+ENCODING 66
+SWIDTH 720 0
+DWIDTH 75 0
+BBX 62 75 8 0
+BITMAP
+FFFFFFFFFF800000
+FFFFFFFFFFFC0000
+FFFFFFFFFFFF8000
+FFFFFFFFFFFFC000
+FFFFFFFFFFFFF000
+FFFFFFFFFFFFF800
+FFFFFFFFFFFFFC00
+FFFFFFFFFFFFFE00
+FFFFFFFFFFFFFF00
+FFFFFFFFFFFFFF00
+FFFFFFFFFFFFFF80
+FFFFFFFFFFFFFF80
+FFFFFFFFFFFFFFC0
+FFFC000003FFFFC0
+FFFC0000007FFFC0
+FFFC0000001FFFE0
+FFFC0000000FFFE0
+FFFC0000000FFFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC0000000FFFC0
+FFFC0000000FFFC0
+FFFC0000001FFFC0
+FFFC0000003FFF80
+FFFC0000007FFF80
+FFFC000003FFFF00
+FFFFFFFFFFFFFE00
+FFFFFFFFFFFFFE00
+FFFFFFFFFFFFFC00
+FFFFFFFFFFFFF000
+FFFFFFFFFFFFE000
+FFFFFFFFFFFF8000
+FFFFFFFFFFFFF000
+FFFFFFFFFFFFFC00
+FFFFFFFFFFFFFE00
+FFFFFFFFFFFFFF00
+FFFFFFFFFFFFFF80
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFE0
+FFFC000003FFFFE0
+FFFC0000003FFFF0
+FFFC0000000FFFF0
+FFFC00000003FFF8
+FFFC00000003FFF8
+FFFC00000001FFF8
+FFFC00000001FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000001FFFC
+FFFC00000001FFFC
+FFFC00000003FFF8
+FFFC00000007FFF8
+FFFC0000001FFFF8
+FFFC000000FFFFF0
+FFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFF80
+FFFFFFFFFFFFFF00
+FFFFFFFFFFFFFE00
+FFFFFFFFFFFFFC00
+FFFFFFFFFFFFF000
+FFFFFFFFFFFFE000
+FFFFFFFFFFFF0000
+FFFFFFFFFFE00000
+ENDCHAR
+STARTCHAR 0043
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 75 0
+BBX 65 76 5 0
+BITMAP
+0000000FFF80000000
+000000FFFFF8000000
+000007FFFFFF000000
+00003FFFFFFFC00000
+00007FFFFFFFE00000
+0001FFFFFFFFF80000
+0003FFFFFFFFFC0000
+000FFFFFFFFFFE0000
+001FFFFFFFFFFF0000
+003FFFFFFFFFFF8000
+007FFFFFFFFFFFC000
+00FFFFFFFFFFFFE000
+00FFFFFFFFFFFFF000
+01FFFFF803FFFFF000
+03FFFFC0007FFFF800
+07FFFF00001FFFF800
+07FFFC00000FFFFC00
+0FFFF8000007FFFC00
+0FFFF0000003FFFE00
+1FFFE0000001FFFE00
+1FFFC0000000FFFE00
+1FFF80000000FFFF00
+3FFF800000007FFF00
+3FFF000000007FFC00
+3FFF000000003F8000
+7FFF00000000300000
+7FFE00000000000000
+7FFE00000000000000
+7FFE00000000000000
+7FFE00000000000000
+7FFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFE00000000000000
+7FFE00000000000000
+7FFE00000000100000
+7FFE000000001E0000
+7FFE000000003FC000
+7FFF000000003FF800
+3FFF000000003FFF00
+3FFF000000007FFF80
+3FFF800000007FFF80
+3FFF80000000FFFF00
+1FFFC0000000FFFF00
+1FFFE0000001FFFF00
+0FFFF0000003FFFE00
+0FFFF8000007FFFE00
+07FFFC00000FFFFC00
+07FFFE00001FFFFC00
+03FFFF80007FFFF800
+01FFFFF803FFFFF800
+01FFFFFFFFFFFFF000
+00FFFFFFFFFFFFE000
+007FFFFFFFFFFFC000
+003FFFFFFFFFFFC000
+001FFFFFFFFFFF8000
+000FFFFFFFFFFF0000
+0007FFFFFFFFFE0000
+0001FFFFFFFFF80000
+0000FFFFFFFFF00000
+00003FFFFFFFC00000
+00000FFFFFFF000000
+000001FFFFF8000000
+0000000FFF80000000
+ENDCHAR
+STARTCHAR 0044
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 75 0
+BBX 62 75 8 0
+BITMAP
+FFFFFFFFF0000000
+FFFFFFFFFFC00000
+FFFFFFFFFFF00000
+FFFFFFFFFFFC0000
+FFFFFFFFFFFF0000
+FFFFFFFFFFFF8000
+FFFFFFFFFFFFE000
+FFFFFFFFFFFFF000
+FFFFFFFFFFFFF800
+FFFFFFFFFFFFF800
+FFFFFFFFFFFFFC00
+FFFFFFFFFFFFFE00
+FFFFFFFFFFFFFF00
+FFFC00007FFFFF00
+FFFC000007FFFF80
+FFFC000001FFFF80
+FFFC0000007FFFC0
+FFFC0000003FFFC0
+FFFC0000001FFFE0
+FFFC0000000FFFE0
+FFFC00000007FFF0
+FFFC00000007FFF0
+FFFC00000003FFF0
+FFFC00000003FFF0
+FFFC00000003FFF8
+FFFC00000001FFF8
+FFFC00000001FFF8
+FFFC00000001FFF8
+FFFC00000001FFF8
+FFFC00000000FFF8
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000000FFFC
+FFFC00000001FFF8
+FFFC00000001FFF8
+FFFC00000001FFF8
+FFFC00000001FFF8
+FFFC00000001FFF8
+FFFC00000003FFF8
+FFFC00000003FFF0
+FFFC00000007FFF0
+FFFC00000007FFF0
+FFFC0000000FFFE0
+FFFC0000000FFFE0
+FFFC0000001FFFC0
+FFFC0000003FFFC0
+FFFC000000FFFF80
+FFFC000003FFFF80
+FFFC00001FFFFF00
+FFFFFFFFFFFFFF00
+FFFFFFFFFFFFFE00
+FFFFFFFFFFFFFC00
+FFFFFFFFFFFFFC00
+FFFFFFFFFFFFF800
+FFFFFFFFFFFFF000
+FFFFFFFFFFFFE000
+FFFFFFFFFFFF8000
+FFFFFFFFFFFF0000
+FFFFFFFFFFFC0000
+FFFFFFFFFFF00000
+FFFFFFFFFF800000
+FFFFFFFFF0000000
+ENDCHAR
+STARTCHAR 0045
+ENCODING 69
+SWIDTH 662 0
+DWIDTH 69 0
+BBX 56 75 8 0
+BITMAP
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFFFFFFFFFFFE
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+FFFFFFFFFFFFFF
+ENDCHAR
+STARTCHAR 0046
+ENCODING 70
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 51 75 8 0
+BITMAP
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFFFFFFFFFC00
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+ENDCHAR
+STARTCHAR 0047
+ENCODING 71
+SWIDTH 777 0
+DWIDTH 81 0
+BBX 69 77 5 -1
+BITMAP
+00000007FFF0000000
+0000007FFFFF800000
+000003FFFFFFF00000
+00001FFFFFFFFC0000
+00003FFFFFFFFF0000
+0000FFFFFFFFFF8000
+0003FFFFFFFFFFC000
+0007FFFFFFFFFFF000
+000FFFFFFFFFFFF800
+001FFFFFFFFFFFFC00
+003FFFFFFFFFFFFC00
+007FFFFFFFFFFFFE00
+00FFFFFFFFFFFFFF00
+01FFFFFE007FFFFF00
+01FFFFE0000FFFFF80
+03FFFF800003FFFFC0
+07FFFE000000FFFFC0
+07FFFC0000007FFFC0
+0FFFF80000003FFFE0
+0FFFF00000001FFFE0
+1FFFE00000000FFFE0
+1FFFC00000000FFFF0
+1FFFC000000007FFF0
+3FFF8000000007FFC0
+3FFF0000000003F800
+3FFF00000000030000
+7FFF00000000000000
+7FFE00000000000000
+7FFE00000000000000
+7FFE00000000000000
+7FFE00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC00000000000000
+FFFC000007FFFFFFF8
+FFFC000007FFFFFFF8
+FFFC000007FFFFFFF8
+FFFC000007FFFFFFF8
+FFFC000007FFFFFFF8
+FFFC000007FFFFFFF8
+FFFC000007FFFFFFF8
+FFFC000007FFFFFFF8
+FFFC000007FFFFFFF8
+7FFE000007FFFFFFF8
+7FFE000007FFFFFFF8
+7FFE000007FFFFFFF8
+7FFE000007FFFFFFF8
+7FFF0000000001FFF8
+3FFF0000000001FFF8
+3FFF0000000001FFF8
+3FFF8000000001FFF8
+3FFF8000000001FFF8
+1FFFC000000001FFF8
+1FFFE000000001FFF8
+0FFFE000000001FFF8
+0FFFF000000001FFF8
+07FFF800000003FFF8
+07FFFC00000007FFF8
+03FFFF0000001FFFF8
+03FFFF800000FFFFF8
+01FFFFF00003FFFFF8
+00FFFFFE003FFFFFF8
+00FFFFFFFFFFFFFFF8
+007FFFFFFFFFFFFFF8
+003FFFFFFFFFFFFFF0
+001FFFFFFFFFFFFFE0
+000FFFFFFFFFFFFF80
+0007FFFFFFFFFFFF00
+0001FFFFFFFFFFFC00
+0000FFFFFFFFFFF000
+00003FFFFFFFFFC000
+00000FFFFFFFFE0000
+000003FFFFFFF80000
+0000007FFFFF800000
+00000003FFF0000000
+ENDCHAR
+STARTCHAR 0048
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 75 0
+BBX 59 75 8 0
+BITMAP
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFFFFFFFFFFFFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+ENDCHAR
+STARTCHAR 0049
+ENCODING 73
+SWIDTH 278 0
+DWIDTH 29 0
+BBX 14 75 7 0
+BITMAP
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+ENDCHAR
+STARTCHAR 004A
+ENCODING 74
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 48 76 2 -1
+BITMAP
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+000000003FFF
+01FC00003FFF
+FFFC00003FFF
+FFFC00003FFF
+FFFC00003FFF
+FFFC00003FFF
+FFFE00007FFF
+FFFE00007FFE
+7FFE00007FFE
+7FFF00007FFE
+7FFF0000FFFE
+7FFF8001FFFE
+7FFFC003FFFC
+3FFFF80FFFFC
+3FFFFFFFFFFC
+1FFFFFFFFFF8
+1FFFFFFFFFF8
+0FFFFFFFFFF0
+0FFFFFFFFFE0
+07FFFFFFFFC0
+03FFFFFFFF80
+01FFFFFFFF00
+00FFFFFFFE00
+007FFFFFFC00
+001FFFFFF000
+0003FFFF8000
+00007FF80000
+ENDCHAR
+STARTCHAR 004B
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 75 0
+BBX 66 75 8 0
+BITMAP
+FFFC00000003FFFF80
+FFFC00000007FFFF00
+FFFC0000000FFFFE00
+FFFC0000001FFFFC00
+FFFC0000003FFFF800
+FFFC0000007FFFF000
+FFFC000000FFFFE000
+FFFC000001FFFFC000
+FFFC000003FFFF8000
+FFFC000007FFFF0000
+FFFC00000FFFFE0000
+FFFC00001FFFFC0000
+FFFC00003FFFF80000
+FFFC00003FFFF00000
+FFFC00007FFFE00000
+FFFC0000FFFFC00000
+FFFC0001FFFF800000
+FFFC0003FFFF000000
+FFFC0007FFFE000000
+FFFC000FFFFC000000
+FFFC001FFFF8000000
+FFFC003FFFF0000000
+FFFC007FFFE0000000
+FFFC00FFFFC0000000
+FFFC01FFFF80000000
+FFFC03FFFF80000000
+FFFC07FFFF00000000
+FFFC0FFFFE00000000
+FFFC1FFFFC00000000
+FFFC1FFFF800000000
+FFFC3FFFFC00000000
+FFFC7FFFFE00000000
+FFFCFFFFFE00000000
+FFFDFFFFFF00000000
+FFFFFFFFFF80000000
+FFFFFFFFFF80000000
+FFFFFFFFFFC0000000
+FFFFFFFFFFC0000000
+FFFFFFFFFFE0000000
+FFFFFFFFFFF0000000
+FFFFFFFFFFF0000000
+FFFFFFBFFFF8000000
+FFFFFF1FFFFC000000
+FFFFFE1FFFFC000000
+FFFFFC0FFFFE000000
+FFFFF807FFFF000000
+FFFFF007FFFF000000
+FFFFE003FFFF800000
+FFFFC003FFFFC00000
+FFFF8001FFFFC00000
+FFFF0000FFFFE00000
+FFFE0000FFFFE00000
+FFFC00007FFFF00000
+FFFC00007FFFF80000
+FFFC00003FFFF80000
+FFFC00001FFFFC0000
+FFFC00001FFFFE0000
+FFFC00000FFFFE0000
+FFFC00000FFFFF0000
+FFFC000007FFFF8000
+FFFC000003FFFF8000
+FFFC000003FFFFC000
+FFFC000001FFFFC000
+FFFC000000FFFFE000
+FFFC000000FFFFF000
+FFFC0000007FFFF000
+FFFC0000007FFFF800
+FFFC0000003FFFFC00
+FFFC0000001FFFFC00
+FFFC0000001FFFFE00
+FFFC0000000FFFFF00
+FFFC0000000FFFFF00
+FFFC00000007FFFF80
+FFFC00000003FFFFC0
+FFFC00000003FFFFC0
+ENDCHAR
+STARTCHAR 004C
+ENCODING 76
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 53 75 8 0
+BITMAP
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+ENDCHAR
+STARTCHAR 004D
+ENCODING 77
+SWIDTH 835 0
+DWIDTH 87 0
+BBX 73 75 7 0
+BITMAP
+FFFFFF0000007FFFFF80
+FFFFFF0000007FFFFF80
+FFFFFF800000FFFFFF80
+FFFFFF800000FFFFFF80
+FFFFFF800000FFFFFF80
+FFFFFF800000FFFFFF80
+FFFFFFC00001FFFFFF80
+FFFFFFC00001FFFFFF80
+FFFFFFC00001FFFFFF80
+FFFFFFC00001FFFFFF80
+FFFFFFE00003FFFFFF80
+FFFFFFE00003FFFFFF80
+FFFFFFE00003FFFFFF80
+FFFFFFE00003FFFFFF80
+FFFFFFF00007FFFFFF80
+FFFFFFF00007FFFFFF80
+FFFFFFF00007FFDFFF80
+FFFFFFF00007FFDFFF80
+FFFDFFF8000FFFDFFF80
+FFFDFFF8000FFFDFFF80
+FFFCFFF8000FFF9FFF80
+FFFCFFF8000FFF9FFF80
+FFFCFFFC001FFF9FFF80
+FFFCFFFC001FFF9FFF80
+FFFC7FFC001FFF9FFF80
+FFFC7FFC001FFF1FFF80
+FFFC7FFE003FFF1FFF80
+FFFC7FFE003FFF1FFF80
+FFFC7FFE003FFF1FFF80
+FFFC3FFE003FFE1FFF80
+FFFC3FFE003FFE1FFF80
+FFFC3FFF007FFE1FFF80
+FFFC3FFF007FFE1FFF80
+FFFC1FFF007FFC1FFF80
+FFFC1FFF007FFC1FFF80
+FFFC1FFF80FFFC1FFF80
+FFFC1FFF80FFFC1FFF80
+FFFC0FFF80FFF81FFF80
+FFFC0FFF80FFF81FFF80
+FFFC0FFFC1FFF81FFF80
+FFFC0FFFC1FFF81FFF80
+FFFC0FFFC1FFF81FFF80
+FFFC07FFC1FFF01FFF80
+FFFC07FFE3FFF01FFF80
+FFFC07FFE3FFF01FFF80
+FFFC07FFE3FFF01FFF80
+FFFC03FFE3FFE01FFF80
+FFFC03FFF7FFE01FFF80
+FFFC03FFF7FFE01FFF80
+FFFC03FFF7FFE01FFF80
+FFFC01FFF7FFC01FFF80
+FFFC01FFFFFFC01FFF80
+FFFC01FFFFFFC01FFF80
+FFFC01FFFFFFC01FFF80
+FFFC00FFFFFF801FFF80
+FFFC00FFFFFF801FFF80
+FFFC00FFFFFF801FFF80
+FFFC00FFFFFF801FFF80
+FFFC00FFFFFF801FFF80
+FFFC007FFFFF001FFF80
+FFFC007FFFFF001FFF80
+FFFC007FFFFF001FFF80
+FFFC007FFFFF001FFF80
+FFFC003FFFFE001FFF80
+FFFC003FFFFE001FFF80
+FFFC003FFFFE001FFF80
+FFFC003FFFFE001FFF80
+FFFC001FFFFC001FFF80
+FFFC001FFFFC001FFF80
+FFFC001FFFFC001FFF80
+FFFC001FFFFC001FFF80
+FFFC000FFFF8001FFF80
+FFFC000FFFF8001FFF80
+FFFC000FFFF8001FFF80
+FFFC000FFFF8001FFF80
+ENDCHAR
+STARTCHAR 004E
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 75 0
+BBX 59 75 8 0
+BITMAP
+FFFE00000007FFE0
+FFFF00000007FFE0
+FFFF00000007FFE0
+FFFF80000007FFE0
+FFFF80000007FFE0
+FFFFC0000007FFE0
+FFFFE0000007FFE0
+FFFFE0000007FFE0
+FFFFF0000007FFE0
+FFFFF0000007FFE0
+FFFFF8000007FFE0
+FFFFFC000007FFE0
+FFFFFC000007FFE0
+FFFFFE000007FFE0
+FFFFFE000007FFE0
+FFFFFF000007FFE0
+FFFFFF800007FFE0
+FFFFFF800007FFE0
+FFFFFFC00007FFE0
+FFFFFFC00007FFE0
+FFFFFFE00007FFE0
+FFFFFFF00007FFE0
+FFFFFFF00007FFE0
+FFFFFFF80007FFE0
+FFFFFFF80007FFE0
+FFFFFFFC0007FFE0
+FFFDFFFE0007FFE0
+FFFDFFFE0007FFE0
+FFFCFFFF0007FFE0
+FFFCFFFF0007FFE0
+FFFC7FFF8007FFE0
+FFFC3FFFC007FFE0
+FFFC3FFFC007FFE0
+FFFC1FFFE007FFE0
+FFFC1FFFE007FFE0
+FFFC0FFFF007FFE0
+FFFC07FFF807FFE0
+FFFC07FFF807FFE0
+FFFC03FFFC07FFE0
+FFFC03FFFE07FFE0
+FFFC01FFFE07FFE0
+FFFC00FFFF07FFE0
+FFFC00FFFF07FFE0
+FFFC007FFF87FFE0
+FFFC007FFFC7FFE0
+FFFC003FFFC7FFE0
+FFFC001FFFE7FFE0
+FFFC001FFFE7FFE0
+FFFC000FFFF7FFE0
+FFFC000FFFFFFFE0
+FFFC0007FFFFFFE0
+FFFC0003FFFFFFE0
+FFFC0003FFFFFFE0
+FFFC0001FFFFFFE0
+FFFC0000FFFFFFE0
+FFFC0000FFFFFFE0
+FFFC00007FFFFFE0
+FFFC00007FFFFFE0
+FFFC00003FFFFFE0
+FFFC00001FFFFFE0
+FFFC00001FFFFFE0
+FFFC00000FFFFFE0
+FFFC00000FFFFFE0
+FFFC000007FFFFE0
+FFFC000003FFFFE0
+FFFC000003FFFFE0
+FFFC000001FFFFE0
+FFFC000001FFFFE0
+FFFC000000FFFFE0
+FFFC0000007FFFE0
+FFFC0000007FFFE0
+FFFC0000003FFFE0
+FFFC0000003FFFE0
+FFFC0000001FFFE0
+FFFC0000000FFFE0
+ENDCHAR
+STARTCHAR 004F
+ENCODING 79
+SWIDTH 777 0
+DWIDTH 81 0
+BBX 71 77 5 -1
+BITMAP
+0000000FFFC0000000
+000000FFFFFE000000
+000007FFFFFFC00000
+00003FFFFFFFF00000
+00007FFFFFFFFC0000
+0001FFFFFFFFFF0000
+0003FFFFFFFFFF8000
+000FFFFFFFFFFFC000
+001FFFFFFFFFFFE000
+003FFFFFFFFFFFF800
+007FFFFFFFFFFFFC00
+007FFFFFFFFFFFFC00
+00FFFFFFFFFFFFFE00
+01FFFFFE007FFFFF00
+03FFFFE0000FFFFF80
+03FFFF800003FFFF80
+07FFFE000000FFFFC0
+0FFFFC0000007FFFC0
+0FFFF80000003FFFE0
+1FFFF00000001FFFE0
+1FFFE00000000FFFF0
+1FFFC000000007FFF0
+3FFFC000000007FFF8
+3FFF8000000003FFF8
+3FFF8000000001FFF8
+7FFF0000000001FFF8
+7FFF0000000001FFFC
+7FFE0000000000FFFC
+7FFE0000000000FFFC
+7FFE0000000000FFFC
+7FFE0000000000FFFC
+FFFE0000000000FFFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFC00000000007FFE
+FFFE0000000000FFFE
+FFFE0000000000FFFC
+7FFE0000000000FFFC
+7FFE0000000000FFFC
+7FFF0000000001FFFC
+7FFF0000000001FFFC
+7FFF0000000001FFFC
+3FFF8000000003FFF8
+3FFF8000000003FFF8
+3FFFC000000007FFF8
+1FFFC000000007FFF0
+1FFFE00000000FFFF0
+1FFFF00000001FFFE0
+0FFFF80000003FFFE0
+0FFFFC0000007FFFE0
+07FFFF000000FFFFC0
+07FFFF800003FFFF80
+03FFFFE0000FFFFF80
+01FFFFFE007FFFFF00
+00FFFFFFFFFFFFFE00
+00FFFFFFFFFFFFFE00
+007FFFFFFFFFFFFC00
+003FFFFFFFFFFFF800
+001FFFFFFFFFFFF000
+000FFFFFFFFFFFE000
+0003FFFFFFFFFF8000
+0001FFFFFFFFFF0000
+00007FFFFFFFFC0000
+00001FFFFFFFF00000
+000007FFFFFFC00000
+000000FFFFFE000000
+00000007FFC0000000
+ENDCHAR
+STARTCHAR 0050
+ENCODING 80
+SWIDTH 662 0
+DWIDTH 69 0
+BBX 56 75 8 0
+BITMAP
+FFFFFFFFF80000
+FFFFFFFFFFC000
+FFFFFFFFFFF800
+FFFFFFFFFFFC00
+FFFFFFFFFFFF00
+FFFFFFFFFFFF80
+FFFFFFFFFFFFC0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFC00007FFFFC
+FFFC00000FFFFE
+FFFC000003FFFE
+FFFC000001FFFE
+FFFC000000FFFE
+FFFC0000007FFF
+FFFC0000007FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000007FFF
+FFFC0000007FFF
+FFFC000000FFFE
+FFFC000001FFFE
+FFFC000003FFFE
+FFFC00000FFFFE
+FFFC0000FFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF8
+FFFFFFFFFFFFF0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFC0
+FFFFFFFFFFFF80
+FFFFFFFFFFFF00
+FFFFFFFFFFFE00
+FFFFFFFFFFF800
+FFFFFFFFFFE000
+FFFFFFFFFF8000
+FFFFFFFFE00000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+ENDCHAR
+STARTCHAR 0051
+ENCODING 81
+SWIDTH 777 0
+DWIDTH 81 0
+BBX 74 83 5 -7
+BITMAP
+00000007FFC000000000
+000000FFFFFE00000000
+000007FFFFFFC0000000
+00001FFFFFFFF0000000
+00007FFFFFFFFC000000
+0001FFFFFFFFFF000000
+0003FFFFFFFFFF800000
+000FFFFFFFFFFFE00000
+001FFFFFFFFFFFF00000
+003FFFFFFFFFFFF80000
+007FFFFFFFFFFFFC0000
+00FFFFFFFFFFFFFE0000
+00FFFFFFFFFFFFFE0000
+01FFFFFE007FFFFF0000
+03FFFFE0000FFFFF8000
+03FFFF800003FFFFC000
+07FFFE000000FFFFC000
+0FFFFC0000007FFFE000
+0FFFF80000003FFFE000
+1FFFF00000001FFFF000
+1FFFE00000000FFFF000
+1FFFC000000007FFF000
+3FFFC000000007FFF800
+3FFF8000000003FFF800
+3FFF8000000003FFF800
+7FFF0000000001FFFC00
+7FFF0000000001FFFC00
+7FFE0000000000FFFC00
+7FFE0000000000FFFC00
+7FFE0000000000FFFC00
+FFFE0000000000FFFC00
+FFFC0000000000FFFE00
+FFFC00000000007FFE00
+FFFC00000000007FFE00
+FFFC00000000007FFE00
+FFFC00000000007FFE00
+FFFC00000000007FFE00
+FFFC00000000007FFE00
+FFFC00000000007FFE00
+FFFC00000000007FFE00
+FFFC00000000007FFE00
+FFFC00000000007FFE00
+FFFC00000000007FFE00
+FFFC00000000007FFE00
+FFFC0000000000FFFE00
+FFFE0000000000FFFE00
+7FFE0000000000FFFC00
+7FFE0000000000FFFC00
+7FFE0000000000FFFC00
+7FFE0000000001FFFC00
+7FFF00000C0001FFFC00
+7FFF00001F0003FFF800
+3FFF80001FC003FFF800
+3FFF80001FF007FFF800
+3FFFC0003FFC07FFF800
+1FFFC0003FFE0FFFF000
+1FFFE0007FFF9FFFF000
+1FFFF0007FFFFFFFE000
+0FFFF800FFFFFFFFE000
+0FFFFC007FFFFFFFC000
+07FFFE000FFFFFFFC000
+07FFFF8003FFFFFF8000
+03FFFFE000FFFFFF8000
+01FFFFFC01FFFFFF0000
+01FFFFFFFFFFFFFE0000
+00FFFFFFFFFFFFFC0000
+007FFFFFFFFFFFFE0000
+003FFFFFFFFFFFFF8000
+001FFFFFFFFFFFFFC000
+000FFFFFFFFFFFFFF000
+0003FFFFFFFFFFFFFC00
+0001FFFFFFFFFFFFFF80
+00007FFFFFFFFFFFFFC0
+00001FFFFFFFFFFFFF80
+000007FFFFFFC7FFFF80
+000000FFFFFE01FFFF00
+00000007FFE000FFFF00
+000000000000003FFE00
+000000000000001FFE00
+0000000000000007FC00
+0000000000000003FC00
+0000000000000000F800
+00000000000000001800
+ENDCHAR
+STARTCHAR 0052
+ENCODING 82
+SWIDTH 720 0
+DWIDTH 75 0
+BBX 66 75 8 0
+BITMAP
+FFFFFFFFFF80000000
+FFFFFFFFFFFE000000
+FFFFFFFFFFFF800000
+FFFFFFFFFFFFE00000
+FFFFFFFFFFFFF80000
+FFFFFFFFFFFFFC0000
+FFFFFFFFFFFFFE0000
+FFFFFFFFFFFFFF0000
+FFFFFFFFFFFFFF0000
+FFFFFFFFFFFFFF8000
+FFFFFFFFFFFFFF8000
+FFFFFFFFFFFFFFC000
+FFFFFFFFFFFFFFC000
+FFFC000001FFFFE000
+FFFC0000003FFFE000
+FFFC0000001FFFE000
+FFFC0000000FFFF000
+FFFC00000007FFF000
+FFFC00000007FFF000
+FFFC00000003FFF000
+FFFC00000003FFF000
+FFFC00000003FFF000
+FFFC00000003FFF000
+FFFC00000003FFF000
+FFFC00000003FFF000
+FFFC00000007FFF000
+FFFC00000007FFE000
+FFFC0000000FFFE000
+FFFC0000001FFFE000
+FFFC0000003FFFE000
+FFFC000003FFFFC000
+FFFFFFFFFFFFFFC000
+FFFFFFFFFFFFFF8000
+FFFFFFFFFFFFFF8000
+FFFFFFFFFFFFFF0000
+FFFFFFFFFFFFFE0000
+FFFFFFFFFFFFFC0000
+FFFFFFFFFFFFF80000
+FFFFFFFFFFFFF00000
+FFFFFFFFFFFFC00000
+FFFFFFFFFFFF000000
+FFFFFFFFFFF0000000
+FFFFFFFFFFC0000000
+FFFFFFFFFFF0000000
+FFFC00FFFFF8000000
+FFFC001FFFFC000000
+FFFC0007FFFE000000
+FFFC0003FFFF000000
+FFFC0001FFFF800000
+FFFC0000FFFFC00000
+FFFC00007FFFE00000
+FFFC00003FFFE00000
+FFFC00001FFFF00000
+FFFC00001FFFF80000
+FFFC00000FFFF80000
+FFFC000007FFFC0000
+FFFC000003FFFE0000
+FFFC000001FFFE0000
+FFFC000001FFFF0000
+FFFC000000FFFF0000
+FFFC0000007FFF8000
+FFFC0000007FFFC000
+FFFC0000003FFFC000
+FFFC0000003FFFE000
+FFFC0000001FFFE000
+FFFC0000000FFFF000
+FFFC0000000FFFF800
+FFFC00000007FFF800
+FFFC00000003FFFC00
+FFFC00000003FFFE00
+FFFC00000001FFFE00
+FFFC00000001FFFF00
+FFFC00000000FFFF00
+FFFC000000007FFF80
+FFFC000000007FFFC0
+ENDCHAR
+STARTCHAR 0053
+ENCODING 83
+SWIDTH 662 0
+DWIDTH 69 0
+BBX 60 77 4 -1
+BITMAP
+000001FFF0000000
+00003FFFFF800000
+0001FFFFFFF00000
+0007FFFFFFFC0000
+000FFFFFFFFE0000
+003FFFFFFFFF8000
+007FFFFFFFFFC000
+00FFFFFFFFFFE000
+01FFFFFFFFFFF000
+01FFFFFFFFFFF800
+03FFFFFFFFFFF800
+07FFFFFFFFFFFC00
+07FFFFFFFFFFFC00
+0FFFFF803FFFFE00
+0FFFF80007FFFE00
+0FFFF00001FFFF00
+1FFFE00000FFFF00
+1FFFC000007FFF00
+1FFF8000007FFF00
+1FFF8000003FFF80
+1FFF8000003FFF80
+1FFF8000003FFF80
+1FFF8000001FFF80
+1FFFC000001FC000
+1FFFE00000000000
+1FFFF00000000000
+0FFFFC0000000000
+0FFFFF0000000000
+0FFFFFE000000000
+07FFFFFE00000000
+07FFFFFFE0000000
+03FFFFFFFE000000
+01FFFFFFFFE00000
+01FFFFFFFFF80000
+00FFFFFFFFFF0000
+007FFFFFFFFFC000
+003FFFFFFFFFE000
+000FFFFFFFFFF800
+0007FFFFFFFFFC00
+0001FFFFFFFFFE00
+00003FFFFFFFFF00
+000007FFFFFFFF00
+000000FFFFFFFF80
+0000000FFFFFFFC0
+00000000FFFFFFC0
+000000000FFFFFC0
+0000000001FFFFE0
+00000000003FFFE0
+00000000001FFFE0
+00000000000FFFF0
+01FC00000007FFF0
+FFFC00000003FFF0
+FFFE00000003FFF0
+FFFE00000003FFF0
+7FFE00000003FFF0
+7FFF00000003FFF0
+7FFF00000003FFF0
+7FFF80000007FFF0
+3FFF80000007FFF0
+3FFFC000000FFFE0
+3FFFE000001FFFE0
+1FFFF800007FFFE0
+1FFFFE0000FFFFC0
+0FFFFFC00FFFFFC0
+0FFFFFFFFFFFFF80
+07FFFFFFFFFFFF80
+07FFFFFFFFFFFF00
+03FFFFFFFFFFFF00
+01FFFFFFFFFFFE00
+00FFFFFFFFFFFC00
+007FFFFFFFFFF800
+003FFFFFFFFFE000
+000FFFFFFFFFC000
+0003FFFFFFFF0000
+0000FFFFFFFC0000
+00001FFFFFE00000
+000001FFFC000000
+ENDCHAR
+STARTCHAR 0054
+ENCODING 84
+SWIDTH 604 0
+DWIDTH 63 0
+BBX 58 75 3 0
+BITMAP
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+FFFFFFFFFFFFFFC0
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+000003FFF0000000
+ENDCHAR
+STARTCHAR 0055
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 75 0
+BBX 59 76 8 -1
+BITMAP
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC00000007FFE0
+FFFC0000000FFFE0
+7FFE0000000FFFC0
+7FFE0000000FFFC0
+7FFE0000000FFFC0
+7FFF0000001FFFC0
+7FFF8000001FFFC0
+7FFF8000003FFFC0
+3FFFC000007FFF80
+3FFFF00000FFFF80
+3FFFFC0003FFFF80
+1FFFFF801FFFFF00
+1FFFFFFFFFFFFF00
+0FFFFFFFFFFFFE00
+0FFFFFFFFFFFFE00
+07FFFFFFFFFFFC00
+03FFFFFFFFFFF800
+01FFFFFFFFFFF800
+00FFFFFFFFFFF000
+007FFFFFFFFFC000
+001FFFFFFFFF8000
+000FFFFFFFFE0000
+0003FFFFFFF80000
+00007FFFFFC00000
+000003FFFC000000
+ENDCHAR
+STARTCHAR 0056
+ENCODING 86
+SWIDTH 662 0
+DWIDTH 69 0
+BBX 69 75 0 0
+BITMAP
+FFFE0000000003FFF8
+7FFE0000000003FFF0
+7FFF0000000007FFF0
+7FFF0000000007FFF0
+3FFF0000000007FFE0
+3FFF800000000FFFE0
+3FFF800000000FFFE0
+1FFF800000000FFFC0
+1FFFC00000001FFFC0
+1FFFC00000001FFFC0
+0FFFC00000003FFF80
+0FFFE00000003FFF80
+07FFE00000003FFF00
+07FFF00000007FFF00
+07FFF00000007FFF00
+03FFF00000007FFE00
+03FFF8000000FFFE00
+03FFF8000000FFFE00
+01FFF8000000FFFC00
+01FFFC000001FFFC00
+01FFFC000001FFFC00
+00FFFC000001FFF800
+00FFFE000003FFF800
+007FFE000003FFF000
+007FFE000003FFF000
+007FFF000007FFF000
+003FFF000007FFE000
+003FFF000007FFE000
+003FFF80000FFFE000
+001FFF80000FFFC000
+001FFFC0001FFFC000
+000FFFC0001FFF8000
+000FFFC0001FFF8000
+000FFFE0003FFF8000
+0007FFE0003FFF0000
+0007FFE0003FFF0000
+0007FFF0007FFF0000
+0003FFF0007FFE0000
+0003FFF0007FFE0000
+0003FFF800FFFE0000
+0001FFF800FFFC0000
+0001FFF800FFFC0000
+0000FFFC01FFF80000
+0000FFFC01FFF80000
+0000FFFC01FFF80000
+00007FFE03FFF00000
+00007FFE03FFF00000
+00007FFF07FFF00000
+00003FFF07FFE00000
+00003FFF07FFE00000
+00003FFF8FFFE00000
+00001FFF8FFFC00000
+00001FFF8FFFC00000
+00000FFFDFFF800000
+00000FFFDFFF800000
+00000FFFDFFF800000
+000007FFFFFF000000
+000007FFFFFF000000
+000007FFFFFF000000
+000003FFFFFE000000
+000003FFFFFE000000
+000001FFFFFE000000
+000001FFFFFC000000
+000001FFFFFC000000
+000000FFFFF8000000
+000000FFFFF8000000
+000000FFFFF8000000
+0000007FFFF0000000
+0000007FFFF0000000
+0000007FFFF0000000
+0000003FFFE0000000
+0000003FFFE0000000
+0000001FFFC0000000
+0000001FFFC0000000
+0000001FFFC0000000
+ENDCHAR
+STARTCHAR 0057
+ENCODING 87
+SWIDTH 950 0
+DWIDTH 99 0
+BBX 99 75 0 0
+BITMAP
+FFFC000000FFFFE000000FFFE0
+FFFE000000FFFFE000000FFFE0
+7FFE000000FFFFE000000FFFC0
+7FFE000001FFFFF000000FFFC0
+7FFE000001FFFFF000000FFFC0
+7FFF000001FFFFF000001FFFC0
+3FFF000003FFFFF800001FFF80
+3FFF000003FFFFF800001FFF80
+3FFF000003FFFFF800001FFF80
+3FFF800003FFFFF800003FFF80
+1FFF800007FFFFFC00003FFF00
+1FFF800007FFFFFC00003FFF00
+1FFF800007FFFFFC00003FFF00
+1FFFC00007FFFFFC00007FFF00
+0FFFC0000FFFFFFE00007FFE00
+0FFFC0000FFFFFFE00007FFE00
+0FFFC0000FFFFFFE00007FFE00
+0FFFC0000FFFFFFE00007FFE00
+07FFE0001FFFFFFF0000FFFC00
+07FFE0001FFFBFFF0000FFFC00
+07FFE0001FFFBFFF0000FFFC00
+07FFE0003FFFBFFF0000FFFC00
+03FFF0003FFFBFFF8001FFFC00
+03FFF0003FFF1FFF8001FFF800
+03FFF0003FFF1FFF8001FFF800
+03FFF0007FFF1FFF8001FFF800
+01FFF8007FFF1FFFC003FFF800
+01FFF8007FFE0FFFC003FFF000
+01FFF8007FFE0FFFC003FFF000
+01FFF800FFFE0FFFE003FFF000
+00FFFC00FFFC07FFE003FFF000
+00FFFC00FFFC07FFE007FFE000
+00FFFC00FFFC07FFE007FFE000
+00FFFC01FFFC07FFF007FFE000
+007FFC01FFF803FFF007FFE000
+007FFE01FFF803FFF00FFFC000
+007FFE03FFF803FFF00FFFC000
+007FFE03FFF803FFF80FFFC000
+003FFE03FFF001FFF80FFFC000
+003FFF03FFF001FFF81FFF8000
+003FFF07FFF001FFF81FFF8000
+003FFF07FFF001FFFC1FFF8000
+001FFF07FFE000FFFC1FFF8000
+001FFF87FFE000FFFC1FFF0000
+001FFF8FFFE000FFFC3FFF0000
+001FFF8FFFC000FFFE3FFF0000
+000FFF8FFFC0007FFE3FFF0000
+000FFFCFFFC0007FFE3FFE0000
+000FFFDFFFC0007FFE7FFE0000
+000FFFDFFF80003FFF7FFE0000
+0007FFDFFF80003FFF7FFE0000
+0007FFFFFF80003FFF7FFC0000
+0007FFFFFF80003FFFFFFC0000
+0007FFFFFF00001FFFFFFC0000
+0003FFFFFF00001FFFFFFC0000
+0003FFFFFF00001FFFFFF80000
+0003FFFFFF00001FFFFFF80000
+0003FFFFFE00000FFFFFF80000
+0001FFFFFE00000FFFFFF80000
+0001FFFFFE00000FFFFFF00000
+0001FFFFFC00000FFFFFF00000
+0001FFFFFC000007FFFFF00000
+0000FFFFFC000007FFFFF00000
+0000FFFFFC000007FFFFE00000
+0000FFFFF8000007FFFFE00000
+0000FFFFF8000003FFFFE00000
+00007FFFF8000003FFFFE00000
+00007FFFF8000003FFFFC00000
+00007FFFF0000003FFFFC00000
+00007FFFF0000001FFFFC00000
+00003FFFF0000001FFFFC00000
+00003FFFF0000001FFFF800000
+00003FFFE0000000FFFF800000
+00003FFFE0000000FFFF800000
+00001FFFE0000000FFFF800000
+ENDCHAR
+STARTCHAR 0058
+ENCODING 88
+SWIDTH 662 0
+DWIDTH 69 0
+BBX 67 75 1 0
+BITMAP
+1FFFE0000000FFFF00
+1FFFF0000001FFFF00
+0FFFF0000001FFFE00
+07FFF8000003FFFC00
+07FFFC000007FFFC00
+03FFFC000007FFF800
+01FFFE00000FFFF000
+01FFFF00001FFFF000
+00FFFF00001FFFE000
+007FFF80003FFFC000
+007FFFC0007FFFC000
+003FFFC0007FFF8000
+001FFFE000FFFF0000
+001FFFF001FFFF0000
+000FFFF001FFFE0000
+0007FFF803FFFC0000
+0007FFFC07FFFC0000
+0003FFFC07FFF80000
+0001FFFE0FFFF80000
+0001FFFE1FFFF00000
+0000FFFF1FFFE00000
+0000FFFFBFFFE00000
+00007FFFBFFFC00000
+00003FFFFFFF800000
+00003FFFFFFF800000
+00001FFFFFFF000000
+00000FFFFFFE000000
+00000FFFFFFE000000
+000007FFFFFC000000
+000003FFFFF8000000
+000003FFFFF8000000
+000001FFFFF0000000
+000000FFFFE0000000
+000000FFFFE0000000
+0000007FFFC0000000
+0000007FFFC0000000
+000000FFFFE0000000
+000000FFFFE0000000
+000001FFFFF0000000
+000001FFFFF0000000
+000003FFFFF8000000
+000007FFFFFC000000
+000007FFFFFC000000
+00000FFFFFFE000000
+00001FFFFFFF000000
+00001FFFFFFF000000
+00003FFFFFFF800000
+00007FFFFFFFC00000
+00007FFFBFFFC00000
+0000FFFF1FFFE00000
+0001FFFF1FFFF00000
+0001FFFE0FFFF00000
+0003FFFC07FFF80000
+0007FFFC07FFFC0000
+0007FFF803FFFC0000
+000FFFF803FFFE0000
+001FFFF001FFFE0000
+001FFFE000FFFF0000
+003FFFE000FFFF8000
+003FFFC0007FFF8000
+007FFF80003FFFC000
+00FFFF80003FFFE000
+00FFFF00001FFFE000
+01FFFE00000FFFF000
+03FFFE00000FFFF800
+03FFFC000007FFF800
+07FFF8000003FFFC00
+0FFFF8000003FFFE00
+0FFFF0000001FFFE00
+1FFFE0000000FFFF00
+3FFFE0000000FFFF80
+3FFFC00000007FFF80
+7FFF800000003FFFC0
+FFFF800000003FFFE0
+FFFF000000001FFFE0
+ENDCHAR
+STARTCHAR 0059
+ENCODING 89
+SWIDTH 652 0
+DWIDTH 68 0
+BBX 68 75 0 0
+BITMAP
+FFFF000000000FFFF0
+FFFF800000001FFFF0
+7FFF800000001FFFE0
+3FFFC00000003FFFC0
+3FFFC00000007FFFC0
+1FFFE00000007FFF80
+0FFFF0000000FFFF00
+0FFFF0000000FFFF00
+07FFF8000001FFFE00
+03FFF8000001FFFE00
+03FFFC000003FFFC00
+01FFFE000007FFF800
+01FFFE000007FFF800
+00FFFF00000FFFF000
+007FFF00000FFFE000
+007FFF80001FFFE000
+003FFF80001FFFC000
+001FFFC0003FFF8000
+001FFFE0007FFF8000
+000FFFE0007FFF0000
+000FFFF000FFFF0000
+0007FFF000FFFE0000
+0003FFF801FFFC0000
+0003FFF801FFFC0000
+0001FFFC03FFF80000
+0000FFFE07FFF00000
+0000FFFE07FFF00000
+00007FFF0FFFE00000
+00003FFF0FFFE00000
+00003FFF9FFFC00000
+00001FFFBFFF800000
+00001FFFFFFF800000
+00000FFFFFFF000000
+000007FFFFFE000000
+000007FFFFFE000000
+000003FFFFFC000000
+000001FFFFF8000000
+000001FFFFF8000000
+000000FFFFF0000000
+0000007FFFF0000000
+0000007FFFE0000000
+0000003FFFC0000000
+0000003FFFC0000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+0000001FFF80000000
+ENDCHAR
+STARTCHAR 005A
+ENCODING 90
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 61 75 1 0
+BITMAP
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+07FFFFFFFFFFFFF0
+00000000003FFFF0
+00000000007FFFE0
+0000000000FFFFC0
+0000000001FFFF80
+0000000003FFFF00
+0000000007FFFE00
+000000000FFFFC00
+000000000FFFF800
+000000001FFFF800
+000000003FFFF000
+000000007FFFE000
+00000000FFFFC000
+00000001FFFF8000
+00000003FFFF0000
+00000007FFFE0000
+0000000FFFFC0000
+0000000FFFFC0000
+0000001FFFF80000
+0000003FFFF00000
+0000007FFFE00000
+000000FFFFC00000
+000001FFFF800000
+000003FFFF000000
+000007FFFE000000
+000007FFFE000000
+00000FFFFC000000
+00001FFFF8000000
+00003FFFF0000000
+00007FFFE0000000
+0000FFFFC0000000
+0001FFFF80000000
+0003FFFF00000000
+0003FFFF00000000
+0007FFFE00000000
+000FFFFC00000000
+001FFFF800000000
+003FFFF000000000
+007FFFE000000000
+00FFFFC000000000
+01FFFF8000000000
+01FFFF0000000000
+03FFFF0000000000
+07FFFE0000000000
+0FFFFC0000000000
+1FFFF80000000000
+3FFFF00000000000
+7FFFE00000000000
+FFFFC00000000000
+FFFF800000000000
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+FFFFFFFFFFFFFFF8
+ENDCHAR
+STARTCHAR 005B
+ENCODING 91
+SWIDTH 336 0
+DWIDTH 35 0
+BBX 27 96 8 -21
+BITMAP
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFC0000
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+ENDCHAR
+STARTCHAR 005C
+ENCODING 92
+SWIDTH 278 0
+DWIDTH 29 0
+BBX 29 75 0 0
+BITMAP
+FFE00000
+FFE00000
+FFF00000
+7FF00000
+7FF00000
+7FF00000
+7FF80000
+7FF80000
+3FF80000
+3FF80000
+3FFC0000
+3FFC0000
+1FFC0000
+1FFC0000
+1FFC0000
+1FFE0000
+0FFE0000
+0FFE0000
+0FFE0000
+0FFF0000
+07FF0000
+07FF0000
+07FF0000
+07FF8000
+03FF8000
+03FF8000
+03FF8000
+03FFC000
+01FFC000
+01FFC000
+01FFC000
+01FFE000
+01FFE000
+00FFE000
+00FFE000
+00FFF000
+00FFF000
+007FF000
+007FF000
+007FF000
+007FF800
+003FF800
+003FF800
+003FF800
+003FFC00
+001FFC00
+001FFC00
+001FFC00
+001FFE00
+000FFE00
+000FFE00
+000FFE00
+000FFF00
+0007FF00
+0007FF00
+0007FF00
+0007FF80
+0007FF80
+0003FF80
+0003FF80
+0003FFC0
+0003FFC0
+0001FFC0
+0001FFC0
+0001FFC0
+0001FFE0
+0000FFE0
+0000FFE0
+0000FFE0
+0000FFF0
+00007FF0
+00007FF0
+00007FF0
+00007FF8
+00003FF8
+ENDCHAR
+STARTCHAR 005D
+ENCODING 93
+SWIDTH 336 0
+DWIDTH 35 0
+BBX 27 96 0 -21
+BITMAP
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+FFFFFFE0
+ENDCHAR
+STARTCHAR 005E
+ENCODING 94
+SWIDTH 585 0
+DWIDTH 61 0
+BBX 48 40 5 36
+BITMAP
+00003FFC0000
+00003FFC0000
+00003FFE0000
+00007FFE0000
+00007FFF0000
+0000FFFF0000
+0000FFFF8000
+0001FFFF8000
+0001FFFFC000
+0003FFFFC000
+0003FFFFE000
+0007FFFFE000
+0007FFFFE000
+000FFFFFF000
+000FFFFFF000
+001FFFFFF800
+001FFFFFF800
+001FFE7FFC00
+003FFE7FFC00
+003FFC3FFE00
+007FFC3FFE00
+007FFC3FFF00
+00FFF81FFF00
+00FFF81FFF00
+01FFF00FFF80
+01FFF00FFF80
+03FFF00FFFC0
+03FFE007FFC0
+07FFE007FFE0
+07FFC003FFE0
+0FFFC003FFF0
+0FFF8001FFF0
+1FFF8001FFF8
+1FFF8001FFF8
+1FFF0000FFF8
+3FFF0000FFFC
+3FFE00007FFC
+7FFE00007FFE
+7FFE00007FFE
+FFFC00003FFF
+ENDCHAR
+STARTCHAR 005F
+ENCODING 95
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 60 9 -1 -21
+BITMAP
+FFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFF0
+ENDCHAR
+STARTCHAR 0060
+ENCODING 96
+SWIDTH 336 0
+DWIDTH 35 0
+BBX 23 15 2 60
+BITMAP
+FFFF00
+7FFF80
+3FFF80
+1FFFC0
+0FFFC0
+07FFE0
+03FFE0
+01FFE0
+00FFF0
+007FF0
+003FF8
+001FF8
+000FFC
+0007FC
+0003FE
+ENDCHAR
+STARTCHAR 0061
+ENCODING 97
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 51 57 3 -1
+BITMAP
+00003FFF000000
+0003FFFFF80000
+000FFFFFFE0000
+003FFFFFFF8000
+007FFFFFFFC000
+00FFFFFFFFE000
+01FFFFFFFFF000
+03FFFFFFFFF800
+07FFFFFFFFF800
+07FFFFFFFFFC00
+0FFFFFFFFFFC00
+0FFFF007FFFC00
+1FFFC001FFFC00
+1FFF8000FFFE00
+3FFF8000FFFE00
+3FFF00007FFE00
+07FF00007FFE00
+000E00007FFE00
+000000007FFE00
+000000007FFE00
+00000000FFFE00
+0000000FFFFE00
+000000FFFFFE00
+00000FFFFFFE00
+0001FFFFFFFE00
+000FFFFFFFFE00
+007FFFFFFFFE00
+01FFFFFFFFFE00
+03FFFFFFFFFE00
+07FFFFFFFFFE00
+0FFFFFFFFFFE00
+1FFFFFFE7FFE00
+3FFFFFE07FFE00
+3FFFFC007FFE00
+7FFFC0007FFE00
+7FFF00007FFE00
+7FFE00007FFE00
+FFFC00007FFE00
+FFFC00007FFE00
+FFFC0000FFFE00
+FFFC0000FFFE00
+FFFC0001FFFE00
+FFFE0001FFFE00
+FFFF0007FFFE00
+FFFF800FFFFE00
+7FFFE07FFFFE00
+7FFFFFFFFFFE00
+7FFFFFFFFFFF00
+3FFFFFFFFFFF00
+3FFFFFFFFFFF00
+1FFFFFFFDFFF00
+0FFFFFFF8FFF80
+07FFFFFF0FFF80
+03FFFFFC0FFFC0
+00FFFFF00FFFC0
+003FFFC007FFE0
+0007FE00000000
+ENDCHAR
+STARTCHAR 0062
+ENCODING 98
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 53 76 7 -1
+BITMAP
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC007FE00000
+FFFC03FFFC0000
+FFFC0FFFFF0000
+FFFC1FFFFFC000
+FFFC7FFFFFE000
+FFFCFFFFFFF800
+FFFDFFFFFFFC00
+FFFFFFFFFFFE00
+FFFFFFFFFFFE00
+FFFFFFFFFFFF00
+FFFFFFFFFFFF80
+FFFFFE03FFFF80
+FFFFF800FFFFC0
+FFFFE0003FFFC0
+FFFFC0001FFFE0
+FFFF80000FFFE0
+FFFF80000FFFE0
+FFFF000007FFF0
+FFFE000007FFF0
+FFFE000003FFF0
+FFFE000003FFF0
+FFFE000003FFF8
+FFFC000003FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFE000001FFF8
+FFFE000003FFF0
+FFFE000003FFF0
+FFFE000003FFF0
+FFFF000007FFF0
+FFFF000007FFF0
+FFFF80000FFFE0
+FFFFC0000FFFE0
+FFFFE0001FFFE0
+FFFFF0003FFFC0
+FFFFF800FFFFC0
+FFFFFF03FFFF80
+FFFFFFFFFFFF80
+FFFFFFFFFFFF00
+FFFFFFFFFFFE00
+FFFDFFFFFFFC00
+FFFCFFFFFFFC00
+FFFC7FFFFFF800
+FFFC3FFFFFE000
+FFFC1FFFFFC000
+FFFC07FFFF8000
+FFFC01FFFC0000
+0000003FE00000
+ENDCHAR
+STARTCHAR 0063
+ENCODING 99
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 50 57 4 -1
+BITMAP
+00000FFF000000
+0000FFFFF00000
+0003FFFFFC0000
+000FFFFFFF0000
+003FFFFFFF8000
+007FFFFFFFC000
+00FFFFFFFFE000
+01FFFFFFFFF000
+03FFFFFFFFF800
+07FFFFFFFFFC00
+07FFFFFFFFFC00
+0FFFFC07FFFE00
+1FFFF001FFFE00
+1FFFC000FFFF00
+3FFF80007FFF00
+3FFF80003FFF80
+3FFF00003FFF80
+7FFF00001FFC00
+7FFE00001E0000
+7FFE0000000000
+7FFE0000000000
+7FFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+7FFE0000000000
+7FFE00000F0000
+7FFE00000FFE00
+7FFE00001FFFC0
+7FFF00001FFFC0
+3FFF00001FFF80
+3FFF80003FFF80
+3FFFC0007FFF80
+1FFFE0007FFF00
+1FFFF001FFFF00
+0FFFFC07FFFE00
+07FFFFFFFFFE00
+07FFFFFFFFFC00
+03FFFFFFFFF800
+01FFFFFFFFF800
+00FFFFFFFFF000
+007FFFFFFFE000
+003FFFFFFF8000
+000FFFFFFF0000
+0003FFFFFC0000
+0000FFFFF00000
+00000FFF000000
+ENDCHAR
+STARTCHAR 0064
+ENCODING 100
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 53 76 4 -1
+BITMAP
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+00003FF001FFF8
+0001FFFE01FFF8
+0007FFFF81FFF8
+001FFFFFC1FFF8
+007FFFFFF1FFF8
+00FFFFFFF9FFF8
+01FFFFFFFDFFF8
+03FFFFFFFFFFF8
+07FFFFFFFFFFF8
+07FFFFFFFFFFF8
+0FFFFFFFFFFFF8
+0FFFFE03FFFFF8
+1FFFF800FFFFF8
+1FFFE0003FFFF8
+3FFFC0001FFFF8
+3FFF80000FFFF8
+7FFF80000FFFF8
+7FFF000007FFF8
+7FFF000007FFF8
+7FFE000003FFF8
+7FFE000003FFF8
+FFFE000003FFF8
+FFFC000003FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+7FFE000003FFF8
+7FFE000003FFF8
+7FFE000003FFF8
+7FFF000007FFF8
+7FFF000007FFF8
+3FFF80000FFFF8
+3FFF80000FFFF8
+3FFFC0001FFFF8
+1FFFE0003FFFF8
+1FFFF800FFFFF8
+0FFFFE03FFFFF8
+0FFFFFFFFFFFF8
+07FFFFFFFFFFF8
+03FFFFFFFFFFF8
+01FFFFFFFDFFF8
+01FFFFFFF9FFF8
+00FFFFFFF1FFF8
+003FFFFFE1FFF8
+001FFFFFC1FFF8
+0007FFFF01FFF8
+0001FFFC01FFF8
+00003FE0000000
+ENDCHAR
+STARTCHAR 0065
+ENCODING 101
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 51 57 3 -1
+BITMAP
+00000FFE000000
+0000FFFFC00000
+0003FFFFF80000
+000FFFFFFE0000
+001FFFFFFF0000
+007FFFFFFFC000
+00FFFFFFFFE000
+01FFFFFFFFF000
+03FFFFFFFFF800
+03FFFFFFFFF800
+07FFFFFFFFFC00
+0FFFFC07FFFE00
+0FFFF001FFFE00
+1FFFE0007FFF00
+1FFF80003FFF00
+3FFF80001FFF80
+3FFF00001FFF80
+3FFE00000FFF80
+7FFE00000FFF80
+7FFE00000FFFC0
+7FFE000007FFC0
+7FFC000007FFC0
+FFFC000007FFC0
+FFFC000007FFC0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFFFFFFFFFFE0
+FFFC0000000000
+FFFC0000000000
+7FFC0000000000
+7FFC0000000000
+7FFE0000000000
+7FFE0000000000
+7FFE00000F0000
+3FFF00001FFE00
+3FFF80001FFFC0
+3FFFC0003FFF80
+1FFFE0007FFF80
+1FFFF000FFFF80
+0FFFFE03FFFF00
+07FFFFFFFFFE00
+07FFFFFFFFFE00
+03FFFFFFFFFC00
+01FFFFFFFFF800
+00FFFFFFFFF000
+007FFFFFFFE000
+003FFFFFFFC000
+000FFFFFFF0000
+0003FFFFFE0000
+0000FFFFF00000
+00000FFF000000
+ENDCHAR
+STARTCHAR 0066
+ENCODING 102
+SWIDTH 336 0
+DWIDTH 35 0
+BBX 35 76 2 0
+BITMAP
+00003FF800
+0001FFFFC0
+0007FFFFE0
+001FFFFFE0
+003FFFFFE0
+007FFFFFC0
+007FFFFFC0
+00FFFFFFC0
+00FFFFFFC0
+00FFFFFFC0
+01FFFFFFC0
+01FFFF00C0
+01FFFC0000
+01FFFC0000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+FFFFFFFE00
+FFFFFFFE00
+FFFFFFFE00
+FFFFFFFE00
+FFFFFFFE00
+FFFFFFFE00
+FFFFFFFE00
+FFFFFFFE00
+FFFFFFFE00
+FFFFFFFE00
+FFFFFFFE00
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+01FFF80000
+ENDCHAR
+STARTCHAR 0067
+ENCODING 103
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 53 78 4 -22
+BITMAP
+00003FE0000000
+0003FFFC01FFF8
+000FFFFF01FFF8
+001FFFFFC1FFF8
+007FFFFFE1FFF8
+00FFFFFFF1FFF8
+01FFFFFFF9FFF8
+03FFFFFFFDFFF8
+07FFFFFFFFFFF8
+07FFFFFFFFFFF8
+0FFFFFFFFFFFF8
+0FFFFE03FFFFF8
+1FFFF800FFFFF8
+1FFFE0003FFFF8
+3FFFC0001FFFF8
+3FFF80000FFFF8
+7FFF80000FFFF8
+7FFF000007FFF8
+7FFF000007FFF8
+7FFE000003FFF8
+7FFE000003FFF8
+FFFE000003FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000003FFF8
+FFFE000003FFF8
+7FFE000003FFF8
+7FFE000003FFF8
+7FFE000007FFF8
+7FFF000007FFF8
+3FFF00000FFFF8
+3FFF80001FFFF8
+3FFFC0001FFFF8
+1FFFE0007FFFF8
+1FFFF000FFFFF8
+0FFFFE07FFFFF8
+0FFFFFFFFFFFF8
+07FFFFFFFFFFF8
+07FFFFFFFDFFF8
+03FFFFFFF9FFF8
+01FFFFFFF1FFF8
+00FFFFFFE1FFF8
+007FFFFFC1FFF8
+003FFFFF81FFF8
+000FFFFE01FFF8
+0003FFF801FFF8
+00007FC001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF0
+3C00000001FFF0
+3FFE000003FFF0
+3FFFE00003FFF0
+3FFFE00007FFF0
+3FFFF0000FFFE0
+3FFFF8001FFFE0
+1FFFFE00FFFFE0
+1FFFFFFFFFFFC0
+0FFFFFFFFFFFC0
+0FFFFFFFFFFF80
+07FFFFFFFFFF00
+03FFFFFFFFFF00
+01FFFFFFFFFE00
+00FFFFFFFFF800
+007FFFFFFFF000
+001FFFFFFFC000
+0003FFFFFE0000
+00001FFFE00000
+ENDCHAR
+STARTCHAR 0068
+ENCODING 104
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 50 75 7 0
+BITMAP
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC001FF00000
+FFFC01FFFE0000
+FFFC07FFFF8000
+FFFC0FFFFFE000
+FFFC3FFFFFF000
+FFFC7FFFFFF800
+FFFCFFFFFFFC00
+FFFDFFFFFFFE00
+FFFFFFFFFFFF00
+FFFFFFFFFFFF00
+FFFFFFFFFFFF00
+FFFFFE03FFFF80
+FFFFF000FFFF80
+FFFFE0007FFF80
+FFFFC0003FFF80
+FFFF80001FFFC0
+FFFF00001FFFC0
+FFFF00001FFFC0
+FFFE00000FFFC0
+FFFE00000FFFC0
+FFFE00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+ENDCHAR
+STARTCHAR 0069
+ENCODING 105
+SWIDTH 278 0
+DWIDTH 29 0
+BBX 14 75 7 0
+BITMAP
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+ENDCHAR
+STARTCHAR 006A
+ENCODING 106
+SWIDTH 278 0
+DWIDTH 29 0
+BBX 27 97 -5 -22
+BITMAP
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+0007FFE0
+000FFFE0
+000FFFE0
+001FFFE0
+007FFFC0
+7FFFFFC0
+7FFFFFC0
+7FFFFFC0
+7FFFFFC0
+7FFFFF80
+7FFFFF80
+7FFFFF00
+FFFFFF00
+FFFFFE00
+FFFFFC00
+FFFFF000
+FFFFE000
+07FE0000
+ENDCHAR
+STARTCHAR 006B
+ENCODING 107
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 49 75 7 0
+BITMAP
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0001FFFF00
+FFFC0003FFFE00
+FFFC0007FFFC00
+FFFC000FFFF800
+FFFC001FFFF000
+FFFC001FFFE000
+FFFC003FFFE000
+FFFC007FFFC000
+FFFC00FFFF8000
+FFFC01FFFF0000
+FFFC03FFFE0000
+FFFC07FFFC0000
+FFFC0FFFF80000
+FFFC1FFFF00000
+FFFC3FFFE00000
+FFFC7FFFC00000
+FFFC7FFF800000
+FFFCFFFF000000
+FFFDFFFE000000
+FFFFFFFE000000
+FFFFFFFC000000
+FFFFFFFE000000
+FFFFFFFE000000
+FFFFFFFF000000
+FFFFFFFF800000
+FFFFFFFF800000
+FFFFFFFFC00000
+FFFFFFFFC00000
+FFFFFFFFE00000
+FFFFFFFFE00000
+FFFFF7FFF00000
+FFFFE3FFF00000
+FFFFE3FFF80000
+FFFFC1FFFC0000
+FFFF81FFFC0000
+FFFF00FFFE0000
+FFFE007FFE0000
+FFFC007FFF0000
+FFFC003FFF0000
+FFFC003FFF8000
+FFFC001FFF8000
+FFFC000FFFC000
+FFFC000FFFE000
+FFFC0007FFE000
+FFFC0007FFF000
+FFFC0003FFF000
+FFFC0003FFF800
+FFFC0001FFF800
+FFFC0000FFFC00
+FFFC0000FFFC00
+FFFC00007FFE00
+FFFC00007FFF00
+FFFC00003FFF00
+FFFC00001FFF80
+FFFC00001FFF80
+ENDCHAR
+STARTCHAR 006C
+ENCODING 108
+SWIDTH 278 0
+DWIDTH 29 0
+BBX 14 75 7 0
+BITMAP
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+FFFC
+ENDCHAR
+STARTCHAR 006D
+ENCODING 109
+SWIDTH 883 0
+DWIDTH 92 0
+BBX 78 56 6 0
+BITMAP
+0000003FC00000FF8000
+FFFC01FFF80007FFF800
+FFFC07FFFE001FFFFE00
+FFFC1FFFFF003FFFFF00
+FFFC3FFFFF80FFFFFF80
+FFFC7FFFFFC1FFFFFFC0
+FFFCFFFFFFE3FFFFFFE0
+FFFDFFFFFFF7FFFFFFE0
+FFFFFFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFFFFFF0
+FFFFFFFFFFFFFFFFFFF8
+FFFFF80FFFFFFC1FFFF8
+FFFFE007FFFFE007FFF8
+FFFFC003FFFFC003FFFC
+FFFF8001FFFF8001FFFC
+FFFF0001FFFF0001FFFC
+FFFF0001FFFF0001FFFC
+FFFE0000FFFE0000FFFC
+FFFE0000FFFE0000FFFC
+FFFE0000FFFE0000FFFC
+FFFE0000FFFE0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+FFFC0000FFFC0000FFFC
+ENDCHAR
+STARTCHAR 006E
+ENCODING 110
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 50 56 7 0
+BITMAP
+0000001FF80000
+FFFC00FFFF0000
+FFFC07FFFFC000
+FFFC0FFFFFF000
+FFFC3FFFFFF800
+FFFC7FFFFFFC00
+FFFCFFFFFFFE00
+FFFDFFFFFFFE00
+FFFFFFFFFFFF00
+FFFFFFFFFFFF00
+FFFFFFFFFFFF80
+FFFFFE03FFFF80
+FFFFF000FFFF80
+FFFFE0007FFF80
+FFFFC0003FFFC0
+FFFF80001FFFC0
+FFFF00001FFFC0
+FFFF00001FFFC0
+FFFE00001FFFC0
+FFFE00000FFFC0
+FFFE00000FFFC0
+FFFE00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+ENDCHAR
+STARTCHAR 006F
+ENCODING 111
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 56 57 4 -1
+BITMAP
+000003FFC00000
+00003FFFFC0000
+0000FFFFFF0000
+0003FFFFFFC000
+000FFFFFFFF000
+003FFFFFFFF800
+007FFFFFFFFC00
+00FFFFFFFFFF00
+01FFFFFFFFFF80
+03FFFFFFFFFF80
+03FFFFFFFFFFC0
+07FFFF00FFFFE0
+0FFFFC003FFFF0
+0FFFF0000FFFF0
+1FFFE00007FFF8
+1FFFC00003FFF8
+3FFF800001FFFC
+3FFF800001FFFC
+7FFF000000FFFC
+7FFF000000FFFE
+7FFE0000007FFE
+7FFE0000007FFE
+FFFE0000007FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+FFFC0000003FFF
+7FFE0000007FFE
+7FFE0000007FFE
+7FFE0000007FFE
+7FFF000000FFFE
+7FFF000000FFFC
+3FFF800001FFFC
+3FFF800001FFFC
+3FFFC00003FFF8
+1FFFE00007FFF8
+1FFFF0000FFFF0
+0FFFFC003FFFF0
+07FFFF00FFFFE0
+07FFFFFFFFFFC0
+03FFFFFFFFFF80
+01FFFFFFFFFF00
+00FFFFFFFFFE00
+007FFFFFFFFC00
+003FFFFFFFF800
+000FFFFFFFF000
+0003FFFFFFC000
+0000FFFFFF0000
+00003FFFFC0000
+000003FFC00000
+ENDCHAR
+STARTCHAR 0070
+ENCODING 112
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 53 77 7 -21
+BITMAP
+0000003FE00000
+FFFC01FFFC0000
+FFFC07FFFF0000
+FFFC1FFFFFC000
+FFFC3FFFFFE000
+FFFC7FFFFFF800
+FFFCFFFFFFFC00
+FFFDFFFFFFFE00
+FFFFFFFFFFFE00
+FFFFFFFFFFFF00
+FFFFFFFFFFFF80
+FFFFFE03FFFF80
+FFFFF800FFFFC0
+FFFFE0003FFFC0
+FFFFC0001FFFE0
+FFFF80000FFFE0
+FFFF80000FFFE0
+FFFF000007FFF0
+FFFF000007FFF0
+FFFE000003FFF0
+FFFE000003FFF0
+FFFE000003FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFE000001FFF8
+FFFE000003FFF0
+FFFE000003FFF0
+FFFE000003FFF0
+FFFF000007FFF0
+FFFF000007FFF0
+FFFF80000FFFE0
+FFFFC0000FFFE0
+FFFFE0001FFFE0
+FFFFF0003FFFC0
+FFFFF8007FFFC0
+FFFFFF03FFFF80
+FFFFFFFFFFFF00
+FFFFFFFFFFFF00
+FFFFFFFFFFFE00
+FFFFFFFFFFFC00
+FFFDFFFFFFF800
+FFFCFFFFFFF000
+FFFC3FFFFFE000
+FFFC1FFFFFC000
+FFFC0FFFFF0000
+FFFC03FFFC0000
+FFFC007FE00000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+FFFC0000000000
+ENDCHAR
+STARTCHAR 0071
+ENCODING 113
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 53 77 4 -21
+BITMAP
+00003FE0000000
+0001FFFE01FFF8
+0007FFFF81FFF8
+001FFFFFC1FFF8
+003FFFFFE1FFF8
+00FFFFFFF1FFF8
+01FFFFFFF9FFF8
+03FFFFFFFDFFF8
+03FFFFFFFFFFF8
+07FFFFFFFFFFF8
+0FFFFFFFFFFFF8
+0FFFFE03FFFFF8
+1FFFF800FFFFF8
+1FFFE0003FFFF8
+3FFFC0001FFFF8
+3FFF80000FFFF8
+3FFF80000FFFF8
+7FFF000007FFF8
+7FFF000007FFF8
+7FFE000003FFF8
+7FFE000003FFF8
+FFFE000003FFF8
+FFFE000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000003FFF8
+7FFE000003FFF8
+7FFE000003FFF8
+7FFE000007FFF8
+7FFE000007FFF8
+7FFF00000FFFF8
+3FFF00000FFFF8
+3FFF80001FFFF8
+1FFFC0003FFFF8
+1FFFE0007FFFF8
+1FFFF000FFFFF8
+0FFFFE07FFFFF8
+07FFFFFFFFFFF8
+07FFFFFFFFFFF8
+03FFFFFFFFFFF8
+01FFFFFFFFFFF8
+00FFFFFFFDFFF8
+007FFFFFF9FFF8
+003FFFFFF1FFF8
+001FFFFFC1FFF8
+0007FFFF81FFF8
+0001FFFE01FFF8
+00003FE001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+0000000001FFF8
+ENDCHAR
+STARTCHAR 0072
+ENCODING 114
+SWIDTH 384 0
+DWIDTH 40 0
+BBX 34 56 7 0
+BITMAP
+000003F800
+FFFC0FFE00
+FFFC1FFF80
+FFFC3FFFC0
+FFFC7FFFC0
+FFFCFFFF80
+FFFDFFFF80
+FFFDFFFF80
+FFFFFFFF80
+FFFFFFFF00
+FFFFFFFF00
+FFFFFFFF00
+FFFFFFFF00
+FFFFFFFE00
+FFFFF81E00
+FFFFE00600
+FFFFC00000
+FFFF800000
+FFFF000000
+FFFF000000
+FFFF000000
+FFFE000000
+FFFE000000
+FFFE000000
+FFFE000000
+FFFE000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+FFFC000000
+ENDCHAR
+STARTCHAR 0073
+ENCODING 115
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 51 57 2 -1
+BITMAP
+00003FFF000000
+0003FFFFF00000
+001FFFFFFE0000
+007FFFFFFF8000
+00FFFFFFFFC000
+01FFFFFFFFE000
+03FFFFFFFFF000
+07FFFFFFFFF800
+0FFFFFFFFFFC00
+0FFFFFFFFFFC00
+1FFFFFFFFFFE00
+1FFFF007FFFE00
+1FFFC001FFFF00
+3FFF80007FFF00
+3FFF00007FFF80
+3FFF00003FFF80
+3FFF00001FFC00
+3FFF80001E0000
+3FFFE000000000
+3FFFF800000000
+3FFFFF80000000
+1FFFFFF8000000
+1FFFFFFF800000
+0FFFFFFFF80000
+0FFFFFFFFF0000
+07FFFFFFFFC000
+03FFFFFFFFF000
+01FFFFFFFFFC00
+00FFFFFFFFFE00
+003FFFFFFFFF00
+000FFFFFFFFF80
+0003FFFFFFFF80
+00007FFFFFFFC0
+000007FFFFFFC0
+0000007FFFFFC0
+00000007FFFFE0
+000000007FFFE0
+000000000FFFE0
+003C000007FFE0
+1FFC000007FFE0
+FFFE000007FFE0
+FFFE000007FFE0
+7FFF00000FFFE0
+7FFF80000FFFC0
+3FFFE0003FFFC0
+3FFFF801FFFFC0
+1FFFFFFFFFFF80
+1FFFFFFFFFFF00
+0FFFFFFFFFFF00
+07FFFFFFFFFE00
+03FFFFFFFFFC00
+01FFFFFFFFF800
+007FFFFFFFF000
+003FFFFFFFC000
+000FFFFFFF0000
+0001FFFFFC0000
+00001FFF800000
+ENDCHAR
+STARTCHAR 0074
+ENCODING 116
+SWIDTH 336 0
+DWIDTH 35 0
+BBX 32 74 2 -1
+BITMAP
+00000800
+00003800
+00007800
+0001F800
+0007F800
+001FF800
+003FF800
+00FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+FFFFFFFE
+FFFFFFFE
+FFFFFFFE
+FFFFFFFE
+FFFFFFFE
+FFFFFFFE
+FFFFFFFE
+FFFFFFFE
+FFFFFFFE
+FFFFFFFE
+FFFFFFFE
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFF800
+01FFFC00
+01FFFE0E
+01FFFFFE
+00FFFFFE
+00FFFFFE
+00FFFFFE
+00FFFFFE
+007FFFFE
+003FFFFF
+001FFFFF
+000FFFFF
+0003FFFE
+0000FFE0
+ENDCHAR
+STARTCHAR 0075
+ENCODING 117
+SWIDTH 614 0
+DWIDTH 64 0
+BBX 50 56 7 -1
+BITMAP
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00000FFFC0
+FFFC00001FFFC0
+FFFC00001FFFC0
+FFFC00001FFFC0
+FFFE00001FFFC0
+FFFE00003FFFC0
+FFFE00007FFFC0
+FFFF0000FFFFC0
+7FFF8001FFFFC0
+7FFFC003FFFFC0
+7FFFF01FFFFFC0
+7FFFFFFFFFFFC0
+3FFFFFFFFFFFC0
+3FFFFFFFFFFFC0
+1FFFFFFFEFFFC0
+1FFFFFFFCFFFC0
+0FFFFFFF8FFFC0
+07FFFFFF0FFFC0
+01FFFFFC0FFFC0
+00FFFFF00FFFC0
+003FFFC00FFFC0
+0007FE00000000
+ENDCHAR
+STARTCHAR 0076
+ENCODING 118
+SWIDTH 537 0
+DWIDTH 56 0
+BBX 53 55 1 0
+BITMAP
+FFFC000001FFF8
+FFFC000001FFF8
+FFFC000001FFF8
+7FFE000003FFF0
+7FFE000003FFF0
+3FFE000007FFE0
+3FFF000007FFE0
+3FFF000007FFE0
+1FFF80000FFFC0
+1FFF80000FFFC0
+0FFF80000FFFC0
+0FFFC0001FFF80
+0FFFC0001FFF80
+07FFC0001FFF00
+07FFE0003FFF00
+07FFE0003FFF00
+03FFE0003FFE00
+03FFF0007FFE00
+01FFF0007FFE00
+01FFF000FFFC00
+01FFF800FFFC00
+00FFF800FFF800
+00FFFC01FFF800
+00FFFC01FFF800
+007FFC01FFF000
+007FFE03FFF000
+003FFE03FFF000
+003FFE03FFE000
+003FFF07FFE000
+001FFF07FFC000
+001FFF07FFC000
+000FFF8FFFC000
+000FFF8FFF8000
+000FFF8FFF8000
+0007FFDFFF8000
+0007FFDFFF0000
+0007FFDFFF0000
+0003FFFFFE0000
+0003FFFFFE0000
+0001FFFFFE0000
+0001FFFFFC0000
+0001FFFFFC0000
+0000FFFFFC0000
+0000FFFFF80000
+0000FFFFF80000
+00007FFFF00000
+00007FFFF00000
+00003FFFF00000
+00003FFFE00000
+00003FFFE00000
+00001FFFE00000
+00001FFFC00000
+00000FFFC00000
+00000FFF800000
+00000FFF800000
+ENDCHAR
+STARTCHAR 0077
+ENCODING 119
+SWIDTH 806 0
+DWIDTH 84 0
+BBX 83 55 0 0
+BITMAP
+FFFC00003FFF800007FFE0
+FFFE00003FFF80000FFFE0
+7FFE00003FFFC0000FFFC0
+7FFE00007FFFC0000FFFC0
+7FFE00007FFFC0000FFFC0
+3FFF00007FFFC0001FFF80
+3FFF00007FFFE0001FFF80
+3FFF0000FFFFE0001FFF80
+1FFF8000FFFFE0003FFF00
+1FFF8000FFFFE0003FFF00
+1FFF8001FFFFF0003FFF00
+0FFF8001FFFFF0003FFE00
+0FFFC001FFFFF0007FFE00
+0FFFC001FFFFF8007FFE00
+07FFC003FFFFF8007FFC00
+07FFE003FFFFF800FFFC00
+07FFE003FFFFF800FFFC00
+03FFE003FFFFFC00FFF800
+03FFE007FFFFFC00FFF800
+03FFF007FFFFFC01FFF800
+01FFF007FFBFFC01FFF800
+01FFF00FFFBFFE01FFF000
+01FFF80FFFBFFE03FFF000
+01FFF80FFF1FFE03FFF000
+00FFF80FFF1FFE03FFE000
+00FFF81FFF1FFF03FFE000
+00FFFC1FFF1FFF07FFE000
+007FFC1FFE0FFF07FFC000
+007FFC1FFE0FFF07FFC000
+007FFE3FFE0FFF8FFFC000
+003FFE3FFE07FF8FFF8000
+003FFE3FFC07FF8FFF8000
+003FFE7FFC07FFCFFF8000
+001FFF7FFC07FFDFFF0000
+001FFF7FF803FFDFFF0000
+001FFF7FF803FFDFFF0000
+000FFFFFF803FFFFFE0000
+000FFFFFF801FFFFFE0000
+000FFFFFF001FFFFFE0000
+0007FFFFF001FFFFFE0000
+0007FFFFF001FFFFFC0000
+0007FFFFF000FFFFFC0000
+0007FFFFE000FFFFFC0000
+0003FFFFE000FFFFF80000
+0003FFFFE000FFFFF80000
+0003FFFFC0007FFFF80000
+0001FFFFC0007FFFF00000
+0001FFFFC0007FFFF00000
+0001FFFFC0003FFFF00000
+0000FFFF80003FFFE00000
+0000FFFF80003FFFE00000
+0000FFFF80003FFFE00000
+00007FFF80001FFFC00000
+00007FFF00001FFFC00000
+00007FFF00001FFFC00000
+ENDCHAR
+STARTCHAR 0078
+ENCODING 120
+SWIDTH 556 0
+DWIDTH 58 0
+BBX 54 55 2 0
+BITMAP
+3FFFC0000FFFF0
+3FFFE0001FFFF0
+1FFFE0003FFFE0
+0FFFF0003FFFC0
+0FFFF8007FFFC0
+07FFF8007FFF80
+03FFFC00FFFF00
+03FFFC01FFFE00
+01FFFE01FFFE00
+00FFFE03FFFC00
+00FFFF07FFF800
+007FFF87FFF800
+007FFF8FFFF000
+003FFFCFFFE000
+001FFFDFFFE000
+001FFFFFFFC000
+000FFFFFFF8000
+0007FFFFFF8000
+0007FFFFFF0000
+0003FFFFFE0000
+0001FFFFFE0000
+0001FFFFFC0000
+0000FFFFF80000
+0000FFFFF80000
+00007FFFF00000
+00003FFFE00000
+00003FFFE00000
+00003FFFF00000
+00007FFFF80000
+00007FFFF80000
+0000FFFFFC0000
+0001FFFFFE0000
+0001FFFFFE0000
+0003FFFFFF0000
+0007FFFFFF8000
+0007FFFFFF8000
+000FFFFFFFC000
+001FFFFFFFE000
+001FFFDFFFE000
+003FFFCFFFF000
+007FFF8FFFF800
+007FFF07FFF800
+00FFFF03FFFC00
+01FFFE03FFFE00
+01FFFE01FFFE00
+03FFFC00FFFF00
+07FFF800FFFF80
+07FFF8007FFF80
+0FFFF0003FFFC0
+1FFFE0003FFFE0
+3FFFE0001FFFE0
+3FFFC0000FFFF0
+7FFFC0000FFFF8
+FFFF800007FFF8
+FFFF000003FFFC
+ENDCHAR
+STARTCHAR 0079
+ENCODING 121
+SWIDTH 528 0
+DWIDTH 55 0
+BBX 53 77 1 -22
+BITMAP
+FFFC000001FFF8
+7FFC000003FFF0
+7FFE000003FFF0
+7FFE000003FFF0
+3FFE000003FFE0
+3FFF000007FFE0
+3FFF000007FFE0
+1FFF000007FFC0
+1FFF80000FFFC0
+1FFF80000FFFC0
+0FFF80000FFF80
+0FFFC0001FFF80
+0FFFC0001FFF80
+07FFC0001FFF00
+07FFE0003FFF00
+07FFE0003FFF00
+03FFE0003FFE00
+03FFF0007FFE00
+01FFF0007FFE00
+01FFF0007FFC00
+01FFF800FFFC00
+00FFF800FFFC00
+00FFF800FFF800
+00FFFC01FFF800
+007FFC01FFF800
+007FFC01FFF000
+007FFE03FFF000
+003FFE03FFE000
+003FFE03FFE000
+003FFE07FFE000
+001FFF07FFC000
+001FFF07FFC000
+001FFF07FFC000
+000FFF8FFF8000
+000FFF8FFF8000
+000FFF8FFF8000
+0007FFDFFF0000
+0007FFDFFF0000
+0003FFDFFF0000
+0003FFFFFE0000
+0003FFFFFE0000
+0001FFFFFE0000
+0001FFFFFC0000
+0001FFFFFC0000
+0000FFFFFC0000
+0000FFFFF80000
+0000FFFFF80000
+00007FFFF80000
+00007FFFF00000
+00007FFFF00000
+00003FFFF00000
+00003FFFE00000
+00003FFFE00000
+00001FFFC00000
+00001FFFC00000
+00001FFFC00000
+00001FFF800000
+00001FFF800000
+00003FFF800000
+00003FFF000000
+00007FFF000000
+00007FFF000000
+0000FFFE000000
+0000FFFE000000
+0001FFFE000000
+0807FFFC000000
+0FFFFFFC000000
+0FFFFFF8000000
+0FFFFFF8000000
+0FFFFFF0000000
+0FFFFFE0000000
+07FFFFE0000000
+07FFFFC0000000
+07FFFF80000000
+07FFFE00000000
+07FFF800000000
+01FFC000000000
+ENDCHAR
+STARTCHAR 007A
+ENCODING 122
+SWIDTH 499 0
+DWIDTH 52 0
+BBX 48 55 2 0
+BITMAP
+3FFFFFFFFFFC
+3FFFFFFFFFFC
+3FFFFFFFFFFC
+3FFFFFFFFFFC
+3FFFFFFFFFFC
+3FFFFFFFFFFC
+3FFFFFFFFFFC
+3FFFFFFFFFFC
+3FFFFFFFFFFC
+3FFFFFFFFFFC
+3FFFFFFFFFFC
+0000000FFFF8
+0000001FFFF0
+0000003FFFE0
+0000007FFFC0
+000000FFFFC0
+000001FFFF80
+000003FFFF00
+000003FFFE00
+000007FFFC00
+00000FFFFC00
+00001FFFF800
+00003FFFF000
+00007FFFE000
+00007FFFC000
+0000FFFF8000
+0001FFFF8000
+0003FFFF0000
+0007FFFE0000
+0007FFFC0000
+000FFFF80000
+001FFFF80000
+003FFFF00000
+007FFFE00000
+007FFFC00000
+00FFFF800000
+01FFFF000000
+03FFFF000000
+07FFFE000000
+0FFFFC000000
+0FFFF8000000
+1FFFF0000000
+3FFFE0000000
+7FFFC0000000
+FFFFFFFFFFFF
+FFFFFFFFFFFF
+FFFFFFFFFFFF
+FFFFFFFFFFFF
+FFFFFFFFFFFF
+FFFFFFFFFFFF
+FFFFFFFFFFFF
+FFFFFFFFFFFF
+FFFFFFFFFFFF
+FFFFFFFFFFFF
+FFFFFFFFFFFF
+ENDCHAR
+STARTCHAR 007B
+ENCODING 123
+SWIDTH 384 0
+DWIDTH 40 0
+BBX 34 98 3 -22
+BITMAP
+000001FFC0
+00000FFFC0
+00007FFFC0
+0000FFFFC0
+0003FFFFC0
+0007FFFFC0
+0007FFFFC0
+000FFFFFC0
+000FFFFFC0
+001FFFFFC0
+001FFFFFC0
+001FFFFFC0
+001FFFFFC0
+003FFFE000
+003FFF8000
+003FFF0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+007FFE0000
+007FFE0000
+007FFE0000
+007FFC0000
+00FFFC0000
+00FFFC0000
+01FFFC0000
+03FFF80000
+1FFFF80000
+FFFFF00000
+FFFFF00000
+FFFFE00000
+FFFFC00000
+FFFF800000
+FFFE000000
+FFFC000000
+FFFE000000
+FFFF800000
+FFFFC00000
+FFFFE00000
+FFFFE00000
+FFFFF00000
+1FFFF80000
+07FFF80000
+01FFF80000
+01FFFC0000
+00FFFC0000
+00FFFC0000
+007FFC0000
+007FFE0000
+007FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFE0000
+003FFF0000
+003FFF8000
+003FFFE000
+001FFFFFC0
+001FFFFFC0
+001FFFFFC0
+001FFFFFC0
+000FFFFFC0
+000FFFFFC0
+0007FFFFC0
+0003FFFFC0
+0001FFFFC0
+0000FFFFC0
+00007FFFC0
+00001FFFC0
+000001FFC0
+ENDCHAR
+STARTCHAR 007C
+ENCODING 124
+SWIDTH 278 0
+DWIDTH 29 0
+BBX 11 98 9 -23
+BITMAP
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+FFE0
+ENDCHAR
+STARTCHAR 007D
+ENCODING 125
+SWIDTH 384 0
+DWIDTH 40 0
+BBX 34 98 3 -22
+BITMAP
+FFE0000000
+FFFE000000
+FFFF800000
+FFFFC00000
+FFFFF00000
+FFFFF00000
+FFFFF80000
+FFFFFC0000
+FFFFFC0000
+FFFFFE0000
+FFFFFE0000
+FFFFFE0000
+FFFFFE0000
+01FFFF0000
+007FFF0000
+003FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF8000
+000FFF8000
+000FFF8000
+000FFFC000
+000FFFC000
+000FFFE000
+0007FFF000
+0007FFFE00
+0003FFFFC0
+0003FFFFC0
+0001FFFFC0
+0000FFFFC0
+00007FFFC0
+00001FFFC0
+00000FFFC0
+00001FFFC0
+00007FFFC0
+0000FFFFC0
+0001FFFFC0
+0001FFFFC0
+0003FFFFC0
+0007FFFE00
+0007FFF000
+000FFFE000
+000FFFE000
+000FFFC000
+000FFF8000
+001FFF8000
+001FFF8000
+001FFF8000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+001FFF0000
+003FFF0000
+007FFF0000
+01FFFF0000
+FFFFFE0000
+FFFFFE0000
+FFFFFE0000
+FFFFFE0000
+FFFFFC0000
+FFFFFC0000
+FFFFF80000
+FFFFF80000
+FFFFF00000
+FFFFC00000
+FFFF800000
+FFFC000000
+FFE0000000
+ENDCHAR
+STARTCHAR 007E
+ENCODING 126
+SWIDTH 585 0
+DWIDTH 61 0
+BBX 54 20 3 26
+BITMAP
+001FF000000004
+00FFFF0000000C
+03FFFFC000001C
+0FFFFFF800003C
+1FFFFFFE0000FC
+7FFFFFFFC003FC
+FFFFFFFFF80FFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFFFFFFFFFFFFC
+FFC03FFFFFFFFC
+FE0007FFFFFFF0
+FC0000FFFFFFE0
+F000003FFFFFC0
+E0000007FFFF00
+C0000001FFFC00
+800000003FE000
+ENDCHAR
+STARTCHAR 00A0
+ENCODING 160
+SWIDTH 268 0
+DWIDTH 28 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/ArialBold.bdf b/gui/themes/fonts/ArialBold.bdf
new file mode 100644
index 0000000000..65869e0e7b
--- /dev/null
+++ b/gui/themes/fonts/ArialBold.bdf
@@ -0,0 +1,1538 @@
+STARTFONT 2.1
+COMMENT
+COMMENT Converted from TrueType font "arialbd.ttf" by "ttf2bdf 2.8".
+COMMENT
+FONT -FreeType-Arial-Bold-R-Normal--12-120-75-75-P-62-ISO10646-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 14 14 -1 -3
+STARTPROPERTIES 19
+FOUNDRY "FreeType"
+FAMILY_NAME "Arial"
+WEIGHT_NAME "Bold"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 62
+CHARSET_REGISTRY "ISO10646"
+CHARSET_ENCODING "1"
+FONT_ASCENT 11
+FONT_DESCENT 2
+COPYRIGHT "Typeface © The Monotype Corporation plc. Data © The Monotype Corporation plc/Type Solutions Inc. 1990-1992. All Rights Reserved"
+_TTF_FONTFILE "arialbd.ttf"
+_TTF_PSNAME "Arial-BoldMT"
+ENDPROPERTIES
+CHARS 96
+STARTCHAR 0020
+ENCODING 32
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR 0021
+ENCODING 33
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 10 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+00
+C0
+C0
+ENDCHAR
+STARTCHAR 0022
+ENCODING 34
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 3 1 7
+BITMAP
+D8
+D8
+D8
+ENDCHAR
+STARTCHAR 0023
+ENCODING 35
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+24
+24
+24
+FC
+48
+48
+FC
+90
+90
+90
+ENDCHAR
+STARTCHAR 0024
+ENCODING 36
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 12 1 -1
+BITMAP
+20
+70
+A8
+A0
+E0
+F0
+78
+38
+28
+A8
+70
+20
+ENDCHAR
+STARTCHAR 0025
+ENCODING 37
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+E4
+A4
+A4
+A8
+E8
+17
+15
+15
+25
+27
+ENDCHAR
+STARTCHAR 0026
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 10 1 0
+BITMAP
+38
+6C
+6C
+3C
+30
+7A
+DA
+CE
+CE
+7B
+ENDCHAR
+STARTCHAR 0027
+ENCODING 39
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 3 1 7
+BITMAP
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR 0028
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 13 1 -3
+BITMAP
+20
+60
+40
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+40
+60
+20
+ENDCHAR
+STARTCHAR 0029
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 13 0 -3
+BITMAP
+80
+C0
+40
+60
+60
+60
+60
+60
+60
+60
+40
+C0
+80
+ENDCHAR
+STARTCHAR 002A
+ENCODING 42
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 5 4 0 6
+BITMAP
+20
+F8
+20
+D8
+ENDCHAR
+STARTCHAR 002B
+ENCODING 43
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 5 1 2
+BITMAP
+30
+30
+FC
+30
+30
+ENDCHAR
+STARTCHAR 002C
+ENCODING 44
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 4 1 -2
+BITMAP
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR 002D
+ENCODING 45
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 1 1 2
+BITMAP
+E0
+ENDCHAR
+STARTCHAR 002E
+ENCODING 46
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 2 1 0
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR 002F
+ENCODING 47
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+10
+10
+20
+20
+20
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0030
+ENCODING 48
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR 0031
+ENCODING 49
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 4 10 1 0
+BITMAP
+30
+70
+F0
+B0
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR 0032
+ENCODING 50
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+CC
+0C
+0C
+18
+38
+30
+60
+C0
+FC
+ENDCHAR
+STARTCHAR 0033
+ENCODING 51
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+CC
+0C
+0C
+30
+0C
+0C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR 0034
+ENCODING 52
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+18
+18
+38
+38
+58
+58
+98
+FC
+18
+18
+ENDCHAR
+STARTCHAR 0035
+ENCODING 53
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+7C
+60
+C0
+F8
+CC
+0C
+0C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR 0036
+ENCODING 54
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+4C
+C0
+C0
+F8
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR 0037
+ENCODING 55
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+FC
+0C
+18
+18
+30
+30
+70
+60
+60
+60
+ENDCHAR
+STARTCHAR 0038
+ENCODING 56
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+CC
+CC
+CC
+78
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR 0039
+ENCODING 57
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+CC
+CC
+CC
+CC
+7C
+0C
+0C
+C8
+70
+ENDCHAR
+STARTCHAR 003A
+ENCODING 58
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 7 1 0
+BITMAP
+C0
+C0
+00
+00
+00
+C0
+C0
+ENDCHAR
+STARTCHAR 003B
+ENCODING 59
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 9 1 -2
+BITMAP
+C0
+C0
+00
+00
+00
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR 003C
+ENCODING 60
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 7 0 1
+BITMAP
+04
+1C
+F0
+C0
+70
+1C
+04
+ENDCHAR
+STARTCHAR 003D
+ENCODING 61
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 3 0 3
+BITMAP
+FE
+00
+FE
+ENDCHAR
+STARTCHAR 003E
+ENCODING 62
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 7 1 1
+BITMAP
+80
+E0
+38
+0C
+38
+E0
+80
+ENDCHAR
+STARTCHAR 003F
+ENCODING 63
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 10 0 0
+BITMAP
+7C
+C6
+06
+06
+0C
+18
+30
+00
+30
+30
+ENDCHAR
+STARTCHAR 0040
+ENCODING 64
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 13 13 0 -3
+BITMAP
+0FC0
+3020
+6010
+4EC8
+9FC8
+B9C8
+B188
+B390
+BFB0
+5DC0
+4008
+3030
+0FC0
+ENDCHAR
+STARTCHAR 0041
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+1C00
+1C00
+3600
+3600
+3600
+6300
+6300
+7F00
+C180
+C180
+ENDCHAR
+STARTCHAR 0042
+ENCODING 66
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+C6
+C6
+C6
+C6
+FC
+ENDCHAR
+STARTCHAR 0043
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 10 1 0
+BITMAP
+3E
+63
+C0
+C0
+C0
+C0
+C0
+C0
+63
+3E
+ENDCHAR
+STARTCHAR 0044
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+F8
+CC
+C6
+C6
+C6
+C6
+C6
+C6
+CC
+F8
+ENDCHAR
+STARTCHAR 0045
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR 0046
+ENCODING 70
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+FC
+C0
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR 0047
+ENCODING 71
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3E
+63
+C0
+C0
+C0
+CF
+C3
+C3
+63
+3E
+ENDCHAR
+STARTCHAR 0048
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR 0049
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 10 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR 004A
+ENCODING 74
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+CC
+CC
+78
+ENDCHAR
+STARTCHAR 004B
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+C6
+CC
+D8
+D8
+F8
+EC
+CC
+CC
+C6
+C6
+ENDCHAR
+STARTCHAR 004C
+ENCODING 76
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR 004D
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+E380
+E380
+F780
+F780
+D780
+D580
+D580
+DD80
+DD80
+C980
+ENDCHAR
+STARTCHAR 004E
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+C6
+E6
+E6
+F6
+D6
+DE
+CE
+CE
+C6
+C6
+ENDCHAR
+STARTCHAR 004F
+ENCODING 79
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3C
+66
+C3
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR 0050
+ENCODING 80
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+FC
+C6
+C6
+C6
+C6
+FC
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR 0051
+ENCODING 81
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 11 1 -1
+BITMAP
+3C
+66
+C3
+C3
+C3
+C3
+C3
+CB
+66
+3E
+01
+ENDCHAR
+STARTCHAR 0052
+ENCODING 82
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 10 1 0
+BITMAP
+FC
+C6
+C6
+C6
+C6
+FC
+CC
+CE
+C6
+C7
+ENDCHAR
+STARTCHAR 0053
+ENCODING 83
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+7C
+C6
+C0
+E0
+78
+3C
+0E
+06
+C6
+7C
+ENDCHAR
+STARTCHAR 0054
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 10 0 0
+BITMAP
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR 0055
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+ENDCHAR
+STARTCHAR 0056
+ENCODING 86
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+C180
+E180
+6300
+6300
+6300
+3600
+3600
+3600
+1C00
+1C00
+ENDCHAR
+STARTCHAR 0057
+ENCODING 87
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 13 10 0 0
+BITMAP
+C718
+C718
+6730
+6DB0
+6DB0
+6DB0
+6DB0
+38E0
+38E0
+38E0
+ENDCHAR
+STARTCHAR 0058
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+C6
+C6
+6C
+38
+38
+38
+38
+6C
+C6
+C6
+ENDCHAR
+STARTCHAR 0059
+ENCODING 89
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 10 0 0
+BITMAP
+C3
+C3
+66
+3C
+3C
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR 005A
+ENCODING 90
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+FE
+06
+0C
+18
+18
+30
+30
+60
+E0
+FE
+ENDCHAR
+STARTCHAR 005B
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 13 1 -3
+BITMAP
+E0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+E0
+ENDCHAR
+STARTCHAR 005C
+ENCODING 92
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+80
+80
+40
+40
+40
+20
+20
+20
+10
+10
+ENDCHAR
+STARTCHAR 005D
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 13 0 -3
+BITMAP
+E0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+E0
+ENDCHAR
+STARTCHAR 005E
+ENCODING 94
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 5 0 4
+BITMAP
+30
+30
+78
+48
+CC
+ENDCHAR
+STARTCHAR 005F
+ENCODING 95
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 1 0 -3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR 0060
+ENCODING 96
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 2 0 8
+BITMAP
+C0
+60
+ENDCHAR
+STARTCHAR 0061
+ENCODING 97
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 7 1 0
+BITMAP
+78
+8C
+3C
+6C
+CC
+CC
+7C
+ENDCHAR
+STARTCHAR 0062
+ENCODING 98
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+C0
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+ENDCHAR
+STARTCHAR 0063
+ENCODING 99
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+78
+CC
+C0
+C0
+C0
+CC
+78
+ENDCHAR
+STARTCHAR 0064
+ENCODING 100
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+0C
+0C
+0C
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR 0065
+ENCODING 101
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 7 1 0
+BITMAP
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR 0066
+ENCODING 102
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 5 10 0 0
+BITMAP
+38
+60
+60
+F0
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR 0067
+ENCODING 103
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 10 1 -3
+BITMAP
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+8C
+78
+ENDCHAR
+STARTCHAR 0068
+ENCODING 104
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+C0
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR 0069
+ENCODING 105
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 10 1 0
+BITMAP
+C0
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR 006A
+ENCODING 106
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 13 -1 -3
+BITMAP
+30
+30
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+E0
+ENDCHAR
+STARTCHAR 006B
+ENCODING 107
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+C0
+C0
+C0
+CC
+D8
+F0
+F0
+D8
+D8
+CC
+ENDCHAR
+STARTCHAR 006C
+ENCODING 108
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 10 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR 006D
+ENCODING 109
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 10 7 1 0
+BITMAP
+DD80
+EEC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR 006E
+ENCODING 110
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 7 1 0
+BITMAP
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR 006F
+ENCODING 111
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 7 1 0
+BITMAP
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR 0070
+ENCODING 112
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 10 1 -3
+BITMAP
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR 0071
+ENCODING 113
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 10 1 -3
+BITMAP
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+0C
+0C
+ENDCHAR
+STARTCHAR 0072
+ENCODING 114
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 7 1 0
+BITMAP
+F0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR 0073
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+E0
+78
+1C
+CC
+78
+ENDCHAR
+STARTCHAR 0074
+ENCODING 116
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+20
+60
+F0
+60
+60
+60
+60
+60
+30
+ENDCHAR
+STARTCHAR 0075
+ENCODING 117
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 7 1 0
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR 0076
+ENCODING 118
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+C6
+C6
+6C
+6C
+6C
+38
+38
+ENDCHAR
+STARTCHAR 0077
+ENCODING 119
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 11 7 0 0
+BITMAP
+C460
+CE60
+6EC0
+6AC0
+7BC0
+3B80
+3980
+ENDCHAR
+STARTCHAR 0078
+ENCODING 120
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 7 1 0
+BITMAP
+CC
+CC
+78
+30
+78
+CC
+CC
+ENDCHAR
+STARTCHAR 0079
+ENCODING 121
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 10 0 -3
+BITMAP
+C6
+C6
+6C
+6C
+6C
+38
+38
+38
+30
+F0
+ENDCHAR
+STARTCHAR 007A
+ENCODING 122
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+F8
+18
+30
+60
+60
+C0
+F8
+ENDCHAR
+STARTCHAR 007B
+ENCODING 123
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 5 13 0 -3
+BITMAP
+38
+60
+60
+60
+60
+60
+C0
+60
+60
+60
+60
+60
+38
+ENDCHAR
+STARTCHAR 007C
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 12 1 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR 007D
+ENCODING 125
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 5 13 0 -3
+BITMAP
+E0
+30
+30
+30
+30
+30
+18
+30
+30
+30
+30
+30
+E0
+ENDCHAR
+STARTCHAR 007E
+ENCODING 126
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 2 0 3
+BITMAP
+72
+9C
+ENDCHAR
+STARTCHAR 00A0
+ENCODING 160
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/README b/gui/themes/fonts/README
new file mode 100644
index 0000000000..594bfc3ea4
--- /dev/null
+++ b/gui/themes/fonts/README
@@ -0,0 +1,3 @@
+These are fonts used in ScummVM. Most of them come from Xorg.
+
+Also other potentially usable fonts are stored here as well.
diff --git a/gui/themes/fonts/clR6x12-iso-8859-1.bdf b/gui/themes/fonts/clR6x12-iso-8859-1.bdf
new file mode 100644
index 0000000000..3e77859d72
--- /dev/null
+++ b/gui/themes/fonts/clR6x12-iso-8859-1.bdf
@@ -0,0 +1,4290 @@
+STARTFONT 2.1
+COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT!
+COMMENT Generated with 'ucs2any.pl clR6x12.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1'
+COMMENT from an ISO10646-1 encoded source BDF font.
+COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000.
+COMMENT $Xorg: clR6x12.bdf,v 1.3 2000/08/18 15:17:40 xorgcvs Exp $
+COMMENT
+COMMENT Copyright 1989 Dale Schumacher, dal@syntel.mn.org
+COMMENT 399 Beacon Ave.
+COMMENT St. Paul, MN 55104-3527
+COMMENT
+COMMENT Permission to use, copy, modify, and distribute this software and
+COMMENT its documentation for any purpose and without fee is hereby
+COMMENT granted, provided that the above copyright notice appear in all
+COMMENT copies and that both that copyright notice and this permission
+COMMENT notice appear in supporting documentation, and that the name of
+COMMENT Dale Schumacher not be used in advertising or publicity pertaining to
+COMMENT distribution of the software without specific, written prior
+COMMENT permission. Dale Schumacher makes no representations about the
+COMMENT suitability of this software for any purpose. It is provided "as
+COMMENT is" without express or implied warranty.
+COMMENT
+COMMENT
+COMMENT Modified by Robert Brady, <rwb197@ecs.soton.ac.uk>
+COMMENT
+FONT -Schumacher-Clean-Medium-R-Normal--12-120-75-75-C-60-ISO8859-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 6 12 0 -3
+STARTPROPERTIES 21
+FONTNAME_REGISTRY ""
+FOUNDRY "Schumacher"
+FAMILY_NAME "Clean"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 60
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+FONT_ASCENT 9
+FONT_DESCENT 3
+DEFAULT_CHAR 0
+COPYRIGHT "Copyright 1989 Dale Schumacher, 1999 Robert Brady."
+CAP_HEIGHT 8
+X_HEIGHT 5
+ENDPROPERTIES
+CHARS 223
+STARTCHAR defaultchar
+ENCODING 0
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A8
+00
+88
+00
+88
+00
+A8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C6
+ENCODING 1
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+20
+70
+F8
+70
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR shade
+ENCODING 2
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+A8
+54
+A8
+54
+A8
+54
+A8
+54
+A8
+54
+A8
+54
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 3
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+A0
+A0
+E0
+A0
+BC
+08
+08
+08
+08
+00
+00
+ENDCHAR
+STARTCHAR uni240C
+ENCODING 4
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+E0
+80
+C0
+9C
+90
+1C
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240D
+ENCODING 5
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+80
+80
+98
+74
+18
+14
+14
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240A
+ENCODING 6
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+9C
+F0
+18
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR degree
+ENCODING 7
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+48
+30
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 8
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+F8
+20
+20
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2424
+ENCODING 9
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+A0
+E0
+E0
+E0
+B0
+10
+10
+10
+1C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240B
+ENCODING 10
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+A0
+A0
+A0
+5C
+48
+08
+08
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR SF040000
+ENCODING 11
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF030000
+ENCODING 12
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+E0
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF010000
+ENCODING 13
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+3F
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF020000
+ENCODING 14
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+3F
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF050000
+ENCODING 15
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni23BA
+ENCODING 16
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+FC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BB
+ENCODING 17
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+FC
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 18
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+FC
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BC
+ENCODING 19
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BD
+ENCODING 20
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+ENDCHAR
+STARTCHAR SF080000
+ENCODING 21
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+3F
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF090000
+ENCODING 22
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+E0
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF070000
+ENCODING 23
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF060000
+ENCODING 24
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 25
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 26
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+18
+60
+80
+60
+18
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 27
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+C0
+30
+08
+30
+C0
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR pi
+ENCODING 28
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR notequal
+ENCODING 29
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+10
+10
+F8
+20
+F8
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 30
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+40
+E0
+40
+40
+48
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 31
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+30
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+20
+20
+20
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+50
+50
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+50
+F8
+50
+F8
+50
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+78
+A0
+70
+28
+F0
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+C0
+C8
+10
+20
+40
+98
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+80
+80
+40
+A8
+90
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+10
+10
+20
+20
+20
+20
+20
+10
+10
+08
+00
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+20
+10
+10
+10
+10
+10
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+A8
+70
+A8
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+20
+F8
+20
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+30
+30
+20
+40
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+F8
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+30
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+08
+10
+10
+20
+20
+40
+40
+80
+80
+00
+00
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+98
+A8
+C8
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+30
+10
+10
+10
+10
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+10
+20
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+30
+08
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+30
+30
+50
+50
+F8
+10
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+80
+80
+F0
+08
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+40
+80
+F0
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+88
+08
+08
+10
+10
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+88
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+88
+88
+78
+08
+10
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+30
+30
+00
+00
+30
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+30
+30
+00
+00
+30
+30
+20
+40
+00
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+0C
+30
+C0
+30
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+00
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+C0
+30
+0C
+30
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+10
+20
+20
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+B8
+B8
+B0
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+50
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+80
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+E0
+90
+88
+88
+88
+90
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+80
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+80
+80
+F0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+98
+88
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+F8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+38
+08
+08
+08
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+90
+A0
+C0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+80
+80
+80
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+D8
+A8
+A8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+C8
+C8
+A8
+98
+98
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+88
+70
+18
+00
+00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+70
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+50
+50
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+A8
+A8
+D8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+50
+20
+50
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+50
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+08
+10
+20
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+38
+20
+20
+20
+20
+20
+20
+20
+20
+20
+38
+00
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+80
+80
+40
+40
+20
+20
+10
+10
+08
+08
+00
+00
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+10
+10
+10
+10
+10
+10
+10
+10
+10
+70
+00
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+88
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+00
+00
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+F0
+88
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+80
+80
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+08
+08
+78
+88
+88
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+38
+40
+40
+F0
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+F0
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+08
+00
+38
+08
+08
+08
+08
+08
+08
+70
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+40
+40
+48
+50
+60
+50
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+20
+20
+20
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+D0
+A8
+A8
+A8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+B0
+C8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F0
+88
+88
+88
+F0
+80
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+88
+88
+78
+08
+08
+08
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+58
+60
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+70
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+70
+20
+20
+20
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+D8
+50
+50
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+A8
+A8
+A8
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+50
+20
+50
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+10
+20
+40
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+10
+10
+10
+10
+20
+10
+10
+10
+10
+08
+00
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+20
+20
+20
+10
+20
+20
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+40
+A8
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+20
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+70
+A8
+A0
+A8
+70
+20
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+40
+E0
+40
+40
+48
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+70
+50
+70
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+50
+20
+70
+20
+70
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+20
+00
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+48
+40
+30
+48
+48
+48
+30
+08
+48
+30
+00
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+50
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+78
+84
+B4
+A4
+A4
+B4
+84
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+08
+38
+48
+38
+00
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+28
+50
+A0
+50
+28
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+78
+08
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+78
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+78
+84
+B4
+AC
+B4
+AC
+84
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+48
+30
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+F8
+20
+20
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+60
+10
+20
+40
+70
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+60
+10
+20
+10
+60
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+C8
+B0
+80
+80
+00
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+E8
+E8
+68
+28
+28
+28
+00
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+30
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+20
+00
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+60
+20
+20
+20
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+48
+48
+48
+30
+00
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+A0
+50
+28
+50
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+40
+40
+48
+10
+28
+38
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+40
+40
+70
+08
+10
+20
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+C0
+40
+20
+C8
+10
+28
+38
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+20
+20
+40
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+50
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+20
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+A0
+A0
+B8
+E0
+A0
+B8
+00
+00
+00
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+80
+80
+88
+70
+20
+40
+00
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+48
+44
+E4
+44
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+50
+00
+88
+C8
+A8
+98
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+50
+20
+50
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+78
+98
+A8
+A8
+A8
+C8
+F0
+80
+00
+00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+88
+50
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+F0
+88
+88
+88
+F0
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+48
+D0
+50
+48
+48
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+50
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+20
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+28
+70
+A0
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+80
+80
+78
+20
+40
+00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+40
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+10
+28
+08
+78
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+50
+00
+B0
+C8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+50
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+20
+00
+F8
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+08
+78
+98
+A8
+C8
+F0
+80
+00
+00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+B0
+C8
+88
+C8
+B0
+80
+80
+00
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/clR6x12-iso-8859-5.bdf b/gui/themes/fonts/clR6x12-iso-8859-5.bdf
new file mode 100644
index 0000000000..4a4a674235
--- /dev/null
+++ b/gui/themes/fonts/clR6x12-iso-8859-5.bdf
@@ -0,0 +1,4291 @@
+STARTFONT 2.1
+COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT!
+COMMENT Generated with 'ucs2any clR6x12.bdf /usr/share/fonts/X11/util/map-ISO8859-5 ISO8859-5'
+COMMENT from an ISO10646-1 encoded source BDF font.
+COMMENT ucs2any by Ben Collver <collver1@attbi.com>, 2003, based on
+COMMENT ucs2any.pl by Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>, 2000.
+COMMENT $XConsortium: clR6x12.bdf,v 1.2 94/04/11 12:08:30 gildea Exp $
+COMMENT
+COMMENT Copyright 1989 Dale Schumacher, dal@syntel.mn.org
+COMMENT 399 Beacon Ave.
+COMMENT St. Paul, MN 55104-3527
+COMMENT
+COMMENT Permission to use, copy, modify, and distribute this software and
+COMMENT its documentation for any purpose and without fee is hereby
+COMMENT granted, provided that the above copyright notice appear in all
+COMMENT copies and that both that copyright notice and this permission
+COMMENT notice appear in supporting documentation, and that the name of
+COMMENT Dale Schumacher not be used in advertising or publicity pertaining to
+COMMENT distribution of the software without specific, written prior
+COMMENT permission. Dale Schumacher makes no representations about the
+COMMENT suitability of this software for any purpose. It is provided "as
+COMMENT is" without express or implied warranty.
+COMMENT
+COMMENT
+COMMENT Modified by Robert Brady, <rwb197@ecs.soton.ac.uk>
+COMMENT
+FONT -Schumacher-Clean-Medium-R-Normal--12-120-75-75-C-60-ISO8859-5
+SIZE 12 75 75
+FONTBOUNDINGBOX 6 12 0 -3
+STARTPROPERTIES 21
+FONTNAME_REGISTRY ""
+FOUNDRY "Schumacher"
+FAMILY_NAME "Clean"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 60
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "5"
+FONT_ASCENT 9
+FONT_DESCENT 3
+DEFAULT_CHAR 0
+COPYRIGHT "Copyright 1989 Dale Schumacher, 1999 Robert Brady."
+CAP_HEIGHT 8
+X_HEIGHT 5
+ENDPROPERTIES
+CHARS 223
+STARTCHAR defaultchar
+ENCODING 0
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A8
+00
+88
+00
+88
+00
+A8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C6
+ENCODING 1
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+20
+70
+F8
+70
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR shade
+ENCODING 2
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+A8
+54
+A8
+54
+A8
+54
+A8
+54
+A8
+54
+A8
+54
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 3
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+A0
+A0
+E0
+A0
+BC
+08
+08
+08
+08
+00
+00
+ENDCHAR
+STARTCHAR uni240C
+ENCODING 4
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+E0
+80
+C0
+9C
+90
+1C
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240D
+ENCODING 5
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+80
+80
+98
+74
+18
+14
+14
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240A
+ENCODING 6
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+9C
+F0
+18
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR degree
+ENCODING 7
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+48
+30
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 8
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+F8
+20
+20
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2424
+ENCODING 9
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+A0
+E0
+E0
+E0
+B0
+10
+10
+10
+1C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240B
+ENCODING 10
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+A0
+A0
+A0
+5C
+48
+08
+08
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR SF040000
+ENCODING 11
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF030000
+ENCODING 12
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+E0
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF010000
+ENCODING 13
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+3F
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF020000
+ENCODING 14
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+3F
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF050000
+ENCODING 15
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni23BA
+ENCODING 16
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+FC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BB
+ENCODING 17
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+FC
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 18
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+FC
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BC
+ENCODING 19
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BD
+ENCODING 20
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+ENDCHAR
+STARTCHAR SF080000
+ENCODING 21
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+3F
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF090000
+ENCODING 22
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+E0
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF070000
+ENCODING 23
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF060000
+ENCODING 24
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 25
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 26
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+18
+60
+80
+60
+18
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 27
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+C0
+30
+08
+30
+C0
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR pi
+ENCODING 28
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR notequal
+ENCODING 29
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+10
+10
+F8
+20
+F8
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 30
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+40
+E0
+40
+40
+48
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 31
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+30
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+20
+20
+20
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+50
+50
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+50
+F8
+50
+F8
+50
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+78
+A0
+70
+28
+F0
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+C0
+C8
+10
+20
+40
+98
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+80
+80
+40
+A8
+90
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+10
+10
+20
+20
+20
+20
+20
+10
+10
+08
+00
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+20
+10
+10
+10
+10
+10
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+A8
+70
+A8
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+20
+F8
+20
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+30
+30
+20
+40
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+F8
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+30
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+08
+10
+10
+20
+20
+40
+40
+80
+80
+00
+00
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+98
+A8
+C8
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+30
+10
+10
+10
+10
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+10
+20
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+30
+08
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+30
+30
+50
+50
+F8
+10
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+80
+80
+F0
+08
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+40
+80
+F0
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+88
+08
+08
+10
+10
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+88
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+88
+88
+78
+08
+10
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+30
+30
+00
+00
+30
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+30
+30
+00
+00
+30
+30
+20
+40
+00
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+0C
+30
+C0
+30
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+00
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+C0
+30
+0C
+30
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+10
+20
+20
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+B8
+B8
+B0
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+50
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+80
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+E0
+90
+88
+88
+88
+90
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+80
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+80
+80
+F0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+98
+88
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+F8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+38
+08
+08
+08
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+90
+A0
+C0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+80
+80
+80
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+D8
+A8
+A8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+C8
+C8
+A8
+98
+98
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+88
+70
+18
+00
+00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+70
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+50
+50
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+A8
+A8
+D8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+50
+20
+50
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+50
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+08
+10
+20
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+38
+20
+20
+20
+20
+20
+20
+20
+20
+20
+38
+00
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+80
+80
+40
+40
+20
+20
+10
+10
+08
+08
+00
+00
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+10
+10
+10
+10
+10
+10
+10
+10
+10
+70
+00
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+88
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+00
+00
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+F0
+88
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+80
+80
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+08
+08
+78
+88
+88
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+38
+40
+40
+F0
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+F0
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+08
+00
+38
+08
+08
+08
+08
+08
+08
+70
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+40
+40
+48
+50
+60
+50
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+20
+20
+20
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+D0
+A8
+A8
+A8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+B0
+C8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F0
+88
+88
+88
+F0
+80
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+88
+88
+78
+08
+08
+08
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+58
+60
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+70
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+70
+20
+20
+20
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+D8
+50
+50
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+A8
+A8
+A8
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+50
+20
+50
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+10
+20
+40
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+10
+10
+10
+10
+20
+10
+10
+10
+10
+08
+00
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+20
+20
+20
+10
+20
+20
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+40
+A8
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10023
+ENCODING 161
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+00
+F8
+80
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10051
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+E0
+40
+40
+70
+48
+48
+48
+08
+30
+00
+ENDCHAR
+STARTCHAR afii10052
+ENCODING 163
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+78
+40
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10053
+ENCODING 164
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+F0
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10054
+ENCODING 165
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+70
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10055
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10056
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+00
+F8
+20
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10057
+ENCODING 168
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+38
+08
+08
+08
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10058
+ENCODING 169
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+A0
+A0
+B0
+A8
+A8
+A8
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10059
+ENCODING 170
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+A0
+A0
+A0
+F0
+A8
+A8
+A8
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10060
+ENCODING 171
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+E0
+40
+40
+70
+48
+48
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10061
+ENCODING 172
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+88
+90
+E0
+90
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+78
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10062
+ENCODING 174
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+70
+00
+88
+88
+88
+78
+08
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10145
+ENCODING 175
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+88
+88
+88
+F8
+20
+20
+00
+ENDCHAR
+STARTCHAR afii10017
+ENCODING 176
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+50
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10018
+ENCODING 177
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+80
+80
+F0
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10019
+ENCODING 178
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10020
+ENCODING 179
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+40
+40
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10021
+ENCODING 180
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+30
+50
+50
+50
+50
+50
+F8
+88
+00
+00
+ENDCHAR
+STARTCHAR afii10022
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+80
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10024
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A8
+A8
+A8
+70
+A8
+A8
+A8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10025
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+10
+08
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10026
+ENCODING 184
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+98
+98
+A8
+C8
+C8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10027
+ENCODING 185
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+70
+88
+98
+98
+A8
+C8
+C8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10028
+ENCODING 186
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+90
+A0
+C0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10029
+ENCODING 187
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+38
+48
+48
+48
+48
+48
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10030
+ENCODING 188
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+D8
+A8
+A8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10031
+ENCODING 189
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+F8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10032
+ENCODING 190
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10033
+ENCODING 191
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+88
+88
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10034
+ENCODING 192
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10035
+ENCODING 193
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+80
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10036
+ENCODING 194
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10037
+ENCODING 195
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+78
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10038
+ENCODING 196
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+20
+70
+A8
+A8
+70
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10039
+ENCODING 197
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+50
+20
+50
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10040
+ENCODING 198
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+90
+90
+90
+90
+90
+90
+F8
+08
+00
+00
+ENDCHAR
+STARTCHAR afii10041
+ENCODING 199
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+78
+08
+08
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10042
+ENCODING 200
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A8
+A8
+A8
+A8
+A8
+A8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10043
+ENCODING 201
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A8
+A8
+A8
+A8
+A8
+A8
+F8
+08
+08
+00
+ENDCHAR
+STARTCHAR afii10044
+ENCODING 202
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+C0
+40
+40
+70
+48
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10045
+ENCODING 203
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+E8
+98
+98
+E8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10046
+ENCODING 204
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+80
+80
+F0
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10047
+ENCODING 205
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+08
+78
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10048
+ENCODING 206
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+90
+A8
+A8
+E8
+A8
+A8
+90
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10049
+ENCODING 207
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+88
+88
+78
+28
+48
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10065
+ENCODING 208
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+08
+78
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10066
+ENCODING 209
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+80
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10067
+ENCODING 210
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F0
+88
+F0
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10068
+ENCODING 211
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10069
+ENCODING 212
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+30
+50
+50
+50
+F8
+88
+00
+00
+ENDCHAR
+STARTCHAR afii10070
+ENCODING 213
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10072
+ENCODING 214
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+A8
+A8
+70
+A8
+A8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10073
+ENCODING 215
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+30
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10074
+ENCODING 216
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+98
+A8
+C8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10075
+ENCODING 217
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+88
+70
+00
+88
+98
+A8
+C8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10076
+ENCODING 218
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+90
+E0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10077
+ENCODING 219
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+38
+48
+48
+48
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10078
+ENCODING 220
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+D8
+A8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10079
+ENCODING 221
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10080
+ENCODING 222
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10081
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10082
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F0
+88
+88
+88
+F0
+80
+80
+80
+ENDCHAR
+STARTCHAR afii10083
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+80
+80
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10084
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10085
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR afii10086
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+70
+A8
+A8
+A8
+70
+20
+20
+00
+ENDCHAR
+STARTCHAR afii10087
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+50
+20
+50
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10088
+ENCODING 230
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+90
+90
+90
+90
+F8
+08
+00
+00
+ENDCHAR
+STARTCHAR afii10089
+ENCODING 231
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+78
+08
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10090
+ENCODING 232
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+A8
+A8
+A8
+A8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10091
+ENCODING 233
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+A8
+A8
+A8
+A8
+F8
+08
+08
+00
+ENDCHAR
+STARTCHAR afii10092
+ENCODING 234
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+C0
+40
+70
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10093
+ENCODING 235
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+E8
+98
+E8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10094
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+80
+80
+F0
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10095
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+38
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10096
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+90
+A8
+E8
+A8
+90
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10097
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+78
+48
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii61352
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A0
+A0
+E0
+E8
+F4
+B4
+A8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10071
+ENCODING 241
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10099
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+F0
+40
+78
+44
+44
+44
+44
+04
+18
+00
+ENDCHAR
+STARTCHAR afii10100
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+78
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10101
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+E0
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10102
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+70
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10103
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10104
+ENCODING 247
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10105
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+08
+00
+38
+08
+08
+08
+08
+08
+08
+70
+ENDCHAR
+STARTCHAR afii10106
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+60
+A0
+B0
+A8
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10107
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+A0
+A0
+F0
+A8
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10108
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+F0
+40
+78
+44
+44
+44
+44
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10109
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+88
+90
+E0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+48
+40
+30
+48
+48
+48
+30
+08
+48
+30
+00
+ENDCHAR
+STARTCHAR afii10110
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+88
+70
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR afii10193
+ENCODING 255
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+88
+F8
+20
+20
+00
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/clR6x12.bdf b/gui/themes/fonts/clR6x12.bdf
new file mode 100644
index 0000000000..0e0924f857
--- /dev/null
+++ b/gui/themes/fonts/clR6x12.bdf
@@ -0,0 +1,22736 @@
+STARTFONT 2.1
+COMMENT $XConsortium: clR6x12.bdf,v 1.2 94/04/11 12:08:30 gildea Exp $
+COMMENT
+COMMENT Copyright 1989 Dale Schumacher, dal@syntel.mn.org
+COMMENT 399 Beacon Ave.
+COMMENT St. Paul, MN 55104-3527
+COMMENT
+COMMENT Permission to use, copy, modify, and distribute this software and
+COMMENT its documentation for any purpose and without fee is hereby
+COMMENT granted, provided that the above copyright notice appear in all
+COMMENT copies and that both that copyright notice and this permission
+COMMENT notice appear in supporting documentation, and that the name of
+COMMENT Dale Schumacher not be used in advertising or publicity pertaining to
+COMMENT distribution of the software without specific, written prior
+COMMENT permission. Dale Schumacher makes no representations about the
+COMMENT suitability of this software for any purpose. It is provided "as
+COMMENT is" without express or implied warranty.
+COMMENT
+COMMENT
+COMMENT Modified by Robert Brady, <rwb197@ecs.soton.ac.uk>
+COMMENT
+FONT -Schumacher-Clean-Medium-R-Normal--12-120-75-75-C-60-ISO10646-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 6 12 0 -3
+STARTPROPERTIES 22
+FONTNAME_REGISTRY ""
+FOUNDRY "Schumacher"
+FAMILY_NAME "Clean"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 60
+CHARSET_REGISTRY "ISO10646"
+CHARSET_ENCODING "1"
+FONT_ASCENT 9
+FONT_DESCENT 3
+DEFAULT_CHAR 0
+COPYRIGHT "Copyright 1989 Dale Schumacher, 1999 Robert Brady."
+_XMBDFED_INFO "Edited with xmbdfed 4.5."
+CAP_HEIGHT 8
+X_HEIGHT 5
+ENDPROPERTIES
+CHARS 1194
+STARTCHAR char0
+ENCODING 0
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A8
+00
+88
+00
+88
+00
+A8
+00
+00
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+20
+20
+20
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+50
+50
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+50
+F8
+50
+F8
+50
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+78
+A0
+70
+28
+F0
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+C0
+C8
+10
+20
+40
+98
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+80
+80
+40
+A8
+90
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+10
+10
+20
+20
+20
+20
+20
+10
+10
+08
+00
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+20
+10
+10
+10
+10
+10
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+A8
+70
+A8
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+20
+F8
+20
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+30
+30
+20
+40
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+F8
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+30
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+08
+10
+10
+20
+20
+40
+40
+80
+80
+00
+00
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+98
+A8
+C8
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+30
+10
+10
+10
+10
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+10
+20
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+30
+08
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+30
+30
+50
+50
+F8
+10
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+80
+80
+F0
+08
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+40
+80
+F0
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+88
+08
+08
+10
+10
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+88
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+88
+88
+78
+08
+10
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+30
+30
+00
+00
+30
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+30
+30
+00
+00
+30
+30
+20
+40
+00
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+0C
+30
+C0
+30
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+00
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+C0
+30
+0C
+30
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+10
+20
+20
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+B8
+B8
+B0
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+50
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+80
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+E0
+90
+88
+88
+88
+90
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+80
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+80
+80
+F0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+98
+88
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+F8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+38
+08
+08
+08
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+90
+A0
+C0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+80
+80
+80
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+D8
+A8
+A8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+C8
+C8
+A8
+98
+98
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+88
+70
+18
+00
+00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+70
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+50
+50
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+A8
+A8
+D8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+50
+20
+50
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+50
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+08
+10
+20
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+38
+20
+20
+20
+20
+20
+20
+20
+20
+20
+38
+00
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+80
+80
+40
+40
+20
+20
+10
+10
+08
+08
+00
+00
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+10
+10
+10
+10
+10
+10
+10
+10
+10
+70
+00
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+88
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+00
+00
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+F0
+88
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+80
+80
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+08
+08
+78
+88
+88
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+38
+40
+40
+F0
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+F0
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+08
+00
+38
+08
+08
+08
+08
+08
+08
+70
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+40
+40
+48
+50
+60
+50
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+20
+20
+20
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+D0
+A8
+A8
+A8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+B0
+C8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F0
+88
+88
+88
+F0
+80
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+88
+88
+78
+08
+08
+08
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+58
+60
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+70
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+70
+20
+20
+20
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+D8
+50
+50
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+A8
+A8
+A8
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+50
+20
+50
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+10
+20
+40
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+10
+10
+10
+10
+20
+10
+10
+10
+10
+08
+00
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+20
+20
+20
+10
+20
+20
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+40
+A8
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+20
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+70
+A8
+A0
+A8
+70
+20
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+40
+E0
+40
+40
+48
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+70
+50
+70
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+50
+20
+70
+20
+70
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+20
+00
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+48
+40
+30
+48
+48
+48
+30
+08
+48
+30
+00
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+50
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+78
+84
+B4
+A4
+A4
+B4
+84
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+08
+38
+48
+38
+00
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+28
+50
+A0
+50
+28
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+78
+08
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+78
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+78
+84
+B4
+AC
+B4
+AC
+84
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+48
+30
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+F8
+20
+20
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+60
+10
+20
+40
+70
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+60
+10
+20
+10
+60
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+C8
+B0
+80
+80
+00
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+E8
+E8
+68
+28
+28
+28
+00
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+30
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+20
+00
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+60
+20
+20
+20
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+48
+48
+48
+30
+00
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+A0
+50
+28
+50
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+40
+40
+48
+10
+28
+38
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+40
+40
+70
+08
+10
+20
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+C0
+40
+20
+C8
+10
+28
+38
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+20
+20
+40
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+50
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+20
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+A0
+A0
+B8
+E0
+A0
+B8
+00
+00
+00
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+80
+80
+88
+70
+20
+40
+00
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+48
+44
+E4
+44
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+50
+00
+88
+C8
+A8
+98
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+50
+20
+50
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+78
+98
+A8
+A8
+A8
+C8
+F0
+80
+00
+00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+88
+50
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+F0
+88
+88
+88
+F0
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+48
+D0
+50
+48
+48
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+50
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+20
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+28
+70
+A0
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+80
+80
+78
+20
+40
+00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+40
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+10
+28
+08
+78
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+50
+00
+B0
+C8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+50
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+20
+00
+F8
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+08
+78
+98
+A8
+C8
+F0
+80
+00
+00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+B0
+C8
+88
+C8
+B0
+80
+80
+00
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR Amacron
+ENCODING 256
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR amacron
+ENCODING 257
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR Abreve
+ENCODING 258
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+70
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR abreve
+ENCODING 259
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+88
+70
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR Aogonek
+ENCODING 260
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+50
+88
+88
+F8
+88
+88
+10
+18
+00
+ENDCHAR
+STARTCHAR aogonek
+ENCODING 261
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+88
+98
+68
+10
+08
+00
+ENDCHAR
+STARTCHAR Cacute
+ENCODING 262
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+70
+88
+88
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR cacute
+ENCODING 263
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+78
+80
+80
+80
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR Ccircumflex
+ENCODING 264
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+70
+88
+88
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ccircumflex
+ENCODING 265
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+78
+80
+80
+80
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR Cdotaccent
+ENCODING 266
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+70
+88
+88
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR cdotaccent
+ENCODING 267
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+78
+80
+80
+80
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR Ccaron
+ENCODING 268
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+70
+88
+88
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ccaron
+ENCODING 269
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+20
+00
+78
+80
+80
+80
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR Dcaron
+ENCODING 270
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+E0
+90
+88
+88
+90
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR dcaron
+ENCODING 271
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+08
+08
+78
+88
+88
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR Dcroat
+ENCODING 272
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+48
+44
+E4
+44
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR dcroat
+ENCODING 273
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+38
+10
+70
+90
+90
+90
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Emacron
+ENCODING 274
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR emacron
+ENCODING 275
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Ebreve
+ENCODING 276
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+70
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR ebreve
+ENCODING 277
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+88
+70
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Edotaccent
+ENCODING 278
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR edotaccent
+ENCODING 279
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Eogonek
+ENCODING 280
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+80
+F0
+80
+80
+F8
+20
+10
+00
+ENDCHAR
+STARTCHAR eogonek
+ENCODING 281
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+F8
+80
+70
+40
+20
+00
+ENDCHAR
+STARTCHAR Ecaron
+ENCODING 282
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR ecaron
+ENCODING 283
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+20
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Gcircumflex
+ENCODING 284
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+70
+88
+80
+98
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR gcircumflex
+ENCODING 285
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+78
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR Gbreve
+ENCODING 286
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+70
+00
+70
+88
+80
+98
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR gbreve
+ENCODING 287
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+88
+70
+00
+78
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR Gdotaccent
+ENCODING 288
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+70
+88
+80
+98
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR gdotaccent
+ENCODING 289
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+78
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR Gcommaaccent
+ENCODING 290
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+98
+88
+88
+78
+20
+40
+00
+ENDCHAR
+STARTCHAR gcommaaccent
+ENCODING 291
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+30
+00
+78
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR Hcircumflex
+ENCODING 292
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+88
+88
+F8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR hcircumflex
+ENCODING 293
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+80
+80
+F0
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Hbar
+ENCODING 294
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+48
+FC
+48
+78
+48
+48
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR hbar
+ENCODING 295
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+F8
+40
+78
+44
+44
+44
+44
+00
+00
+00
+ENDCHAR
+STARTCHAR Itilde
+ENCODING 296
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+50
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR itilde
+ENCODING 297
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+50
+00
+30
+10
+10
+10
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR Imacron
+ENCODING 298
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR imacron
+ENCODING 299
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Ibreve
+ENCODING 300
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+70
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR ibreve
+ENCODING 301
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+88
+70
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Iogonek
+ENCODING 302
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+F8
+20
+10
+00
+ENDCHAR
+STARTCHAR iogonek
+ENCODING 303
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+60
+20
+20
+20
+70
+20
+10
+00
+ENDCHAR
+STARTCHAR Idotaccent
+ENCODING 304
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR dotlessi
+ENCODING 305
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR IJ
+ENCODING 306
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+88
+88
+88
+A8
+A8
+90
+00
+00
+00
+ENDCHAR
+STARTCHAR ij
+ENCODING 307
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+48
+00
+D8
+48
+48
+48
+E8
+08
+48
+30
+ENDCHAR
+STARTCHAR Jcircumflex
+ENCODING 308
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+28
+00
+38
+08
+08
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR jcircumflex
+ENCODING 309
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+28
+00
+70
+10
+10
+10
+10
+10
+10
+E0
+ENDCHAR
+STARTCHAR Kcommaaccent
+ENCODING 310
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+90
+A0
+C0
+A0
+90
+88
+40
+C0
+00
+ENDCHAR
+STARTCHAR kcommaaccent
+ENCODING 311
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+40
+40
+48
+50
+60
+50
+48
+20
+60
+00
+ENDCHAR
+STARTCHAR kgreenlandic
+ENCODING 312
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+90
+E0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Lacute
+ENCODING 313
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+40
+00
+80
+80
+80
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR lacute
+ENCODING 314
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+20
+20
+20
+20
+20
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR Lcommaaccent
+ENCODING 315
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+80
+80
+80
+80
+80
+F8
+20
+40
+00
+ENDCHAR
+STARTCHAR lcommaaccent
+ENCODING 316
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+20
+20
+20
+20
+20
+20
+70
+20
+40
+00
+ENDCHAR
+STARTCHAR Lcaron
+ENCODING 317
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+80
+80
+80
+80
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR lcaron
+ENCODING 318
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+20
+20
+20
+20
+20
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR Ldot
+ENCODING 319
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+80
+80
+90
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR ldot
+ENCODING 320
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+C0
+40
+40
+40
+48
+40
+40
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR Lslash
+ENCODING 321
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+40
+40
+60
+C0
+40
+40
+7C
+00
+00
+00
+ENDCHAR
+STARTCHAR lslash
+ENCODING 322
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+20
+20
+30
+60
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Nacute
+ENCODING 323
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+88
+C8
+A8
+98
+98
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR nacute
+ENCODING 324
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+B0
+C8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Ncommaaccent
+ENCODING 325
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+C8
+C8
+A8
+98
+98
+88
+40
+C0
+00
+ENDCHAR
+STARTCHAR ncommaaccent
+ENCODING 326
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+B0
+C8
+88
+88
+88
+40
+C0
+00
+ENDCHAR
+STARTCHAR Ncaron
+ENCODING 327
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+88
+C8
+A8
+98
+98
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR ncaron
+ENCODING 328
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+20
+00
+B0
+C8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR napostrophe
+ENCODING 329
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+C0
+40
+80
+00
+B0
+C8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Eng
+ENCODING 330
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+C8
+C8
+A8
+98
+98
+88
+08
+30
+00
+ENDCHAR
+STARTCHAR eng
+ENCODING 331
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+B0
+C8
+88
+88
+88
+08
+30
+00
+ENDCHAR
+STARTCHAR Omacron
+ENCODING 332
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR omacron
+ENCODING 333
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Obreve
+ENCODING 334
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+70
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR obreve
+ENCODING 335
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+88
+70
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Ohungarumlaut
+ENCODING 336
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+48
+90
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ohungarumlaut
+ENCODING 337
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+48
+90
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR OE
+ENCODING 338
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+A0
+A0
+B0
+A0
+A0
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR oe
+ENCODING 339
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+A8
+B8
+A0
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR Racute
+ENCODING 340
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+F0
+88
+F0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR racute
+ENCODING 341
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+58
+60
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR Rcommaaccent
+ENCODING 342
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+A0
+90
+88
+40
+C0
+00
+ENDCHAR
+STARTCHAR rcommaaccent
+ENCODING 343
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+58
+60
+40
+40
+40
+20
+60
+00
+ENDCHAR
+STARTCHAR Rcaron
+ENCODING 344
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+F0
+88
+F0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR rcaron
+ENCODING 345
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+10
+00
+58
+60
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR Sacute
+ENCODING 346
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+70
+80
+70
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR sacute
+ENCODING 347
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+78
+80
+70
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR Scircumflex
+ENCODING 348
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+70
+80
+70
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR scircumflex
+ENCODING 349
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+78
+80
+70
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR Scedilla
+ENCODING 350
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+70
+08
+88
+70
+20
+60
+00
+ENDCHAR
+STARTCHAR scedilla
+ENCODING 351
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+70
+08
+F0
+20
+60
+00
+ENDCHAR
+STARTCHAR Scaron
+ENCODING 352
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+70
+80
+70
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR scaron
+ENCODING 353
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+20
+00
+78
+80
+70
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 354
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+20
+10
+30
+00
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 355
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+F8
+20
+20
+20
+18
+10
+30
+00
+ENDCHAR
+STARTCHAR Tcaron
+ENCODING 356
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+F8
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR tcaron
+ENCODING 357
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+20
+20
+F8
+20
+20
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR Tbar
+ENCODING 358
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+70
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR tbar
+ENCODING 359
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+F8
+20
+70
+20
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR Utilde
+ENCODING 360
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+50
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR utilde
+ENCODING 361
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+50
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR Umacron
+ENCODING 362
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR umacron
+ENCODING 363
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR Ubreve
+ENCODING 364
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+70
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ubreve
+ENCODING 365
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+88
+70
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR Uring
+ENCODING 366
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+20
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uring
+ENCODING 367
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+20
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR Uhungarumlaut
+ENCODING 368
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+48
+90
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uhungarumlaut
+ENCODING 369
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+48
+90
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR Uogonek
+ENCODING 370
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+88
+88
+88
+88
+88
+70
+40
+20
+00
+ENDCHAR
+STARTCHAR uogonek
+ENCODING 371
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+98
+68
+10
+08
+00
+ENDCHAR
+STARTCHAR Wcircumflex
+ENCODING 372
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+88
+88
+A8
+A8
+D8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR wcircumflex
+ENCODING 373
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+88
+A8
+A8
+A8
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR Ycircumflex
+ENCODING 374
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+88
+50
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR ycircumflex
+ENCODING 375
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR Ydieresis
+ENCODING 376
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+88
+50
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR Zacute
+ENCODING 377
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+F8
+10
+20
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR zacute
+ENCODING 378
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+F8
+10
+20
+40
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Zdotaccent
+ENCODING 379
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+F8
+10
+20
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR zdotaccent
+ENCODING 380
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+F8
+10
+20
+40
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Zcaron
+ENCODING 381
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+F8
+10
+20
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR zcaron
+ENCODING 382
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+20
+00
+F8
+10
+20
+40
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR longs
+ENCODING 383
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+18
+20
+20
+60
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0180
+ENCODING 384
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+E0
+40
+78
+44
+44
+44
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0181
+ENCODING 385
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+48
+48
+70
+48
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0182
+ENCODING 386
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+40
+40
+70
+48
+48
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0183
+ENCODING 387
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+80
+80
+F0
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0184
+ENCODING 388
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+60
+E0
+78
+24
+24
+24
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0185
+ENCODING 389
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+C0
+C0
+70
+48
+48
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0186
+ENCODING 390
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+08
+08
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0187
+ENCODING 391
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+18
+70
+88
+80
+80
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0188
+ENCODING 392
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+10
+68
+80
+80
+80
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0189
+ENCODING 393
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+48
+44
+E4
+44
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni018A
+ENCODING 394
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+E0
+50
+48
+48
+48
+50
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uni018B
+ENCODING 395
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+78
+08
+08
+78
+88
+88
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR uni018C
+ENCODING 396
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+78
+08
+08
+78
+88
+88
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR uni018D
+ENCODING 397
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+88
+88
+70
+50
+20
+00
+ENDCHAR
+STARTCHAR uni018E
+ENCODING 398
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+08
+08
+78
+08
+08
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni018F
+ENCODING 399
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+08
+F8
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0190
+ENCODING 400
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+60
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0191
+ENCODING 401
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+40
+40
+70
+40
+40
+40
+40
+80
+00
+ENDCHAR
+STARTCHAR florin
+ENCODING 402
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+38
+40
+40
+F0
+40
+40
+40
+40
+40
+80
+00
+ENDCHAR
+STARTCHAR uni0193
+ENCODING 403
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+70
+90
+80
+98
+88
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0194
+ENCODING 404
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+50
+50
+20
+20
+50
+20
+ENDCHAR
+STARTCHAR uni0195
+ENCODING 405
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+C8
+A8
+A8
+A8
+90
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0196
+ENCODING 406
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+60
+20
+20
+20
+20
+28
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0197
+ENCODING 407
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+70
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0198
+ENCODING 408
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+90
+A8
+A8
+C0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0199
+ENCODING 409
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+40
+48
+50
+60
+50
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR uni019A
+ENCODING 410
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+20
+20
+F8
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni019B
+ENCODING 411
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+68
+30
+60
+A0
+50
+50
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni019C
+ENCODING 412
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+A8
+A8
+A8
+58
+00
+00
+00
+ENDCHAR
+STARTCHAR uni019D
+ENCODING 413
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+44
+64
+64
+54
+4C
+4C
+44
+40
+80
+00
+ENDCHAR
+STARTCHAR uni019E
+ENCODING 414
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+B0
+C8
+88
+88
+88
+08
+08
+00
+ENDCHAR
+STARTCHAR uni019F
+ENCODING 415
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+F8
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Ohorn
+ENCODING 416
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+18
+08
+10
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ohorn
+ENCODING 417
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+18
+08
+10
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01A2
+ENCODING 418
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+40
+B0
+A8
+A8
+A8
+A8
+48
+08
+08
+00
+ENDCHAR
+STARTCHAR uni01A3
+ENCODING 419
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+50
+A8
+A8
+A8
+48
+08
+08
+00
+ENDCHAR
+STARTCHAR uni01A4
+ENCODING 420
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+48
+48
+70
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01A5
+ENCODING 421
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+08
+10
+F0
+88
+88
+88
+F0
+80
+80
+80
+ENDCHAR
+STARTCHAR uni01A6
+ENCODING 422
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+F0
+88
+F0
+A0
+90
+88
+08
+00
+00
+ENDCHAR
+STARTCHAR uni01A7
+ENCODING 423
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+08
+70
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01A8
+ENCODING 424
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F0
+08
+70
+80
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01A9
+ENCODING 425
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+40
+20
+10
+20
+40
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01AA
+ENCODING 426
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+30
+10
+10
+10
+10
+10
+10
+10
+08
+00
+ENDCHAR
+STARTCHAR uni01AB
+ENCODING 427
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+F8
+20
+20
+20
+18
+10
+60
+00
+ENDCHAR
+STARTCHAR uni01AC
+ENCODING 428
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+A0
+A0
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01AD
+ENCODING 429
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+40
+E0
+40
+40
+40
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01AE
+ENCODING 430
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+20
+20
+18
+00
+ENDCHAR
+STARTCHAR Uhorn
+ENCODING 431
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+18
+08
+10
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uhorn
+ENCODING 432
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+18
+08
+10
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B1
+ENCODING 433
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+50
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B2
+ENCODING 434
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+90
+88
+88
+88
+90
+90
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B3
+ENCODING 435
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+44
+A8
+10
+10
+10
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B4
+ENCODING 436
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+08
+90
+90
+90
+90
+70
+10
+10
+60
+ENDCHAR
+STARTCHAR uni01B5
+ENCODING 437
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+08
+10
+F8
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B6
+ENCODING 438
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+10
+F8
+40
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B7
+ENCODING 439
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+08
+10
+20
+70
+08
+08
+90
+60
+00
+ENDCHAR
+STARTCHAR uni01B8
+ENCODING 440
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+80
+40
+20
+70
+80
+80
+48
+30
+00
+ENDCHAR
+STARTCHAR uni01B9
+ENCODING 441
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+40
+20
+70
+80
+80
+78
+00
+ENDCHAR
+STARTCHAR uni01BA
+ENCODING 442
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+40
+20
+70
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR uni01BB
+ENCODING 443
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+10
+F8
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01BC
+ENCODING 444
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+48
+20
+10
+08
+08
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01BD
+ENCODING 445
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+40
+30
+08
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01BE
+ENCODING 446
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+70
+20
+30
+08
+48
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01BF
+ENCODING 447
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+10
+28
+48
+48
+50
+60
+40
+40
+ENDCHAR
+STARTCHAR uni01C0
+ENCODING 448
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C1
+ENCODING 449
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+50
+50
+50
+50
+50
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C2
+ENCODING 450
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+70
+20
+70
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C3
+ENCODING 451
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+70
+70
+20
+20
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C4
+ENCODING 452
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+14
+08
+DC
+A4
+A4
+A8
+B0
+B0
+DC
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C5
+ENCODING 453
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+14
+C8
+A0
+BC
+A4
+A8
+B0
+DC
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C6
+ENCODING 454
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+14
+28
+20
+7C
+A4
+A8
+B0
+7C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C7
+ENCODING 455
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+84
+84
+84
+84
+84
+94
+E8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C8
+ENCODING 456
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+84
+80
+84
+84
+84
+84
+E4
+04
+24
+18
+ENDCHAR
+STARTCHAR uni01C9
+ENCODING 457
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+48
+40
+48
+48
+48
+48
+28
+08
+30
+00
+ENDCHAR
+STARTCHAR uni01CA
+ENCODING 458
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+94
+94
+D4
+B4
+94
+94
+94
+04
+18
+00
+ENDCHAR
+STARTCHAR uni01CB
+ENCODING 459
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+94
+90
+D4
+B4
+94
+94
+94
+04
+18
+00
+ENDCHAR
+STARTCHAR uni01CC
+ENCODING 460
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+08
+00
+C8
+A8
+A8
+A8
+A8
+08
+30
+00
+ENDCHAR
+STARTCHAR uni01CD
+ENCODING 461
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01CE
+ENCODING 462
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+20
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01CF
+ENCODING 463
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+50
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D0
+ENCODING 464
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+50
+00
+30
+10
+10
+10
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D1
+ENCODING 465
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D2
+ENCODING 466
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D3
+ENCODING 467
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+48
+90
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D4
+ENCODING 468
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+48
+90
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D5
+ENCODING 469
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+00
+50
+00
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D6
+ENCODING 470
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+00
+50
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D7
+ENCODING 471
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+50
+00
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D8
+ENCODING 472
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+50
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D9
+ENCODING 473
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+50
+00
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DA
+ENCODING 474
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+50
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DB
+ENCODING 475
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+50
+00
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DC
+ENCODING 476
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+50
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DD
+ENCODING 477
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+08
+F8
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DE
+ENCODING 478
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+00
+50
+00
+70
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DF
+ENCODING 479
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+00
+50
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E0
+ENCODING 480
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+00
+20
+00
+70
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E1
+ENCODING 481
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+00
+20
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E2
+ENCODING 482
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+00
+78
+A0
+A0
+B8
+E0
+A0
+B8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E3
+ENCODING 483
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+00
+70
+28
+70
+A0
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E4
+ENCODING 484
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+80
+90
+90
+B8
+90
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E5
+ENCODING 485
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+90
+B8
+90
+70
+10
+10
+60
+ENDCHAR
+STARTCHAR Gcaron
+ENCODING 486
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+70
+88
+80
+98
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR gcaron
+ENCODING 487
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+20
+00
+78
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR uni01E8
+ENCODING 488
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+88
+90
+A0
+C0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E9
+ENCODING 489
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+10
+40
+40
+48
+50
+60
+50
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01EA
+ENCODING 490
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+88
+70
+40
+60
+00
+ENDCHAR
+STARTCHAR uni01EB
+ENCODING 491
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+88
+88
+70
+40
+60
+00
+ENDCHAR
+STARTCHAR uni01EC
+ENCODING 492
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+00
+70
+88
+88
+88
+88
+70
+40
+60
+00
+ENDCHAR
+STARTCHAR uni01ED
+ENCODING 493
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+70
+88
+88
+88
+70
+40
+60
+00
+ENDCHAR
+STARTCHAR uni01EE
+ENCODING 494
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+F8
+10
+20
+70
+08
+08
+90
+60
+00
+ENDCHAR
+STARTCHAR uni01EF
+ENCODING 495
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+20
+00
+F8
+10
+20
+70
+08
+08
+F0
+00
+ENDCHAR
+STARTCHAR uni01F0
+ENCODING 496
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+10
+00
+70
+10
+10
+10
+10
+10
+10
+E0
+ENDCHAR
+STARTCHAR uni01F1
+ENCODING 497
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+DC
+A4
+A4
+A8
+B0
+B0
+DC
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01F2
+ENCODING 498
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+04
+C0
+A0
+BC
+A4
+A8
+B0
+DC
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01F3
+ENCODING 499
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+7C
+A4
+A8
+B0
+7C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01F4
+ENCODING 500
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+70
+80
+80
+98
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01F5
+ENCODING 501
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+78
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR Aringacute
+ENCODING 506
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+20
+50
+20
+70
+88
+F8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR aringacute
+ENCODING 507
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+20
+50
+20
+00
+78
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR AEacute
+ENCODING 508
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+78
+A0
+B8
+E0
+A0
+B8
+00
+00
+00
+ENDCHAR
+STARTCHAR aeacute
+ENCODING 509
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+70
+28
+70
+A0
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR Oslashacute
+ENCODING 510
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+08
+78
+98
+A8
+A8
+C8
+F0
+80
+00
+00
+ENDCHAR
+STARTCHAR oslashacute
+ENCODING 511
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+08
+78
+98
+A8
+C8
+F0
+80
+00
+00
+ENDCHAR
+STARTCHAR uni0200
+ENCODING 512
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+90
+48
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0201
+ENCODING 513
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+90
+48
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0202
+ENCODING 514
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+88
+00
+70
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0203
+ENCODING 515
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+00
+78
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0204
+ENCODING 516
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+90
+48
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0205
+ENCODING 517
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+90
+48
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0206
+ENCODING 518
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+88
+00
+F8
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0207
+ENCODING 519
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0208
+ENCODING 520
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+90
+48
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0209
+ENCODING 521
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+90
+48
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020A
+ENCODING 522
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+88
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020B
+ENCODING 523
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020C
+ENCODING 524
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+90
+48
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020D
+ENCODING 525
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+90
+48
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020E
+ENCODING 526
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+88
+00
+70
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020F
+ENCODING 527
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0210
+ENCODING 528
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+90
+48
+00
+F0
+88
+F0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0211
+ENCODING 529
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+90
+48
+00
+B0
+C0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0212
+ENCODING 530
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+88
+00
+F0
+88
+F0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0213
+ENCODING 531
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+00
+B0
+C0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0214
+ENCODING 532
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+90
+48
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0215
+ENCODING 533
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+90
+48
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0216
+ENCODING 534
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+88
+00
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0217
+ENCODING 535
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+00
+88
+88
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR Scommaaccent
+ENCODING 536
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+70
+08
+88
+70
+60
+20
+40
+ENDCHAR
+STARTCHAR scommaaccent
+ENCODING 537
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+70
+08
+F0
+60
+20
+40
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 538
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+20
+30
+10
+20
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 539
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+F8
+20
+20
+20
+18
+30
+10
+20
+ENDCHAR
+STARTCHAR uni0259
+ENCODING 601
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+08
+F8
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02BB
+ENCODING 699
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+30
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57929
+ENCODING 700
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+10
+20
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii64937
+ENCODING 701
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+20
+10
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02BE
+ENCODING 702
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+10
+10
+20
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02BF
+ENCODING 703
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+20
+10
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR circumflex
+ENCODING 710
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR caron
+ENCODING 711
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 713
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02D6
+ENCODING 726
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+70
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR breve
+ENCODING 728
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+48
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dotaccent
+ENCODING 729
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ring
+ENCODING 730
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ogonek
+ENCODING 731
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+20
+40
+30
+ENDCHAR
+STARTCHAR tilde
+ENCODING 732
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+28
+50
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hungarumlaut
+ENCODING 733
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+48
+90
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR gravecomb
+ENCODING 768
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR acutecomb
+ENCODING 769
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0302
+ENCODING 770
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR tildecomb
+ENCODING 771
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+50
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0304
+ENCODING 772
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0305
+ENCODING 773
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0306
+ENCODING 774
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0307
+ENCODING 775
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0308
+ENCODING 776
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hookabovecomb
+ENCODING 777
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+60
+10
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni030A
+ENCODING 778
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni030B
+ENCODING 779
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+48
+90
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni030C
+ENCODING 780
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni030D
+ENCODING 781
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni030E
+ENCODING 782
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni030F
+ENCODING 783
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+90
+48
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0310
+ENCODING 784
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+88
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0311
+ENCODING 785
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+88
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0338
+ENCODING 824
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+08
+10
+10
+20
+40
+40
+80
+80
+00
+00
+ENDCHAR
+STARTCHAR uni0374
+ENCODING 884
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0375
+ENCODING 885
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+20
+00
+ENDCHAR
+STARTCHAR uni037A
+ENCODING 890
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+20
+30
+ENDCHAR
+STARTCHAR uni037E
+ENCODING 894
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+30
+30
+00
+00
+30
+30
+20
+40
+00
+ENDCHAR
+STARTCHAR tonos
+ENCODING 900
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dieresistonos
+ENCODING 901
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+50
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Alphatonos
+ENCODING 902
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+90
+28
+44
+44
+7C
+44
+44
+00
+00
+00
+ENDCHAR
+STARTCHAR anoteleia
+ENCODING 903
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+30
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Epsilontonos
+ENCODING 904
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+BC
+20
+20
+38
+20
+20
+3C
+00
+00
+00
+ENDCHAR
+STARTCHAR Etatonos
+ENCODING 905
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+A4
+24
+24
+3C
+24
+24
+24
+00
+00
+00
+ENDCHAR
+STARTCHAR Iotatonos
+ENCODING 906
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+B8
+10
+10
+10
+10
+10
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR Omicrontonos
+ENCODING 908
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+98
+24
+24
+24
+24
+24
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR Upsilontonos
+ENCODING 910
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+A8
+28
+10
+10
+10
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR Omegatonos
+ENCODING 911
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+90
+28
+44
+44
+44
+28
+6C
+00
+00
+00
+ENDCHAR
+STARTCHAR iotadieresistonos
+ENCODING 912
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+50
+00
+60
+20
+28
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR Alpha
+ENCODING 913
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+50
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Beta
+ENCODING 914
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR Gamma
+ENCODING 915
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+40
+40
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR Delta
+ENCODING 916
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+50
+50
+50
+88
+88
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Epsilon
+ENCODING 917
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+80
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Zeta
+ENCODING 918
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+08
+10
+20
+40
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Eta
+ENCODING 919
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+F8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Theta
+ENCODING 920
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+A8
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Iota
+ENCODING 921
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Kappa
+ENCODING 922
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+90
+A0
+C0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Lambda
+ENCODING 923
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+50
+50
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Mu
+ENCODING 924
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+D8
+A8
+A8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Nu
+ENCODING 925
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+C8
+C8
+A8
+98
+98
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Xi
+ENCODING 926
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+00
+70
+00
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Omicron
+ENCODING 927
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Pi
+ENCODING 928
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+88
+88
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Rho
+ENCODING 929
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR Sigma
+ENCODING 931
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+40
+20
+10
+20
+40
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Tau
+ENCODING 932
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR Upsilon
+ENCODING 933
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+50
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR Phi
+ENCODING 934
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+20
+70
+A8
+A8
+70
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR Chi
+ENCODING 935
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+50
+20
+50
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR Psi
+ENCODING 936
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A8
+A8
+A8
+70
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 937
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+50
+D8
+00
+00
+00
+ENDCHAR
+STARTCHAR Iotadieresis
+ENCODING 938
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+F8
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Upsilondieresis
+ENCODING 939
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+88
+50
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR alphatonos
+ENCODING 940
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+00
+68
+98
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR epsilontonos
+ENCODING 941
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+00
+70
+88
+60
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR etatonos
+ENCODING 942
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+00
+B0
+C8
+88
+88
+88
+08
+08
+00
+ENDCHAR
+STARTCHAR iotatonos
+ENCODING 943
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+00
+60
+20
+20
+28
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR upsilondieresistonos
+ENCODING 944
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+88
+00
+90
+88
+88
+90
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR alpha
+ENCODING 945
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+68
+98
+88
+98
+68
+00
+00
+00
+ENDCHAR
+STARTCHAR beta
+ENCODING 946
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+F0
+88
+88
+C8
+B0
+80
+00
+ENDCHAR
+STARTCHAR gamma
+ENCODING 947
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+44
+A8
+28
+10
+10
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR delta
+ENCODING 948
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+48
+20
+10
+30
+48
+48
+48
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR epsilon
+ENCODING 949
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+60
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR zeta
+ENCODING 950
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+38
+20
+40
+40
+40
+40
+38
+08
+30
+00
+ENDCHAR
+STARTCHAR eta
+ENCODING 951
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+B0
+C8
+88
+88
+88
+08
+08
+00
+ENDCHAR
+STARTCHAR theta
+ENCODING 952
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+30
+48
+48
+78
+48
+48
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR iota
+ENCODING 953
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+60
+20
+20
+28
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR kappa
+ENCODING 954
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+48
+50
+60
+50
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR lambda
+ENCODING 955
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+A0
+20
+20
+50
+50
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 956
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+98
+E8
+80
+80
+00
+ENDCHAR
+STARTCHAR nu
+ENCODING 957
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+D8
+50
+50
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR xi
+ENCODING 958
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+70
+80
+80
+70
+80
+80
+70
+08
+30
+00
+ENDCHAR
+STARTCHAR omicron
+ENCODING 959
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR pi
+ENCODING 960
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR rho
+ENCODING 961
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+88
+88
+B0
+80
+80
+80
+ENDCHAR
+STARTCHAR sigma1
+ENCODING 962
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+70
+08
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR sigma
+ENCODING 963
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+90
+90
+90
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR tau
+ENCODING 964
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+20
+20
+28
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR upsilon
+ENCODING 965
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+90
+88
+88
+88
+90
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR phi
+ENCODING 966
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+30
+A8
+A8
+A8
+70
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR chi
+ENCODING 967
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+50
+20
+50
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR psi
+ENCODING 968
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+A8
+A8
+70
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR omega
+ENCODING 969
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+50
+88
+A8
+A8
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR iotadieresis
+ENCODING 970
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+60
+20
+20
+28
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR upsilondieresis
+ENCODING 971
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+90
+88
+88
+88
+90
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR omicrontonos
+ENCODING 972
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR upsilontonos
+ENCODING 973
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+00
+90
+88
+88
+88
+90
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR omegatonos
+ENCODING 974
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+00
+50
+88
+A8
+A8
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR theta1
+ENCODING 977
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+90
+90
+78
+10
+90
+90
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR phi1
+ENCODING 981
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+70
+A8
+A8
+A8
+70
+20
+20
+00
+ENDCHAR
+STARTCHAR omega1
+ENCODING 982
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+FC
+44
+54
+54
+28
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03F1
+ENCODING 1009
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+30
+48
+48
+48
+70
+40
+38
+00
+ENDCHAR
+STARTCHAR afii10023
+ENCODING 1025
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+00
+F8
+80
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10051
+ENCODING 1026
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+E0
+40
+40
+70
+48
+48
+48
+08
+30
+00
+ENDCHAR
+STARTCHAR afii10052
+ENCODING 1027
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+78
+40
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10053
+ENCODING 1028
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+F0
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10054
+ENCODING 1029
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+70
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10055
+ENCODING 1030
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10056
+ENCODING 1031
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+00
+F8
+20
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10057
+ENCODING 1032
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+38
+08
+08
+08
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10058
+ENCODING 1033
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+A0
+A0
+B0
+A8
+A8
+A8
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10059
+ENCODING 1034
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+A0
+A0
+A0
+F0
+A8
+A8
+A8
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10060
+ENCODING 1035
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+E0
+40
+40
+70
+48
+48
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10061
+ENCODING 1036
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+88
+90
+E0
+90
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10062
+ENCODING 1038
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+70
+00
+88
+88
+88
+78
+08
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10145
+ENCODING 1039
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+88
+88
+88
+F8
+20
+20
+00
+ENDCHAR
+STARTCHAR afii10017
+ENCODING 1040
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+50
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10018
+ENCODING 1041
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+80
+80
+F0
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10019
+ENCODING 1042
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10020
+ENCODING 1043
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+40
+40
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10021
+ENCODING 1044
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+30
+50
+50
+50
+50
+50
+F8
+88
+00
+00
+ENDCHAR
+STARTCHAR afii10022
+ENCODING 1045
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+80
+80
+F0
+80
+80
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10024
+ENCODING 1046
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A8
+A8
+A8
+70
+A8
+A8
+A8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10025
+ENCODING 1047
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+88
+08
+10
+08
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10026
+ENCODING 1048
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+98
+98
+A8
+C8
+C8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10027
+ENCODING 1049
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+70
+88
+98
+98
+A8
+C8
+C8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10028
+ENCODING 1050
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+90
+A0
+C0
+A0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10029
+ENCODING 1051
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+38
+48
+48
+48
+48
+48
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10030
+ENCODING 1052
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+D8
+A8
+A8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10031
+ENCODING 1053
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+F8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10032
+ENCODING 1054
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10033
+ENCODING 1055
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+88
+88
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10034
+ENCODING 1056
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+88
+88
+F0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10035
+ENCODING 1057
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+80
+80
+80
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10036
+ENCODING 1058
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10037
+ENCODING 1059
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+78
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10038
+ENCODING 1060
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+20
+70
+A8
+A8
+70
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10039
+ENCODING 1061
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+50
+20
+50
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10040
+ENCODING 1062
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+90
+90
+90
+90
+90
+90
+F8
+08
+00
+00
+ENDCHAR
+STARTCHAR afii10041
+ENCODING 1063
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+78
+08
+08
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10042
+ENCODING 1064
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A8
+A8
+A8
+A8
+A8
+A8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10043
+ENCODING 1065
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A8
+A8
+A8
+A8
+A8
+A8
+F8
+08
+08
+00
+ENDCHAR
+STARTCHAR afii10044
+ENCODING 1066
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+C0
+40
+40
+70
+48
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10045
+ENCODING 1067
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+E8
+98
+98
+E8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10046
+ENCODING 1068
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+80
+80
+F0
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10047
+ENCODING 1069
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+08
+78
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10048
+ENCODING 1070
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+90
+A8
+A8
+E8
+A8
+A8
+90
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10049
+ENCODING 1071
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+88
+88
+78
+28
+48
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10065
+ENCODING 1072
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+08
+78
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10066
+ENCODING 1073
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+80
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10067
+ENCODING 1074
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F0
+88
+F0
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10068
+ENCODING 1075
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10069
+ENCODING 1076
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+30
+50
+50
+50
+F8
+88
+00
+00
+ENDCHAR
+STARTCHAR afii10070
+ENCODING 1077
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10072
+ENCODING 1078
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+A8
+A8
+70
+A8
+A8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10073
+ENCODING 1079
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+30
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10074
+ENCODING 1080
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+98
+A8
+C8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10075
+ENCODING 1081
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+88
+70
+00
+88
+98
+A8
+C8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10076
+ENCODING 1082
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+90
+E0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10077
+ENCODING 1083
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+38
+48
+48
+48
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10078
+ENCODING 1084
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+D8
+A8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10079
+ENCODING 1085
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+F8
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10080
+ENCODING 1086
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10081
+ENCODING 1087
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10082
+ENCODING 1088
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F0
+88
+88
+88
+F0
+80
+80
+80
+ENDCHAR
+STARTCHAR afii10083
+ENCODING 1089
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+80
+80
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10084
+ENCODING 1090
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10085
+ENCODING 1091
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR afii10086
+ENCODING 1092
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+70
+A8
+A8
+A8
+70
+20
+20
+00
+ENDCHAR
+STARTCHAR afii10087
+ENCODING 1093
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+50
+20
+50
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10088
+ENCODING 1094
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+90
+90
+90
+90
+F8
+08
+00
+00
+ENDCHAR
+STARTCHAR afii10089
+ENCODING 1095
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+78
+08
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10090
+ENCODING 1096
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+A8
+A8
+A8
+A8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10091
+ENCODING 1097
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+A8
+A8
+A8
+A8
+F8
+08
+08
+00
+ENDCHAR
+STARTCHAR afii10092
+ENCODING 1098
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+C0
+40
+70
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10093
+ENCODING 1099
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+E8
+98
+E8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10094
+ENCODING 1100
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+80
+80
+F0
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10095
+ENCODING 1101
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+38
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10096
+ENCODING 1102
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+90
+A8
+E8
+A8
+90
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10097
+ENCODING 1103
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+88
+78
+48
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10071
+ENCODING 1105
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+70
+88
+F8
+80
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10099
+ENCODING 1106
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+F0
+40
+78
+44
+44
+44
+44
+04
+18
+00
+ENDCHAR
+STARTCHAR afii10100
+ENCODING 1107
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+78
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10101
+ENCODING 1108
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+E0
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10102
+ENCODING 1109
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+80
+70
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10103
+ENCODING 1110
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10104
+ENCODING 1111
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+60
+20
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10105
+ENCODING 1112
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+08
+00
+38
+08
+08
+08
+08
+08
+08
+70
+ENDCHAR
+STARTCHAR afii10106
+ENCODING 1113
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+60
+A0
+B0
+A8
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10107
+ENCODING 1114
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+A0
+A0
+F0
+A8
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10108
+ENCODING 1115
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+F0
+40
+78
+44
+44
+44
+44
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10109
+ENCODING 1116
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+88
+90
+E0
+90
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10110
+ENCODING 1118
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+88
+70
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR afii10193
+ENCODING 1119
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+88
+88
+88
+88
+F8
+20
+20
+00
+ENDCHAR
+STARTCHAR afii10146
+ENCODING 1122
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+E0
+40
+40
+70
+48
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10194
+ENCODING 1123
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+40
+E0
+40
+70
+48
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0470
+ENCODING 1136
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A8
+A8
+A8
+70
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0471
+ENCODING 1137
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+A8
+A8
+70
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10147
+ENCODING 1138
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+F8
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10195
+ENCODING 1139
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+F8
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10148
+ENCODING 1140
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+98
+90
+50
+50
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10196
+ENCODING 1141
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+80
+98
+50
+60
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0476
+ENCODING 1142
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+A0
+50
+80
+98
+90
+50
+50
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0477
+ENCODING 1143
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A0
+50
+80
+98
+50
+60
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10050
+ENCODING 1168
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+78
+40
+40
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10098
+ENCODING 1169
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+08
+78
+40
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57664
+ENCODING 1488
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+88
+48
+70
+A0
+90
+C8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57665
+ENCODING 1489
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F0
+10
+10
+10
+10
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57666
+ENCODING 1490
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+70
+10
+10
+10
+28
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57667
+ENCODING 1491
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+10
+10
+10
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57668
+ENCODING 1492
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+10
+90
+90
+90
+90
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57669
+ENCODING 1493
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+70
+10
+10
+10
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57670
+ENCODING 1494
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+20
+10
+10
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57671
+ENCODING 1495
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+48
+48
+48
+48
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57672
+ENCODING 1496
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+98
+A8
+A8
+88
+88
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57673
+ENCODING 1497
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+30
+10
+10
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57674
+ENCODING 1498
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+08
+08
+08
+08
+08
+08
+08
+00
+ENDCHAR
+STARTCHAR afii57675
+ENCODING 1499
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+08
+08
+08
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57676
+ENCODING 1500
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+F8
+08
+08
+10
+20
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57677
+ENCODING 1501
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+48
+48
+48
+48
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57678
+ENCODING 1502
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+98
+A8
+48
+88
+88
+B8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57679
+ENCODING 1503
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+30
+10
+10
+10
+10
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR afii57680
+ENCODING 1504
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+18
+08
+08
+08
+08
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57681
+ENCODING 1505
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+48
+48
+48
+50
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57682
+ENCODING 1506
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+D8
+48
+48
+48
+50
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57683
+ENCODING 1507
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+48
+48
+08
+08
+08
+08
+08
+00
+ENDCHAR
+STARTCHAR afii57684
+ENCODING 1508
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+48
+48
+08
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57685
+ENCODING 1509
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+90
+48
+50
+60
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii57686
+ENCODING 1510
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+90
+48
+28
+10
+08
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57687
+ENCODING 1511
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+08
+88
+88
+88
+B0
+80
+80
+00
+ENDCHAR
+STARTCHAR afii57688
+ENCODING 1512
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F0
+08
+08
+08
+08
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57689
+ENCODING 1513
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+A8
+A8
+A8
+E8
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57690
+ENCODING 1514
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+48
+48
+48
+48
+C8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E02
+ENCODING 7682
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+F0
+88
+F0
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E03
+ENCODING 7683
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+80
+80
+F0
+88
+88
+88
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E08
+ENCODING 7688
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E09
+ENCODING 7689
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E0A
+ENCODING 7690
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+E0
+90
+88
+88
+90
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E0B
+ENCODING 7691
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+08
+08
+78
+88
+88
+88
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E1E
+ENCODING 7710
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+F8
+80
+F0
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E1F
+ENCODING 7711
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+38
+40
+40
+F0
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E40
+ENCODING 7744
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+88
+D8
+A8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E41
+ENCODING 7745
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+D0
+A8
+A8
+A8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E56
+ENCODING 7766
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+F0
+88
+88
+F0
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E57
+ENCODING 7767
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+F0
+88
+88
+88
+F0
+80
+80
+80
+ENDCHAR
+STARTCHAR uni1E60
+ENCODING 7776
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+70
+80
+70
+08
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E61
+ENCODING 7777
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+78
+80
+70
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E6A
+ENCODING 7786
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+F8
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E6B
+ENCODING 7787
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+20
+20
+F8
+20
+20
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR Wgrave
+ENCODING 7808
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+88
+88
+A8
+A8
+D8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR wgrave
+ENCODING 7809
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+88
+A8
+A8
+A8
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR Wacute
+ENCODING 7810
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+20
+00
+88
+88
+A8
+A8
+D8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR wacute
+ENCODING 7811
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+00
+88
+A8
+A8
+A8
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR Wdieresis
+ENCODING 7812
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+00
+88
+88
+A8
+A8
+D8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR wdieresis
+ENCODING 7813
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+00
+88
+A8
+A8
+A8
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E86
+ENCODING 7814
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+00
+88
+88
+A8
+A8
+D8
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E87
+ENCODING 7815
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+88
+A8
+A8
+A8
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR Ygrave
+ENCODING 7922
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+20
+00
+88
+50
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR ygrave
+ENCODING 7923
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+20
+00
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR uni2000
+ENCODING 8192
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2001
+ENCODING 8193
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2002
+ENCODING 8194
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2003
+ENCODING 8195
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2004
+ENCODING 8196
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2005
+ENCODING 8197
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2006
+ENCODING 8198
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2007
+ENCODING 8199
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2008
+ENCODING 8200
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2009
+ENCODING 8201
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni200A
+ENCODING 8202
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2010
+ENCODING 8208
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+70
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2011
+ENCODING 8209
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+70
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR figuredash
+ENCODING 8210
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+78
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR endash
+ENCODING 8211
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+78
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR emdash
+ENCODING 8212
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+F8
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii00208
+ENCODING 8213
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+FC
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2016
+ENCODING 8214
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+50
+50
+50
+50
+50
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR underscoredbl
+ENCODING 8215
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+F8
+00
+F8
+ENDCHAR
+STARTCHAR quoteleft
+ENCODING 8216
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+20
+30
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quoteright
+ENCODING 8217
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+10
+20
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotesinglbase
+ENCODING 8218
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+30
+10
+20
+00
+ENDCHAR
+STARTCHAR quotereversed
+ENCODING 8219
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+20
+10
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblleft
+ENCODING 8220
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+48
+90
+D8
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblright
+ENCODING 8221
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+D8
+48
+90
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblbase
+ENCODING 8222
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+D8
+48
+90
+00
+ENDCHAR
+STARTCHAR uni201F
+ENCODING 8223
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+D8
+90
+48
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dagger
+ENCODING 8224
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+70
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR daggerdbl
+ENCODING 8225
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+70
+20
+70
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR bullet
+ENCODING 8226
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+30
+78
+78
+78
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2023
+ENCODING 8227
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+40
+60
+70
+78
+70
+60
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR onedotenleader
+ENCODING 8228
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR twodotenleader
+ENCODING 8229
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR ellipsis
+ENCODING 8230
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+A8
+00
+00
+00
+ENDCHAR
+STARTCHAR perthousand
+ENCODING 8240
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+C0
+D0
+20
+58
+98
+60
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR minute
+ENCODING 8242
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+10
+20
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR second
+ENCODING 8243
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+48
+48
+90
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2034
+ENCODING 8244
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+54
+54
+A8
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2035
+ENCODING 8245
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+10
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2036
+ENCODING 8246
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+90
+90
+48
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2037
+ENCODING 8247
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+A8
+A8
+54
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR guilsinglleft
+ENCODING 8249
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+10
+20
+40
+20
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR guilsinglright
+ENCODING 8250
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+40
+20
+10
+20
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR exclamdbl
+ENCODING 8252
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+50
+50
+50
+50
+50
+50
+00
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR uni203E
+ENCODING 8254
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8260
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+08
+10
+10
+20
+20
+40
+40
+80
+80
+00
+00
+ENDCHAR
+STARTCHAR zerosuperior
+ENCODING 8304
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+50
+50
+20
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2071
+ENCODING 8305
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+00
+60
+20
+70
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR foursuperior
+ENCODING 8308
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+40
+60
+70
+20
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR fivesuperior
+ENCODING 8309
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+40
+60
+10
+60
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR sixsuperior
+ENCODING 8310
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+40
+60
+50
+20
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR sevensuperior
+ENCODING 8311
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+10
+20
+20
+20
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR eightsuperior
+ENCODING 8312
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+20
+50
+20
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ninesuperior
+ENCODING 8313
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+30
+10
+60
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni207A
+ENCODING 8314
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+70
+20
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni207B
+ENCODING 8315
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni207C
+ENCODING 8316
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+00
+70
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleftsuperior
+ENCODING 8317
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+40
+40
+40
+20
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenrightsuperior
+ENCODING 8318
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+10
+10
+10
+20
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR nsuperior
+ENCODING 8319
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+50
+50
+50
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR zeroinferior
+ENCODING 8320
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+20
+50
+50
+50
+20
+00
+ENDCHAR
+STARTCHAR oneinferior
+ENCODING 8321
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+20
+60
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR twoinferior
+ENCODING 8322
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+20
+50
+10
+20
+70
+00
+ENDCHAR
+STARTCHAR threeinferior
+ENCODING 8323
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+20
+50
+20
+10
+60
+00
+ENDCHAR
+STARTCHAR fourinferior
+ENCODING 8324
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+40
+40
+60
+70
+20
+00
+ENDCHAR
+STARTCHAR fiveinferior
+ENCODING 8325
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+70
+40
+60
+10
+60
+00
+ENDCHAR
+STARTCHAR sixinferior
+ENCODING 8326
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+30
+40
+60
+50
+20
+00
+ENDCHAR
+STARTCHAR seveninferior
+ENCODING 8327
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+70
+10
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR eightinferior
+ENCODING 8328
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+20
+50
+20
+50
+20
+00
+ENDCHAR
+STARTCHAR nineinferior
+ENCODING 8329
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+20
+50
+30
+10
+60
+00
+ENDCHAR
+STARTCHAR uni208A
+ENCODING 8330
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+20
+70
+20
+00
+00
+ENDCHAR
+STARTCHAR uni208B
+ENCODING 8331
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR uni208C
+ENCODING 8332
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+70
+00
+70
+00
+00
+ENDCHAR
+STARTCHAR parenleftinferior
+ENCODING 8333
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+20
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR parenrightinferior
+ENCODING 8334
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+20
+10
+10
+10
+20
+00
+ENDCHAR
+STARTCHAR franc
+ENCODING 8355
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+80
+D8
+A0
+A0
+A0
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR lira
+ENCODING 8356
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+E0
+40
+E0
+40
+48
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR peseta
+ENCODING 8359
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+48
+FC
+48
+70
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR Euro
+ENCODING 8364
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+30
+48
+E0
+40
+E0
+48
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20AF
+ENCODING 8367
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+E0
+50
+48
+48
+48
+E8
+D0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20D0
+ENCODING 8400
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+F8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20D1
+ENCODING 8401
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+F8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20D2
+ENCODING 8402
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+20
+20
+20
+20
+20
+20
+00
+00
+ENDCHAR
+STARTCHAR uni20D3
+ENCODING 8403
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+20
+20
+20
+20
+20
+20
+00
+00
+ENDCHAR
+STARTCHAR uni20D4
+ENCODING 8404
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+B0
+C8
+E0
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20D5
+ENCODING 8405
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+68
+98
+38
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20D6
+ENCODING 8406
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+F8
+40
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20D7
+ENCODING 8407
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+F8
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2102
+ENCODING 8450
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+A8
+A0
+A0
+A0
+A8
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR afii61248
+ENCODING 8453
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+60
+80
+80
+60
+00
+30
+48
+48
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR afii61289
+ENCODING 8467
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+28
+28
+28
+30
+30
+20
+58
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2115
+ENCODING 8469
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+C8
+C8
+E8
+D8
+D8
+C8
+00
+00
+00
+ENDCHAR
+STARTCHAR afii61352
+ENCODING 8470
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A0
+A0
+E0
+E8
+F4
+B4
+A8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni211A
+ENCODING 8474
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+A8
+A8
+A8
+A8
+A8
+70
+18
+00
+00
+ENDCHAR
+STARTCHAR uni211D
+ENCODING 8477
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F0
+A8
+A8
+B0
+B0
+A8
+A8
+00
+00
+00
+ENDCHAR
+STARTCHAR trademark
+ENCODING 8482
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F4
+5C
+54
+54
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2124
+ENCODING 8484
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+28
+50
+50
+A0
+A0
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 8486
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+50
+50
+D8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2127
+ENCODING 8487
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+D8
+50
+50
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR estimated
+ENCODING 8494
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+D8
+F8
+C0
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR oneeighth
+ENCODING 8539
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+90
+A8
+10
+28
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR threeeighths
+ENCODING 8540
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+40
+A0
+40
+28
+D4
+08
+14
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR fiveeighths
+ENCODING 8541
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+E0
+80
+C0
+28
+D4
+08
+14
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR seveneighths
+ENCODING 8542
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+E0
+20
+40
+48
+54
+08
+14
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowleft
+ENCODING 8592
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+40
+F8
+40
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowup
+ENCODING 8593
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+70
+A8
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowright
+ENCODING 8594
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+10
+F8
+10
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdown
+ENCODING 8595
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+20
+20
+A8
+70
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowboth
+ENCODING 8596
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+48
+FC
+48
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowupdn
+ENCODING 8597
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+70
+A8
+20
+20
+20
+A8
+70
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A4
+ENCODING 8612
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+24
+44
+FC
+44
+24
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A5
+ENCODING 8613
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+70
+A8
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A6
+ENCODING 8614
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+90
+88
+FC
+88
+90
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A7
+ENCODING 8615
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+20
+20
+20
+A8
+70
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowupdnbse
+ENCODING 8616
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+70
+A8
+20
+A8
+70
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21C4
+ENCODING 8644
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+10
+F8
+10
+20
+40
+F8
+40
+20
+00
+ENDCHAR
+STARTCHAR uni21C6
+ENCODING 8646
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+40
+F8
+40
+20
+10
+F8
+10
+20
+00
+ENDCHAR
+STARTCHAR uni21CB
+ENCODING 8651
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+20
+40
+F8
+00
+F8
+10
+20
+00
+ENDCHAR
+STARTCHAR uni21CC
+ENCODING 8652
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+20
+10
+F8
+00
+F8
+40
+20
+00
+ENDCHAR
+STARTCHAR arrowdblleft
+ENCODING 8656
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+10
+20
+7C
+C0
+7C
+20
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdblup
+ENCODING 8657
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+50
+D8
+50
+50
+50
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdblright
+ENCODING 8658
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+10
+F8
+0C
+F8
+10
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdbldown
+ENCODING 8659
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+50
+50
+50
+D8
+50
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdblboth
+ENCODING 8660
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+48
+FC
+84
+FC
+48
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21D5
+ENCODING 8661
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+D8
+50
+50
+50
+50
+D8
+50
+20
+00
+ENDCHAR
+STARTCHAR universal
+ENCODING 8704
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+F8
+88
+50
+50
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2201
+ENCODING 8705
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+50
+40
+40
+40
+50
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR partialdiff
+ENCODING 8706
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+30
+48
+08
+38
+48
+48
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR existential
+ENCODING 8707
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+08
+08
+78
+08
+08
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2204
+ENCODING 8708
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+10
+F8
+28
+28
+78
+28
+28
+F8
+40
+40
+00
+ENDCHAR
+STARTCHAR emptyset
+ENCODING 8709
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+34
+48
+94
+A4
+48
+B0
+00
+00
+00
+ENDCHAR
+STARTCHAR Delta
+ENCODING 8710
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+50
+50
+50
+88
+88
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR gradient
+ENCODING 8711
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+88
+88
+50
+50
+50
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR element
+ENCODING 8712
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+78
+80
+F0
+80
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR notelement
+ENCODING 8713
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+10
+78
+A0
+F0
+A0
+78
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR suchthat
+ENCODING 8715
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F0
+08
+78
+08
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni220C
+ENCODING 8716
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+10
+10
+F0
+28
+78
+28
+F0
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR product
+ENCODING 8719
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+50
+50
+50
+50
+50
+50
+50
+50
+50
+00
+00
+ENDCHAR
+STARTCHAR uni2210
+ENCODING 8720
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+50
+50
+50
+50
+F8
+00
+00
+ENDCHAR
+STARTCHAR summation
+ENCODING 8721
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+80
+40
+20
+10
+10
+20
+40
+80
+F8
+00
+00
+ENDCHAR
+STARTCHAR minus
+ENCODING 8722
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+F8
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2213
+ENCODING 8723
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+20
+20
+F8
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8725
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+08
+10
+10
+20
+20
+40
+40
+80
+80
+00
+00
+ENDCHAR
+STARTCHAR uni2218
+ENCODING 8728
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+30
+48
+48
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 8729
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+30
+78
+78
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR radical
+ENCODING 8730
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+04
+04
+08
+08
+90
+50
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR proportional
+ENCODING 8733
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+28
+50
+28
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR infinity
+ENCODING 8734
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+50
+A8
+50
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR orthogonal
+ENCODING 8735
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+80
+80
+80
+80
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2221
+ENCODING 8737
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+10
+10
+F0
+28
+48
+7C
+08
+08
+00
+ENDCHAR
+STARTCHAR uni2223
+ENCODING 8739
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2224
+ENCODING 8740
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+28
+30
+20
+60
+A0
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2225
+ENCODING 8741
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+50
+50
+50
+50
+50
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2226
+ENCODING 8742
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+50
+58
+70
+D0
+50
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR logicaland
+ENCODING 8743
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+20
+50
+50
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR logicalor
+ENCODING 8744
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+88
+88
+50
+50
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR intersection
+ENCODING 8745
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+70
+88
+88
+88
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR union
+ENCODING 8746
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR integral
+ENCODING 8747
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+28
+20
+20
+20
+20
+20
+20
+A0
+40
+00
+00
+ENDCHAR
+STARTCHAR uni222E
+ENCODING 8750
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+28
+20
+70
+A8
+A8
+70
+20
+A0
+40
+00
+00
+ENDCHAR
+STARTCHAR similar
+ENCODING 8764
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+40
+A8
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2243
+ENCODING 8771
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+40
+A8
+10
+00
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR congruent
+ENCODING 8773
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+40
+A8
+10
+00
+F8
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR approxequal
+ENCODING 8776
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+40
+A8
+50
+A8
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2249
+ENCODING 8777
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+60
+A8
+70
+A8
+30
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2259
+ENCODING 8793
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+50
+00
+F8
+00
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni225F
+ENCODING 8799
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+50
+10
+20
+00
+20
+F8
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR notequal
+ENCODING 8800
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+10
+10
+F8
+20
+F8
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR equivalence
+ENCODING 8801
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+00
+F8
+00
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2262
+ENCODING 8802
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+F8
+20
+F8
+20
+F8
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2263
+ENCODING 8803
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+00
+F8
+00
+F8
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 8804
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+18
+60
+80
+60
+18
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 8805
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+C0
+30
+08
+30
+C0
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni226A
+ENCODING 8810
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+24
+48
+90
+48
+24
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni226B
+ENCODING 8811
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+90
+48
+24
+48
+90
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR propersubset
+ENCODING 8834
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+78
+80
+80
+80
+80
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR propersuperset
+ENCODING 8835
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F0
+08
+08
+08
+08
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR notsubset
+ENCODING 8836
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+78
+A0
+A0
+A0
+A0
+78
+20
+00
+00
+ENDCHAR
+STARTCHAR uni2285
+ENCODING 8837
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+F0
+28
+28
+28
+28
+F0
+20
+00
+00
+ENDCHAR
+STARTCHAR reflexsubset
+ENCODING 8838
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+78
+80
+80
+80
+80
+78
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR reflexsuperset
+ENCODING 8839
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F0
+08
+08
+08
+08
+F0
+00
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2288
+ENCODING 8840
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+78
+A0
+A0
+A0
+A0
+78
+20
+F8
+20
+00
+00
+ENDCHAR
+STARTCHAR uni2289
+ENCODING 8841
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+F0
+28
+28
+28
+28
+F0
+20
+F8
+20
+00
+00
+ENDCHAR
+STARTCHAR uni228A
+ENCODING 8842
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+78
+80
+80
+80
+80
+78
+20
+F8
+20
+00
+00
+ENDCHAR
+STARTCHAR uni228B
+ENCODING 8843
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F0
+08
+08
+08
+08
+F0
+20
+F8
+20
+00
+00
+ENDCHAR
+STARTCHAR circleplus
+ENCODING 8853
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+70
+A8
+F8
+A8
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2296
+ENCODING 8854
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+70
+88
+F8
+88
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR circlemultiply
+ENCODING 8855
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+70
+D8
+A8
+D8
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2298
+ENCODING 8856
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+70
+98
+A8
+C8
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2299
+ENCODING 8857
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+70
+88
+A8
+88
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni229E
+ENCODING 8862
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+A8
+F8
+A8
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni229F
+ENCODING 8863
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+88
+F8
+88
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A0
+ENCODING 8864
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+D8
+A8
+D8
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A1
+ENCODING 8865
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+F8
+88
+A8
+88
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A2
+ENCODING 8866
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+80
+80
+F8
+80
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A3
+ENCODING 8867
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+08
+08
+08
+F8
+08
+08
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A4
+ENCODING 8868
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+F8
+20
+20
+20
+20
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR perpendicular
+ENCODING 8869
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+20
+20
+20
+20
+20
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A6
+ENCODING 8870
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+40
+40
+40
+70
+40
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A7
+ENCODING 8871
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+40
+40
+70
+40
+70
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A8
+ENCODING 8872
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+80
+F8
+80
+F8
+80
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A9
+ENCODING 8873
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+A0
+A0
+A0
+B8
+A0
+A0
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22C0
+ENCODING 8896
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+50
+50
+50
+50
+88
+88
+88
+00
+00
+ENDCHAR
+STARTCHAR uni22C1
+ENCODING 8897
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+88
+88
+50
+50
+50
+50
+20
+20
+20
+00
+00
+ENDCHAR
+STARTCHAR uni22C2
+ENCODING 8898
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+88
+88
+88
+88
+88
+88
+88
+88
+88
+00
+00
+ENDCHAR
+STARTCHAR uni22C3
+ENCODING 8899
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+88
+88
+88
+88
+88
+88
+88
+88
+88
+70
+00
+00
+ENDCHAR
+STARTCHAR dotmath
+ENCODING 8901
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+20
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22EE
+ENCODING 8942
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+00
+00
+20
+00
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22EF
+ENCODING 8943
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+A8
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22F0
+ENCODING 8944
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+08
+00
+00
+20
+00
+00
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22F1
+ENCODING 8945
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+00
+00
+20
+00
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2300
+ENCODING 8960
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+98
+A8
+C8
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR house
+ENCODING 8962
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+20
+50
+88
+88
+88
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2308
+ENCODING 8968
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+38
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR uni2309
+ENCODING 8969
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+70
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR uni230A
+ENCODING 8970
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+38
+00
+ENDCHAR
+STARTCHAR uni230B
+ENCODING 8971
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+70
+00
+ENDCHAR
+STARTCHAR revlogicalnot
+ENCODING 8976
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+78
+40
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR integraltp
+ENCODING 8992
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+14
+10
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR integralbt
+ENCODING 8993
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+10
+50
+20
+00
+ENDCHAR
+STARTCHAR uni23BA
+ENCODING 9146
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+FC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BB
+ENCODING 9147
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+FC
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BC
+ENCODING 9148
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BD
+ENCODING 9149
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 9225
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+A0
+A0
+E0
+A0
+BC
+08
+08
+08
+08
+00
+00
+ENDCHAR
+STARTCHAR uni240A
+ENCODING 9226
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+80
+80
+80
+9C
+F0
+18
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240B
+ENCODING 9227
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+A0
+A0
+A0
+5C
+48
+08
+08
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240C
+ENCODING 9228
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+E0
+80
+C0
+9C
+90
+1C
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240D
+ENCODING 9229
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+80
+80
+98
+74
+18
+14
+14
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2420
+ENCODING 9248
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+80
+40
+38
+D4
+18
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2423
+ENCODING 9251
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+88
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2424
+ENCODING 9252
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+A0
+E0
+E0
+E0
+B0
+10
+10
+10
+1C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2440
+ENCODING 9280
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+38
+28
+28
+20
+A0
+A0
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2441
+ENCODING 9281
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+08
+08
+08
+F8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2442
+ENCODING 9282
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+88
+88
+88
+F8
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2443
+ENCODING 9283
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+20
+20
+F8
+88
+88
+88
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2444
+ENCODING 9284
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+F8
+A8
+20
+20
+20
+A8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2445
+ENCODING 9285
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+88
+D8
+A8
+D8
+88
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9472
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+FC
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2501
+ENCODING 9473
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+FC
+FC
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9474
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2503
+ENCODING 9475
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2504
+ENCODING 9476
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+B4
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2505
+ENCODING 9477
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+B4
+B4
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2506
+ENCODING 9478
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+00
+20
+20
+20
+20
+00
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2507
+ENCODING 9479
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+00
+30
+30
+30
+30
+00
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2508
+ENCODING 9480
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+B4
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2509
+ENCODING 9481
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+B4
+B4
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni250A
+ENCODING 9482
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+00
+20
+20
+00
+20
+20
+00
+20
+20
+ENDCHAR
+STARTCHAR uni250B
+ENCODING 9483
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+00
+30
+30
+00
+30
+30
+00
+30
+30
+ENDCHAR
+STARTCHAR SF010000
+ENCODING 9484
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+3F
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni250D
+ENCODING 9485
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+3F
+3F
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni250E
+ENCODING 9486
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+3F
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni250F
+ENCODING 9487
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+3F
+3F
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR SF030000
+ENCODING 9488
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+E0
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2511
+ENCODING 9489
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+E0
+E0
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2512
+ENCODING 9490
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+F0
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2513
+ENCODING 9491
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+F0
+F0
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR SF020000
+ENCODING 9492
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+3F
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2515
+ENCODING 9493
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+3F
+3F
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2516
+ENCODING 9494
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+3F
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2517
+ENCODING 9495
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+3F
+3F
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF040000
+ENCODING 9496
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2519
+ENCODING 9497
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+E0
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni251A
+ENCODING 9498
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+F0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni251B
+ENCODING 9499
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+F0
+F0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF080000
+ENCODING 9500
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+3F
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni251D
+ENCODING 9501
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+3F
+3F
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni251E
+ENCODING 9502
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+3F
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni251F
+ENCODING 9503
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+3F
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2520
+ENCODING 9504
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+3F
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2521
+ENCODING 9505
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+3F
+3F
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2522
+ENCODING 9506
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+3F
+3F
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2523
+ENCODING 9507
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+3F
+3F
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR SF090000
+ENCODING 9508
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+E0
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2525
+ENCODING 9509
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+E0
+E0
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2526
+ENCODING 9510
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+E0
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2527
+ENCODING 9511
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+F0
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2528
+ENCODING 9512
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+F0
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2529
+ENCODING 9513
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+F0
+E0
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni252A
+ENCODING 9514
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+E0
+F0
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni252B
+ENCODING 9515
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+F0
+F0
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR SF060000
+ENCODING 9516
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni252D
+ENCODING 9517
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+E0
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni252E
+ENCODING 9518
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+3F
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni252F
+ENCODING 9519
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+FF
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2530
+ENCODING 9520
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+FF
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2531
+ENCODING 9521
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+E0
+FF
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2532
+ENCODING 9522
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+3F
+FF
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2533
+ENCODING 9523
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+FF
+FF
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR SF070000
+ENCODING 9524
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2535
+ENCODING 9525
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+E0
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2536
+ENCODING 9526
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+3F
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2537
+ENCODING 9527
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+FF
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2538
+ENCODING 9528
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2539
+ENCODING 9529
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+F0
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni253A
+ENCODING 9530
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+3F
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni253B
+ENCODING 9531
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+FF
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF050000
+ENCODING 9532
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni253D
+ENCODING 9533
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+E0
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni253E
+ENCODING 9534
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+3F
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni253F
+ENCODING 9535
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+FF
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2540
+ENCODING 9536
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2541
+ENCODING 9537
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+FF
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2542
+ENCODING 9538
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+FF
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2543
+ENCODING 9539
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+F0
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2544
+ENCODING 9540
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+3F
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2545
+ENCODING 9541
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+E0
+FF
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2546
+ENCODING 9542
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+3F
+FF
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni2547
+ENCODING 9543
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+FF
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2548
+ENCODING 9544
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+FF
+FF
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2549
+ENCODING 9545
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+F0
+FF
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni254A
+ENCODING 9546
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+3F
+FF
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni254B
+ENCODING 9547
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+FF
+FF
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni254C
+ENCODING 9548
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+EC
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni254D
+ENCODING 9549
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+EC
+EC
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni254E
+ENCODING 9550
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+00
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni254F
+ENCODING 9551
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+00
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR SF430000
+ENCODING 9552
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+FC
+00
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF240000
+ENCODING 9553
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+50
+50
+50
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF510000
+ENCODING 9554
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+3F
+20
+3F
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF520000
+ENCODING 9555
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+7F
+50
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF390000
+ENCODING 9556
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+7C
+40
+5C
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF220000
+ENCODING 9557
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+E0
+20
+E0
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF210000
+ENCODING 9558
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+F0
+50
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF250000
+ENCODING 9559
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+F0
+10
+D0
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF500000
+ENCODING 9560
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+3C
+20
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF490000
+ENCODING 9561
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+50
+7C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF380000
+ENCODING 9562
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+5C
+40
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF280000
+ENCODING 9563
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+E0
+20
+E0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF270000
+ENCODING 9564
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+50
+F0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF260000
+ENCODING 9565
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+D0
+10
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF360000
+ENCODING 9566
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+3C
+20
+3C
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF370000
+ENCODING 9567
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+50
+5C
+50
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF420000
+ENCODING 9568
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+5C
+40
+5C
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF190000
+ENCODING 9569
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+E0
+20
+E0
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF200000
+ENCODING 9570
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+50
+D0
+50
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF230000
+ENCODING 9571
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+D0
+10
+D0
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF470000
+ENCODING 9572
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+FC
+00
+FC
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF480000
+ENCODING 9573
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+FC
+50
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF410000
+ENCODING 9574
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+FC
+00
+DC
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF450000
+ENCODING 9575
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+FC
+00
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF460000
+ENCODING 9576
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+50
+FC
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF400000
+ENCODING 9577
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+DC
+00
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF540000
+ENCODING 9578
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+FC
+20
+FC
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF530000
+ENCODING 9579
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+50
+FC
+50
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR SF440000
+ENCODING 9580
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+50
+50
+50
+50
+50
+DC
+00
+DC
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR uni256D
+ENCODING 9581
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+0C
+10
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni256E
+ENCODING 9582
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+80
+40
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni256F
+ENCODING 9583
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+40
+80
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2570
+ENCODING 9584
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+10
+0C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2571
+ENCODING 9585
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+04
+04
+08
+08
+10
+10
+20
+20
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR uni2572
+ENCODING 9586
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+80
+80
+40
+40
+20
+20
+10
+10
+08
+08
+04
+04
+ENDCHAR
+STARTCHAR uni2573
+ENCODING 9587
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+84
+84
+48
+48
+30
+30
+30
+30
+48
+48
+84
+84
+ENDCHAR
+STARTCHAR uni2574
+ENCODING 9588
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2575
+ENCODING 9589
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2576
+ENCODING 9590
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+3F
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2577
+ENCODING 9591
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2578
+ENCODING 9592
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+E0
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2579
+ENCODING 9593
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni257A
+ENCODING 9594
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+3F
+3F
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni257B
+ENCODING 9595
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni257C
+ENCODING 9596
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+3F
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni257D
+ENCODING 9597
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni257E
+ENCODING 9598
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+E0
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni257F
+ENCODING 9599
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR upblock
+ENCODING 9600
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+FC
+FC
+FC
+FC
+FC
+FC
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2581
+ENCODING 9601
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+ENDCHAR
+STARTCHAR uni2582
+ENCODING 9602
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR uni2583
+ENCODING 9603
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FC
+FC
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR dnblock
+ENCODING 9604
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+FC
+FC
+FC
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR uni2585
+ENCODING 9605
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR uni2586
+ENCODING 9606
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR uni2587
+ENCODING 9607
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR block
+ENCODING 9608
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR uni2589
+ENCODING 9609
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni258A
+ENCODING 9610
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+ENDCHAR
+STARTCHAR uni258B
+ENCODING 9611
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+ENDCHAR
+STARTCHAR lfblock
+ENCODING 9612
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR uni258D
+ENCODING 9613
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni258E
+ENCODING 9614
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni258F
+ENCODING 9615
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR rtblock
+ENCODING 9616
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR ltshade
+ENCODING 9617
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+A8
+00
+54
+00
+A8
+00
+54
+00
+A8
+00
+54
+00
+ENDCHAR
+STARTCHAR shade
+ENCODING 9618
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+A8
+54
+A8
+54
+A8
+54
+A8
+54
+A8
+54
+A8
+54
+ENDCHAR
+STARTCHAR dkshade
+ENCODING 9619
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+A8
+FC
+54
+FC
+A8
+FC
+54
+FC
+A8
+FC
+54
+FC
+ENDCHAR
+STARTCHAR uni2594
+ENCODING 9620
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+FC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2595
+ENCODING 9621
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+04
+04
+04
+04
+04
+04
+04
+04
+04
+04
+04
+04
+ENDCHAR
+STARTCHAR uni2596
+ENCODING 9622
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR uni2597
+ENCODING 9623
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+00
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2598
+ENCODING 9624
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2599
+ENCODING 9625
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+FC
+FC
+FC
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR uni259A
+ENCODING 9626
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni259B
+ENCODING 9627
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+FC
+FC
+FC
+FC
+FC
+FC
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR uni259C
+ENCODING 9628
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+FC
+FC
+FC
+FC
+FC
+FC
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni259D
+ENCODING 9629
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni259E
+ENCODING 9630
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR uni259F
+ENCODING 9631
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+FC
+FC
+FC
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR filledbox
+ENCODING 9632
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+F8
+F8
+F8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR H22073
+ENCODING 9633
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+F8
+88
+88
+88
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR H18543
+ENCODING 9642
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+78
+78
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR H18551
+ENCODING 9643
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+78
+48
+48
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR filledrect
+ENCODING 9644
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+FC
+FC
+FC
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25AD
+ENCODING 9645
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+FC
+84
+84
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25AE
+ENCODING 9646
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+78
+78
+78
+78
+78
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR triagup
+ENCODING 9650
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+70
+70
+70
+F8
+F8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B3
+ENCODING 9651
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+20
+50
+50
+50
+88
+88
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B6
+ENCODING 9654
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+C0
+F0
+F8
+F0
+C0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B7
+ENCODING 9655
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+C0
+B0
+88
+B0
+C0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B8
+ENCODING 9656
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+60
+78
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B9
+ENCODING 9657
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+60
+58
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR triagrt
+ENCODING 9658
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+C0
+F0
+FC
+F0
+C0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25BB
+ENCODING 9659
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+C0
+B0
+8C
+B0
+C0
+00
+00
+00
+ENDCHAR
+STARTCHAR triagdn
+ENCODING 9660
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+F8
+F8
+70
+70
+70
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25BD
+ENCODING 9661
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+F8
+88
+88
+50
+50
+50
+20
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C0
+ENCODING 9664
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+18
+78
+F8
+78
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C1
+ENCODING 9665
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+18
+68
+88
+68
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C2
+ENCODING 9666
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+18
+78
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C3
+ENCODING 9667
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+00
+18
+68
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR triaglf
+ENCODING 9668
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+0C
+3C
+FC
+3C
+0C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C5
+ENCODING 9669
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+0C
+34
+C4
+34
+0C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C6
+ENCODING 9670
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+20
+70
+F8
+70
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR lozenge
+ENCODING 9674
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+20
+50
+50
+88
+88
+50
+50
+20
+20
+00
+ENDCHAR
+STARTCHAR circle
+ENCODING 9675
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR H18533
+ENCODING 9679
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+F8
+F8
+F8
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR invbullet
+ENCODING 9688
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+FC
+FC
+FC
+FC
+CC
+84
+84
+CC
+FC
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR invcircle
+ENCODING 9689
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+FC
+FC
+FC
+FC
+CC
+B4
+B4
+CC
+FC
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR openbullet
+ENCODING 9702
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+30
+48
+48
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2639
+ENCODING 9785
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+48
+00
+30
+48
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR smileface
+ENCODING 9786
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+48
+00
+48
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR invsmileface
+ENCODING 9787
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+78
+FC
+B4
+FC
+B4
+CC
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR sun
+ENCODING 9788
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+20
+A8
+70
+D8
+70
+A8
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR female
+ENCODING 9792
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+00
+00
+70
+88
+88
+88
+70
+20
+70
+20
+ENDCHAR
+STARTCHAR uni2641
+ENCODING 9793
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+20
+70
+20
+70
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR male
+ENCODING 9794
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+1C
+0C
+74
+88
+88
+88
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR spade
+ENCODING 9824
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+78
+FC
+FC
+FC
+78
+30
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR club
+ENCODING 9827
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+30
+78
+30
+B4
+FC
+FC
+B4
+30
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR heart
+ENCODING 9829
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+50
+F8
+F8
+F8
+70
+70
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR diamond
+ENCODING 9830
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+20
+20
+70
+70
+F8
+70
+70
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2669
+ENCODING 9833
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+08
+08
+08
+08
+08
+38
+78
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR musicalnote
+ENCODING 9834
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+28
+20
+20
+20
+60
+E0
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR musicalnotedbl
+ENCODING 9835
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+60
+58
+48
+48
+48
+C8
+D8
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR uni266C
+ENCODING 9836
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+78
+48
+78
+48
+48
+C8
+D8
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR uni266D
+ENCODING 9837
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+80
+80
+B0
+C8
+88
+90
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni266E
+ENCODING 9838
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+00
+40
+48
+58
+68
+48
+58
+68
+48
+08
+00
+ENDCHAR
+STARTCHAR uni27E8
+ENCODING 10216
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+10
+10
+20
+20
+40
+20
+20
+10
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni27E9
+ENCODING 10217
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+40
+40
+20
+20
+10
+20
+20
+40
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR fi
+ENCODING 64257
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+48
+40
+E8
+48
+48
+48
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR fl
+ENCODING 64258
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+30
+50
+50
+F0
+50
+50
+50
+48
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFFFD
+ENCODING 65533
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+00
+70
+D8
+A8
+E8
+D8
+F8
+D8
+70
+00
+00
+00
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/courr12-iso-8859-1.bdf b/gui/themes/fonts/courr12-iso-8859-1.bdf
new file mode 100644
index 0000000000..fdd7cbacab
--- /dev/null
+++ b/gui/themes/fonts/courr12-iso-8859-1.bdf
@@ -0,0 +1,2926 @@
+STARTFONT 2.1
+COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT!
+COMMENT Generated with 'ucs2any.pl courR12.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1'
+COMMENT from an ISO10646-1 encoded source BDF font.
+COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000.
+FONT -Adobe-Courier-Medium-R-Normal--12-120-75-75-M-70-ISO8859-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 8 14 0 -3
+COMMENT $Xorg: $
+COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20
+COMMENT
+COMMENT +
+COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated.
+COMMENT Copyright 1988, 1994 Digital Equipment Corporation.
+COMMENT
+COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be
+COMMENT registered in certain jurisdictions.
+COMMENT Permission to use these trademarks is hereby granted only in
+COMMENT association with the images described in this file.
+COMMENT
+COMMENT Permission to use, copy, modify, distribute and sell this software
+COMMENT and its documentation for any purpose and without fee is hereby
+COMMENT granted, provided that the above copyright notices appear in all
+COMMENT copies and that both those copyright notices and this permission
+COMMENT notice appear in supporting documentation, and that the names of
+COMMENT Adobe Systems and Digital Equipment Corporation not be used in
+COMMENT advertising or publicity pertaining to distribution of the software
+COMMENT without specific, written prior permission. Adobe Systems and
+COMMENT Digital Equipment Corporation make no representations about the
+COMMENT suitability of this software for any purpose. It is provided "as
+COMMENT is" without express or implied warranty.
+COMMENT -
+STARTPROPERTIES 26
+FOUNDRY "Adobe"
+FAMILY_NAME "Courier"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "M"
+AVERAGE_WIDTH 70
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 8
+X_HEIGHT 6
+FONT_ASCENT 10
+FONT_DESCENT 3
+FACE_NAME "Courier"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Courier"
+DEFAULT_CHAR 0
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Courier"
+ENDPROPERTIES
+CHARS 192
+STARTCHAR defaultchar
+ENCODING 0
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+AA
+00
+82
+00
+82
+00
+AA
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 1 9 3 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 3 3 2 5
+BITMAP
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+14
+14
+7E
+28
+28
+FC
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 10 1 -1
+BITMAP
+20
+70
+88
+80
+60
+30
+88
+88
+70
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 1 0
+BITMAP
+60
+90
+64
+18
+60
+98
+24
+18
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+38
+48
+40
+22
+74
+88
+8C
+72
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 1 3 3 5
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 3 11 3 -2
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 3 11 1 -2
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 5 1 3
+BITMAP
+20
+20
+F8
+20
+50
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+20
+F8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 2 3 1 -1
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 1 1 3
+BITMAP
+F8
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 1 1 2 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 10 1 -1
+BITMAP
+04
+08
+08
+10
+10
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+20
+E0
+20
+20
+20
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+10
+20
+40
+88
+F8
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+08
+30
+08
+08
+88
+70
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+08
+18
+28
+28
+48
+88
+FC
+08
+1C
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+7C
+40
+40
+40
+78
+04
+04
+84
+78
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+38
+40
+80
+80
+F0
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+F8
+88
+10
+10
+10
+10
+20
+20
+20
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+88
+78
+08
+10
+E0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 1 5 3 0
+BITMAP
+80
+00
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 2 6 2 -1
+BITMAP
+40
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 4 7 1 0
+BITMAP
+10
+20
+40
+80
+40
+20
+10
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 3 1 2
+BITMAP
+F8
+00
+F8
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 4 7 2 0
+BITMAP
+80
+40
+20
+10
+20
+40
+80
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+70
+88
+08
+10
+20
+20
+00
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 1 0
+BITMAP
+70
+88
+98
+A8
+A8
+9C
+80
+70
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+70
+10
+28
+28
+7C
+44
+44
+EE
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+F8
+44
+44
+78
+44
+44
+44
+F8
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+70
+88
+88
+80
+80
+88
+88
+70
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+F8
+44
+44
+44
+44
+44
+44
+F8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+FC
+44
+50
+70
+50
+40
+44
+FC
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+FC
+44
+54
+70
+50
+40
+40
+F0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+70
+88
+88
+80
+98
+88
+88
+70
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+EE
+44
+44
+7C
+44
+44
+44
+EE
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+F8
+20
+20
+20
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+78
+10
+10
+10
+10
+90
+90
+60
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+EC
+48
+50
+60
+70
+48
+44
+E6
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+E0
+40
+40
+40
+40
+44
+44
+FC
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+C6
+6C
+6C
+54
+54
+54
+44
+EE
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+CE
+64
+64
+54
+54
+4C
+4C
+E4
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+70
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+F8
+4C
+44
+4C
+78
+40
+40
+F0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 -1
+BITMAP
+70
+88
+88
+88
+88
+88
+88
+70
+18
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+F8
+44
+44
+78
+48
+44
+44
+E6
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+78
+88
+80
+E0
+38
+08
+88
+F0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+FE
+92
+92
+10
+10
+10
+10
+7C
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+EE
+44
+44
+44
+44
+44
+6C
+38
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+EE
+44
+44
+6C
+28
+28
+38
+10
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+EE
+44
+54
+54
+54
+6C
+28
+28
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+EE
+44
+28
+10
+28
+28
+44
+EE
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+EE
+44
+28
+28
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+F8
+88
+90
+20
+20
+48
+88
+F8
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 2 11 3 -2
+BITMAP
+C0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+C0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 10 1 -1
+BITMAP
+80
+40
+40
+20
+20
+10
+10
+08
+08
+04
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 2 11 2 -2
+BITMAP
+C0
+40
+40
+40
+40
+40
+40
+40
+40
+40
+C0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 3 1 5
+BITMAP
+20
+50
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 1 0 -3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 2 2 1 7
+BITMAP
+80
+40
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 6 1 0
+BITMAP
+F0
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+C0
+40
+40
+78
+44
+44
+44
+44
+B8
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+70
+88
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+18
+08
+08
+78
+88
+88
+88
+88
+74
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+70
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+38
+40
+40
+F8
+40
+40
+40
+40
+F0
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 1 -3
+BITMAP
+74
+88
+88
+88
+88
+78
+08
+08
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+C0
+40
+40
+58
+64
+44
+44
+44
+EE
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+20
+00
+00
+E0
+20
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 4 12 1 -3
+BITMAP
+10
+00
+00
+F0
+10
+10
+10
+10
+10
+10
+10
+E0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+C0
+40
+40
+4C
+50
+60
+50
+48
+C6
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+E0
+20
+20
+20
+20
+20
+20
+20
+FC
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 6 0 0
+BITMAP
+E8
+54
+54
+54
+54
+D6
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 6 0 0
+BITMAP
+B8
+64
+44
+44
+44
+E6
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 0 -3
+BITMAP
+B8
+44
+44
+44
+44
+78
+40
+40
+E0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 1 -3
+BITMAP
+74
+88
+88
+88
+88
+78
+08
+08
+1C
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+B8
+40
+40
+40
+40
+F0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+70
+88
+70
+08
+88
+70
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 1 0
+BITMAP
+40
+40
+F8
+40
+40
+40
+44
+38
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 6 0 0
+BITMAP
+CC
+44
+44
+44
+44
+3A
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 6 0 0
+BITMAP
+EE
+44
+44
+28
+38
+10
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 6 0 0
+BITMAP
+EE
+44
+54
+54
+28
+28
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 6 0 0
+BITMAP
+EE
+28
+10
+28
+44
+C6
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 9 0 -3
+BITMAP
+EE
+44
+44
+28
+38
+10
+10
+10
+60
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+F8
+90
+20
+40
+88
+F8
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 3 10 2 -2
+BITMAP
+20
+40
+40
+40
+80
+40
+40
+40
+40
+20
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 1 10 3 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 3 10 2 -2
+BITMAP
+80
+40
+40
+40
+20
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 3 1 2
+BITMAP
+48
+A8
+90
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 1 9 3 -3
+BITMAP
+80
+00
+00
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 -1
+BITMAP
+20
+20
+70
+A8
+A0
+A8
+70
+20
+20
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 1 0
+BITMAP
+30
+48
+40
+F8
+20
+20
+44
+F8
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 6 0 1
+BITMAP
+84
+78
+48
+48
+78
+84
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+EE
+44
+28
+7C
+10
+7C
+10
+38
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 1 10 3 -2
+BITMAP
+80
+80
+80
+80
+00
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 10 1 -1
+BITMAP
+78
+48
+60
+90
+88
+48
+30
+90
+90
+F0
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 3 1 2 7
+BITMAP
+A0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+38
+44
+9A
+A2
+A2
+9A
+44
+38
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 4 6 1 2
+BITMAP
+60
+10
+70
+50
+00
+F0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+24
+48
+90
+48
+24
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 3 1 2
+BITMAP
+F8
+08
+08
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 1 1 3
+BITMAP
+F8
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+38
+44
+BA
+AA
+B2
+AA
+44
+38
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 1 1 7
+BITMAP
+F8
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 4 4 1 4
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+F8
+20
+00
+F8
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 4 5 1 3
+BITMAP
+60
+90
+20
+40
+F0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 4 5 1 3
+BITMAP
+60
+90
+20
+90
+60
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 2 2 3 7
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 9 0 -3
+BITMAP
+CC
+44
+44
+44
+44
+7A
+40
+40
+40
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 10 0 -1
+BITMAP
+7C
+A8
+A8
+A8
+68
+28
+28
+28
+28
+6C
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 1 1 3 3
+BITMAP
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 3 3 2 -3
+BITMAP
+40
+20
+C0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 3 5 2 3
+BITMAP
+40
+C0
+40
+40
+E0
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 4 6 1 2
+BITMAP
+60
+90
+90
+60
+00
+F0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 5 1 1
+BITMAP
+90
+48
+24
+48
+90
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 8 10 0 -1
+BITMAP
+40
+C1
+42
+44
+E8
+12
+26
+4A
+8F
+02
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 8 10 0 -1
+BITMAP
+40
+C1
+42
+44
+E8
+16
+29
+42
+84
+0F
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 8 10 0 -1
+BITMAP
+60
+91
+22
+94
+68
+12
+26
+4A
+8F
+02
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 -2
+BITMAP
+20
+00
+20
+20
+40
+80
+88
+70
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+20
+10
+00
+70
+10
+28
+28
+7C
+44
+44
+EE
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+08
+10
+00
+70
+10
+28
+28
+7C
+44
+44
+EE
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+10
+28
+00
+70
+10
+28
+28
+7C
+44
+44
+EE
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+28
+50
+00
+70
+10
+28
+28
+7C
+44
+44
+EE
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+28
+00
+70
+10
+28
+28
+7C
+44
+44
+EE
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+10
+28
+10
+70
+10
+28
+28
+7C
+44
+44
+EE
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+7C
+30
+50
+5C
+50
+F0
+90
+9C
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 11 1 -3
+BITMAP
+70
+88
+88
+80
+80
+88
+88
+70
+20
+10
+60
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+20
+10
+00
+FC
+44
+48
+78
+48
+44
+44
+FC
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+08
+10
+00
+FC
+44
+48
+78
+48
+44
+44
+FC
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+10
+28
+00
+FC
+44
+48
+78
+48
+44
+44
+FC
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+28
+00
+FC
+44
+48
+78
+48
+44
+44
+FC
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+40
+20
+00
+F8
+20
+20
+20
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+10
+20
+00
+F8
+20
+20
+20
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+20
+50
+00
+F8
+20
+20
+20
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+50
+00
+F8
+20
+20
+20
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+F8
+44
+44
+E4
+44
+44
+44
+F8
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+14
+28
+00
+EE
+64
+54
+54
+4C
+4C
+44
+E4
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+10
+20
+00
+70
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+50
+00
+70
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+88
+50
+20
+50
+88
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 10 1 -1
+BITMAP
+08
+70
+98
+A8
+A8
+A8
+A8
+C8
+70
+80
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+20
+10
+00
+EE
+44
+44
+44
+44
+44
+6C
+38
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+08
+10
+00
+EE
+44
+44
+44
+44
+44
+6C
+38
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+10
+28
+00
+EE
+44
+44
+44
+44
+44
+6C
+38
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+28
+00
+EE
+44
+44
+44
+44
+44
+6C
+38
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+08
+10
+00
+EE
+44
+28
+10
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+E0
+40
+78
+44
+44
+78
+40
+E0
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+30
+48
+48
+48
+50
+48
+44
+54
+D8
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+40
+20
+00
+F0
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+10
+20
+00
+F0
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+20
+50
+00
+F0
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+28
+50
+00
+F0
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 8 1 0
+BITMAP
+50
+00
+F0
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+20
+50
+20
+F0
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 6 0 0
+BITMAP
+6C
+12
+7E
+90
+92
+6C
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 -3
+BITMAP
+70
+88
+80
+80
+88
+70
+20
+10
+60
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+70
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+10
+20
+00
+70
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+70
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+70
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+E0
+20
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+10
+20
+00
+E0
+20
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+E0
+20
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+E0
+20
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+C0
+38
+60
+90
+78
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+28
+50
+00
+B8
+64
+44
+44
+44
+E6
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+20
+40
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+A0
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+00
+F8
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 5 8 1 -1
+BITMAP
+08
+70
+98
+A8
+A8
+C8
+70
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+20
+10
+00
+CC
+44
+44
+44
+44
+3A
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+10
+20
+00
+CC
+44
+44
+44
+44
+3A
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+10
+28
+00
+CC
+44
+44
+44
+44
+3A
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+28
+00
+CC
+44
+44
+44
+44
+3A
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 12 0 -3
+BITMAP
+08
+10
+00
+EE
+44
+44
+28
+38
+10
+10
+10
+60
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+C0
+40
+40
+78
+44
+44
+44
+44
+78
+40
+40
+E0
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 600 0
+DWIDTH 7 0
+BBX 7 11 0 -3
+BITMAP
+28
+00
+EE
+44
+44
+28
+38
+10
+10
+10
+60
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/fixed5x8-iso-8859-1.bdf b/gui/themes/fonts/fixed5x8-iso-8859-1.bdf
new file mode 100644
index 0000000000..80ea041db5
--- /dev/null
+++ b/gui/themes/fonts/fixed5x8-iso-8859-1.bdf
@@ -0,0 +1,3380 @@
+STARTFONT 2.1
+COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT!
+COMMENT Generated with 'ucs2any.pl 5x8.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1'
+COMMENT from an ISO10646-1 encoded source BDF font.
+COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000.
+COMMENT Id: 5x8.bdf,v 1.28 2001-04-03 13:37:48+01 mgk25 Exp mgk25 $
+COMMENT Send bug reports to Markus Kuhn <mkuhn@acm.org>
+FONT -Misc-Fixed-Medium-R-Normal--8-80-75-75-C-50-ISO8859-1
+SIZE 11 75 75
+FONTBOUNDINGBOX 5 8 0 -1
+STARTPROPERTIES 21
+FONTNAME_REGISTRY ""
+FOUNDRY "Misc"
+FAMILY_NAME "Fixed"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 8
+POINT_SIZE 80
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 50
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+FONT_DESCENT 1
+FONT_ASCENT 7
+COPYRIGHT "Public domain font. Share and enjoy."
+DEFAULT_CHAR 0
+CAP_HEIGHT 6
+X_HEIGHT 4
+ENDPROPERTIES
+CHARS 223
+STARTCHAR defaultchar
+ENCODING 0
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+A0
+10
+80
+10
+80
+50
+00
+ENDCHAR
+STARTCHAR uni25C6
+ENCODING 1
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+20
+70
+F8
+70
+20
+00
+ENDCHAR
+STARTCHAR shade
+ENCODING 2
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+50
+A8
+50
+A8
+50
+A8
+50
+A8
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 3
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+A0
+70
+20
+20
+ENDCHAR
+STARTCHAR uni240C
+ENCODING 4
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+E0
+80
+C0
+B8
+A0
+30
+20
+20
+ENDCHAR
+STARTCHAR uni240D
+ENCODING 5
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+60
+80
+80
+60
+30
+28
+30
+28
+ENDCHAR
+STARTCHAR uni240A
+ENCODING 6
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+80
+80
+80
+E0
+38
+20
+30
+20
+ENDCHAR
+STARTCHAR degree
+ENCODING 7
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+50
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 8
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+20
+70
+20
+00
+70
+00
+ENDCHAR
+STARTCHAR uni2424
+ENCODING 9
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+90
+D0
+B0
+90
+20
+20
+20
+38
+ENDCHAR
+STARTCHAR uni240B
+ENCODING 10
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+A0
+A0
+A0
+40
+38
+10
+10
+10
+ENDCHAR
+STARTCHAR SF040000
+ENCODING 11
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+E0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF030000
+ENCODING 12
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+E0
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF010000
+ENCODING 13
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+38
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF020000
+ENCODING 14
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF050000
+ENCODING 15
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+F8
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni23BA
+ENCODING 16
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BB
+ENCODING 17
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+F8
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 18
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BC
+ENCODING 19
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+F8
+00
+ENDCHAR
+STARTCHAR uni23BD
+ENCODING 20
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+F8
+ENDCHAR
+STARTCHAR SF080000
+ENCODING 21
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+38
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF090000
+ENCODING 22
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+E0
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF070000
+ENCODING 23
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF060000
+ENCODING 24
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+F8
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 25
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 26
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+10
+20
+40
+20
+10
+70
+00
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 27
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+40
+20
+10
+20
+40
+70
+00
+ENDCHAR
+STARTCHAR pi
+ENCODING 28
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+F8
+50
+50
+50
+00
+ENDCHAR
+STARTCHAR notequal
+ENCODING 29
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+20
+F0
+60
+F0
+40
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 30
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+50
+E0
+40
+50
+A0
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 31
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+20
+20
+20
+00
+20
+00
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+50
+50
+50
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+50
+50
+F8
+50
+F8
+50
+50
+00
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+70
+A0
+70
+28
+70
+20
+00
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+40
+50
+20
+50
+10
+00
+00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+40
+A0
+A0
+40
+A0
+A0
+50
+00
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+20
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+40
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+40
+20
+20
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+90
+60
+F0
+60
+90
+00
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+20
+20
+F8
+20
+20
+00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+00
+30
+20
+40
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+00
+20
+70
+20
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+10
+10
+20
+40
+80
+80
+00
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+50
+50
+50
+50
+20
+00
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+60
+20
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+90
+10
+60
+80
+F0
+00
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+F0
+20
+60
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+60
+A0
+F0
+20
+20
+00
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+F0
+80
+E0
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+80
+E0
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+F0
+10
+20
+20
+40
+40
+00
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+90
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+90
+90
+70
+10
+60
+00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+60
+60
+00
+60
+60
+00
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+30
+30
+00
+30
+20
+40
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+10
+20
+40
+40
+20
+10
+00
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+40
+20
+10
+10
+20
+40
+00
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+50
+10
+20
+00
+20
+00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+30
+48
+98
+A8
+A8
+90
+40
+30
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+90
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+E0
+90
+E0
+90
+90
+E0
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+90
+80
+80
+90
+60
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+E0
+90
+90
+90
+90
+E0
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+F0
+80
+E0
+80
+80
+F0
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+F0
+80
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+90
+80
+B0
+90
+60
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+90
+90
+F0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+70
+20
+20
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+70
+20
+20
+20
+A0
+40
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+90
+A0
+C0
+A0
+A0
+90
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+80
+80
+80
+80
+80
+F0
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+90
+F0
+F0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+90
+D0
+F0
+B0
+B0
+90
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+E0
+90
+90
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+90
+90
+D0
+B0
+60
+10
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+E0
+90
+90
+E0
+90
+90
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+90
+40
+20
+90
+60
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+70
+20
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+90
+90
+90
+90
+60
+60
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+90
+90
+90
+F0
+F0
+90
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+90
+90
+60
+60
+90
+90
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+88
+88
+50
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+F0
+10
+20
+40
+80
+F0
+00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+70
+40
+40
+40
+40
+70
+00
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+80
+80
+40
+20
+10
+10
+00
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+70
+10
+10
+10
+10
+70
+00
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+50
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+F0
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+40
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+70
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+80
+80
+E0
+90
+90
+E0
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+30
+40
+40
+30
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+10
+10
+70
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+60
+B0
+C0
+60
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+50
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+60
+90
+70
+10
+60
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+80
+80
+E0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+00
+60
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+10
+00
+10
+10
+10
+50
+20
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+80
+80
+90
+E0
+90
+90
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+20
+20
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+D0
+A8
+A8
+A8
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+E0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+E0
+90
+E0
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+70
+90
+70
+10
+10
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+A0
+D0
+80
+80
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+30
+60
+10
+60
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+40
+40
+E0
+40
+50
+20
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+50
+50
+50
+20
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+88
+A8
+A8
+50
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+90
+90
+70
+90
+60
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+F0
+20
+40
+F0
+00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+30
+40
+20
+C0
+20
+40
+30
+00
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+20
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+C0
+20
+40
+30
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+50
+A0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+00
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+20
+70
+A0
+A0
+70
+20
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+50
+E0
+40
+50
+A0
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+88
+70
+50
+70
+88
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+88
+50
+F8
+20
+F8
+20
+00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+00
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+70
+80
+E0
+90
+70
+10
+E0
+00
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+50
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+70
+A8
+C8
+C8
+A8
+70
+00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+30
+50
+30
+00
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+50
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+70
+10
+10
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+70
+E8
+D8
+E8
+D8
+70
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+70
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+50
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+20
+70
+20
+00
+70
+00
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+50
+10
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+60
+10
+60
+10
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+40
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+90
+90
+90
+E0
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+78
+E8
+E8
+68
+28
+28
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+20
+40
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+60
+20
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+50
+20
+00
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+A0
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+80
+80
+80
+A0
+60
+F0
+20
+00
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+80
+80
+A0
+D0
+10
+20
+70
+00
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+80
+40
+80
+60
+A0
+F0
+20
+00
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+20
+00
+20
+40
+50
+20
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+40
+20
+60
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+40
+60
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+60
+90
+60
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+50
+A0
+60
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+90
+00
+60
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+60
+90
+60
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+70
+A0
+A0
+F0
+A0
+B0
+00
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+90
+80
+80
+90
+60
+40
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+40
+20
+F0
+80
+E0
+80
+F0
+00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+40
+F0
+80
+E0
+80
+F0
+00
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+60
+90
+F0
+80
+E0
+80
+F0
+00
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+90
+00
+F0
+80
+E0
+80
+F0
+00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+40
+20
+70
+20
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+10
+20
+70
+20
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+50
+70
+20
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+50
+00
+70
+20
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+70
+48
+E8
+48
+48
+70
+00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+50
+A0
+90
+D0
+B0
+90
+90
+00
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+40
+20
+60
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+40
+60
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+60
+90
+60
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+50
+A0
+60
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+90
+00
+60
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+00
+50
+20
+50
+00
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+70
+B0
+B0
+D0
+D0
+E0
+00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+40
+20
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+40
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+60
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+90
+00
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+10
+20
+88
+50
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+80
+E0
+90
+90
+E0
+80
+00
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+60
+90
+A0
+A0
+90
+A0
+00
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+40
+20
+00
+70
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+40
+00
+70
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+50
+00
+70
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+50
+A0
+00
+70
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+50
+00
+70
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+60
+90
+60
+70
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+F0
+68
+B0
+78
+00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+30
+40
+40
+30
+20
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+40
+20
+00
+60
+B0
+C0
+60
+00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+40
+00
+60
+B0
+C0
+60
+00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+60
+90
+00
+60
+B0
+C0
+60
+00
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+50
+00
+60
+B0
+C0
+60
+00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+40
+20
+00
+60
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+10
+20
+00
+60
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+50
+00
+60
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+50
+00
+60
+20
+20
+70
+00
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+A0
+40
+A0
+10
+70
+90
+60
+00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+50
+A0
+00
+E0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+40
+20
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+40
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+60
+90
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+50
+A0
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+90
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+20
+00
+70
+00
+20
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+00
+00
+70
+B0
+D0
+E0
+00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+40
+20
+00
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+40
+00
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+60
+90
+00
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+90
+00
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+40
+00
+90
+90
+70
+90
+60
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+80
+80
+E0
+90
+E0
+80
+80
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+00
+90
+00
+90
+90
+70
+90
+60
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/fixed5x8-iso-8859-5.bdf b/gui/themes/fonts/fixed5x8-iso-8859-5.bdf
new file mode 100644
index 0000000000..7d0a93cb39
--- /dev/null
+++ b/gui/themes/fonts/fixed5x8-iso-8859-5.bdf
@@ -0,0 +1,2309 @@
+STARTFONT 2.1
+COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT!
+COMMENT Generated with 'ucs2any koi5x8-ucs.bdf /usr/share/fonts/X11/util/map-ISO8859-5 ISO8859-5'
+COMMENT from an ISO10646-1 encoded source BDF font.
+COMMENT ucs2any by Ben Collver <collver1@attbi.com>, 2003, based on
+COMMENT ucs2any.pl by Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>, 2000.
+COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT!
+COMMENT Generated with 'ucs2any.pl 5x8.bdf ../xcyr-2.3/tryfont/KOI8-C.TXT KOI8-C'
+COMMENT from an ISO10646-1 encoded source BDF font.
+COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 1999.
+COMMENT $Id$
+COMMENT Send bug reports to Markus Kuhn <mkuhn@acm.org>
+COMMENT Changes 1999 by Serge Winitzki.
+COMMENT $XFree86$
+FONT -Misc-Fixed-Medium-R-Normal--8-80-75-75-C-50-ISO8859-5
+SIZE 11 75 75
+FONTBOUNDINGBOX 5 8 0 -1
+STARTPROPERTIES 22
+FONTNAME_REGISTRY ""
+FOUNDRY "Misc"
+FAMILY_NAME "Fixed"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 8
+POINT_SIZE 80
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 50
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "5"
+FONT_DESCENT 1
+FONT_ASCENT 7
+COPYRIGHT "Public domain font. Share and enjoy."
+DEFAULT_CHAR 0
+CAP_HEIGHT 6
+X_HEIGHT 4
+_XFREE86_GLYPH_RANGES "0_126 149 152_154 156_158 163 179 191_255"
+ENDPROPERTIES
+CHARS 185
+STARTCHAR uni25C6
+ENCODING 1
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+20
+70
+F8
+70
+20
+ENDCHAR
+STARTCHAR uni2592
+ENCODING 2
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+50
+A8
+50
+A8
+50
+A8
+50
+A8
+ENDCHAR
+STARTCHAR uni00B1
+ENCODING 8
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+20
+70
+20
+00
+70
+ENDCHAR
+STARTCHAR uni2518
+ENCODING 11
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 3
+BITMAP
+20
+20
+20
+E0
+ENDCHAR
+STARTCHAR uni2510
+ENCODING 12
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+E0
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni250C
+ENCODING 13
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+38
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2514
+ENCODING 14
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 3
+BITMAP
+20
+20
+20
+38
+ENDCHAR
+STARTCHAR uni253C
+ENCODING 15
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+F8
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2500
+ENCODING 18
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 1 0 3
+BITMAP
+F8
+ENDCHAR
+STARTCHAR uni251C
+ENCODING 21
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+38
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2524
+ENCODING 22
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+E0
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2534
+ENCODING 23
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 3
+BITMAP
+20
+20
+20
+F8
+ENDCHAR
+STARTCHAR uni252C
+ENCODING 24
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+F8
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2502
+ENCODING 25
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni2264
+ENCODING 26
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+10
+20
+40
+20
+10
+70
+ENDCHAR
+STARTCHAR uni2265
+ENCODING 27
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+40
+20
+10
+20
+40
+70
+ENDCHAR
+STARTCHAR uni03C0
+ENCODING 28
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+F8
+50
+50
+50
+ENDCHAR
+STARTCHAR uni2260
+ENCODING 29
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+20
+F0
+60
+F0
+40
+ENDCHAR
+STARTCHAR uni00A3
+ENCODING 30
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+10
+20
+40
+20
+10
+70
+ENDCHAR
+STARTCHAR uni00B7
+ENCODING 31
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+40
+20
+10
+20
+40
+70
+ENDCHAR
+STARTCHAR uni0020
+ENCODING 32
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 0 0 0 0
+BITMAP
+ENDCHAR
+STARTCHAR uni0021
+ENCODING 33
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+20
+20
+20
+00
+20
+ENDCHAR
+STARTCHAR uni0022
+ENCODING 34
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 3 0 3
+BITMAP
+50
+50
+50
+ENDCHAR
+STARTCHAR uni0023
+ENCODING 35
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+50
+50
+F8
+50
+F8
+50
+50
+ENDCHAR
+STARTCHAR uni0024
+ENCODING 36
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+20
+70
+A0
+70
+28
+70
+20
+ENDCHAR
+STARTCHAR uni0025
+ENCODING 37
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 1
+BITMAP
+40
+50
+20
+50
+10
+ENDCHAR
+STARTCHAR uni0026
+ENCODING 38
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+40
+A0
+A0
+40
+A0
+A0
+50
+ENDCHAR
+STARTCHAR uni0027
+ENCODING 39
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 3 0 3
+BITMAP
+20
+20
+20
+ENDCHAR
+STARTCHAR uni0028
+ENCODING 40
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+40
+40
+40
+40
+20
+ENDCHAR
+STARTCHAR uni0029
+ENCODING 41
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+40
+20
+20
+20
+20
+40
+ENDCHAR
+STARTCHAR uni002A
+ENCODING 42
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+90
+60
+F0
+60
+90
+ENDCHAR
+STARTCHAR uni002B
+ENCODING 43
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+20
+20
+F8
+20
+20
+ENDCHAR
+STARTCHAR uni002C
+ENCODING 44
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 3 0 -1
+BITMAP
+30
+20
+40
+ENDCHAR
+STARTCHAR uni002D
+ENCODING 45
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 1 0 2
+BITMAP
+F0
+ENDCHAR
+STARTCHAR uni002E
+ENCODING 46
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 3 0 -1
+BITMAP
+20
+70
+20
+ENDCHAR
+STARTCHAR uni002F
+ENCODING 47
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+10
+10
+20
+40
+80
+80
+ENDCHAR
+STARTCHAR uni0030
+ENCODING 48
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+50
+50
+50
+50
+20
+ENDCHAR
+STARTCHAR uni0031
+ENCODING 49
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+60
+20
+20
+20
+70
+ENDCHAR
+STARTCHAR uni0032
+ENCODING 50
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+10
+60
+80
+F0
+ENDCHAR
+STARTCHAR uni0033
+ENCODING 51
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+F0
+20
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR uni0034
+ENCODING 52
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+60
+A0
+F0
+20
+20
+ENDCHAR
+STARTCHAR uni0035
+ENCODING 53
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+F0
+80
+E0
+10
+90
+60
+ENDCHAR
+STARTCHAR uni0036
+ENCODING 54
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+80
+E0
+90
+90
+60
+ENDCHAR
+STARTCHAR uni0037
+ENCODING 55
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+F0
+10
+20
+20
+40
+40
+ENDCHAR
+STARTCHAR uni0038
+ENCODING 56
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR uni0039
+ENCODING 57
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+90
+70
+10
+60
+ENDCHAR
+STARTCHAR uni003A
+ENCODING 58
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+60
+60
+00
+60
+60
+ENDCHAR
+STARTCHAR uni003B
+ENCODING 59
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 -1
+BITMAP
+30
+30
+00
+30
+20
+40
+ENDCHAR
+STARTCHAR uni003C
+ENCODING 60
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+10
+20
+40
+40
+20
+10
+ENDCHAR
+STARTCHAR uni003D
+ENCODING 61
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 3 0 1
+BITMAP
+F0
+00
+F0
+ENDCHAR
+STARTCHAR uni003E
+ENCODING 62
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+40
+20
+10
+10
+20
+40
+ENDCHAR
+STARTCHAR uni003F
+ENCODING 63
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+50
+10
+20
+00
+20
+ENDCHAR
+STARTCHAR uni0040
+ENCODING 64
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 8 0 -1
+BITMAP
+30
+48
+98
+A8
+A8
+90
+40
+30
+ENDCHAR
+STARTCHAR uni0041
+ENCODING 65
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+90
+F0
+90
+90
+ENDCHAR
+STARTCHAR uni0042
+ENCODING 66
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+E0
+90
+E0
+90
+90
+E0
+ENDCHAR
+STARTCHAR uni0043
+ENCODING 67
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+80
+80
+90
+60
+ENDCHAR
+STARTCHAR uni0044
+ENCODING 68
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+E0
+90
+90
+90
+90
+E0
+ENDCHAR
+STARTCHAR uni0045
+ENCODING 69
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+F0
+80
+E0
+80
+80
+F0
+ENDCHAR
+STARTCHAR uni0046
+ENCODING 70
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+F0
+80
+E0
+80
+80
+80
+ENDCHAR
+STARTCHAR uni0047
+ENCODING 71
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+80
+B0
+90
+60
+ENDCHAR
+STARTCHAR uni0048
+ENCODING 72
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+90
+F0
+90
+90
+90
+ENDCHAR
+STARTCHAR uni0049
+ENCODING 73
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+70
+20
+20
+20
+20
+70
+ENDCHAR
+STARTCHAR uni004A
+ENCODING 74
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+70
+20
+20
+20
+A0
+40
+ENDCHAR
+STARTCHAR uni004B
+ENCODING 75
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+A0
+C0
+A0
+A0
+90
+ENDCHAR
+STARTCHAR uni004C
+ENCODING 76
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+80
+80
+80
+80
+80
+F0
+ENDCHAR
+STARTCHAR uni004D
+ENCODING 77
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+F0
+F0
+90
+90
+90
+ENDCHAR
+STARTCHAR uni004E
+ENCODING 78
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+D0
+F0
+B0
+B0
+90
+ENDCHAR
+STARTCHAR uni004F
+ENCODING 79
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR uni0050
+ENCODING 80
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+E0
+90
+90
+E0
+80
+80
+ENDCHAR
+STARTCHAR uni0051
+ENCODING 81
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+D0
+B0
+60
+10
+ENDCHAR
+STARTCHAR uni0052
+ENCODING 82
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+E0
+90
+90
+E0
+90
+90
+ENDCHAR
+STARTCHAR uni0053
+ENCODING 83
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+40
+20
+90
+60
+ENDCHAR
+STARTCHAR uni0054
+ENCODING 84
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+70
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni0055
+ENCODING 85
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR uni0056
+ENCODING 86
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+90
+90
+90
+60
+60
+ENDCHAR
+STARTCHAR uni0057
+ENCODING 87
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+90
+90
+F0
+F0
+90
+ENDCHAR
+STARTCHAR uni0058
+ENCODING 88
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+90
+60
+60
+90
+90
+ENDCHAR
+STARTCHAR uni0059
+ENCODING 89
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+88
+88
+50
+20
+20
+20
+ENDCHAR
+STARTCHAR uni005A
+ENCODING 90
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+F0
+10
+20
+40
+80
+F0
+ENDCHAR
+STARTCHAR uni005B
+ENCODING 91
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+70
+40
+40
+40
+40
+70
+ENDCHAR
+STARTCHAR uni005C
+ENCODING 92
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+80
+80
+40
+20
+10
+10
+ENDCHAR
+STARTCHAR uni005D
+ENCODING 93
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+70
+10
+10
+10
+10
+70
+ENDCHAR
+STARTCHAR uni005E
+ENCODING 94
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 2 0 4
+BITMAP
+20
+50
+ENDCHAR
+STARTCHAR uni005F
+ENCODING 95
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 1 0 -1
+BITMAP
+F0
+ENDCHAR
+STARTCHAR uni0060
+ENCODING 96
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 2 0 4
+BITMAP
+40
+20
+ENDCHAR
+STARTCHAR uni0061
+ENCODING 97
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+70
+90
+90
+70
+ENDCHAR
+STARTCHAR uni0062
+ENCODING 98
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+80
+80
+E0
+90
+90
+E0
+ENDCHAR
+STARTCHAR uni0063
+ENCODING 99
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+30
+40
+40
+30
+ENDCHAR
+STARTCHAR uni0064
+ENCODING 100
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+10
+10
+70
+90
+90
+70
+ENDCHAR
+STARTCHAR uni0065
+ENCODING 101
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+60
+B0
+C0
+60
+ENDCHAR
+STARTCHAR uni0066
+ENCODING 102
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+50
+40
+E0
+40
+40
+ENDCHAR
+STARTCHAR uni0067
+ENCODING 103
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+60
+90
+70
+10
+60
+ENDCHAR
+STARTCHAR uni0068
+ENCODING 104
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+80
+80
+E0
+90
+90
+90
+ENDCHAR
+STARTCHAR uni0069
+ENCODING 105
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+00
+60
+20
+20
+70
+ENDCHAR
+STARTCHAR uni006A
+ENCODING 106
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+10
+00
+10
+10
+10
+50
+20
+ENDCHAR
+STARTCHAR uni006B
+ENCODING 107
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+80
+80
+90
+E0
+90
+90
+ENDCHAR
+STARTCHAR uni006C
+ENCODING 108
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+20
+20
+20
+20
+70
+ENDCHAR
+STARTCHAR uni006D
+ENCODING 109
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+D0
+A8
+A8
+A8
+ENDCHAR
+STARTCHAR uni006E
+ENCODING 110
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+E0
+90
+90
+90
+ENDCHAR
+STARTCHAR uni006F
+ENCODING 111
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR uni0070
+ENCODING 112
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+E0
+90
+E0
+80
+80
+ENDCHAR
+STARTCHAR uni0071
+ENCODING 113
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+70
+90
+70
+10
+10
+ENDCHAR
+STARTCHAR uni0072
+ENCODING 114
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+A0
+D0
+80
+80
+ENDCHAR
+STARTCHAR uni0073
+ENCODING 115
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+30
+60
+10
+60
+ENDCHAR
+STARTCHAR uni0074
+ENCODING 116
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+40
+40
+E0
+40
+50
+20
+ENDCHAR
+STARTCHAR uni0075
+ENCODING 117
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+90
+90
+90
+70
+ENDCHAR
+STARTCHAR uni0076
+ENCODING 118
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+50
+50
+50
+20
+ENDCHAR
+STARTCHAR uni0077
+ENCODING 119
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+88
+A8
+A8
+50
+ENDCHAR
+STARTCHAR uni0078
+ENCODING 120
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+90
+60
+60
+90
+ENDCHAR
+STARTCHAR uni0079
+ENCODING 121
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+90
+90
+70
+90
+60
+ENDCHAR
+STARTCHAR uni007A
+ENCODING 122
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+F0
+20
+40
+F0
+ENDCHAR
+STARTCHAR uni007B
+ENCODING 123
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+30
+40
+20
+C0
+20
+40
+30
+ENDCHAR
+STARTCHAR uni007C
+ENCODING 124
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni007D
+ENCODING 125
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+C0
+20
+40
+30
+40
+20
+C0
+ENDCHAR
+STARTCHAR uni007E
+ENCODING 126
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 2 0 4
+BITMAP
+50
+A0
+ENDCHAR
+STARTCHAR uni0401
+ENCODING 161
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+F0
+80
+E0
+80
+80
+F0
+ENDCHAR
+STARTCHAR uni0410
+ENCODING 176
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+90
+F0
+90
+90
+ENDCHAR
+STARTCHAR uni0411
+ENCODING 177
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+E0
+80
+E0
+90
+90
+E0
+ENDCHAR
+STARTCHAR uni0412
+ENCODING 178
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+E0
+90
+E0
+90
+90
+E0
+ENDCHAR
+STARTCHAR uni0413
+ENCODING 179
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+F0
+90
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uni0414
+ENCODING 180
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+A0
+A0
+A0
+A0
+F0
+90
+ENDCHAR
+STARTCHAR uni0415
+ENCODING 181
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+F0
+80
+E0
+80
+80
+F0
+ENDCHAR
+STARTCHAR uni0416
+ENCODING 182
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+A8
+A8
+70
+A8
+A8
+A8
+ENDCHAR
+STARTCHAR uni0417
+ENCODING 183
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+20
+10
+90
+60
+ENDCHAR
+STARTCHAR uni0418
+ENCODING 184
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+90
+B0
+D0
+90
+90
+ENDCHAR
+STARTCHAR uni0419
+ENCODING 185
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+60
+90
+90
+B0
+D0
+90
+90
+ENDCHAR
+STARTCHAR uni041A
+ENCODING 186
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+A0
+C0
+A0
+90
+90
+ENDCHAR
+STARTCHAR uni041B
+ENCODING 187
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+30
+50
+50
+50
+50
+90
+ENDCHAR
+STARTCHAR uni041C
+ENCODING 188
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+F0
+F0
+90
+90
+90
+ENDCHAR
+STARTCHAR uni041D
+ENCODING 189
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+90
+F0
+90
+90
+90
+ENDCHAR
+STARTCHAR uni041E
+ENCODING 190
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR uni041F
+ENCODING 191
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+F0
+90
+90
+90
+90
+90
+ENDCHAR
+STARTCHAR uni0420
+ENCODING 192
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+E0
+90
+90
+E0
+80
+80
+ENDCHAR
+STARTCHAR uni0421
+ENCODING 193
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+90
+80
+80
+90
+60
+ENDCHAR
+STARTCHAR uni0422
+ENCODING 194
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+70
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni0423
+ENCODING 195
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+90
+90
+70
+10
+E0
+ENDCHAR
+STARTCHAR uni0424
+ENCODING 196
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+70
+A8
+A8
+70
+20
+ENDCHAR
+STARTCHAR uni0425
+ENCODING 197
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+50
+50
+20
+20
+50
+50
+ENDCHAR
+STARTCHAR uni0426
+ENCODING 198
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+A0
+F0
+10
+ENDCHAR
+STARTCHAR uni0427
+ENCODING 199
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+50
+50
+50
+30
+10
+10
+ENDCHAR
+STARTCHAR uni0428
+ENCODING 200
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+A8
+A8
+A8
+A8
+A8
+F8
+ENDCHAR
+STARTCHAR uni0429
+ENCODING 201
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+A8
+A8
+A8
+A8
+A8
+F8
+08
+ENDCHAR
+STARTCHAR uni042A
+ENCODING 202
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+E0
+20
+30
+28
+28
+30
+ENDCHAR
+STARTCHAR uni042B
+ENCODING 203
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+88
+88
+C8
+A8
+A8
+C8
+ENDCHAR
+STARTCHAR uni042C
+ENCODING 204
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+40
+40
+60
+50
+50
+60
+ENDCHAR
+STARTCHAR uni042D
+ENCODING 205
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+E0
+10
+70
+10
+10
+E0
+ENDCHAR
+STARTCHAR uni042E
+ENCODING 206
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+90
+A8
+E8
+A8
+A8
+90
+ENDCHAR
+STARTCHAR uni042F
+ENCODING 207
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+70
+90
+90
+70
+90
+90
+ENDCHAR
+STARTCHAR uni0430
+ENCODING 208
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+70
+90
+90
+70
+ENDCHAR
+STARTCHAR uni0431
+ENCODING 209
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+10
+60
+80
+E0
+90
+90
+60
+ENDCHAR
+STARTCHAR uni0432
+ENCODING 210
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+E0
+E0
+90
+E0
+ENDCHAR
+STARTCHAR uni0433
+ENCODING 211
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+70
+40
+40
+40
+ENDCHAR
+STARTCHAR uni0434
+ENCODING 212
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+70
+50
+90
+F0
+90
+ENDCHAR
+STARTCHAR uni0435
+ENCODING 213
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+60
+B0
+C0
+60
+ENDCHAR
+STARTCHAR uni0436
+ENCODING 214
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+A8
+70
+A8
+A8
+ENDCHAR
+STARTCHAR uni0437
+ENCODING 215
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+70
+30
+10
+60
+ENDCHAR
+STARTCHAR uni0438
+ENCODING 216
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+90
+B0
+D0
+90
+ENDCHAR
+STARTCHAR uni0439
+ENCODING 217
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+60
+00
+90
+B0
+D0
+90
+ENDCHAR
+STARTCHAR uni043A
+ENCODING 218
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+90
+E0
+A0
+90
+ENDCHAR
+STARTCHAR uni043B
+ENCODING 219
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+30
+50
+50
+90
+ENDCHAR
+STARTCHAR uni043C
+ENCODING 220
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+88
+D8
+A8
+A8
+ENDCHAR
+STARTCHAR uni043D
+ENCODING 221
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+90
+F0
+90
+90
+ENDCHAR
+STARTCHAR uni043E
+ENCODING 222
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR uni043F
+ENCODING 223
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+F0
+90
+90
+90
+ENDCHAR
+STARTCHAR uni0440
+ENCODING 224
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+E0
+90
+90
+E0
+80
+ENDCHAR
+STARTCHAR uni0441
+ENCODING 225
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+30
+40
+40
+30
+ENDCHAR
+STARTCHAR uni0442
+ENCODING 226
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+70
+20
+20
+20
+ENDCHAR
+STARTCHAR uni0443
+ENCODING 227
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+90
+90
+50
+20
+40
+ENDCHAR
+STARTCHAR uni0444
+ENCODING 228
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+70
+50
+50
+70
+20
+ENDCHAR
+STARTCHAR uni0445
+ENCODING 229
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+90
+60
+60
+90
+ENDCHAR
+STARTCHAR uni0446
+ENCODING 230
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+90
+90
+90
+F0
+10
+ENDCHAR
+STARTCHAR uni0447
+ENCODING 231
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+90
+90
+70
+10
+ENDCHAR
+STARTCHAR uni0448
+ENCODING 232
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+A8
+A8
+A8
+F8
+ENDCHAR
+STARTCHAR uni0449
+ENCODING 233
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+BITMAP
+A8
+A8
+A8
+F8
+08
+ENDCHAR
+STARTCHAR uni044A
+ENCODING 234
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+C0
+60
+50
+60
+ENDCHAR
+STARTCHAR uni044B
+ENCODING 235
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+90
+D0
+B0
+D0
+ENDCHAR
+STARTCHAR uni044C
+ENCODING 236
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+80
+E0
+90
+E0
+ENDCHAR
+STARTCHAR uni044D
+ENCODING 237
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+60
+30
+10
+60
+ENDCHAR
+STARTCHAR uni044E
+ENCODING 238
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+A0
+D0
+D0
+A0
+ENDCHAR
+STARTCHAR uni044F
+ENCODING 239
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 4 0 0
+BITMAP
+30
+50
+30
+50
+ENDCHAR
+STARTCHAR uni0451
+ENCODING 241
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+A0
+00
+60
+B0
+C0
+60
+ENDCHAR
+STARTCHAR uni0459
+ENCODING 249
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 0 0 0 0
+BITMAP
+ENDCHAR
+STARTCHAR uni045A
+ENCODING 250
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 3 0 3
+BITMAP
+20
+50
+20
+ENDCHAR
+STARTCHAR uni045B
+ENCODING 251
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 1 0 2
+BITMAP
+20
+ENDCHAR
+STARTCHAR uni045C
+ENCODING 252
+SWIDTH 436 0
+DWIDTH 5 0
+BBX 5 5 0 2
+BITMAP
+20
+50
+10
+20
+70
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/helvB12-iso-8859-1.bdf b/gui/themes/fonts/helvB12-iso-8859-1.bdf
new file mode 100644
index 0000000000..1eabe21c57
--- /dev/null
+++ b/gui/themes/fonts/helvB12-iso-8859-1.bdf
@@ -0,0 +1,3059 @@
+STARTFONT 2.1
+COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT!
+COMMENT Generated with 'ucs2any.pl helvB12.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1'
+COMMENT from an ISO10646-1 encoded source BDF font.
+COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000.
+FONT -Adobe-Helvetica-Bold-R-Normal--12-120-75-75-P-70-ISO8859-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 13 15 -1 -3
+COMMENT $Xorg: $
+COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20
+COMMENT
+COMMENT +
+COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated.
+COMMENT Copyright 1988, 1994 Digital Equipment Corporation.
+COMMENT
+COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be
+COMMENT registered in certain jurisdictions.
+COMMENT Permission to use these trademarks is hereby granted only in
+COMMENT association with the images described in this file.
+COMMENT
+COMMENT Permission to use, copy, modify, distribute and sell this software
+COMMENT and its documentation for any purpose and without fee is hereby
+COMMENT granted, provided that the above copyright notices appear in all
+COMMENT copies and that both those copyright notices and this permission
+COMMENT notice appear in supporting documentation, and that the names of
+COMMENT Adobe Systems and Digital Equipment Corporation not be used in
+COMMENT advertising or publicity pertaining to distribution of the software
+COMMENT without specific, written prior permission. Adobe Systems and
+COMMENT Digital Equipment Corporation make no representations about the
+COMMENT suitability of this software for any purpose. It is provided "as
+COMMENT is" without express or implied warranty.
+COMMENT -
+STARTPROPERTIES 26
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Bold"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 70
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 7
+FONT_ASCENT 11
+FONT_DESCENT 3
+FACE_NAME "Helvetica Bold"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica-Bold"
+DEFAULT_CHAR 0
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 70
+FULL_NAME "Helvetica Bold"
+ENDPROPERTIES
+CHARS 192
+STARTCHAR defaultchar
+ENCODING 0
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+AA
+00
+82
+00
+82
+00
+82
+00
+AA
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+80
+00
+C0
+C0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 474 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 8 0 0
+BITMAP
+14
+14
+7E
+28
+28
+FC
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 11 0 -2
+BITMAP
+10
+78
+D4
+D0
+78
+1C
+94
+D4
+78
+10
+10
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 889 0
+DWIDTH 12 0
+BBX 11 9 0 0
+BITMAP
+7100
+DB00
+DA00
+7400
+0400
+09C0
+0B60
+1B60
+11C0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+3800
+6C00
+6C00
+3800
+7900
+CF00
+C600
+CF00
+7980
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 238 0
+DWIDTH 3 0
+BBX 1 3 1 6
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 333 0
+DWIDTH 6 0
+BBX 4 12 1 -3
+BITMAP
+30
+60
+60
+C0
+C0
+C0
+C0
+C0
+C0
+60
+60
+30
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 333 0
+DWIDTH 6 0
+BBX 4 12 1 -3
+BITMAP
+C0
+60
+60
+30
+30
+30
+30
+30
+30
+60
+60
+C0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 389 0
+DWIDTH 6 0
+BBX 5 4 0 5
+BITMAP
+20
+F8
+70
+50
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+30
+30
+FC
+30
+30
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 4 1 -2
+BITMAP
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 2 1 0
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+30
+30
+20
+60
+60
+40
+40
+C0
+C0
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 4 9 0 0
+BITMAP
+30
+F0
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+0C
+18
+30
+60
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+0C
+38
+0C
+0C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+0C
+1C
+2C
+2C
+4C
+8C
+FE
+0C
+0C
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+7C
+60
+C0
+F8
+0C
+0C
+CC
+CC
+78
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+C0
+C0
+F8
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+FC
+0C
+18
+18
+30
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+CC
+78
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+CC
+CC
+7C
+0C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 7 1 0
+BITMAP
+C0
+C0
+00
+00
+00
+C0
+C0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 9 1 -2
+BITMAP
+C0
+C0
+00
+00
+00
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+18
+70
+C0
+70
+18
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 3 0 2
+BITMAP
+FC
+00
+FC
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+C0
+70
+18
+70
+C0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+CC
+CC
+18
+30
+30
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 975 0
+DWIDTH 12 0
+BBX 10 10 1 -1
+BITMAP
+1F00
+6080
+4040
+8D40
+9240
+A240
+A680
+9B00
+4000
+3E00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+C6
+C6
+C6
+FC
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+C0
+C0
+C0
+C0
+C0
+66
+3C
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+F8
+CC
+C6
+C6
+C6
+C6
+C6
+CC
+F8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+FC
+C0
+C0
+C0
+F8
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3E
+63
+C0
+C0
+CF
+C3
+C3
+63
+3D
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+0C
+0C
+0C
+0C
+0C
+0C
+CC
+CC
+78
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+C6
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+C3
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 833 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+C180
+C180
+E380
+E380
+F780
+D580
+DD80
+C980
+C980
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+66
+C3
+C3
+C3
+CB
+CF
+66
+3F
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+66
+66
+66
+24
+3C
+18
+18
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+CCC0
+CCC0
+CCC0
+4C80
+6D80
+6D80
+3300
+3300
+3300
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+66
+3C
+18
+3C
+66
+C3
+C3
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+66
+66
+3C
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+FE
+06
+0C
+18
+30
+30
+60
+C0
+FE
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 12 1 -3
+BITMAP
+E0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+E0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+C0
+C0
+40
+60
+60
+20
+20
+30
+30
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 12 0 -3
+BITMAP
+E0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+E0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 4 0 5
+BITMAP
+10
+38
+6C
+C6
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 0 -3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 0 8
+BITMAP
+C0
+60
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+C0
+C0
+C0
+CC
+78
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+0C
+0C
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 9 0 0
+BITMAP
+38
+60
+F0
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 9 0 0
+BITMAP
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 -1 -3
+BITMAP
+60
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+C0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+C0
+C0
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 9 0 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+BB80
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+74
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+0C
+0C
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+E0
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 9 0 0
+BITMAP
+60
+60
+F0
+60
+60
+60
+60
+68
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+C6
+C6
+6C
+6C
+38
+38
+10
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 778 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+CCC0
+CCC0
+6D80
+6D80
+6D80
+3300
+3300
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+CC
+CC
+78
+30
+78
+CC
+CC
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 10 0 -3
+BITMAP
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+F8
+18
+30
+20
+60
+C0
+F8
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 4 12 0 -3
+BITMAP
+30
+60
+60
+60
+60
+C0
+60
+60
+60
+60
+60
+30
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 280 0
+DWIDTH 4 0
+BBX 2 12 1 -3
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 4 12 0 -3
+BITMAP
+C0
+60
+60
+60
+60
+30
+60
+60
+60
+60
+60
+C0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 2 0 3
+BITMAP
+76
+DC
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 10 1 -3
+BITMAP
+C0
+C0
+00
+40
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 -1
+BITMAP
+10
+78
+DC
+90
+A0
+A0
+EC
+78
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+38
+6C
+60
+60
+F8
+60
+60
+EC
+D8
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 6 0 1
+BITMAP
+CC
+78
+48
+48
+78
+CC
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+CC
+CC
+48
+FC
+30
+FC
+30
+30
+30
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 280 0
+DWIDTH 4 0
+BBX 2 11 1 -2
+BITMAP
+C0
+C0
+C0
+C0
+00
+00
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+78
+CC
+E0
+70
+D8
+CC
+CC
+6C
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 1 0 8
+BITMAP
+D8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3E00
+4100
+9C80
+A280
+A080
+A280
+9C80
+4100
+3E00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 370 0
+DWIDTH 6 0
+BBX 4 6 1 3
+BITMAP
+E0
+30
+F0
+B0
+00
+F0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 6 5 1 1
+BITMAP
+24
+6C
+D8
+6C
+24
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 6 4 1 2
+BITMAP
+FC
+04
+04
+04
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3E00
+4100
+9C80
+9480
+9880
+9480
+9480
+4100
+3E00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 0 8
+BITMAP
+F0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 0 4
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+30
+30
+FC
+30
+30
+00
+FC
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 0 4
+BITMAP
+60
+B0
+60
+C0
+F0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 0 4
+BITMAP
+60
+B0
+60
+30
+E0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 0 8
+BITMAP
+60
+C0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+EC
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 12 0 -3
+BITMAP
+3E
+74
+F4
+F4
+F4
+74
+34
+14
+14
+14
+14
+14
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 2 1 3
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 4 0 -3
+BITMAP
+60
+30
+30
+E0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 5 0 4
+BITMAP
+60
+E0
+60
+60
+60
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 365 0
+DWIDTH 6 0
+BBX 4 6 1 3
+BITMAP
+60
+D0
+D0
+60
+00
+F0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 6 5 1 1
+BITMAP
+90
+D8
+6C
+D8
+90
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+6300
+E600
+6600
+6C00
+6D80
+0B80
+1A80
+37C0
+3180
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+6300
+E600
+6600
+6C00
+6D80
+0AC0
+1980
+3300
+33C0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+6300
+B300
+6600
+3600
+ED80
+0B80
+1A80
+37C0
+3180
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 10 1 -3
+BITMAP
+30
+30
+00
+30
+30
+30
+60
+CC
+CC
+78
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+30
+18
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+0C
+18
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+1C
+36
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+1A
+2C
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+36
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+18
+24
+18
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 11 9 1 0
+BITMAP
+1FE0
+3600
+2600
+6600
+67E0
+7E00
+C600
+C600
+C7E0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 7 12 1 -3
+BITMAP
+3C
+66
+C0
+C0
+C0
+C0
+C0
+66
+3C
+18
+18
+70
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+60
+30
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+18
+30
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+38
+6C
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+6C
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 3 12 0 0
+BITMAP
+C0
+60
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 3 12 1 0
+BITMAP
+60
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 12 0 0
+BITMAP
+70
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 11 0 0
+BITMAP
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+7C
+66
+63
+63
+F3
+63
+63
+66
+7C
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+34
+58
+00
+C6
+C6
+E6
+E6
+F6
+CE
+CE
+C6
+C6
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+30
+18
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+0C
+18
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+1C
+36
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+1A
+2C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+66
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+CC
+78
+30
+78
+CC
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 10 1 -1
+BITMAP
+3D
+66
+CF
+CB
+DB
+D3
+F3
+66
+7C
+80
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+30
+18
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+0C
+18
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+38
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+0C
+18
+00
+C3
+C3
+66
+66
+24
+3C
+18
+18
+18
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+C0
+C0
+FC
+C6
+C6
+C6
+FC
+C0
+C0
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+CC
+CC
+CC
+D8
+CC
+CC
+CC
+D8
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+30
+18
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+18
+30
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+38
+6C
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+34
+58
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+6C
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+30
+48
+30
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+7780
+CCC0
+0CC0
+7FC0
+CC00
+CCC0
+7780
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+78
+CC
+C0
+C0
+C0
+CC
+78
+10
+18
+70
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+60
+30
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+18
+30
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+6C
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+6C
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 10 -1 0
+BITMAP
+C0
+60
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+60
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 10 -1 0
+BITMAP
+70
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 9 -1 0
+BITMAP
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+D8
+70
+90
+18
+7C
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+34
+58
+00
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+60
+30
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+18
+30
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+6C
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+34
+58
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+6C
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+30
+00
+FC
+00
+30
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 -1 0
+BITMAP
+3D
+66
+6E
+76
+66
+66
+BC
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+60
+30
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+18
+30
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+6C
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+6C
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 13 0 -3
+BITMAP
+0C
+18
+00
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 12 0 -3
+BITMAP
+6C
+00
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/helvB12-iso-8859-5.bdf b/gui/themes/fonts/helvB12-iso-8859-5.bdf
new file mode 100644
index 0000000000..dcfd6f0105
--- /dev/null
+++ b/gui/themes/fonts/helvB12-iso-8859-5.bdf
@@ -0,0 +1,2763 @@
+STARTFONT 2.1
+COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT!
+COMMENT Generated with 'ucs2any helvB12c.bdf /usr/share/fonts/X11/util/map-ISO8859-5 ISO8859-5'
+COMMENT from an ISO10646-1 encoded source BDF font.
+COMMENT ucs2any by Ben Collver <collver1@attbi.com>, 2003, based on
+COMMENT ucs2any.pl by Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>, 2000.
+FONT -Adobe-Helvetica-Bold-R-Normal--12-120-75-75-P-70-ISO8859-5
+SIZE 12 75 75
+FONTBOUNDINGBOX 13 15 -1 -3
+COMMENT $XConsortium: helvB12.bdf,v 1.13 95/01/26 18:01:34 gildea Exp $
+COMMENT
+COMMENT +
+COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated.
+COMMENT Copyright 1988, 1994 Digital Equipment Corporation.
+COMMENT
+COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be
+COMMENT registered in certain jurisdictions.
+COMMENT Permission to use these trademarks is hereby granted only in
+COMMENT association with the images described in this file.
+COMMENT
+COMMENT Permission to use, copy, modify, distribute and sell this software
+COMMENT and its documentation for any purpose and without fee is hereby
+COMMENT granted, provided that the above copyright notices appear in all
+COMMENT copies and that both those copyright notices and this permission
+COMMENT notice appear in supporting documentation, and that the names of
+COMMENT Adobe Systems and Digital Equipment Corporation not be used in
+COMMENT advertising or publicity pertaining to distribution of the software
+COMMENT without specific, written prior permission. Adobe Systems and
+COMMENT Digital Equipment Corporation make no representations about the
+COMMENT suitability of this software for any purpose. It is provided "as
+COMMENT is" without express or implied warranty.
+COMMENT -
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Bold"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 70
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "5"
+CAP_HEIGHT 9
+X_HEIGHT 7
+FONT_ASCENT 11
+FONT_DESCENT 3
+FACE_NAME "Helvetica Bold"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica-Bold"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+DEFAULT_CHAR 32
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 70
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Helvetica Bold"
+COPYRIGHT2 "Cyrillic glyphs copyright 2000 Dmitry Yu. Bolkhovityanov, bolkhov@inp.nsk.su"
+SOURCEDATE "Sun Jan 23 14:44:29 2000"
+PKGVERSION "1.1"
+ASSEMBLER "cvtbdf.pl (Linux)"
+ENDPROPERTIES
+CHARS 177
+STARTCHAR defaultchar
+ENCODING 0
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 0 0 0 0
+BITMAP
+ENDCHAR
+STARTCHAR defaultchar
+ENCODING 32
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 0 0 0 0
+BITMAP
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+80
+00
+C0
+C0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 474 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 8 0 0
+BITMAP
+14
+14
+7E
+28
+28
+FC
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 11 0 -2
+BITMAP
+10
+78
+D4
+D0
+78
+1C
+94
+D4
+78
+10
+10
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 889 0
+DWIDTH 12 0
+BBX 11 9 0 0
+BITMAP
+7100
+DB00
+DA00
+7400
+0400
+09C0
+0B60
+1B60
+11C0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+3800
+6C00
+6C00
+3800
+7900
+CF00
+C600
+CF00
+7980
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 238 0
+DWIDTH 3 0
+BBX 1 3 1 6
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 333 0
+DWIDTH 6 0
+BBX 4 12 1 -3
+BITMAP
+30
+60
+60
+C0
+C0
+C0
+C0
+C0
+C0
+60
+60
+30
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 333 0
+DWIDTH 6 0
+BBX 4 12 1 -3
+BITMAP
+C0
+60
+60
+30
+30
+30
+30
+30
+30
+60
+60
+C0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 389 0
+DWIDTH 6 0
+BBX 5 4 0 5
+BITMAP
+20
+F8
+70
+50
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+30
+30
+FC
+30
+30
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 4 1 -2
+BITMAP
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 5 1 1 3
+BITMAP
+F8
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 2 1 0
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+30
+30
+20
+60
+60
+40
+40
+C0
+C0
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 4 9 0 0
+BITMAP
+30
+F0
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+0C
+18
+30
+60
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+0C
+38
+0C
+0C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+0C
+1C
+2C
+2C
+4C
+8C
+FE
+0C
+0C
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+7C
+60
+C0
+F8
+0C
+0C
+CC
+CC
+78
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+C0
+C0
+F8
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+FC
+0C
+18
+18
+30
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+CC
+78
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+CC
+CC
+7C
+0C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 7 1 0
+BITMAP
+C0
+C0
+00
+00
+00
+C0
+C0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 9 1 -2
+BITMAP
+C0
+C0
+00
+00
+00
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+18
+70
+C0
+70
+18
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 3 0 2
+BITMAP
+FC
+00
+FC
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+C0
+70
+18
+70
+C0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+CC
+CC
+18
+30
+30
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 975 0
+DWIDTH 12 0
+BBX 10 10 1 -1
+BITMAP
+1F00
+6080
+4040
+8D40
+9240
+A240
+A680
+9B00
+4000
+3E00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+C6
+C6
+C6
+FC
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+C0
+C0
+C0
+C0
+C0
+66
+3C
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+F8
+CC
+C6
+C6
+C6
+C6
+C6
+CC
+F8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+FC
+C0
+C0
+C0
+F8
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3E
+63
+C0
+C0
+CF
+C3
+C3
+63
+3D
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+0C
+0C
+0C
+0C
+0C
+0C
+CC
+CC
+78
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+C6
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+C3
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 833 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+C180
+C180
+E380
+E380
+F780
+D580
+DD80
+C980
+C980
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+66
+C3
+C3
+C3
+CB
+CF
+66
+3F
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+66
+66
+66
+24
+3C
+18
+18
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+CCC0
+CCC0
+CCC0
+4C80
+6D80
+6D80
+3300
+3300
+3300
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+66
+3C
+18
+3C
+66
+C3
+C3
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+66
+66
+3C
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+FE
+06
+0C
+18
+30
+30
+60
+C0
+FE
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 12 1 -3
+BITMAP
+E0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+E0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+C0
+C0
+40
+60
+60
+20
+20
+30
+30
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 12 0 -3
+BITMAP
+E0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+E0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 4 0 5
+BITMAP
+10
+38
+6C
+C6
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 0 -3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 0 8
+BITMAP
+C0
+60
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+C0
+C0
+C0
+CC
+78
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+0C
+0C
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 9 0 0
+BITMAP
+38
+60
+F0
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 9 0 0
+BITMAP
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 -1 -3
+BITMAP
+60
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+C0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+C0
+C0
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 9 0 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+BB80
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+74
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+0C
+0C
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+E0
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 9 0 0
+BITMAP
+60
+60
+F0
+60
+60
+60
+60
+68
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+C6
+C6
+6C
+6C
+38
+38
+10
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 778 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+CCC0
+CCC0
+6D80
+6D80
+6D80
+3300
+3300
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+CC
+CC
+78
+30
+78
+CC
+CC
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 10 0 -3
+BITMAP
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+F8
+18
+30
+20
+60
+C0
+F8
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 4 12 0 -3
+BITMAP
+30
+60
+60
+60
+60
+C0
+60
+60
+60
+60
+60
+30
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 280 0
+DWIDTH 4 0
+BBX 2 12 1 -3
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 4 12 0 -3
+BITMAP
+C0
+60
+60
+60
+60
+30
+60
+60
+60
+60
+60
+C0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 2 0 3
+BITMAP
+76
+DC
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 0 0 0 0
+BITMAP
+ENDCHAR
+STARTCHAR afii10023
+ENCODING 161
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+6C
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR afii10053
+ENCODING 164
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+C0
+C0
+F8
+C0
+C0
+66
+3C
+ENDCHAR
+STARTCHAR afii10054
+ENCODING 165
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+ENDCHAR
+STARTCHAR afii10055
+ENCODING 166
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR afii10056
+ENCODING 167
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 11 0 0
+BITMAP
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR afii10057
+ENCODING 168
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+0C
+0C
+0C
+0C
+0C
+0C
+CC
+CC
+78
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR afii10062
+ENCODING 174
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+66
+3C
+00
+C3
+C3
+66
+66
+24
+3C
+18
+18
+70
+ENDCHAR
+STARTCHAR afii10017
+ENCODING 176
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR afii10018
+ENCODING 177
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FE
+C0
+C0
+C0
+FC
+C6
+C6
+C6
+FC
+ENDCHAR
+STARTCHAR afii10019
+ENCODING 178
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+C6
+C6
+C6
+FC
+ENDCHAR
+STARTCHAR afii10020
+ENCODING 179
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+FC
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR afii10021
+ENCODING 180
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 11 0 -2
+BITMAP
+3F00
+3300
+3300
+3300
+3300
+3300
+6300
+6300
+FF80
+C180
+C180
+ENDCHAR
+STARTCHAR afii10022
+ENCODING 181
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR afii10024
+ENCODING 182
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 12 9 0 0
+BITMAP
+C630
+6660
+36C0
+1F80
+0F00
+1F80
+36C0
+6660
+C630
+ENDCHAR
+STARTCHAR afii10025
+ENCODING 183
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+7C
+C6
+06
+06
+3C
+06
+06
+C6
+7C
+ENDCHAR
+STARTCHAR afii10026
+ENCODING 184
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+C6
+CE
+CE
+D6
+D6
+E6
+E6
+C6
+ENDCHAR
+STARTCHAR afii10027
+ENCODING 185
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+6C
+38
+00
+C6
+C6
+CE
+CE
+D6
+D6
+E6
+E6
+C6
+ENDCHAR
+STARTCHAR afii10028
+ENCODING 186
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+C6
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+C3
+ENDCHAR
+STARTCHAR afii10029
+ENCODING 187
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3F
+33
+33
+33
+33
+33
+33
+33
+E3
+ENDCHAR
+STARTCHAR afii10030
+ENCODING 188
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+C180
+C180
+E380
+E380
+F780
+D580
+DD80
+C980
+C980
+ENDCHAR
+STARTCHAR afii10031
+ENCODING 189
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR afii10032
+ENCODING 190
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR afii10033
+ENCODING 191
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FE
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR afii10034
+ENCODING 192
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR afii10035
+ENCODING 193
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+C0
+C0
+C0
+C0
+C0
+66
+3C
+ENDCHAR
+STARTCHAR afii10036
+ENCODING 194
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR afii10037
+ENCODING 195
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+66
+66
+24
+3C
+18
+18
+70
+ENDCHAR
+STARTCHAR afii10038
+ENCODING 196
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 10 9 1 0
+BITMAP
+0C00
+3F00
+6D80
+CCC0
+CCC0
+CCC0
+6D80
+3F00
+0C00
+ENDCHAR
+STARTCHAR afii10039
+ENCODING 197
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+66
+3C
+18
+3C
+66
+C3
+C3
+ENDCHAR
+STARTCHAR afii10040
+ENCODING 198
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 11 1 -2
+BITMAP
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+FF
+03
+03
+ENDCHAR
+STARTCHAR afii10041
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+C6
+C6
+C6
+7E
+06
+06
+06
+06
+ENDCHAR
+STARTCHAR afii10042
+ENCODING 200
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 10 9 1 0
+BITMAP
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+FFC0
+ENDCHAR
+STARTCHAR afii10043
+ENCODING 201
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 11 11 1 -2
+BITMAP
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+FFE0
+0060
+0060
+ENDCHAR
+STARTCHAR afii10044
+ENCODING 202
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+F000
+3000
+3000
+3000
+3F00
+3180
+3180
+3180
+3F00
+ENDCHAR
+STARTCHAR afii10045
+ENCODING 203
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 11 9 1 0
+BITMAP
+C060
+C060
+C060
+C060
+FC60
+C660
+C660
+C660
+FC60
+ENDCHAR
+STARTCHAR afii10046
+ENCODING 204
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+FC
+C6
+C6
+C6
+FC
+ENDCHAR
+STARTCHAR afii10047
+ENCODING 205
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+78
+CC
+06
+06
+3E
+06
+06
+CC
+78
+ENDCHAR
+STARTCHAR afii10048
+ENCODING 206
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 11 9 1 0
+BITMAP
+C780
+CCC0
+D860
+D860
+F860
+D860
+D860
+CCC0
+C780
+ENDCHAR
+STARTCHAR afii10049
+ENCODING 207
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+7E
+C6
+C6
+C6
+7E
+66
+66
+C6
+C6
+ENDCHAR
+STARTCHAR afii10065
+ENCODING 208
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR afii10066
+ENCODING 209
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+0C
+78
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR afii10067
+ENCODING 210
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+F8
+CC
+CC
+F8
+CC
+CC
+F8
+ENDCHAR
+STARTCHAR afii10068
+ENCODING 211
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+F8
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR afii10069
+ENCODING 212
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 8 0 -1
+BITMAP
+3E
+36
+36
+36
+66
+66
+FF
+C3
+ENDCHAR
+STARTCHAR afii10070
+ENCODING 213
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR afii10072
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+DB
+DB
+7E
+3C
+7E
+DB
+DB
+ENDCHAR
+STARTCHAR afii10073
+ENCODING 215
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+0C
+38
+0C
+CC
+78
+ENDCHAR
+STARTCHAR afii10074
+ENCODING 216
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+CC
+CC
+DC
+FC
+EC
+CC
+CC
+ENDCHAR
+STARTCHAR afii10075
+ENCODING 217
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+48
+78
+00
+CC
+CC
+DC
+FC
+EC
+CC
+CC
+ENDCHAR
+STARTCHAR afii10076
+ENCODING 218
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+ENDCHAR
+STARTCHAR afii10077
+ENCODING 219
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 7 -1 0
+BITMAP
+3F
+33
+33
+33
+33
+33
+E3
+ENDCHAR
+STARTCHAR afii10078
+ENCODING 220
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 7 0 0
+BITMAP
+C180
+E380
+E380
+F780
+D580
+DD80
+C980
+ENDCHAR
+STARTCHAR afii10079
+ENCODING 221
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+CC
+CC
+CC
+FC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR afii10080
+ENCODING 222
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR afii10081
+ENCODING 223
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+FC
+CC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR afii10082
+ENCODING 224
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR afii10083
+ENCODING 225
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+C0
+C0
+C0
+CC
+78
+ENDCHAR
+STARTCHAR afii10084
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+FC
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR afii10085
+ENCODING 227
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 10 0 -3
+BITMAP
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR afii10086
+ENCODING 228
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 10 12 0 -3
+BITMAP
+0C00
+0C00
+7F80
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+7F80
+0C00
+0C00
+0C00
+ENDCHAR
+STARTCHAR afii10087
+ENCODING 229
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+CC
+CC
+78
+30
+78
+CC
+CC
+ENDCHAR
+STARTCHAR afii10088
+ENCODING 230
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 8 0 -1
+BITMAP
+CC
+CC
+CC
+CC
+CC
+CC
+FE
+06
+ENDCHAR
+STARTCHAR afii10089
+ENCODING 231
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+CC
+CC
+CC
+7C
+0C
+0C
+0C
+ENDCHAR
+STARTCHAR afii10090
+ENCODING 232
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+FFC0
+ENDCHAR
+STARTCHAR afii10091
+ENCODING 233
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 11 8 0 -1
+BITMAP
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+FFE0
+0060
+ENDCHAR
+STARTCHAR afii10092
+ENCODING 234
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 7 -1 0
+BITMAP
+F0
+30
+30
+3E
+33
+33
+3E
+ENDCHAR
+STARTCHAR afii10093
+ENCODING 235
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 7 0 0
+BITMAP
+C180
+C180
+C180
+F980
+CD80
+CD80
+F980
+ENDCHAR
+STARTCHAR afii10094
+ENCODING 236
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+C0
+C0
+C0
+F8
+CC
+CC
+F8
+ENDCHAR
+STARTCHAR afii10095
+ENCODING 237
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+0C
+3C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR afii10096
+ENCODING 238
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+C780
+CCC0
+CCC0
+FCC0
+CCC0
+CCC0
+C780
+ENDCHAR
+STARTCHAR afii10097
+ENCODING 239
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+7C
+CC
+CC
+7C
+6C
+CC
+CC
+ENDCHAR
+STARTCHAR afii10071
+ENCODING 241
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+6C
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR afii10101
+ENCODING 244
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+C0
+F0
+C0
+CC
+78
+ENDCHAR
+STARTCHAR afii10102
+ENCODING 245
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+E0
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR afii10103
+ENCODING 246
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 9 0 0
+BITMAP
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR afii10104
+ENCODING 247
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 9 -1 0
+BITMAP
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR afii10105
+ENCODING 248
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 -1 -3
+BITMAP
+60
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+C0
+ENDCHAR
+STARTCHAR section
+ENCODING 253
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+78
+CC
+E0
+70
+D8
+CC
+CC
+6C
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR afii10110
+ENCODING 254
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 13 0 -3
+BITMAP
+44
+38
+00
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/helvB12.bdf b/gui/themes/fonts/helvB12.bdf
new file mode 100644
index 0000000000..76f5dbc552
--- /dev/null
+++ b/gui/themes/fonts/helvB12.bdf
@@ -0,0 +1,12708 @@
+STARTFONT 2.1
+FONT -Adobe-Helvetica-Bold-R-Normal--12-120-75-75-P-70-ISO10646-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 15 20 -2 -5
+COMMENT $Xorg: $
+COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20
+COMMENT
+COMMENT +
+COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated.
+COMMENT Copyright 1988, 1994 Digital Equipment Corporation.
+COMMENT
+COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be
+COMMENT registered in certain jurisdictions.
+COMMENT Permission to use these trademarks is hereby granted only in
+COMMENT association with the images described in this file.
+COMMENT
+COMMENT Permission to use, copy, modify, distribute and sell this software
+COMMENT and its documentation for any purpose and without fee is hereby
+COMMENT granted, provided that the above copyright notices appear in all
+COMMENT copies and that both those copyright notices and this permission
+COMMENT notice appear in supporting documentation, and that the names of
+COMMENT Adobe Systems and Digital Equipment Corporation not be used in
+COMMENT advertising or publicity pertaining to distribution of the software
+COMMENT without specific, written prior permission. Adobe Systems and
+COMMENT Digital Equipment Corporation make no representations about the
+COMMENT suitability of this software for any purpose. It is provided "as
+COMMENT is" without express or implied warranty.
+COMMENT -
+STARTPROPERTIES 26
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Bold"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 70
+CHARSET_REGISTRY "ISO10646"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 7
+FONT_ASCENT 11
+FONT_DESCENT 3
+FACE_NAME "Helvetica Bold"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica-Bold"
+DEFAULT_CHAR 0
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 70
+FULL_NAME "Helvetica Bold"
+ENDPROPERTIES
+CHARS 756
+STARTCHAR char0
+ENCODING 0
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+AA
+00
+82
+00
+82
+00
+82
+00
+AA
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+80
+00
+C0
+C0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 474 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 8 0 0
+BITMAP
+14
+14
+7E
+28
+28
+FC
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 11 0 -2
+BITMAP
+10
+78
+D4
+D0
+78
+1C
+94
+D4
+78
+10
+10
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 889 0
+DWIDTH 12 0
+BBX 11 9 0 0
+BITMAP
+7100
+DB00
+DA00
+7400
+0400
+09C0
+0B60
+1B60
+11C0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+3800
+6C00
+6C00
+3800
+7900
+CF00
+C600
+CF00
+7980
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 238 0
+DWIDTH 3 0
+BBX 1 3 1 6
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 333 0
+DWIDTH 6 0
+BBX 4 12 1 -3
+BITMAP
+30
+60
+60
+C0
+C0
+C0
+C0
+C0
+C0
+60
+60
+30
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 333 0
+DWIDTH 6 0
+BBX 4 12 1 -3
+BITMAP
+C0
+60
+60
+30
+30
+30
+30
+30
+30
+60
+60
+C0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 389 0
+DWIDTH 6 0
+BBX 5 4 0 5
+BITMAP
+20
+F8
+70
+50
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+30
+30
+FC
+30
+30
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 4 1 -2
+BITMAP
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 2 1 0
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+30
+30
+20
+60
+60
+40
+40
+C0
+C0
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 4 9 0 0
+BITMAP
+30
+F0
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+0C
+18
+30
+60
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+0C
+38
+0C
+0C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+0C
+1C
+2C
+2C
+4C
+8C
+FE
+0C
+0C
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+7C
+60
+C0
+F8
+0C
+0C
+CC
+CC
+78
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+C0
+C0
+F8
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+FC
+0C
+18
+18
+30
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+CC
+78
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+CC
+CC
+7C
+0C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 7 1 0
+BITMAP
+C0
+C0
+00
+00
+00
+C0
+C0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 9 1 -2
+BITMAP
+C0
+C0
+00
+00
+00
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+18
+70
+C0
+70
+18
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 3 0 2
+BITMAP
+FC
+00
+FC
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+C0
+70
+18
+70
+C0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+CC
+CC
+18
+30
+30
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 975 0
+DWIDTH 12 0
+BBX 10 10 1 -1
+BITMAP
+1F00
+6080
+4040
+8D40
+9240
+A240
+A680
+9B00
+4000
+3E00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+C6
+C6
+C6
+FC
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+C0
+C0
+C0
+C0
+C0
+66
+3C
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+F8
+CC
+C6
+C6
+C6
+C6
+C6
+CC
+F8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+FC
+C0
+C0
+C0
+F8
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3E
+63
+C0
+C0
+CF
+C3
+C3
+63
+3D
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+0C
+0C
+0C
+0C
+0C
+0C
+CC
+CC
+78
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+C6
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+C3
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 833 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+C180
+C180
+E380
+E380
+F780
+D580
+DD80
+C980
+C980
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+66
+C3
+C3
+C3
+CB
+CF
+66
+3F
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+66
+66
+66
+24
+3C
+18
+18
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+CCC0
+CCC0
+CCC0
+4C80
+6D80
+6D80
+3300
+3300
+3300
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+66
+3C
+18
+3C
+66
+C3
+C3
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+66
+66
+3C
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+FE
+06
+0C
+18
+30
+30
+60
+C0
+FE
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 12 1 -3
+BITMAP
+E0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+E0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+C0
+C0
+40
+60
+60
+20
+20
+30
+30
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 12 0 -3
+BITMAP
+E0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+E0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 4 0 5
+BITMAP
+10
+38
+6C
+C6
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 0 -3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 0 8
+BITMAP
+C0
+60
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+C0
+C0
+C0
+CC
+78
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+0C
+0C
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 9 0 0
+BITMAP
+38
+60
+F0
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 9 0 0
+BITMAP
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 -1 -3
+BITMAP
+60
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+C0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+C0
+C0
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 9 0 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+BB80
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+74
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+0C
+0C
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+E0
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 9 0 0
+BITMAP
+60
+60
+F0
+60
+60
+60
+60
+68
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+C6
+C6
+6C
+6C
+38
+38
+10
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 778 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+CCC0
+CCC0
+6D80
+6D80
+6D80
+3300
+3300
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+CC
+CC
+78
+30
+78
+CC
+CC
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 10 0 -3
+BITMAP
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+F8
+18
+30
+20
+60
+C0
+F8
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 4 12 0 -3
+BITMAP
+30
+60
+60
+60
+60
+C0
+60
+60
+60
+60
+60
+30
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 280 0
+DWIDTH 4 0
+BBX 2 12 1 -3
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 4 12 0 -3
+BITMAP
+C0
+60
+60
+60
+60
+30
+60
+60
+60
+60
+60
+C0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 2 0 3
+BITMAP
+76
+DC
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 10 1 -3
+BITMAP
+C0
+C0
+00
+40
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 -1
+BITMAP
+10
+78
+DC
+90
+A0
+A0
+EC
+78
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+38
+6C
+60
+60
+F8
+60
+60
+EC
+D8
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 6 0 1
+BITMAP
+CC
+78
+48
+48
+78
+CC
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+CC
+CC
+48
+FC
+30
+FC
+30
+30
+30
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 280 0
+DWIDTH 4 0
+BBX 2 11 1 -2
+BITMAP
+C0
+C0
+C0
+C0
+00
+00
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+78
+CC
+E0
+70
+D8
+CC
+CC
+6C
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 1 0 8
+BITMAP
+D8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3E00
+4100
+9C80
+A280
+A080
+A280
+9C80
+4100
+3E00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 370 0
+DWIDTH 6 0
+BBX 4 6 1 3
+BITMAP
+E0
+30
+F0
+B0
+00
+F0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 6 5 1 1
+BITMAP
+24
+6C
+D8
+6C
+24
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 6 4 1 2
+BITMAP
+FC
+04
+04
+04
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3E00
+4100
+9C80
+9480
+9880
+9480
+9480
+4100
+3E00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 0 8
+BITMAP
+F0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 0 4
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+30
+30
+FC
+30
+30
+00
+FC
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 0 4
+BITMAP
+60
+B0
+60
+C0
+F0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 0 4
+BITMAP
+60
+B0
+60
+30
+E0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 0 8
+BITMAP
+60
+C0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+EC
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 12 0 -3
+BITMAP
+3E
+74
+F4
+F4
+F4
+74
+34
+14
+14
+14
+14
+14
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 2 1 3
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 4 0 -3
+BITMAP
+60
+30
+30
+E0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 5 0 4
+BITMAP
+60
+E0
+60
+60
+60
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 365 0
+DWIDTH 6 0
+BBX 4 6 1 3
+BITMAP
+60
+D0
+D0
+60
+00
+F0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 6 5 1 1
+BITMAP
+90
+D8
+6C
+D8
+90
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+6300
+E600
+6600
+6C00
+6D80
+0B80
+1A80
+37C0
+3180
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+6300
+E600
+6600
+6C00
+6D80
+0AC0
+1980
+3300
+33C0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+6300
+B300
+6600
+3600
+ED80
+0B80
+1A80
+37C0
+3180
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 10 1 -3
+BITMAP
+30
+30
+00
+30
+30
+30
+60
+CC
+CC
+78
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+30
+18
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+0C
+18
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+1C
+36
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+1A
+2C
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+36
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+18
+24
+18
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 11 9 1 0
+BITMAP
+1FE0
+3600
+2600
+6600
+67E0
+7E00
+C600
+C600
+C7E0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 7 12 1 -3
+BITMAP
+3C
+66
+C0
+C0
+C0
+C0
+C0
+66
+3C
+18
+18
+70
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+60
+30
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+18
+30
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+38
+6C
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+6C
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 3 12 0 0
+BITMAP
+C0
+60
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 3 12 1 0
+BITMAP
+60
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 12 0 0
+BITMAP
+70
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 11 0 0
+BITMAP
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+7C
+66
+63
+63
+F3
+63
+63
+66
+7C
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+34
+58
+00
+C6
+C6
+E6
+E6
+F6
+CE
+CE
+C6
+C6
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+30
+18
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+0C
+18
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+1C
+36
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+1A
+2C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+66
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+CC
+78
+30
+78
+CC
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 10 1 -1
+BITMAP
+3D
+66
+CF
+CB
+DB
+D3
+F3
+66
+7C
+80
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+30
+18
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+0C
+18
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+38
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+0C
+18
+00
+C3
+C3
+66
+66
+24
+3C
+18
+18
+18
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+C0
+C0
+FC
+C6
+C6
+C6
+FC
+C0
+C0
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+CC
+CC
+CC
+D8
+CC
+CC
+CC
+D8
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+30
+18
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+18
+30
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+38
+6C
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+34
+58
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+6C
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+30
+48
+30
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+7780
+CCC0
+0CC0
+7FC0
+CC00
+CCC0
+7780
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+78
+CC
+C0
+C0
+C0
+CC
+78
+10
+18
+70
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+60
+30
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+18
+30
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+6C
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+6C
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 10 -1 0
+BITMAP
+C0
+60
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+60
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 10 -1 0
+BITMAP
+70
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 9 -1 0
+BITMAP
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+D8
+70
+90
+18
+7C
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+34
+58
+00
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+60
+30
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+18
+30
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+6C
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+34
+58
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+6C
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+30
+00
+FC
+00
+30
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 -1 0
+BITMAP
+3D
+66
+6E
+76
+66
+66
+BC
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+60
+30
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+18
+30
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+6C
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+6C
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 13 0 -3
+BITMAP
+0C
+18
+00
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 12 0 -3
+BITMAP
+6C
+00
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR Amacron
+ENCODING 256
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+3C
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR amacron
+ENCODING 257
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+78
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR Abreve
+ENCODING 258
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+22
+1C
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR abreve
+ENCODING 259
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+44
+38
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR Aogonek
+ENCODING 260
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 -3
+BITMAP
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+DB
+30
+30
+1C
+ENDCHAR
+STARTCHAR aogonek
+ENCODING 261
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 -3
+BITMAP
+78
+CC
+0C
+7C
+CC
+CC
+7E
+30
+30
+1C
+ENDCHAR
+STARTCHAR Cacute
+ENCODING 262
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 7 12 1 0
+BITMAP
+18
+30
+00
+3C
+66
+C0
+C0
+C0
+C0
+C0
+66
+3C
+ENDCHAR
+STARTCHAR cacute
+ENCODING 263
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+18
+30
+00
+78
+CC
+C0
+C0
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Ccircumflex
+ENCODING 264
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 7 12 1 0
+BITMAP
+38
+6C
+00
+3C
+66
+C0
+C0
+C0
+C0
+C0
+66
+3C
+ENDCHAR
+STARTCHAR ccircumflex
+ENCODING 265
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+6C
+00
+78
+CC
+C0
+C0
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Cdotaccent
+ENCODING 266
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+30
+00
+3C
+66
+C0
+C0
+C0
+C0
+C0
+66
+3C
+ENDCHAR
+STARTCHAR cdotaccent
+ENCODING 267
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+30
+00
+78
+CC
+C0
+C0
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Ccaron
+ENCODING 268
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 7 12 1 0
+BITMAP
+6C
+38
+00
+3C
+66
+C0
+C0
+C0
+C0
+C0
+66
+3C
+ENDCHAR
+STARTCHAR ccaron
+ENCODING 269
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+6C
+38
+00
+78
+CC
+C0
+C0
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Dcaron
+ENCODING 270
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+6C
+38
+00
+F8
+CC
+C6
+C6
+C6
+C6
+C6
+CC
+F8
+ENDCHAR
+STARTCHAR dcaron
+ENCODING 271
+SWIDTH 858 0
+DWIDTH 11 0
+BBX 10 9 0 0
+BITMAP
+0CC0
+0C40
+6C80
+DC00
+CC00
+CC00
+CC00
+DC00
+6C00
+ENDCHAR
+STARTCHAR Dcroat
+ENCODING 272
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+7C
+66
+63
+63
+F3
+63
+63
+66
+7C
+ENDCHAR
+STARTCHAR dcroat
+ENCODING 273
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+0C
+3E
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR Emacron
+ENCODING 274
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+F0
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR emacron
+ENCODING 275
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Ebreve
+ENCODING 276
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+88
+70
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR ebreve
+ENCODING 277
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+44
+38
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Edotaccent
+ENCODING 278
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+60
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR edotaccent
+ENCODING 279
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+30
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Eogonek
+ENCODING 280
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+60
+60
+38
+ENDCHAR
+STARTCHAR eogonek
+ENCODING 281
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+78
+CC
+CC
+FC
+C0
+CC
+78
+60
+60
+38
+ENDCHAR
+STARTCHAR Ecaron
+ENCODING 282
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+D8
+70
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR ecaron
+ENCODING 283
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+6C
+38
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Gcircumflex
+ENCODING 284
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+38
+6C
+00
+3E
+63
+C0
+C0
+CF
+C3
+C3
+63
+3D
+ENDCHAR
+STARTCHAR gcircumflex
+ENCODING 285
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 0 -3
+BITMAP
+38
+6C
+00
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR Gbreve
+ENCODING 286
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+44
+38
+00
+3E
+63
+C0
+C0
+CF
+C3
+C3
+63
+3D
+ENDCHAR
+STARTCHAR gbreve
+ENCODING 287
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 0 -3
+BITMAP
+44
+38
+00
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR Gdotaccent
+ENCODING 288
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+18
+00
+3E
+63
+C0
+C0
+CF
+C3
+C3
+63
+3D
+ENDCHAR
+STARTCHAR gdotaccent
+ENCODING 289
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+30
+00
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR Gcommaaccent
+ENCODING 290
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 -5
+BITMAP
+3E
+63
+C0
+C0
+CF
+C3
+C3
+63
+3D
+00
+18
+18
+08
+10
+ENDCHAR
+STARTCHAR gcommaaccent
+ENCODING 291
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 14 0 -3
+BITMAP
+10
+20
+30
+00
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR Hcircumflex
+ENCODING 292
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+38
+6C
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR hcircumflex
+ENCODING 293
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+70
+D8
+00
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR Hbar
+ENCODING 294
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+FE
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR hbar
+ENCODING 295
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+C0
+F8
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR Itilde
+ENCODING 296
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 12 0 0
+BITMAP
+68
+B0
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR itilde
+ENCODING 297
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 10 -1 0
+BITMAP
+68
+B0
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Imacron
+ENCODING 298
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 11 0 0
+BITMAP
+F0
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR imacron
+ENCODING 299
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 9 -1 0
+BITMAP
+F0
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Ibreve
+ENCODING 300
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 12 0 0
+BITMAP
+88
+70
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR ibreve
+ENCODING 301
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 10 -1 0
+BITMAP
+88
+70
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Iogonek
+ENCODING 302
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 12 0 -3
+BITMAP
+60
+60
+60
+60
+60
+60
+60
+60
+60
+C0
+C0
+70
+ENDCHAR
+STARTCHAR iogonek
+ENCODING 303
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 12 -1 -3
+BITMAP
+60
+00
+60
+60
+60
+60
+60
+60
+60
+C0
+C0
+70
+ENDCHAR
+STARTCHAR Idotaccent
+ENCODING 304
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 11 1 0
+BITMAP
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR dotlessi
+ENCODING 305
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 7 0 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR IJ
+ENCODING 306
+SWIDTH 820 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+C180
+C180
+C180
+C180
+C180
+C180
+D980
+D980
+CF00
+ENDCHAR
+STARTCHAR ij
+ENCODING 307
+SWIDTH 542 0
+DWIDTH 6 0
+BBX 5 12 0 -3
+BITMAP
+D8
+00
+D8
+D8
+D8
+D8
+D8
+D8
+D8
+18
+18
+30
+ENDCHAR
+STARTCHAR Jcircumflex
+ENCODING 308
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 12 0 0
+BITMAP
+1C
+36
+00
+0C
+0C
+0C
+0C
+0C
+0C
+CC
+CC
+78
+ENDCHAR
+STARTCHAR jcircumflex
+ENCODING 309
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 13 -2 -3
+BITMAP
+70
+D8
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+60
+ENDCHAR
+STARTCHAR Kcommaaccent
+ENCODING 310
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 14 1 -5
+BITMAP
+C6
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+C3
+00
+18
+18
+08
+10
+ENDCHAR
+STARTCHAR kcommaaccent
+ENCODING 311
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 14 0 -5
+BITMAP
+C0
+C0
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+00
+30
+30
+10
+20
+ENDCHAR
+STARTCHAR kgreenlandic
+ENCODING 312
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+ENDCHAR
+STARTCHAR Lacute
+ENCODING 313
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 1 0
+BITMAP
+30
+60
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR lacute
+ENCODING 314
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 0 0
+BITMAP
+60
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR Lcommaaccent
+ENCODING 315
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 14 1 -5
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+FC
+00
+60
+60
+20
+40
+ENDCHAR
+STARTCHAR lcommaaccent
+ENCODING 316
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 14 0 -5
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+00
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR Lcaron
+ENCODING 317
+SWIDTH 858 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+C180
+C080
+C100
+C000
+C000
+C000
+C000
+C000
+FC00
+ENDCHAR
+STARTCHAR lcaron
+ENCODING 318
+SWIDTH 542 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+CC
+C4
+C8
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR Ldot
+ENCODING 319
+SWIDTH 858 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+C000
+C000
+C000
+C000
+C180
+C180
+C000
+C000
+FC00
+ENDCHAR
+STARTCHAR ldot
+ENCODING 320
+SWIDTH 542 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+C0
+C0
+C0
+C0
+CC
+CC
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR Lslash
+ENCODING 321
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+60
+60
+78
+70
+E0
+60
+60
+60
+7E
+ENDCHAR
+STARTCHAR lslash
+ENCODING 322
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 9 -1 0
+BITMAP
+60
+60
+70
+60
+E0
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Nacute
+ENCODING 323
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+18
+30
+00
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+ENDCHAR
+STARTCHAR nacute
+ENCODING 324
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+18
+30
+00
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR Ncommaaccent
+ENCODING 325
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 14 1 -5
+BITMAP
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+00
+18
+18
+08
+10
+ENDCHAR
+STARTCHAR ncommaaccent
+ENCODING 326
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -5
+BITMAP
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+00
+30
+30
+10
+20
+ENDCHAR
+STARTCHAR Ncaron
+ENCODING 327
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+6C
+38
+00
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+ENDCHAR
+STARTCHAR ncaron
+ENCODING 328
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+D8
+70
+00
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR napostrophe
+ENCODING 329
+SWIDTH 875 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+C000
+4000
+9B00
+1D80
+1980
+1980
+1980
+1980
+1980
+ENDCHAR
+STARTCHAR Eng
+ENCODING 330
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+06
+06
+0C
+ENDCHAR
+STARTCHAR eng
+ENCODING 331
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+0C
+0C
+18
+ENDCHAR
+STARTCHAR Omacron
+ENCODING 332
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+3C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR omacron
+ENCODING 333
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR Obreve
+ENCODING 334
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+22
+1C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR obreve
+ENCODING 335
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+44
+38
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR Ohungarumlaut
+ENCODING 336
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+1A
+2C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR ohungarumlaut
+ENCODING 337
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+34
+58
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR OE
+ENCODING 338
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 11 9 1 0
+BITMAP
+3FE0
+6600
+C600
+C600
+C7E0
+C600
+C600
+6600
+3FE0
+ENDCHAR
+STARTCHAR oe
+ENCODING 339
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+7780
+CCC0
+CCC0
+CFC0
+CC00
+CCC0
+7780
+ENDCHAR
+STARTCHAR Racute
+ENCODING 340
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+18
+30
+00
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR racute
+ENCODING 341
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 10 0 0
+BITMAP
+30
+60
+00
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR Rcommaaccent
+ENCODING 342
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 14 1 -5
+BITMAP
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+00
+18
+18
+08
+10
+ENDCHAR
+STARTCHAR rcommaaccent
+ENCODING 343
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 12 0 -5
+BITMAP
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+00
+60
+60
+20
+40
+ENDCHAR
+STARTCHAR Rcaron
+ENCODING 344
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+6C
+38
+00
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR rcaron
+ENCODING 345
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 10 0 0
+BITMAP
+D8
+70
+00
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR Sacute
+ENCODING 346
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+18
+30
+00
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+ENDCHAR
+STARTCHAR sacute
+ENCODING 347
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+18
+30
+00
+78
+CC
+E0
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR Scircumflex
+ENCODING 348
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+38
+6C
+00
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+ENDCHAR
+STARTCHAR scircumflex
+ENCODING 349
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+6C
+00
+78
+CC
+E0
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR Scedilla
+ENCODING 350
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+18
+18
+70
+ENDCHAR
+STARTCHAR scedilla
+ENCODING 351
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+78
+CC
+E0
+38
+1C
+CC
+78
+18
+18
+70
+ENDCHAR
+STARTCHAR Scaron
+ENCODING 352
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+6C
+38
+00
+78
+CC
+E0
+78
+1C
+CE
+7C
+ENDCHAR
+STARTCHAR scaron
+ENCODING 353
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+D8
+70
+00
+78
+CC
+E0
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 354
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 12 0 -3
+BITMAP
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+0C
+0C
+38
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 355
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 12 0 -3
+BITMAP
+60
+60
+F0
+60
+60
+60
+60
+68
+70
+30
+30
+E0
+ENDCHAR
+STARTCHAR Tcaron
+ENCODING 356
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+36
+1C
+00
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR tcaron
+ENCODING 357
+SWIDTH 594 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+63
+61
+F2
+60
+60
+60
+60
+68
+30
+ENDCHAR
+STARTCHAR Tbar
+ENCODING 358
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+FF
+18
+18
+18
+3E
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR tbar
+ENCODING 359
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 9 0 0
+BITMAP
+60
+60
+F0
+60
+60
+F8
+60
+68
+30
+ENDCHAR
+STARTCHAR Utilde
+ENCODING 360
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+34
+58
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR utilde
+ENCODING 361
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+34
+58
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR Umacron
+ENCODING 362
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+3C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR umacron
+ENCODING 363
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR Ubreve
+ENCODING 364
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+44
+38
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR ubreve
+ENCODING 365
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+44
+38
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR Uring
+ENCODING 366
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+38
+6C
+38
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR uring
+ENCODING 367
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+38
+6C
+38
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR Uhungarumlaut
+ENCODING 368
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+34
+58
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR uhungarumlaut
+ENCODING 369
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+34
+58
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR Uogonek
+ENCODING 370
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+30
+30
+1C
+ENDCHAR
+STARTCHAR uogonek
+ENCODING 371
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+7C
+30
+30
+1C
+ENDCHAR
+STARTCHAR Wcircumflex
+ENCODING 372
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 12 0 0
+BITMAP
+0E00
+1B00
+0000
+CCC0
+CCC0
+CCC0
+4C80
+6D80
+6D80
+3300
+3300
+3300
+ENDCHAR
+STARTCHAR wcircumflex
+ENCODING 373
+SWIDTH 778 0
+DWIDTH 11 0
+BBX 10 10 0 0
+BITMAP
+0E00
+1B00
+0000
+CCC0
+CCC0
+6D80
+6D80
+6D80
+3300
+3300
+ENDCHAR
+STARTCHAR Ycircumflex
+ENCODING 374
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+1C
+36
+00
+C3
+C3
+66
+66
+3C
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR ycircumflex
+ENCODING 375
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 13 0 -3
+BITMAP
+38
+6C
+00
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR Ydieresis
+ENCODING 376
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+6C
+00
+C3
+66
+24
+3C
+18
+18
+18
+ENDCHAR
+STARTCHAR Zacute
+ENCODING 377
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 12 0 0
+BITMAP
+0C
+18
+00
+FE
+06
+0C
+18
+30
+30
+60
+C0
+FE
+ENDCHAR
+STARTCHAR zacute
+ENCODING 378
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 10 0 0
+BITMAP
+18
+30
+00
+F8
+18
+30
+20
+60
+C0
+F8
+ENDCHAR
+STARTCHAR Zdotaccent
+ENCODING 379
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+18
+00
+FE
+06
+0C
+18
+30
+30
+60
+C0
+FE
+ENDCHAR
+STARTCHAR zdotaccent
+ENCODING 380
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+30
+00
+F8
+18
+30
+20
+60
+C0
+F8
+ENDCHAR
+STARTCHAR Zcaron
+ENCODING 381
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+6C
+38
+00
+FC
+18
+30
+30
+60
+C0
+FE
+ENDCHAR
+STARTCHAR zcaron
+ENCODING 382
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 10 0 0
+BITMAP
+D8
+70
+00
+F8
+18
+30
+20
+60
+C0
+F8
+ENDCHAR
+STARTCHAR uni0186
+ENCODING 390
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+78
+CC
+06
+06
+06
+06
+06
+CC
+78
+ENDCHAR
+STARTCHAR uni0189
+ENCODING 393
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+7C
+66
+63
+63
+F3
+63
+63
+66
+7C
+ENDCHAR
+STARTCHAR uni018E
+ENCODING 398
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+0C
+0C
+0C
+FC
+0C
+0C
+0C
+FC
+ENDCHAR
+STARTCHAR florin
+ENCODING 402
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 11 0 -3
+BITMAP
+0E
+18
+18
+7C
+30
+30
+30
+30
+30
+E0
+C0
+ENDCHAR
+STARTCHAR uni0197
+ENCODING 407
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 9 0 0
+BITMAP
+60
+60
+60
+60
+F8
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni019A
+ENCODING 410
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 9 -1 0
+BITMAP
+60
+60
+60
+60
+F8
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni019D
+ENCODING 413
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 12 0 -3
+BITMAP
+63
+73
+73
+6B
+6B
+67
+67
+63
+63
+60
+60
+C0
+ENDCHAR
+STARTCHAR uni019F
+ENCODING 415
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+66
+C3
+C3
+FF
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR Ohorn
+ENCODING 416
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+3CC0
+6640
+C380
+C300
+C300
+C300
+C300
+6600
+3C00
+ENDCHAR
+STARTCHAR ohorn
+ENCODING 417
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+7B
+CD
+CE
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni01A7
+ENCODING 423
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+7C
+C6
+C6
+1C
+70
+E0
+C6
+C6
+7C
+ENDCHAR
+STARTCHAR uni01A8
+ENCODING 424
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+1C
+70
+E0
+CC
+78
+ENDCHAR
+STARTCHAR uni01AE
+ENCODING 430
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 12 0 -3
+BITMAP
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+0C
+ENDCHAR
+STARTCHAR Uhorn
+ENCODING 431
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+C780
+C680
+C700
+C600
+C600
+C600
+C600
+6C00
+7C00
+ENDCHAR
+STARTCHAR uhorn
+ENCODING 432
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+CF
+CD
+CE
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni01B5
+ENCODING 437
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+FE
+06
+0C
+18
+7C
+30
+60
+C0
+FE
+ENDCHAR
+STARTCHAR uni01B6
+ENCODING 438
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+F8
+18
+30
+F8
+60
+C0
+F8
+ENDCHAR
+STARTCHAR uni01BB
+ENCODING 443
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+78
+CC
+0C
+18
+FC
+60
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR uni01BC
+ENCODING 444
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+7C
+60
+C0
+F8
+0C
+0C
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni01C0
+ENCODING 448
+SWIDTH 280 0
+DWIDTH 4 0
+BBX 2 12 1 -3
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni01C2
+ENCODING 450
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 12 0 -2
+BITMAP
+30
+30
+30
+30
+30
+FC
+30
+FC
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni01C3
+ENCODING 451
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 9 1 0
+BITMAP
+C0
+C0
+C0
+C0
+C0
+80
+00
+C0
+C0
+ENDCHAR
+STARTCHAR uni01CD
+ENCODING 461
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+36
+1C
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni01CE
+ENCODING 462
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+6C
+38
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni01CF
+ENCODING 463
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 12 0 0
+BITMAP
+D8
+70
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni01D0
+ENCODING 464
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 10 -1 0
+BITMAP
+D8
+70
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni01D1
+ENCODING 465
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+36
+1C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni01D2
+ENCODING 466
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+6C
+38
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni01D3
+ENCODING 467
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+6C
+38
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR uni01D4
+ENCODING 468
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+6C
+38
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni01D5
+ENCODING 469
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+3C
+00
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR uni01D6
+ENCODING 470
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+78
+00
+6C
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni01D7
+ENCODING 471
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+18
+30
+00
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR uni01D8
+ENCODING 472
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+18
+30
+00
+6C
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni01D9
+ENCODING 473
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+6C
+38
+00
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR uni01DA
+ENCODING 474
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+6C
+38
+00
+6C
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni01DB
+ENCODING 475
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+30
+18
+00
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR uni01DC
+ENCODING 476
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+60
+30
+00
+6C
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni01DD
+ENCODING 477
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+0C
+FC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni01DE
+ENCODING 478
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 13 0 0
+BITMAP
+3C
+00
+36
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni01DF
+ENCODING 479
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+78
+00
+6C
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni01E0
+ENCODING 480
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 13 0 0
+BITMAP
+3C
+00
+18
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni01E1
+ENCODING 481
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+78
+00
+30
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni01E2
+ENCODING 482
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 11 11 1 0
+BITMAP
+0F00
+0000
+1FE0
+3600
+2600
+6600
+67E0
+7E00
+C600
+C600
+C7E0
+ENDCHAR
+STARTCHAR uni01E3
+ENCODING 483
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 10 9 0 0
+BITMAP
+1E00
+0000
+7780
+CCC0
+0CC0
+7FC0
+CC00
+CCC0
+7780
+ENDCHAR
+STARTCHAR uni01E4
+ENCODING 484
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+3E00
+6300
+C000
+C000
+CF00
+CF80
+C300
+6300
+3D00
+ENDCHAR
+STARTCHAR uni01E5
+ENCODING 485
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+FC
+CC
+78
+ENDCHAR
+STARTCHAR Gcaron
+ENCODING 486
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+6C
+38
+00
+3E
+63
+C0
+C0
+CF
+C3
+C3
+63
+3D
+ENDCHAR
+STARTCHAR gcaron
+ENCODING 487
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 0 -3
+BITMAP
+6C
+38
+00
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR uni01E8
+ENCODING 488
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 12 1 0
+BITMAP
+6C
+38
+00
+C6
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+C3
+ENDCHAR
+STARTCHAR uni01E9
+ENCODING 489
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 12 0 0
+BITMAP
+D8
+70
+00
+C0
+C0
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+ENDCHAR
+STARTCHAR uni01EA
+ENCODING 490
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 -3
+BITMAP
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+30
+30
+1C
+ENDCHAR
+STARTCHAR uni01EB
+ENCODING 491
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+78
+CC
+CC
+CC
+CC
+CC
+78
+60
+60
+38
+ENDCHAR
+STARTCHAR uni01EC
+ENCODING 492
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 -3
+BITMAP
+3C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+30
+30
+1C
+ENDCHAR
+STARTCHAR uni01ED
+ENCODING 493
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+78
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+60
+60
+38
+ENDCHAR
+STARTCHAR uni01F0
+ENCODING 496
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 13 -2 -3
+BITMAP
+D8
+70
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+60
+ENDCHAR
+STARTCHAR uni01F4
+ENCODING 500
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+0C
+18
+00
+3E
+63
+C0
+C0
+CF
+C3
+C3
+63
+3D
+ENDCHAR
+STARTCHAR uni01F5
+ENCODING 501
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 0 -3
+BITMAP
+18
+30
+00
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR uni01F8
+ENCODING 504
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+30
+18
+00
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+ENDCHAR
+STARTCHAR uni01F9
+ENCODING 505
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+60
+30
+00
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR Aringacute
+ENCODING 506
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 0 0
+BITMAP
+0C
+18
+00
+18
+24
+18
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR aringacute
+ENCODING 507
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 14 0 0
+BITMAP
+18
+30
+00
+30
+48
+30
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR AEacute
+ENCODING 508
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 11 12 1 0
+BITMAP
+0300
+0600
+0000
+1FE0
+3600
+2600
+6600
+67E0
+7E00
+C600
+C600
+C7E0
+ENDCHAR
+STARTCHAR aeacute
+ENCODING 509
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 10 10 0 0
+BITMAP
+0600
+0C00
+0000
+7780
+CCC0
+0CC0
+7FC0
+CC00
+CCC0
+7780
+ENDCHAR
+STARTCHAR Oslashacute
+ENCODING 510
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 13 1 -1
+BITMAP
+0C
+18
+00
+3D
+66
+CF
+CB
+DB
+D3
+F3
+66
+7C
+80
+ENDCHAR
+STARTCHAR oslashacute
+ENCODING 511
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 -1 0
+BITMAP
+0C
+18
+00
+3D
+66
+6E
+76
+66
+66
+BC
+ENDCHAR
+STARTCHAR uni0200
+ENCODING 512
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+58
+34
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni0201
+ENCODING 513
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+B0
+68
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni0202
+ENCODING 514
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+1C
+22
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni0203
+ENCODING 515
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+38
+44
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni0204
+ENCODING 516
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+B0
+68
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR uni0205
+ENCODING 517
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+B0
+68
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni0206
+ENCODING 518
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+70
+88
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR uni0207
+ENCODING 519
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+44
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni0208
+ENCODING 520
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 12 -1 0
+BITMAP
+B0
+68
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni0209
+ENCODING 521
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 10 -2 0
+BITMAP
+B0
+68
+00
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR uni020A
+ENCODING 522
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 12 0 0
+BITMAP
+70
+88
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni020B
+ENCODING 523
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 10 -1 0
+BITMAP
+70
+88
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni020C
+ENCODING 524
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+58
+34
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni020D
+ENCODING 525
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+B0
+68
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni020E
+ENCODING 526
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+1C
+22
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni020F
+ENCODING 527
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+44
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni0210
+ENCODING 528
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+58
+34
+00
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR uni0211
+ENCODING 529
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 10 0 0
+BITMAP
+B0
+68
+00
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni0212
+ENCODING 530
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+38
+44
+00
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR uni0213
+ENCODING 531
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 10 0 0
+BITMAP
+70
+88
+00
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni0214
+ENCODING 532
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+58
+34
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR uni0215
+ENCODING 533
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+B0
+68
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni0216
+ENCODING 534
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+38
+44
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR uni0217
+ENCODING 535
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+44
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR Scommaaccent
+ENCODING 536
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 14 1 -5
+BITMAP
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+00
+18
+18
+08
+10
+ENDCHAR
+STARTCHAR scommaaccent
+ENCODING 537
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 0 -5
+BITMAP
+78
+CC
+E0
+38
+1C
+CC
+78
+00
+30
+30
+10
+20
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 538
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 14 0 -5
+BITMAP
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+00
+18
+18
+08
+10
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 539
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 14 0 -5
+BITMAP
+60
+60
+F0
+60
+60
+60
+60
+68
+30
+00
+30
+30
+10
+20
+ENDCHAR
+STARTCHAR uni021E
+ENCODING 542
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+6C
+38
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR uni021F
+ENCODING 543
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+D8
+70
+00
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR uni0226
+ENCODING 550
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+18
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni0227
+ENCODING 551
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+30
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni0228
+ENCODING 552
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+30
+30
+E0
+ENDCHAR
+STARTCHAR uni0229
+ENCODING 553
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+78
+CC
+CC
+FC
+C0
+CC
+78
+18
+18
+70
+ENDCHAR
+STARTCHAR uni022A
+ENCODING 554
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3C
+00
+66
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni022B
+ENCODING 555
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+78
+00
+6C
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni022C
+ENCODING 556
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+3C
+00
+1A
+2C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni022D
+ENCODING 557
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+78
+00
+34
+58
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni022E
+ENCODING 558
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+18
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni022F
+ENCODING 559
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+30
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni0230
+ENCODING 560
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3C
+00
+18
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni0231
+ENCODING 561
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+78
+00
+30
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni0232
+ENCODING 562
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+3C
+00
+C3
+C3
+66
+66
+3C
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni0233
+ENCODING 563
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 12 0 -3
+BITMAP
+3C
+00
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR uni0250
+ENCODING 592
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+DC
+66
+66
+7C
+60
+66
+3C
+ENDCHAR
+STARTCHAR uni0254
+ENCODING 596
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+0C
+0C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR uni0258
+ENCODING 600
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+CC
+FC
+0C
+CC
+78
+ENDCHAR
+STARTCHAR uni0259
+ENCODING 601
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+0C
+FC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni025F
+ENCODING 607
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 9 0 -2
+BITMAP
+30
+30
+30
+30
+30
+30
+78
+30
+E0
+ENDCHAR
+STARTCHAR uni0265
+ENCODING 613
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 -2
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+0C
+0C
+ENDCHAR
+STARTCHAR uni0275
+ENCODING 629
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+78
+CC
+CC
+FC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni0279
+ENCODING 633
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+18
+18
+18
+18
+38
+F8
+D8
+ENDCHAR
+STARTCHAR uni0287
+ENCODING 647
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 9 0 0
+BITMAP
+60
+B0
+30
+30
+30
+30
+78
+30
+30
+ENDCHAR
+STARTCHAR uni0288
+ENCODING 648
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 12 0 -3
+BITMAP
+60
+60
+F0
+60
+60
+60
+60
+60
+60
+60
+60
+30
+ENDCHAR
+STARTCHAR uni0289
+ENCODING 649
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+CC
+CC
+CC
+FC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni028C
+ENCODING 652
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+10
+38
+38
+6C
+6C
+C6
+C6
+ENDCHAR
+STARTCHAR uni028D
+ENCODING 653
+SWIDTH 778 0
+DWIDTH 11 0
+BBX 10 7 0 0
+BITMAP
+3300
+3300
+6D80
+6D80
+6D80
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR uni028E
+ENCODING 654
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 10 0 0
+BITMAP
+0C
+18
+10
+30
+38
+38
+6C
+6C
+C6
+C6
+ENDCHAR
+STARTCHAR uni029E
+ENCODING 670
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 -2
+BITMAP
+C6
+66
+36
+1E
+1E
+36
+66
+06
+06
+ENDCHAR
+STARTCHAR uni02BB
+ENCODING 699
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 3 1 6
+BITMAP
+40
+80
+C0
+ENDCHAR
+STARTCHAR afii57929
+ENCODING 700
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 3 1 6
+BITMAP
+C0
+40
+80
+ENDCHAR
+STARTCHAR afii64937
+ENCODING 701
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 3 1 6
+BITMAP
+C0
+80
+40
+ENDCHAR
+STARTCHAR circumflex
+ENCODING 710
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 2 0 8
+BITMAP
+70
+D8
+ENDCHAR
+STARTCHAR caron
+ENCODING 711
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 2 0 8
+BITMAP
+D8
+70
+ENDCHAR
+STARTCHAR uni02C8
+ENCODING 712
+SWIDTH 238 0
+DWIDTH 3 0
+BBX 1 3 1 6
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR macron
+ENCODING 713
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 0 8
+BITMAP
+F0
+ENDCHAR
+STARTCHAR uni02CA
+ENCODING 714
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 0 8
+BITMAP
+60
+C0
+ENDCHAR
+STARTCHAR uni02CB
+ENCODING 715
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 0 8
+BITMAP
+C0
+60
+ENDCHAR
+STARTCHAR uni02CD
+ENCODING 717
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 0 -2
+BITMAP
+F0
+ENDCHAR
+STARTCHAR uni02CE
+ENCODING 718
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 0 -3
+BITMAP
+C0
+60
+ENDCHAR
+STARTCHAR uni02CF
+ENCODING 719
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 0 -3
+BITMAP
+60
+C0
+ENDCHAR
+STARTCHAR breve
+ENCODING 728
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 2 0 8
+BITMAP
+88
+70
+ENDCHAR
+STARTCHAR dotaccent
+ENCODING 729
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 1 1 8
+BITMAP
+C0
+ENDCHAR
+STARTCHAR ring
+ENCODING 730
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 3 0 7
+BITMAP
+70
+D8
+70
+ENDCHAR
+STARTCHAR ogonek
+ENCODING 731
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 4 0 -3
+BITMAP
+60
+C0
+C0
+70
+ENDCHAR
+STARTCHAR tilde
+ENCODING 732
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 2 0 8
+BITMAP
+68
+B0
+ENDCHAR
+STARTCHAR hungarumlaut
+ENCODING 733
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 2 1 8
+BITMAP
+68
+B0
+ENDCHAR
+STARTCHAR uni02EE
+ENCODING 750
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 3 1 6
+BITMAP
+D8
+48
+90
+ENDCHAR
+STARTCHAR uni037E
+ENCODING 894
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 9 1 -2
+BITMAP
+C0
+C0
+00
+00
+00
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR tonos
+ENCODING 900
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 0 8
+BITMAP
+60
+C0
+ENDCHAR
+STARTCHAR dieresistonos
+ENCODING 901
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 4 0 8
+BITMAP
+30
+60
+00
+D8
+ENDCHAR
+STARTCHAR anoteleia
+ENCODING 903
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 2 1 3
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR mu
+ENCODING 956
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+EC
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E00
+ENCODING 7680
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 13 0 -4
+BITMAP
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+00
+1C
+36
+1C
+ENDCHAR
+STARTCHAR uni1E01
+ENCODING 7681
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 11 0 -4
+BITMAP
+78
+CC
+0C
+7C
+CC
+CC
+76
+00
+38
+6C
+38
+ENDCHAR
+STARTCHAR uni1E02
+ENCODING 7682
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+30
+00
+FC
+C6
+C6
+C6
+FC
+C6
+C6
+C6
+FC
+ENDCHAR
+STARTCHAR uni1E03
+ENCODING 7683
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+60
+00
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+ENDCHAR
+STARTCHAR uni1E04
+ENCODING 7684
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+FC
+C6
+C6
+C6
+FC
+C6
+C6
+C6
+FC
+00
+30
+ENDCHAR
+STARTCHAR uni1E05
+ENCODING 7685
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 -2
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+00
+30
+ENDCHAR
+STARTCHAR uni1E06
+ENCODING 7686
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+FC
+C6
+C6
+C6
+FC
+C6
+C6
+C6
+FC
+00
+78
+ENDCHAR
+STARTCHAR uni1E07
+ENCODING 7687
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 -2
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+00
+78
+ENDCHAR
+STARTCHAR uni1E08
+ENCODING 7688
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 7 15 1 -3
+BITMAP
+18
+30
+00
+3C
+66
+C0
+C0
+C0
+C0
+C0
+66
+3C
+18
+18
+70
+ENDCHAR
+STARTCHAR uni1E09
+ENCODING 7689
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 0 -3
+BITMAP
+18
+30
+00
+78
+CC
+C0
+C0
+C0
+CC
+78
+10
+18
+70
+ENDCHAR
+STARTCHAR uni1E0A
+ENCODING 7690
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+30
+00
+F8
+CC
+C6
+C6
+C6
+C6
+C6
+CC
+F8
+ENDCHAR
+STARTCHAR uni1E0B
+ENCODING 7691
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+18
+00
+0C
+0C
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni1E0C
+ENCODING 7692
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+F8
+CC
+C6
+C6
+C6
+C6
+C6
+CC
+F8
+00
+30
+ENDCHAR
+STARTCHAR uni1E0D
+ENCODING 7693
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 -2
+BITMAP
+0C
+0C
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+00
+30
+ENDCHAR
+STARTCHAR uni1E0E
+ENCODING 7694
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+F8
+CC
+C6
+C6
+C6
+C6
+C6
+CC
+F8
+00
+78
+ENDCHAR
+STARTCHAR uni1E0F
+ENCODING 7695
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 -2
+BITMAP
+0C
+0C
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+00
+78
+ENDCHAR
+STARTCHAR uni1E10
+ENCODING 7696
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+F8
+CC
+C6
+C6
+C6
+C6
+C6
+CC
+F8
+18
+18
+70
+ENDCHAR
+STARTCHAR uni1E11
+ENCODING 7697
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+0C
+0C
+6C
+DC
+CC
+CC
+CC
+DC
+7C
+18
+18
+70
+ENDCHAR
+STARTCHAR uni1E12
+ENCODING 7698
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+F8
+CC
+C6
+C6
+C6
+C6
+C6
+CC
+F8
+00
+38
+6C
+ENDCHAR
+STARTCHAR uni1E13
+ENCODING 7699
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+0C
+0C
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+00
+38
+6C
+ENDCHAR
+STARTCHAR uni1E14
+ENCODING 7700
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 14 1 0
+BITMAP
+60
+30
+00
+F0
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR uni1E15
+ENCODING 7701
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+60
+30
+00
+78
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1E16
+ENCODING 7702
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 14 1 0
+BITMAP
+18
+30
+00
+F0
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR uni1E17
+ENCODING 7703
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+18
+30
+00
+78
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1E18
+ENCODING 7704
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+00
+70
+D8
+ENDCHAR
+STARTCHAR uni1E19
+ENCODING 7705
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+78
+CC
+CC
+FC
+C0
+CC
+78
+00
+38
+6C
+ENDCHAR
+STARTCHAR uni1E1A
+ENCODING 7706
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+00
+68
+B0
+ENDCHAR
+STARTCHAR uni1E1B
+ENCODING 7707
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+78
+CC
+CC
+FC
+C0
+CC
+78
+00
+68
+B0
+ENDCHAR
+STARTCHAR uni1E1C
+ENCODING 7708
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 15 1 -3
+BITMAP
+88
+70
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+30
+30
+E0
+ENDCHAR
+STARTCHAR uni1E1D
+ENCODING 7709
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 0 -3
+BITMAP
+44
+38
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+18
+18
+70
+ENDCHAR
+STARTCHAR uni1E1E
+ENCODING 7710
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+60
+00
+FC
+C0
+C0
+C0
+F8
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E1F
+ENCODING 7711
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 11 0 0
+BITMAP
+30
+00
+38
+60
+F0
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni1E20
+ENCODING 7712
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+3C
+00
+3E
+63
+C0
+C0
+CF
+C3
+C3
+63
+3D
+ENDCHAR
+STARTCHAR uni1E21
+ENCODING 7713
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+78
+00
+6C
+DC
+CC
+CC
+CC
+DC
+6C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR uni1E22
+ENCODING 7714
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+18
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR uni1E23
+ENCODING 7715
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+60
+00
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR uni1E24
+ENCODING 7716
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+18
+ENDCHAR
+STARTCHAR uni1E25
+ENCODING 7717
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 -2
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+00
+30
+ENDCHAR
+STARTCHAR uni1E26
+ENCODING 7718
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+6C
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR uni1E27
+ENCODING 7719
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+D8
+00
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR uni1E28
+ENCODING 7720
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+F6
+18
+18
+70
+ENDCHAR
+STARTCHAR uni1E29
+ENCODING 7721
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+FC
+18
+18
+70
+ENDCHAR
+STARTCHAR uni1E2A
+ENCODING 7722
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+44
+38
+ENDCHAR
+STARTCHAR uni1E2B
+ENCODING 7723
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+00
+44
+38
+ENDCHAR
+STARTCHAR uni1E2C
+ENCODING 7724
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 12 -1 -3
+BITMAP
+30
+30
+30
+30
+30
+30
+30
+30
+30
+00
+68
+B0
+ENDCHAR
+STARTCHAR uni1E2D
+ENCODING 7725
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 12 -2 -3
+BITMAP
+30
+00
+30
+30
+30
+30
+30
+30
+30
+00
+68
+B0
+ENDCHAR
+STARTCHAR uni1E2E
+ENCODING 7726
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 5 14 0 0
+BITMAP
+30
+60
+00
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni1E2F
+ENCODING 7727
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 12 -1 0
+BITMAP
+30
+60
+00
+D8
+00
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni1E30
+ENCODING 7728
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 12 1 0
+BITMAP
+18
+30
+00
+C6
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+C3
+ENDCHAR
+STARTCHAR uni1E31
+ENCODING 7729
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 12 0 0
+BITMAP
+30
+60
+00
+C0
+C0
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+ENDCHAR
+STARTCHAR uni1E32
+ENCODING 7730
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 11 1 -2
+BITMAP
+C6
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+C3
+00
+18
+ENDCHAR
+STARTCHAR uni1E33
+ENCODING 7731
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 11 0 -2
+BITMAP
+C0
+C0
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+00
+30
+ENDCHAR
+STARTCHAR uni1E34
+ENCODING 7732
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 11 1 -2
+BITMAP
+C6
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+C3
+00
+3C
+ENDCHAR
+STARTCHAR uni1E35
+ENCODING 7733
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 11 0 -2
+BITMAP
+C0
+C0
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+00
+78
+ENDCHAR
+STARTCHAR uni1E36
+ENCODING 7734
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 1 -2
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+FC
+00
+60
+ENDCHAR
+STARTCHAR uni1E37
+ENCODING 7735
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 11 0 -2
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+00
+C0
+ENDCHAR
+STARTCHAR uni1E38
+ENCODING 7736
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 1 -2
+BITMAP
+F0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+FC
+00
+60
+ENDCHAR
+STARTCHAR uni1E39
+ENCODING 7737
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 13 -1 -2
+BITMAP
+F0
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+00
+60
+ENDCHAR
+STARTCHAR uni1E3A
+ENCODING 7738
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 1 -2
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+FC
+00
+F0
+ENDCHAR
+STARTCHAR uni1E3B
+ENCODING 7739
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 11 -1 -2
+BITMAP
+60
+60
+60
+60
+60
+60
+60
+60
+60
+00
+F0
+ENDCHAR
+STARTCHAR uni1E3C
+ENCODING 7740
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 1 -3
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+FC
+00
+70
+D8
+ENDCHAR
+STARTCHAR uni1E3D
+ENCODING 7741
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 12 -1 -3
+BITMAP
+60
+60
+60
+60
+60
+60
+60
+60
+60
+00
+70
+D8
+ENDCHAR
+STARTCHAR uni1E3E
+ENCODING 7742
+SWIDTH 833 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0C00
+1800
+0000
+C180
+C180
+E380
+E380
+F780
+D580
+DD80
+C980
+C980
+ENDCHAR
+STARTCHAR uni1E3F
+ENCODING 7743
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 10 10 0 0
+BITMAP
+0600
+0C00
+0000
+BB80
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR uni1E40
+ENCODING 7744
+SWIDTH 833 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+0C00
+0000
+C180
+C180
+E380
+E380
+F780
+D580
+DD80
+C980
+C980
+ENDCHAR
+STARTCHAR uni1E41
+ENCODING 7745
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 10 9 0 0
+BITMAP
+0C00
+0000
+BB80
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR uni1E42
+ENCODING 7746
+SWIDTH 833 0
+DWIDTH 11 0
+BBX 9 11 1 -2
+BITMAP
+C180
+C180
+E380
+E380
+F780
+D580
+DD80
+C980
+C980
+0000
+0C00
+ENDCHAR
+STARTCHAR uni1E43
+ENCODING 7747
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 10 9 0 -2
+BITMAP
+BB80
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+0000
+0C00
+ENDCHAR
+STARTCHAR uni1E44
+ENCODING 7748
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+30
+00
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+ENDCHAR
+STARTCHAR uni1E45
+ENCODING 7749
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+30
+00
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR uni1E46
+ENCODING 7750
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+00
+18
+ENDCHAR
+STARTCHAR uni1E47
+ENCODING 7751
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 -2
+BITMAP
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+00
+30
+ENDCHAR
+STARTCHAR uni1E48
+ENCODING 7752
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+00
+3C
+ENDCHAR
+STARTCHAR uni1E49
+ENCODING 7753
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 -2
+BITMAP
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+00
+78
+ENDCHAR
+STARTCHAR uni1E4A
+ENCODING 7754
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+C6
+E6
+E6
+D6
+D6
+CE
+CE
+C6
+C6
+00
+38
+6C
+ENDCHAR
+STARTCHAR uni1E4B
+ENCODING 7755
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+00
+38
+6C
+ENDCHAR
+STARTCHAR uni1E4C
+ENCODING 7756
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 15 1 0
+BITMAP
+0C
+18
+00
+1A
+2C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni1E4D
+ENCODING 7757
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 0 0
+BITMAP
+18
+30
+00
+34
+58
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni1E4E
+ENCODING 7758
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+36
+00
+1A
+2C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni1E4F
+ENCODING 7759
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+6C
+00
+34
+58
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni1E50
+ENCODING 7760
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+30
+18
+00
+3C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni1E51
+ENCODING 7761
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+60
+30
+00
+78
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni1E52
+ENCODING 7762
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+0C
+18
+00
+3C
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni1E53
+ENCODING 7763
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+18
+30
+00
+78
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni1E54
+ENCODING 7764
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 12 1 0
+BITMAP
+18
+30
+00
+FC
+C6
+C6
+C6
+FC
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E55
+ENCODING 7765
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 0 -3
+BITMAP
+18
+30
+00
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E56
+ENCODING 7766
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+30
+00
+FC
+C6
+C6
+C6
+FC
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E57
+ENCODING 7767
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+30
+00
+D8
+EC
+CC
+CC
+CC
+EC
+D8
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E58
+ENCODING 7768
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+30
+00
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+ENDCHAR
+STARTCHAR uni1E59
+ENCODING 7769
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 9 0 0
+BITMAP
+30
+00
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E5A
+ENCODING 7770
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+00
+18
+ENDCHAR
+STARTCHAR uni1E5B
+ENCODING 7771
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 9 0 -2
+BITMAP
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+00
+60
+ENDCHAR
+STARTCHAR uni1E5C
+ENCODING 7772
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 13 1 -2
+BITMAP
+78
+00
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+00
+18
+ENDCHAR
+STARTCHAR uni1E5D
+ENCODING 7773
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 11 0 -2
+BITMAP
+F0
+00
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+00
+60
+ENDCHAR
+STARTCHAR uni1E5E
+ENCODING 7774
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+FC
+C6
+C6
+C6
+FC
+CC
+C6
+C6
+C6
+00
+3C
+ENDCHAR
+STARTCHAR uni1E5F
+ENCODING 7775
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 5 9 0 -2
+BITMAP
+D8
+F8
+E0
+C0
+C0
+C0
+C0
+00
+F0
+ENDCHAR
+STARTCHAR uni1E60
+ENCODING 7776
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+18
+00
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+ENDCHAR
+STARTCHAR uni1E61
+ENCODING 7777
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+30
+00
+78
+CC
+E0
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR uni1E62
+ENCODING 7778
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+00
+18
+ENDCHAR
+STARTCHAR uni1E63
+ENCODING 7779
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 -2
+BITMAP
+78
+CC
+E0
+38
+1C
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1E64
+ENCODING 7780
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+18
+00
+18
+30
+00
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+ENDCHAR
+STARTCHAR uni1E65
+ENCODING 7781
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+30
+00
+18
+30
+00
+78
+CC
+E0
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR uni1E66
+ENCODING 7782
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+18
+00
+6C
+38
+00
+78
+CC
+E0
+78
+1C
+CE
+7C
+ENDCHAR
+STARTCHAR uni1E67
+ENCODING 7783
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 0 0
+BITMAP
+30
+00
+D8
+70
+00
+78
+CC
+E0
+38
+1C
+CC
+78
+ENDCHAR
+STARTCHAR uni1E68
+ENCODING 7784
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 13 1 -2
+BITMAP
+18
+00
+7C
+C6
+C6
+70
+1C
+0E
+C6
+C6
+7C
+00
+18
+ENDCHAR
+STARTCHAR uni1E69
+ENCODING 7785
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 11 0 -2
+BITMAP
+30
+00
+78
+CC
+E0
+38
+1C
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1E6A
+ENCODING 7786
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+18
+00
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni1E6B
+ENCODING 7787
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 11 0 0
+BITMAP
+60
+00
+60
+60
+F0
+60
+60
+60
+60
+68
+30
+ENDCHAR
+STARTCHAR uni1E6C
+ENCODING 7788
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 11 0 -2
+BITMAP
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+00
+18
+ENDCHAR
+STARTCHAR uni1E6D
+ENCODING 7789
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 11 0 -2
+BITMAP
+60
+60
+F0
+60
+60
+60
+60
+68
+30
+00
+30
+ENDCHAR
+STARTCHAR uni1E6E
+ENCODING 7790
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 11 0 -2
+BITMAP
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+00
+3C
+ENDCHAR
+STARTCHAR uni1E6F
+ENCODING 7791
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 11 0 -2
+BITMAP
+60
+60
+F0
+60
+60
+60
+60
+68
+30
+00
+78
+ENDCHAR
+STARTCHAR uni1E70
+ENCODING 7792
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 8 12 0 -3
+BITMAP
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+00
+1C
+36
+ENDCHAR
+STARTCHAR uni1E71
+ENCODING 7793
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 12 0 -3
+BITMAP
+60
+60
+F0
+60
+60
+60
+60
+68
+30
+00
+70
+D8
+ENDCHAR
+STARTCHAR uni1E72
+ENCODING 7794
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+00
+6C
+ENDCHAR
+STARTCHAR uni1E73
+ENCODING 7795
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 -2
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+00
+6C
+ENDCHAR
+STARTCHAR uni1E74
+ENCODING 7796
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+00
+34
+58
+ENDCHAR
+STARTCHAR uni1E75
+ENCODING 7797
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+00
+68
+B0
+ENDCHAR
+STARTCHAR uni1E76
+ENCODING 7798
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+00
+38
+6C
+ENDCHAR
+STARTCHAR uni1E77
+ENCODING 7799
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+00
+38
+6C
+ENDCHAR
+STARTCHAR uni1E78
+ENCODING 7800
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 15 1 0
+BITMAP
+18
+30
+00
+34
+58
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR uni1E79
+ENCODING 7801
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 0 0
+BITMAP
+18
+30
+00
+34
+58
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni1E7A
+ENCODING 7802
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+6C
+00
+3C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+ENDCHAR
+STARTCHAR uni1E7B
+ENCODING 7803
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+6C
+00
+78
+00
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni1E7C
+ENCODING 7804
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+1A
+2C
+00
+C3
+C3
+66
+66
+66
+24
+3C
+18
+18
+ENDCHAR
+STARTCHAR uni1E7D
+ENCODING 7805
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 10 0 0
+BITMAP
+34
+58
+00
+C6
+C6
+6C
+6C
+38
+38
+10
+ENDCHAR
+STARTCHAR uni1E7E
+ENCODING 7806
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 11 0 -2
+BITMAP
+C3
+C3
+66
+66
+66
+24
+3C
+18
+18
+00
+18
+ENDCHAR
+STARTCHAR uni1E7F
+ENCODING 7807
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 9 0 -2
+BITMAP
+C6
+C6
+6C
+6C
+38
+38
+10
+00
+18
+ENDCHAR
+STARTCHAR Wgrave
+ENCODING 7808
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 12 0 0
+BITMAP
+1800
+0C00
+0000
+CCC0
+CCC0
+CCC0
+4C80
+6D80
+6D80
+3300
+3300
+3300
+ENDCHAR
+STARTCHAR wgrave
+ENCODING 7809
+SWIDTH 778 0
+DWIDTH 11 0
+BBX 10 10 0 0
+BITMAP
+1800
+0C00
+0000
+CCC0
+CCC0
+6D80
+6D80
+6D80
+3300
+3300
+ENDCHAR
+STARTCHAR Wacute
+ENCODING 7810
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 12 0 0
+BITMAP
+0600
+0C00
+0000
+CCC0
+CCC0
+CCC0
+4C80
+6D80
+6D80
+3300
+3300
+3300
+ENDCHAR
+STARTCHAR wacute
+ENCODING 7811
+SWIDTH 778 0
+DWIDTH 11 0
+BBX 10 10 0 0
+BITMAP
+0600
+0C00
+0000
+CCC0
+CCC0
+6D80
+6D80
+6D80
+3300
+3300
+ENDCHAR
+STARTCHAR Wdieresis
+ENCODING 7812
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 11 0 0
+BITMAP
+1B00
+0000
+CCC0
+CCC0
+CCC0
+4C80
+6D80
+6D80
+3300
+3300
+3300
+ENDCHAR
+STARTCHAR wdieresis
+ENCODING 7813
+SWIDTH 778 0
+DWIDTH 11 0
+BBX 10 9 0 0
+BITMAP
+1B00
+0000
+CCC0
+CCC0
+6D80
+6D80
+6D80
+3300
+3300
+ENDCHAR
+STARTCHAR uni1E86
+ENCODING 7814
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 11 0 0
+BITMAP
+0C00
+0000
+CCC0
+CCC0
+CCC0
+4C80
+6D80
+6D80
+3300
+3300
+3300
+ENDCHAR
+STARTCHAR uni1E87
+ENCODING 7815
+SWIDTH 778 0
+DWIDTH 11 0
+BBX 10 9 0 0
+BITMAP
+0C00
+0000
+CCC0
+CCC0
+6D80
+6D80
+6D80
+3300
+3300
+ENDCHAR
+STARTCHAR uni1E88
+ENCODING 7816
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 11 0 -2
+BITMAP
+CCC0
+CCC0
+CCC0
+4C80
+6D80
+6D80
+3300
+3300
+3300
+0000
+0C00
+ENDCHAR
+STARTCHAR uni1E89
+ENCODING 7817
+SWIDTH 778 0
+DWIDTH 11 0
+BBX 10 9 0 -2
+BITMAP
+CCC0
+CCC0
+6D80
+6D80
+6D80
+3300
+3300
+0000
+0C00
+ENDCHAR
+STARTCHAR uni1E8A
+ENCODING 7818
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+18
+00
+C3
+C3
+66
+3C
+18
+3C
+66
+C3
+C3
+ENDCHAR
+STARTCHAR uni1E8B
+ENCODING 7819
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+30
+00
+CC
+CC
+78
+30
+78
+CC
+CC
+ENDCHAR
+STARTCHAR uni1E8C
+ENCODING 7820
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+36
+00
+C3
+C3
+66
+3C
+18
+3C
+66
+C3
+C3
+ENDCHAR
+STARTCHAR uni1E8D
+ENCODING 7821
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+6C
+00
+CC
+CC
+78
+30
+78
+CC
+CC
+ENDCHAR
+STARTCHAR uni1E8E
+ENCODING 7822
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+18
+00
+C3
+C3
+66
+66
+3C
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni1E8F
+ENCODING 7823
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 12 0 -3
+BITMAP
+18
+00
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR uni1E90
+ENCODING 7824
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 12 0 0
+BITMAP
+38
+6C
+00
+FE
+06
+0C
+18
+30
+30
+60
+C0
+FE
+ENDCHAR
+STARTCHAR uni1E91
+ENCODING 7825
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 10 0 0
+BITMAP
+70
+D8
+00
+F8
+18
+30
+20
+60
+C0
+F8
+ENDCHAR
+STARTCHAR uni1E92
+ENCODING 7826
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 11 0 -2
+BITMAP
+FE
+06
+0C
+18
+30
+30
+60
+C0
+FE
+00
+30
+ENDCHAR
+STARTCHAR uni1E93
+ENCODING 7827
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 9 0 -2
+BITMAP
+F8
+18
+30
+20
+60
+C0
+F8
+00
+60
+ENDCHAR
+STARTCHAR uni1E94
+ENCODING 7828
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 11 0 -2
+BITMAP
+FE
+06
+0C
+18
+30
+30
+60
+C0
+FE
+00
+78
+ENDCHAR
+STARTCHAR uni1E95
+ENCODING 7829
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 9 0 -2
+BITMAP
+F8
+18
+30
+20
+60
+C0
+F8
+00
+F0
+ENDCHAR
+STARTCHAR uni1E96
+ENCODING 7830
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 0 -2
+BITMAP
+C0
+C0
+D8
+EC
+CC
+CC
+CC
+CC
+CC
+00
+78
+ENDCHAR
+STARTCHAR uni1E97
+ENCODING 7831
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 11 0 0
+BITMAP
+D8
+00
+60
+60
+F0
+60
+60
+60
+60
+68
+30
+ENDCHAR
+STARTCHAR uni1E98
+ENCODING 7832
+SWIDTH 778 0
+DWIDTH 11 0
+BBX 10 11 0 0
+BITMAP
+0E00
+1B00
+0E00
+0000
+CCC0
+CCC0
+6D80
+6D80
+6D80
+3300
+3300
+ENDCHAR
+STARTCHAR uni1E99
+ENCODING 7833
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 14 0 -3
+BITMAP
+38
+6C
+38
+00
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR uni1EA0
+ENCODING 7840
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 11 0 -2
+BITMAP
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+00
+18
+ENDCHAR
+STARTCHAR uni1EA1
+ENCODING 7841
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 0 -2
+BITMAP
+78
+CC
+0C
+7C
+CC
+CC
+76
+00
+18
+ENDCHAR
+STARTCHAR uni1EA4
+ENCODING 7844
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 0 0
+BITMAP
+0C
+18
+00
+1C
+36
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni1EA5
+ENCODING 7845
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 13 0 0
+BITMAP
+18
+30
+00
+38
+6C
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni1EA6
+ENCODING 7846
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 0 0
+BITMAP
+30
+18
+00
+1C
+36
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni1EA7
+ENCODING 7847
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 13 0 0
+BITMAP
+30
+18
+00
+38
+6C
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni1EAA
+ENCODING 7850
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 0 0
+BITMAP
+1A
+2C
+00
+1C
+36
+00
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni1EAB
+ENCODING 7851
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 13 0 0
+BITMAP
+34
+58
+00
+38
+6C
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni1EAC
+ENCODING 7852
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 14 0 -2
+BITMAP
+1C
+36
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+00
+18
+ENDCHAR
+STARTCHAR uni1EAD
+ENCODING 7853
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 12 0 -2
+BITMAP
+38
+6C
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+00
+18
+ENDCHAR
+STARTCHAR uni1EAE
+ENCODING 7854
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 0 0
+BITMAP
+0C
+18
+00
+22
+1C
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni1EAF
+ENCODING 7855
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 13 0 0
+BITMAP
+18
+30
+00
+44
+38
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni1EB0
+ENCODING 7856
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 0 0
+BITMAP
+30
+18
+00
+22
+1C
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni1EB1
+ENCODING 7857
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 13 0 0
+BITMAP
+30
+18
+00
+44
+38
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni1EB4
+ENCODING 7860
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 0 0
+BITMAP
+1A
+2C
+00
+22
+1C
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni1EB5
+ENCODING 7861
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 13 0 0
+BITMAP
+34
+58
+00
+44
+38
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+ENDCHAR
+STARTCHAR uni1EB6
+ENCODING 7862
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 14 0 -2
+BITMAP
+22
+1C
+00
+18
+3C
+24
+66
+66
+7E
+C3
+C3
+C3
+00
+18
+ENDCHAR
+STARTCHAR uni1EB7
+ENCODING 7863
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 12 0 -2
+BITMAP
+44
+38
+00
+78
+CC
+0C
+7C
+CC
+CC
+76
+00
+18
+ENDCHAR
+STARTCHAR uni1EB8
+ENCODING 7864
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 -2
+BITMAP
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+00
+60
+ENDCHAR
+STARTCHAR uni1EB9
+ENCODING 7865
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 -2
+BITMAP
+78
+CC
+CC
+FC
+C0
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1EBC
+ENCODING 7868
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+68
+B0
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR uni1EBD
+ENCODING 7869
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+34
+58
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1EBE
+ENCODING 7870
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 15 1 0
+BITMAP
+18
+30
+00
+38
+6C
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR uni1EBF
+ENCODING 7871
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 0 0
+BITMAP
+18
+30
+00
+38
+6C
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1EC0
+ENCODING 7872
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 15 1 0
+BITMAP
+60
+30
+00
+38
+6C
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR uni1EC1
+ENCODING 7873
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 0 0
+BITMAP
+30
+18
+00
+38
+6C
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1EC4
+ENCODING 7876
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 15 1 0
+BITMAP
+34
+58
+00
+38
+6C
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+ENDCHAR
+STARTCHAR uni1EC5
+ENCODING 7877
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 0 0
+BITMAP
+34
+58
+00
+38
+6C
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1EC6
+ENCODING 7878
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 14 1 -2
+BITMAP
+70
+D8
+00
+FC
+C0
+C0
+C0
+FC
+C0
+C0
+C0
+FC
+00
+60
+ENDCHAR
+STARTCHAR uni1EC7
+ENCODING 7879
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 0 -2
+BITMAP
+38
+6C
+00
+78
+CC
+CC
+FC
+C0
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1ECA
+ENCODING 7882
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 11 1 -2
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+00
+C0
+ENDCHAR
+STARTCHAR uni1ECB
+ENCODING 7883
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 11 0 -2
+BITMAP
+C0
+00
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+00
+C0
+ENDCHAR
+STARTCHAR uni1ECC
+ENCODING 7884
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 -2
+BITMAP
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+00
+18
+ENDCHAR
+STARTCHAR uni1ECD
+ENCODING 7885
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 -2
+BITMAP
+78
+CC
+CC
+CC
+CC
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1ED0
+ENCODING 7888
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 15 1 0
+BITMAP
+0C
+18
+00
+1C
+36
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni1ED1
+ENCODING 7889
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 0 0
+BITMAP
+18
+30
+00
+38
+6C
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni1ED2
+ENCODING 7890
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 15 1 0
+BITMAP
+30
+18
+00
+1C
+36
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni1ED3
+ENCODING 7891
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 0 0
+BITMAP
+30
+18
+00
+38
+6C
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni1ED6
+ENCODING 7894
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 15 1 0
+BITMAP
+1A
+2C
+00
+1C
+36
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+ENDCHAR
+STARTCHAR uni1ED7
+ENCODING 7895
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 0 0
+BITMAP
+34
+58
+00
+38
+6C
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni1ED8
+ENCODING 7896
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 -2
+BITMAP
+1C
+36
+00
+3C
+66
+C3
+C3
+C3
+C3
+C3
+66
+3C
+00
+18
+ENDCHAR
+STARTCHAR uni1ED9
+ENCODING 7897
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 0 -2
+BITMAP
+38
+6C
+00
+78
+CC
+CC
+CC
+CC
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1EDA
+ENCODING 7898
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 12 1 0
+BITMAP
+0600
+0C00
+0000
+3CC0
+6640
+C380
+C300
+C300
+C300
+C300
+6600
+3C00
+ENDCHAR
+STARTCHAR uni1EDB
+ENCODING 7899
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0C
+18
+00
+7B
+CD
+CE
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni1EDC
+ENCODING 7900
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 12 1 0
+BITMAP
+1800
+0C00
+0000
+3CC0
+6640
+C380
+C300
+C300
+C300
+C300
+6600
+3C00
+ENDCHAR
+STARTCHAR uni1EDD
+ENCODING 7901
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+30
+18
+00
+7B
+CD
+CE
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni1EE0
+ENCODING 7904
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 12 1 0
+BITMAP
+0D00
+1600
+0000
+3CC0
+6640
+C380
+C300
+C300
+C300
+C300
+6600
+3C00
+ENDCHAR
+STARTCHAR uni1EE1
+ENCODING 7905
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+1A
+2C
+00
+7B
+CD
+CE
+CC
+CC
+CC
+78
+ENDCHAR
+STARTCHAR uni1EE2
+ENCODING 7906
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 11 1 -2
+BITMAP
+3CC0
+6640
+C380
+C300
+C300
+C300
+C300
+6600
+3C00
+0000
+1800
+ENDCHAR
+STARTCHAR uni1EE3
+ENCODING 7907
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 -2
+BITMAP
+7B
+CD
+CE
+CC
+CC
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1EE4
+ENCODING 7908
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+7C
+00
+18
+ENDCHAR
+STARTCHAR uni1EE5
+ENCODING 7909
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 -2
+BITMAP
+CC
+CC
+CC
+CC
+CC
+DC
+6C
+00
+30
+ENDCHAR
+STARTCHAR uni1EE8
+ENCODING 7912
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0C00
+1800
+0000
+C780
+C680
+C700
+C600
+C600
+C600
+C600
+6C00
+7C00
+ENDCHAR
+STARTCHAR uni1EE9
+ENCODING 7913
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0C
+18
+00
+CF
+CD
+CE
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni1EEA
+ENCODING 7914
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+1800
+0C00
+0000
+C780
+C680
+C700
+C600
+C600
+C600
+C600
+6C00
+7C00
+ENDCHAR
+STARTCHAR uni1EEB
+ENCODING 7915
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+30
+18
+00
+CF
+CD
+CE
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni1EEE
+ENCODING 7918
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+1A00
+2C00
+0000
+C780
+C680
+C700
+C600
+C600
+C600
+C600
+6C00
+7C00
+ENDCHAR
+STARTCHAR uni1EEF
+ENCODING 7919
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+1A
+2C
+00
+CF
+CD
+CE
+CC
+CC
+DC
+6C
+ENDCHAR
+STARTCHAR uni1EF0
+ENCODING 7920
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 11 1 -2
+BITMAP
+C780
+C680
+C700
+C600
+C600
+C600
+C600
+6C00
+7C00
+0000
+1800
+ENDCHAR
+STARTCHAR uni1EF1
+ENCODING 7921
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 -2
+BITMAP
+CF
+CD
+CE
+CC
+CC
+DC
+6C
+00
+18
+ENDCHAR
+STARTCHAR Ygrave
+ENCODING 7922
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+30
+18
+00
+C3
+C3
+66
+66
+3C
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR ygrave
+ENCODING 7923
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 13 0 -3
+BITMAP
+30
+18
+00
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR uni1EF4
+ENCODING 7924
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 11 0 -2
+BITMAP
+C3
+C3
+66
+66
+3C
+18
+18
+18
+18
+00
+18
+ENDCHAR
+STARTCHAR uni1EF5
+ENCODING 7925
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 12 0 -5
+BITMAP
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+00
+30
+ENDCHAR
+STARTCHAR uni1EF8
+ENCODING 7928
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+1A
+2C
+00
+C3
+C3
+66
+66
+3C
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni1EF9
+ENCODING 7929
+SWIDTH 556 0
+DWIDTH 8 0
+BBX 7 13 0 -3
+BITMAP
+34
+58
+00
+C6
+C6
+6C
+6C
+38
+38
+18
+10
+30
+60
+ENDCHAR
+STARTCHAR uni2000
+ENCODING 8192
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2001
+ENCODING 8193
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2002
+ENCODING 8194
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2003
+ENCODING 8195
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2004
+ENCODING 8196
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2005
+ENCODING 8197
+SWIDTH 250 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2006
+ENCODING 8198
+SWIDTH 167 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2007
+ENCODING 8199
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2008
+ENCODING 8200
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2009
+ENCODING 8201
+SWIDTH 200 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni200A
+ENCODING 8202
+SWIDTH 100 0
+DWIDTH 1 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni200B
+ENCODING 8203
+SWIDTH 0 0
+DWIDTH 0 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2010
+ENCODING 8208
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR uni2011
+ENCODING 8209
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR figuredash
+ENCODING 8210
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 0 3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR endash
+ENCODING 8211
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 0 3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR emdash
+ENCODING 8212
+SWIDTH 1000 0
+DWIDTH 12 0
+BBX 12 1 0 3
+BITMAP
+FFF0
+ENDCHAR
+STARTCHAR afii00208
+ENCODING 8213
+SWIDTH 1000 0
+DWIDTH 12 0
+BBX 12 1 0 3
+BITMAP
+FFF0
+ENDCHAR
+STARTCHAR quoteleft
+ENCODING 8216
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 3 1 6
+BITMAP
+40
+80
+C0
+ENDCHAR
+STARTCHAR quoteright
+ENCODING 8217
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 3 1 6
+BITMAP
+C0
+40
+80
+ENDCHAR
+STARTCHAR quotesinglbase
+ENCODING 8218
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 3 1 -2
+BITMAP
+C0
+40
+80
+ENDCHAR
+STARTCHAR quotereversed
+ENCODING 8219
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 3 1 6
+BITMAP
+C0
+80
+40
+ENDCHAR
+STARTCHAR quotedblleft
+ENCODING 8220
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 3 1 6
+BITMAP
+48
+90
+D8
+ENDCHAR
+STARTCHAR quotedblright
+ENCODING 8221
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 3 1 6
+BITMAP
+D8
+48
+90
+ENDCHAR
+STARTCHAR quotedblbase
+ENCODING 8222
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 3 1 -2
+BITMAP
+D8
+48
+90
+ENDCHAR
+STARTCHAR uni201F
+ENCODING 8223
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 3 1 6
+BITMAP
+D8
+90
+48
+ENDCHAR
+STARTCHAR dagger
+ENCODING 8224
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+FC
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR daggerdbl
+ENCODING 8225
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+30
+30
+30
+FC
+30
+30
+30
+FC
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR bullet
+ENCODING 8226
+SWIDTH 350 0
+DWIDTH 4 0
+BBX 4 3 0 2
+BITMAP
+60
+F0
+60
+ENDCHAR
+STARTCHAR ellipsis
+ENCODING 8230
+SWIDTH 1000 0
+DWIDTH 12 0
+BBX 10 1 1 0
+BITMAP
+CCC0
+ENDCHAR
+STARTCHAR perthousand
+ENCODING 8240
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 13 8 0 0
+BITMAP
+7100
+DB00
+DA00
+7400
+05B0
+0B68
+1B68
+11B0
+ENDCHAR
+STARTCHAR guilsinglleft
+ENCODING 8249
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 3 5 1 1
+BITMAP
+20
+60
+C0
+60
+20
+ENDCHAR
+STARTCHAR guilsinglright
+ENCODING 8250
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 3 5 1 1
+BITMAP
+80
+C0
+60
+C0
+80
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8260
+SWIDTH 167 0
+DWIDTH 4 0
+BBX 5 8 -1 0
+BITMAP
+18
+18
+30
+30
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR oneinferior
+ENCODING 8321
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 5 0 -3
+BITMAP
+60
+E0
+60
+60
+60
+ENDCHAR
+STARTCHAR twoinferior
+ENCODING 8322
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 0 -3
+BITMAP
+60
+B0
+60
+C0
+F0
+ENDCHAR
+STARTCHAR threeinferior
+ENCODING 8323
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 0 -3
+BITMAP
+60
+B0
+60
+30
+E0
+ENDCHAR
+STARTCHAR uni20A5
+ENCODING 8357
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 10 9 0 -1
+BITMAP
+0600
+BF80
+CCC0
+CCC0
+CCC0
+CCC0
+CCC0
+DCC0
+1800
+ENDCHAR
+STARTCHAR uni20A6
+ENCODING 8358
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+C6
+E6
+E6
+FE
+D6
+FE
+CE
+C6
+C6
+ENDCHAR
+STARTCHAR uni20A9
+ENCODING 8361
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+CCC0
+CCC0
+CCC0
+7F80
+6D80
+7F80
+3300
+3300
+3300
+ENDCHAR
+STARTCHAR Euro
+ENCODING 8364
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 9 -1 0
+BITMAP
+0F00
+1980
+3000
+FC00
+3000
+FC00
+3000
+1980
+0F00
+ENDCHAR
+STARTCHAR uni20AD
+ENCODING 8365
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+C6
+CC
+D8
+F0
+FF
+D8
+CC
+C6
+C3
+ENDCHAR
+STARTCHAR uni2103
+ENCODING 8451
+SWIDTH 1102 0
+DWIDTH 13 0
+BBX 13 9 0 0
+BITMAP
+00F0
+6198
+9300
+9300
+6300
+0300
+0300
+0198
+00F0
+ENDCHAR
+STARTCHAR uni2109
+ENCODING 8457
+SWIDTH 991 0
+DWIDTH 12 0
+BBX 12 9 0 0
+BITMAP
+03F0
+6300
+9300
+9300
+63E0
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR trademark
+ENCODING 8482
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 9 5 1 3
+BITMAP
+E880
+4D80
+4A80
+4A80
+4A80
+ENDCHAR
+STARTCHAR uni212A
+ENCODING 8490
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+C6
+CC
+D8
+F0
+F0
+D8
+CC
+C6
+C3
+ENDCHAR
+STARTCHAR uni212B
+ENCODING 8491
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+18
+24
+18
+18
+18
+3C
+24
+66
+7E
+C3
+C3
+C3
+ENDCHAR
+STARTCHAR uni2132
+ENCODING 8498
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+0C
+0C
+0C
+0C
+7C
+0C
+0C
+0C
+FC
+ENDCHAR
+STARTCHAR universal
+ENCODING 8704
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+C3
+C3
+C3
+7E
+66
+66
+24
+3C
+18
+ENDCHAR
+STARTCHAR existential
+ENCODING 8707
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+0C
+0C
+0C
+FC
+0C
+0C
+0C
+FC
+ENDCHAR
+STARTCHAR uni2204
+ENCODING 8708
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+1C
+1C
+3C
+FC
+2C
+2C
+6C
+FC
+ENDCHAR
+STARTCHAR minus
+ENCODING 8722
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 5 1 1 3
+BITMAP
+F8
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8725
+SWIDTH 167 0
+DWIDTH 4 0
+BBX 5 8 -1 0
+BITMAP
+18
+18
+30
+30
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 8729
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 2 1 3
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR uni2236
+ENCODING 8758
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 7 1 0
+BITMAP
+C0
+C0
+00
+00
+00
+C0
+C0
+ENDCHAR
+STARTCHAR uni2259
+ENCODING 8793
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 6 0 2
+BITMAP
+38
+6C
+00
+FC
+00
+FC
+ENDCHAR
+STARTCHAR uni225A
+ENCODING 8794
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 6 0 2
+BITMAP
+6C
+38
+00
+FC
+00
+FC
+ENDCHAR
+STARTCHAR notequal
+ENCODING 8800
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 9 0 -1
+BITMAP
+18
+18
+10
+FC
+30
+FC
+20
+60
+60
+ENDCHAR
+STARTCHAR equivalence
+ENCODING 8801
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+FC
+00
+FC
+00
+FC
+ENDCHAR
+STARTCHAR uni2262
+ENCODING 8802
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 9 0 -1
+BITMAP
+18
+18
+FC
+30
+FC
+20
+FC
+60
+60
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 8804
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 7 1 -1
+BITMAP
+18
+70
+C0
+70
+18
+00
+F8
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 8805
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 7 1 -1
+BITMAP
+C0
+70
+18
+70
+C0
+00
+F8
+ENDCHAR
+STARTCHAR uni226E
+ENCODING 8814
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 9 1 -1
+BITMAP
+18
+18
+18
+70
+F0
+70
+38
+60
+60
+ENDCHAR
+STARTCHAR uni226F
+ENCODING 8815
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 9 1 -1
+BITMAP
+18
+18
+D0
+70
+38
+70
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2270
+ENCODING 8816
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 9 1 -2
+BITMAP
+18
+18
+70
+F0
+70
+38
+20
+F8
+60
+ENDCHAR
+STARTCHAR uni2271
+ENCODING 8817
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 9 1 -2
+BITMAP
+18
+D8
+70
+38
+70
+E0
+20
+F8
+60
+ENDCHAR
+STARTCHAR fi
+ENCODING -1
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+36
+60
+F6
+66
+66
+66
+66
+66
+66
+ENDCHAR
+STARTCHAR fl
+ENCODING -1
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+36
+66
+F6
+66
+66
+66
+66
+66
+66
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/helvBO12-iso-8859-1.bdf b/gui/themes/fonts/helvBO12-iso-8859-1.bdf
new file mode 100644
index 0000000000..9073827992
--- /dev/null
+++ b/gui/themes/fonts/helvBO12-iso-8859-1.bdf
@@ -0,0 +1,3058 @@
+STARTFONT 2.1
+COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT!
+COMMENT Generated with 'ucs2any.pl helvBO12.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1'
+COMMENT from an ISO10646-1 encoded source BDF font.
+COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000.
+FONT -Adobe-Helvetica-Bold-O-Normal--12-120-75-75-P-69-ISO8859-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 16 15 -2 -3
+COMMENT $Xorg: $
+COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20
+COMMENT
+COMMENT +
+COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated.
+COMMENT Copyright 1988, 1994 Digital Equipment Corporation.
+COMMENT
+COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be
+COMMENT registered in certain jurisdictions.
+COMMENT Permission to use these trademarks is hereby granted only in
+COMMENT association with the images described in this file.
+COMMENT
+COMMENT Permission to use, copy, modify, distribute and sell this software
+COMMENT and its documentation for any purpose and without fee is hereby
+COMMENT granted, provided that the above copyright notices appear in all
+COMMENT copies and that both those copyright notices and this permission
+COMMENT notice appear in supporting documentation, and that the names of
+COMMENT Adobe Systems and Digital Equipment Corporation not be used in
+COMMENT advertising or publicity pertaining to distribution of the software
+COMMENT without specific, written prior permission. Adobe Systems and
+COMMENT Digital Equipment Corporation make no representations about the
+COMMENT suitability of this software for any purpose. It is provided "as
+COMMENT is" without express or implied warranty.
+COMMENT -
+STARTPROPERTIES 26
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Bold"
+SLANT "O"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 69
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 7
+FONT_ASCENT 11
+FONT_DESCENT 3
+FACE_NAME "Helvetica Bold Oblique"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica-BoldOblique"
+DEFAULT_CHAR 0
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 70
+FULL_NAME "Helvetica Bold Oblique"
+ENDPROPERTIES
+CHARS 192
+STARTCHAR defaultchar
+ENCODING 0
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+AA80
+0000
+8080
+0000
+8080
+0000
+8080
+0000
+AA80
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 5 9 1 0
+BITMAP
+18
+18
+30
+30
+60
+40
+00
+C0
+C0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 474 0
+DWIDTH 6 0
+BBX 7 3 2 6
+BITMAP
+36
+6C
+D8
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 8 1 0
+BITMAP
+14
+14
+7E
+28
+28
+FC
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 1 -1
+BITMAP
+08
+3C
+6E
+70
+38
+1C
+2C
+EC
+78
+40
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 889 0
+DWIDTH 13 0
+BBX 11 9 2 0
+BITMAP
+70C0
+D980
+DB00
+7600
+0600
+0DC0
+1B60
+3360
+61C0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+1C
+36
+36
+1C
+39
+6F
+C6
+CE
+7B
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 238 0
+DWIDTH 4 0
+BBX 4 3 2 6
+BITMAP
+30
+60
+C0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 12 0 -3
+BITMAP
+0C
+18
+30
+30
+60
+60
+C0
+C0
+C0
+60
+60
+30
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 12 0 -3
+BITMAP
+30
+18
+18
+0C
+0C
+0C
+18
+18
+30
+30
+60
+C0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 389 0
+DWIDTH 6 0
+BBX 4 4 3 5
+BITMAP
+50
+60
+F0
+40
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 7 5 1 1
+BITMAP
+18
+18
+FE
+30
+30
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 4 0 -2
+BITMAP
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 1 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 2 0 0
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 7 9 0 0
+BITMAP
+02
+06
+0C
+18
+10
+30
+60
+C0
+80
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+66
+46
+C6
+C4
+CC
+CC
+78
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 2 0
+BITMAP
+18
+F8
+30
+60
+60
+60
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+06
+0C
+18
+30
+60
+C0
+F8
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+06
+06
+3C
+0C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+06
+0E
+16
+26
+4C
+CC
+FE
+18
+18
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+1E
+30
+60
+78
+0C
+0C
+0C
+D8
+70
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+1C
+36
+60
+78
+EC
+CC
+C4
+CC
+78
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+7E
+06
+0C
+0C
+18
+30
+30
+60
+C0
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+66
+2C
+78
+CC
+CC
+DC
+78
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+46
+66
+6E
+3C
+0C
+D8
+70
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 7 1 0
+BITMAP
+30
+30
+00
+00
+00
+C0
+C0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 9 1 -2
+BITMAP
+30
+30
+00
+00
+00
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 2 1
+BITMAP
+1C
+70
+C0
+60
+30
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 3 1 2
+BITMAP
+7C
+00
+F8
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 1 1
+BITMAP
+30
+18
+0C
+38
+E0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 9 3 0
+BITMAP
+78
+CC
+9C
+38
+60
+40
+00
+C0
+C0
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 975 0
+DWIDTH 11 0
+BBX 11 10 1 -1
+BITMAP
+0F80
+3040
+6020
+46A0
+8920
+9120
+9240
+4D80
+6000
+1E00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+FC00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 9 1 0
+BITMAP
+1E
+33
+63
+60
+C0
+C0
+C6
+CC
+78
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3180
+6180
+6300
+6300
+C600
+FC00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 9 1 0
+BITMAP
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 9 1 0
+BITMAP
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+0F00
+3980
+3180
+6000
+6700
+C300
+C600
+CE00
+7A00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+18C0
+18C0
+3180
+3180
+7F00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 5 9 1 0
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 9 9 0 0
+BITMAP
+0180
+0180
+0300
+0300
+0600
+0600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 10 9 1 0
+BITMAP
+18C0
+1980
+3300
+3600
+3C00
+6600
+6600
+C300
+C300
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+FC
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 833 0
+DWIDTH 12 0
+BBX 12 9 1 0
+BITMAP
+1830
+1870
+38E0
+38E0
+6940
+6AC0
+6EC0
+CD80
+C980
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+18C0
+18C0
+3980
+2980
+6980
+6500
+6700
+C600
+C600
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3300
+7E00
+6000
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+0F00
+3980
+3180
+6180
+6300
+C300
+DE00
+CE00
+7B00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 1 0
+BITMAP
+1E
+33
+63
+70
+3C
+0E
+C6
+CC
+78
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 2 0
+BITMAP
+FF
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 9 1 0
+BITMAP
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 8 9 3 0
+BITMAP
+C3
+C3
+C6
+C6
+CC
+CC
+58
+70
+60
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 9 2 0
+BITMAP
+CCC0
+CCC0
+CD80
+DD80
+DD00
+ED00
+EE00
+4400
+4400
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 10 9 1 0
+BITMAP
+30C0
+3180
+1B00
+1E00
+0C00
+1E00
+3600
+6300
+C300
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 667 0
+DWIDTH 7 0
+BBX 7 9 2 0
+BITMAP
+C6
+C6
+6C
+6C
+38
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 9 0 0
+BITMAP
+3F80
+0300
+0600
+0C00
+1800
+3000
+6000
+C000
+FE00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 8 12 -1 -3
+BITMAP
+0F
+0C
+18
+18
+30
+30
+30
+60
+60
+60
+C0
+F0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 3 9 2 0
+BITMAP
+C0
+C0
+C0
+40
+40
+40
+60
+60
+60
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 8 12 -2 -3
+BITMAP
+0F
+03
+06
+06
+0C
+0C
+0C
+18
+18
+18
+30
+F0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 584 0
+DWIDTH 6 0
+BBX 6 6 1 3
+BITMAP
+18
+38
+6C
+6C
+CC
+CC
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 -1 -3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 3 7
+BITMAP
+C0
+60
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 7 0 0
+BITMAP
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+18
+18
+36
+3B
+63
+66
+C6
+CC
+F8
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+1E
+33
+60
+60
+C6
+CC
+78
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 9 0 0
+BITMAP
+0180
+0180
+1B00
+3700
+6300
+6600
+C600
+CC00
+7C00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 7 9 1 0
+BITMAP
+0E
+18
+7C
+30
+30
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 10 -1 -3
+BITMAP
+0E80
+1B80
+3180
+3300
+6300
+6600
+3E00
+0600
+CC00
+7800
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+18
+18
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 9 0 0
+BITMAP
+18
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 7 12 -2 -3
+BITMAP
+06
+00
+0C
+0C
+18
+18
+18
+30
+30
+30
+60
+C0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+18
+18
+33
+36
+7C
+78
+6C
+CC
+C6
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 9 0 0
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 12 7 0 0
+BITMAP
+2EE0
+3330
+3330
+6660
+6660
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 10 -1 -3
+BITMAP
+1B00
+1D80
+3180
+3300
+6300
+6600
+7C00
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+1D
+37
+63
+66
+C6
+CC
+7C
+0C
+18
+18
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 7 0 0
+BITMAP
+36
+3C
+70
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+1E
+33
+38
+1C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 9 1 0
+BITMAP
+18
+18
+7C
+30
+60
+60
+60
+C0
+E0
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 2 0
+BITMAP
+CC
+CC
+D8
+D8
+F0
+60
+40
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 7 1 0
+BITMAP
+CCC0
+CCC0
+DD80
+DD80
+5500
+7700
+6600
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+33
+36
+1C
+18
+38
+6C
+CC
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 -3
+BITMAP
+CC
+CC
+CC
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 7 7 0 0
+BITMAP
+3E
+06
+0C
+38
+60
+C0
+F8
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 12 1 -3
+BITMAP
+0E
+18
+30
+30
+60
+C0
+60
+60
+60
+C0
+C0
+70
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 280 0
+DWIDTH 4 0
+BBX 5 12 0 -3
+BITMAP
+18
+18
+18
+10
+30
+30
+20
+60
+60
+40
+C0
+C0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 12 -1 -3
+BITMAP
+1C
+06
+06
+0C
+0C
+06
+0C
+18
+18
+18
+30
+E0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 2 1 3
+BITMAP
+74
+B8
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 5 10 -1 -3
+BITMAP
+18
+18
+00
+10
+30
+30
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 -1
+BITMAP
+04
+3C
+6E
+D0
+D0
+E6
+EC
+78
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+0E
+19
+10
+7C
+30
+30
+60
+E6
+DC
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 6 0 1
+BITMAP
+33
+1E
+34
+2C
+78
+CC
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+66
+66
+6C
+38
+FC
+30
+F8
+60
+60
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 280 0
+DWIDTH 4 0
+BBX 6 11 0 -2
+BITMAP
+0C
+0C
+18
+18
+00
+00
+60
+60
+40
+C0
+C0
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 12 0 -3
+BITMAP
+0E
+1B
+19
+38
+6C
+66
+66
+36
+1C
+98
+D8
+70
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 1 3 8
+BITMAP
+D8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 10 9 1 0
+BITMAP
+1F00
+2080
+4E40
+5140
+A040
+A280
+9C80
+4100
+3E00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 370 0
+DWIDTH 6 0
+BBX 5 6 2 3
+BITMAP
+38
+08
+78
+50
+00
+F0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 556 0
+DWIDTH 10 0
+BBX 9 5 1 1
+BITMAP
+1980
+7700
+CC00
+6600
+3300
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 6 4 2 1
+BITMAP
+FC
+04
+08
+08
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 1 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 10 9 1 0
+BITMAP
+1F00
+2080
+4E40
+4A40
+9C40
+9480
+9280
+4100
+3E00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 3 8
+BITMAP
+F0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 2 4
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 8 7 0 0
+BITMAP
+0C
+0C
+7F
+18
+18
+00
+FE
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 1 4
+BITMAP
+60
+B0
+20
+40
+F0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 1 4
+BITMAP
+70
+30
+60
+30
+E0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 3 7
+BITMAP
+60
+C0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 10 10 -2 -3
+BITMAP
+0CC0
+0CC0
+18C0
+1980
+3180
+3300
+6D00
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 12 2 -3
+BITMAP
+3E
+74
+F4
+F4
+E8
+E8
+68
+50
+50
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 2 2 3
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 4 0 -3
+BITMAP
+60
+30
+90
+E0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 5 1 4
+BITMAP
+20
+E0
+20
+40
+40
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 365 0
+DWIDTH 6 0
+BBX 5 6 2 3
+BITMAP
+38
+68
+58
+70
+00
+F0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 556 0
+DWIDTH 10 0
+BBX 9 5 1 1
+BITMAP
+6600
+3300
+1980
+7700
+CC00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 9 9 2 0
+BITMAP
+2000
+E300
+2600
+4C00
+5900
+1300
+3500
+6F80
+C200
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+2000
+E300
+2600
+4C00
+5B00
+1580
+3100
+6200
+C780
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+7000
+3180
+6300
+3600
+EC80
+0980
+1A80
+37C0
+6100
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 -2
+BITMAP
+0C
+0C
+00
+08
+18
+70
+E4
+CC
+78
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+0C
+06
+00
+06
+06
+0F
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+03
+06
+00
+06
+06
+0F
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 0 0
+BITMAP
+0700
+0D80
+0000
+0600
+0600
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 0 0
+BITMAP
+0680
+0B00
+0000
+0600
+0600
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 11 0 0
+BITMAP
+0D80
+0000
+0600
+0600
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 0 0
+BITMAP
+0300
+0480
+0300
+0300
+0700
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 14 9 0 0
+BITMAP
+07FC
+0DC0
+0980
+1980
+33F0
+3F00
+6300
+C600
+C7E0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 1 -3
+BITMAP
+1E
+33
+63
+60
+C0
+C0
+C6
+CC
+78
+30
+90
+E0
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0C00
+0600
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0300
+0600
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0700
+0D80
+0000
+1F80
+1000
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 11 1 0
+BITMAP
+0D80
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 5 12 1 0
+BITMAP
+30
+18
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 7 12 1 0
+BITMAP
+06
+0C
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 7 12 1 0
+BITMAP
+1C
+36
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 7 11 1 0
+BITMAP
+36
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3180
+F980
+6300
+6300
+C600
+FC00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 12 1 0
+BITMAP
+0340
+0580
+0000
+18C0
+18C0
+38C0
+3980
+6980
+6500
+6700
+C600
+C600
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0600
+0300
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0180
+0300
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0700
+0D80
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0680
+0B00
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 11 1 0
+BITMAP
+0D80
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 7 5 1 1
+BITMAP
+66
+3C
+38
+78
+CC
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 11 9 0 0
+BITMAP
+07A0
+1CC0
+19C0
+32C0
+3580
+6980
+7300
+6700
+BC00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0C00
+0600
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0300
+0600
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0700
+0D80
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 11 1 0
+BITMAP
+1B00
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 667 0
+DWIDTH 7 0
+BBX 7 12 2 0
+BITMAP
+0C
+18
+00
+C6
+C6
+C6
+6C
+6C
+38
+30
+60
+60
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 1 0
+BITMAP
+18
+18
+3E
+33
+23
+66
+7C
+C0
+C0
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+0E
+1B
+33
+36
+6C
+66
+66
+CC
+D8
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+30
+18
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+06
+0C
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+1C
+36
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+1A
+2C
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 9 0 0
+BITMAP
+36
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+0C
+12
+0C
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 889 0
+DWIDTH 10 0
+BBX 11 7 0 0
+BITMAP
+3BC0
+6660
+0460
+7FC0
+CC00
+9980
+EF00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+1E
+33
+60
+60
+C6
+CC
+78
+30
+90
+E0
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+18
+0C
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+06
+0C
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0E
+1B
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+1B
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 10 0 0
+BITMAP
+60
+30
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 10 0 0
+BITMAP
+18
+30
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 6 10 0 0
+BITMAP
+38
+6C
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 6 9 0 0
+BITMAP
+6C
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+32
+1C
+26
+1F
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0D
+16
+00
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+18
+0C
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+06
+0C
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0E
+1B
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0D
+16
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+1B
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 7 5 1 1
+BITMAP
+18
+00
+FE
+00
+30
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 8 -1 0
+BITMAP
+0080
+0F00
+1B80
+3580
+3B00
+7300
+6600
+BC00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+18
+0C
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+06
+0C
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0E
+1B
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+1B
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 1 -3
+BITMAP
+18
+30
+00
+CC
+CC
+D8
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 12 -1 -3
+BITMAP
+0C00
+0C00
+1B00
+1D80
+1180
+3300
+3300
+6600
+7C00
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 1 -3
+BITMAP
+6C
+00
+CC
+CC
+D8
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/helvBO12.bdf b/gui/themes/fonts/helvBO12.bdf
new file mode 100644
index 0000000000..728796dc26
--- /dev/null
+++ b/gui/themes/fonts/helvBO12.bdf
@@ -0,0 +1,12195 @@
+STARTFONT 2.1
+FONT -Adobe-Helvetica-Bold-O-Normal--12-120-75-75-P-69-ISO10646-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 17 20 -2 -5
+COMMENT $Xorg: $
+COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20
+COMMENT
+COMMENT +
+COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated.
+COMMENT Copyright 1988, 1994 Digital Equipment Corporation.
+COMMENT
+COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be
+COMMENT registered in certain jurisdictions.
+COMMENT Permission to use these trademarks is hereby granted only in
+COMMENT association with the images described in this file.
+COMMENT
+COMMENT Permission to use, copy, modify, distribute and sell this software
+COMMENT and its documentation for any purpose and without fee is hereby
+COMMENT granted, provided that the above copyright notices appear in all
+COMMENT copies and that both those copyright notices and this permission
+COMMENT notice appear in supporting documentation, and that the names of
+COMMENT Adobe Systems and Digital Equipment Corporation not be used in
+COMMENT advertising or publicity pertaining to distribution of the software
+COMMENT without specific, written prior permission. Adobe Systems and
+COMMENT Digital Equipment Corporation make no representations about the
+COMMENT suitability of this software for any purpose. It is provided "as
+COMMENT is" without express or implied warranty.
+COMMENT -
+STARTPROPERTIES 26
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Bold"
+SLANT "O"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 69
+CHARSET_REGISTRY "ISO10646"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 7
+FONT_ASCENT 11
+FONT_DESCENT 3
+FACE_NAME "Helvetica Bold Oblique"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica-BoldOblique"
+DEFAULT_CHAR 0
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 70
+FULL_NAME "Helvetica Bold Oblique"
+ENDPROPERTIES
+CHARS 723
+STARTCHAR char0
+ENCODING 0
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+AA80
+0000
+8080
+0000
+8080
+0000
+8080
+0000
+AA80
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 5 9 1 0
+BITMAP
+18
+18
+30
+30
+60
+40
+00
+C0
+C0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 474 0
+DWIDTH 6 0
+BBX 7 3 2 6
+BITMAP
+36
+6C
+D8
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 8 1 0
+BITMAP
+14
+14
+7E
+28
+28
+FC
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 1 -1
+BITMAP
+08
+3C
+6E
+70
+38
+1C
+2C
+EC
+78
+40
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 889 0
+DWIDTH 13 0
+BBX 11 9 2 0
+BITMAP
+70C0
+D980
+DB00
+7600
+0600
+0DC0
+1B60
+3360
+61C0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+1C
+36
+36
+1C
+39
+6F
+C6
+CE
+7B
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 238 0
+DWIDTH 4 0
+BBX 4 3 2 6
+BITMAP
+30
+60
+C0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 12 0 -3
+BITMAP
+0C
+18
+30
+30
+60
+60
+C0
+C0
+C0
+60
+60
+30
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 12 0 -3
+BITMAP
+30
+18
+18
+0C
+0C
+0C
+18
+18
+30
+30
+60
+C0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 389 0
+DWIDTH 6 0
+BBX 4 4 3 5
+BITMAP
+50
+60
+F0
+40
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 7 5 1 1
+BITMAP
+18
+18
+FE
+30
+30
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 4 0 -2
+BITMAP
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 1 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 2 0 0
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 7 9 0 0
+BITMAP
+02
+06
+0C
+18
+10
+30
+60
+C0
+80
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+66
+46
+C6
+C4
+CC
+CC
+78
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 2 0
+BITMAP
+18
+F8
+30
+60
+60
+60
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+06
+0C
+18
+30
+60
+C0
+F8
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+06
+06
+3C
+0C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+06
+0E
+16
+26
+4C
+CC
+FE
+18
+18
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+1E
+30
+60
+78
+0C
+0C
+0C
+D8
+70
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+1C
+36
+60
+78
+EC
+CC
+C4
+CC
+78
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+7E
+06
+0C
+0C
+18
+30
+30
+60
+C0
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+66
+2C
+78
+CC
+CC
+DC
+78
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+46
+66
+6E
+3C
+0C
+D8
+70
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 7 1 0
+BITMAP
+30
+30
+00
+00
+00
+C0
+C0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 9 1 -2
+BITMAP
+30
+30
+00
+00
+00
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 2 1
+BITMAP
+1C
+70
+C0
+60
+30
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 3 1 2
+BITMAP
+7C
+00
+F8
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 1 1
+BITMAP
+30
+18
+0C
+38
+E0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 9 3 0
+BITMAP
+78
+CC
+9C
+38
+60
+40
+00
+C0
+C0
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 975 0
+DWIDTH 11 0
+BBX 11 10 1 -1
+BITMAP
+0F80
+3040
+6020
+46A0
+8920
+9120
+9240
+4D80
+6000
+1E00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+FC00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 9 1 0
+BITMAP
+1E
+33
+63
+60
+C0
+C0
+C6
+CC
+78
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3180
+6180
+6300
+6300
+C600
+FC00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 9 1 0
+BITMAP
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 9 1 0
+BITMAP
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+0F00
+3980
+3180
+6000
+6700
+C300
+C600
+CE00
+7A00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+18C0
+18C0
+3180
+3180
+7F00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 5 9 1 0
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 9 9 0 0
+BITMAP
+0180
+0180
+0300
+0300
+0600
+0600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 10 9 1 0
+BITMAP
+18C0
+1980
+3300
+3600
+3C00
+6600
+6600
+C300
+C300
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+FC
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 833 0
+DWIDTH 12 0
+BBX 12 9 1 0
+BITMAP
+1830
+1870
+38E0
+38E0
+6940
+6AC0
+6EC0
+CD80
+C980
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+18C0
+18C0
+3980
+2980
+6980
+6500
+6700
+C600
+C600
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3300
+7E00
+6000
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+0F00
+3980
+3180
+6180
+6300
+C300
+DE00
+CE00
+7B00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 1 0
+BITMAP
+1E
+33
+63
+70
+3C
+0E
+C6
+CC
+78
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 2 0
+BITMAP
+FF
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 9 1 0
+BITMAP
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 8 9 3 0
+BITMAP
+C3
+C3
+C6
+C6
+CC
+CC
+58
+70
+60
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 9 2 0
+BITMAP
+CCC0
+CCC0
+CD80
+DD80
+DD00
+ED00
+EE00
+4400
+4400
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 10 9 1 0
+BITMAP
+30C0
+3180
+1B00
+1E00
+0C00
+1E00
+3600
+6300
+C300
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 667 0
+DWIDTH 7 0
+BBX 7 9 2 0
+BITMAP
+C6
+C6
+6C
+6C
+38
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 9 0 0
+BITMAP
+3F80
+0300
+0600
+0C00
+1800
+3000
+6000
+C000
+FE00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 8 12 -1 -3
+BITMAP
+0F
+0C
+18
+18
+30
+30
+30
+60
+60
+60
+C0
+F0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 3 9 2 0
+BITMAP
+C0
+C0
+C0
+40
+40
+40
+60
+60
+60
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 8 12 -2 -3
+BITMAP
+0F
+03
+06
+06
+0C
+0C
+0C
+18
+18
+18
+30
+F0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 584 0
+DWIDTH 6 0
+BBX 6 6 1 3
+BITMAP
+18
+38
+6C
+6C
+CC
+CC
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 -1 -3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 3 7
+BITMAP
+C0
+60
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 7 0 0
+BITMAP
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+18
+18
+36
+3B
+63
+66
+C6
+CC
+F8
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+1E
+33
+60
+60
+C6
+CC
+78
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 9 0 0
+BITMAP
+0180
+0180
+1B00
+3700
+6300
+6600
+C600
+CC00
+7C00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 7 9 1 0
+BITMAP
+0E
+18
+7C
+30
+30
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 10 -1 -3
+BITMAP
+0E80
+1B80
+3180
+3300
+6300
+6600
+3E00
+0600
+CC00
+7800
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+18
+18
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 9 0 0
+BITMAP
+18
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 7 12 -2 -3
+BITMAP
+06
+00
+0C
+0C
+18
+18
+18
+30
+30
+30
+60
+C0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+18
+18
+33
+36
+7C
+78
+6C
+CC
+C6
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 9 0 0
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 12 7 0 0
+BITMAP
+2EE0
+3330
+3330
+6660
+6660
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 10 -1 -3
+BITMAP
+1B00
+1D80
+3180
+3300
+6300
+6600
+7C00
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+1D
+37
+63
+66
+C6
+CC
+7C
+0C
+18
+18
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 7 0 0
+BITMAP
+36
+3C
+70
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+1E
+33
+38
+1C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 9 1 0
+BITMAP
+18
+18
+7C
+30
+60
+60
+60
+C0
+E0
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 2 0
+BITMAP
+CC
+CC
+D8
+D8
+F0
+60
+40
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 7 1 0
+BITMAP
+CCC0
+CCC0
+DD80
+DD80
+5500
+7700
+6600
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+33
+36
+1C
+18
+38
+6C
+CC
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 -3
+BITMAP
+CC
+CC
+CC
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 7 7 0 0
+BITMAP
+3E
+06
+0C
+38
+60
+C0
+F8
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 12 1 -3
+BITMAP
+0E
+18
+30
+30
+60
+C0
+60
+60
+60
+C0
+C0
+70
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 280 0
+DWIDTH 4 0
+BBX 5 12 0 -3
+BITMAP
+18
+18
+18
+10
+30
+30
+20
+60
+60
+40
+C0
+C0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 12 -1 -3
+BITMAP
+1C
+06
+06
+0C
+0C
+06
+0C
+18
+18
+18
+30
+E0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 2 1 3
+BITMAP
+74
+B8
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 5 10 -1 -3
+BITMAP
+18
+18
+00
+10
+30
+30
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 -1
+BITMAP
+04
+3C
+6E
+D0
+D0
+E6
+EC
+78
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+0E
+19
+10
+7C
+30
+30
+60
+E6
+DC
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 6 0 1
+BITMAP
+33
+1E
+34
+2C
+78
+CC
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+66
+66
+6C
+38
+FC
+30
+F8
+60
+60
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 280 0
+DWIDTH 4 0
+BBX 6 11 0 -2
+BITMAP
+0C
+0C
+18
+18
+00
+00
+60
+60
+40
+C0
+C0
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 12 0 -3
+BITMAP
+0E
+1B
+19
+38
+6C
+66
+66
+36
+1C
+98
+D8
+70
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 1 3 8
+BITMAP
+D8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 10 9 1 0
+BITMAP
+1F00
+2080
+4E40
+5140
+A040
+A280
+9C80
+4100
+3E00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 370 0
+DWIDTH 6 0
+BBX 5 6 2 3
+BITMAP
+38
+08
+78
+50
+00
+F0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 556 0
+DWIDTH 10 0
+BBX 9 5 1 1
+BITMAP
+1980
+7700
+CC00
+6600
+3300
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 6 4 2 1
+BITMAP
+FC
+04
+08
+08
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 1 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 10 9 1 0
+BITMAP
+1F00
+2080
+4E40
+4A40
+9C40
+9480
+9280
+4100
+3E00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 3 8
+BITMAP
+F0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 2 4
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 8 7 0 0
+BITMAP
+0C
+0C
+7F
+18
+18
+00
+FE
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 1 4
+BITMAP
+60
+B0
+20
+40
+F0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 1 4
+BITMAP
+70
+30
+60
+30
+E0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 3 7
+BITMAP
+60
+C0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 10 10 -2 -3
+BITMAP
+0CC0
+0CC0
+18C0
+1980
+3180
+3300
+6D00
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 12 2 -3
+BITMAP
+3E
+74
+F4
+F4
+E8
+E8
+68
+50
+50
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 2 2 3
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 4 0 -3
+BITMAP
+60
+30
+90
+E0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 5 1 4
+BITMAP
+20
+E0
+20
+40
+40
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 365 0
+DWIDTH 6 0
+BBX 5 6 2 3
+BITMAP
+38
+68
+58
+70
+00
+F0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 556 0
+DWIDTH 10 0
+BBX 9 5 1 1
+BITMAP
+6600
+3300
+1980
+7700
+CC00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 9 9 2 0
+BITMAP
+2000
+E300
+2600
+4C00
+5900
+1300
+3500
+6F80
+C200
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+2000
+E300
+2600
+4C00
+5B00
+1580
+3100
+6200
+C780
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+7000
+3180
+6300
+3600
+EC80
+0980
+1A80
+37C0
+6100
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 0 -2
+BITMAP
+0C
+0C
+00
+08
+18
+70
+E4
+CC
+78
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+0C
+06
+00
+06
+06
+0F
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+03
+06
+00
+06
+06
+0F
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 0 0
+BITMAP
+0700
+0D80
+0000
+0600
+0600
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 0 0
+BITMAP
+0680
+0B00
+0000
+0600
+0600
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 11 0 0
+BITMAP
+0D80
+0000
+0600
+0600
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 0 0
+BITMAP
+0300
+0480
+0300
+0300
+0700
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 14 9 0 0
+BITMAP
+07FC
+0DC0
+0980
+1980
+33F0
+3F00
+6300
+C600
+C7E0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 1 -3
+BITMAP
+1E
+33
+63
+60
+C0
+C0
+C6
+CC
+78
+30
+90
+E0
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0C00
+0600
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0300
+0600
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0700
+0D80
+0000
+1F80
+1000
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 11 1 0
+BITMAP
+0D80
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 5 12 1 0
+BITMAP
+30
+18
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 7 12 1 0
+BITMAP
+06
+0C
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 7 12 1 0
+BITMAP
+1C
+36
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 7 11 1 0
+BITMAP
+36
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3180
+F980
+6300
+6300
+C600
+FC00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 12 1 0
+BITMAP
+0340
+0580
+0000
+18C0
+18C0
+38C0
+3980
+6980
+6500
+6700
+C600
+C600
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0600
+0300
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0180
+0300
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0700
+0D80
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0680
+0B00
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 11 1 0
+BITMAP
+0D80
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 7 5 1 1
+BITMAP
+66
+3C
+38
+78
+CC
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 11 9 0 0
+BITMAP
+07A0
+1CC0
+19C0
+32C0
+3580
+6980
+7300
+6700
+BC00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0C00
+0600
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0300
+0600
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0700
+0D80
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 11 1 0
+BITMAP
+1B00
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 667 0
+DWIDTH 7 0
+BBX 7 12 2 0
+BITMAP
+0C
+18
+00
+C6
+C6
+C6
+6C
+6C
+38
+30
+60
+60
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 9 1 0
+BITMAP
+18
+18
+3E
+33
+23
+66
+7C
+C0
+C0
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+0E
+1B
+33
+36
+6C
+66
+66
+CC
+D8
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+30
+18
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+06
+0C
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+1C
+36
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+1A
+2C
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 9 0 0
+BITMAP
+36
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+0C
+12
+0C
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 889 0
+DWIDTH 10 0
+BBX 11 7 0 0
+BITMAP
+3BC0
+6660
+0460
+7FC0
+CC00
+9980
+EF00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+1E
+33
+60
+60
+C6
+CC
+78
+30
+90
+E0
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+18
+0C
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+06
+0C
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0E
+1B
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+1B
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 10 0 0
+BITMAP
+60
+30
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 10 0 0
+BITMAP
+18
+30
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 6 10 0 0
+BITMAP
+38
+6C
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 6 9 0 0
+BITMAP
+6C
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+32
+1C
+26
+1F
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0D
+16
+00
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+18
+0C
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+06
+0C
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0E
+1B
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0D
+16
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+1B
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 7 5 1 1
+BITMAP
+18
+00
+FE
+00
+30
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 8 -1 0
+BITMAP
+0080
+0F00
+1B80
+3580
+3B00
+7300
+6600
+BC00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+18
+0C
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+06
+0C
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0E
+1B
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+1B
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 1 -3
+BITMAP
+18
+30
+00
+CC
+CC
+D8
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 12 -1 -3
+BITMAP
+0C00
+0C00
+1B00
+1D80
+1180
+3300
+3300
+6600
+7C00
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 1 -3
+BITMAP
+6C
+00
+CC
+CC
+D8
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+STARTCHAR Amacron
+ENCODING 256
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+1E
+00
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR amacron
+ENCODING 257
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 9 0 0
+BITMAP
+3C
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR Abreve
+ENCODING 258
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+1B
+0E
+00
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR abreve
+ENCODING 259
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+6C
+38
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR Aogonek
+ENCODING 260
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 0 -3
+BITMAP
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+CF
+18
+10
+1C
+ENDCHAR
+STARTCHAR aogonek
+ENCODING 261
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 10 0 -3
+BITMAP
+3C
+66
+06
+7C
+CC
+98
+FC
+30
+20
+38
+ENDCHAR
+STARTCHAR Cacute
+ENCODING 262
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 1 0
+BITMAP
+0C
+18
+00
+1E
+33
+63
+60
+C0
+C0
+C6
+CC
+78
+ENDCHAR
+STARTCHAR cacute
+ENCODING 263
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+06
+0C
+00
+1E
+33
+60
+60
+C6
+CC
+78
+ENDCHAR
+STARTCHAR Ccircumflex
+ENCODING 264
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 13 1 0
+BITMAP
+08
+1C
+36
+00
+1E
+33
+63
+60
+C0
+C0
+C6
+CC
+78
+ENDCHAR
+STARTCHAR ccircumflex
+ENCODING 265
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+08
+1C
+36
+00
+1E
+33
+60
+60
+C6
+CC
+78
+ENDCHAR
+STARTCHAR Cdotaccent
+ENCODING 266
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 11 1 0
+BITMAP
+0C
+00
+1E
+33
+63
+60
+C0
+C0
+C6
+CC
+78
+ENDCHAR
+STARTCHAR cdotaccent
+ENCODING 267
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+0C
+00
+1E
+33
+60
+60
+C6
+CC
+78
+ENDCHAR
+STARTCHAR Ccaron
+ENCODING 268
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 13 1 0
+BITMAP
+36
+1C
+08
+00
+1E
+33
+63
+60
+C0
+C0
+C6
+CC
+78
+ENDCHAR
+STARTCHAR ccaron
+ENCODING 269
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+36
+1C
+08
+00
+1E
+33
+60
+60
+C6
+CC
+78
+ENDCHAR
+STARTCHAR Dcaron
+ENCODING 270
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 13 1 0
+BITMAP
+1B00
+0E00
+0400
+0000
+1F00
+1980
+3180
+3180
+6180
+6300
+6300
+C600
+FC00
+ENDCHAR
+STARTCHAR dcaron
+ENCODING 271
+SWIDTH 858 0
+DWIDTH 11 0
+BBX 13 9 0 0
+BITMAP
+0198
+0198
+1B30
+3700
+6300
+6600
+C600
+CC00
+7C00
+ENDCHAR
+STARTCHAR Dcroat
+ENCODING 272
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3180
+F980
+6300
+6300
+C600
+FC00
+ENDCHAR
+STARTCHAR dcroat
+ENCODING 273
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 9 0 0
+BITMAP
+0180
+0F80
+1B00
+3700
+6300
+6600
+C600
+CC00
+7C00
+ENDCHAR
+STARTCHAR Emacron
+ENCODING 274
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 11 1 0
+BITMAP
+1E00
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR emacron
+ENCODING 275
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+1E
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Ebreve
+ENCODING 276
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+3600
+1C00
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR ebreve
+ENCODING 277
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+36
+1C
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Edotaccent
+ENCODING 278
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 11 1 0
+BITMAP
+0C00
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR edotaccent
+ENCODING 279
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+0C
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Eogonek
+ENCODING 280
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 -3
+BITMAP
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+3000
+2000
+3800
+ENDCHAR
+STARTCHAR eogonek
+ENCODING 281
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+1E
+33
+63
+7E
+C0
+CC
+78
+30
+20
+38
+ENDCHAR
+STARTCHAR Ecaron
+ENCODING 282
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 13 1 0
+BITMAP
+3600
+1C00
+0800
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR ecaron
+ENCODING 283
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+36
+1C
+08
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR Gcircumflex
+ENCODING 284
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 13 1 0
+BITMAP
+0400
+0E00
+1B00
+0000
+0F00
+3980
+3180
+6000
+6700
+C300
+C600
+CE00
+7A00
+ENDCHAR
+STARTCHAR gcircumflex
+ENCODING 285
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 14 -1 -3
+BITMAP
+0400
+0E00
+1B00
+0000
+0E80
+1B80
+3180
+3300
+6300
+6600
+3E00
+0600
+CC00
+7800
+ENDCHAR
+STARTCHAR Gbreve
+ENCODING 286
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+1B00
+0E00
+0000
+0F00
+3980
+3180
+6000
+6700
+C300
+C600
+CE00
+7A00
+ENDCHAR
+STARTCHAR gbreve
+ENCODING 287
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 13 -1 -3
+BITMAP
+1B00
+0E00
+0000
+0E80
+1B80
+3180
+3300
+6300
+6600
+3E00
+0600
+CC00
+7800
+ENDCHAR
+STARTCHAR Gdotaccent
+ENCODING 288
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 11 1 0
+BITMAP
+0C00
+0000
+0F00
+3980
+3180
+6000
+6700
+C300
+C600
+CE00
+7A00
+ENDCHAR
+STARTCHAR gdotaccent
+ENCODING 289
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 12 -1 -3
+BITMAP
+0C00
+0000
+0E80
+1B80
+3180
+3300
+6300
+6600
+3E00
+0600
+CC00
+7800
+ENDCHAR
+STARTCHAR Gcommaaccent
+ENCODING 290
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 14 1 -5
+BITMAP
+0F00
+3980
+3180
+6000
+6700
+C300
+C600
+CE00
+7A00
+0000
+1800
+1800
+0800
+1000
+ENDCHAR
+STARTCHAR gcommaaccent
+ENCODING 291
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 14 -1 -3
+BITMAP
+0600
+0C00
+0C00
+0000
+0E80
+1B80
+3180
+3300
+6300
+6600
+3E00
+0600
+CC00
+7800
+ENDCHAR
+STARTCHAR Hcircumflex
+ENCODING 292
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 13 1 0
+BITMAP
+0400
+0E00
+1B00
+0000
+18C0
+18C0
+3180
+3180
+7F00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR hcircumflex
+ENCODING 293
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+08
+1C
+36
+00
+18
+18
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR Hbar
+ENCODING 294
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+18C0
+FFC0
+3180
+3180
+7F00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR hbar
+ENCODING 295
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+18
+F8
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR Itilde
+ENCODING 296
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 6 12 1 0
+BITMAP
+34
+58
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR itilde
+ENCODING 297
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 10 0 0
+BITMAP
+68
+B0
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Imacron
+ENCODING 298
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 5 11 1 0
+BITMAP
+78
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR imacron
+ENCODING 299
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 9 0 0
+BITMAP
+78
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Ibreve
+ENCODING 300
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 6 12 1 0
+BITMAP
+6C
+38
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR ibreve
+ENCODING 301
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 10 0 0
+BITMAP
+D8
+70
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Iogonek
+ENCODING 302
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 5 12 1 -3
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+E0
+C0
+80
+E0
+ENDCHAR
+STARTCHAR iogonek
+ENCODING 303
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 12 0 -3
+BITMAP
+18
+00
+30
+30
+60
+60
+60
+C0
+E0
+C0
+80
+E0
+ENDCHAR
+STARTCHAR Idotaccent
+ENCODING 304
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 5 11 1 0
+BITMAP
+30
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR dotlessi
+ENCODING 305
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 7 0 0
+BITMAP
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR IJ
+ENCODING 306
+SWIDTH 820 0
+DWIDTH 12 0
+BBX 13 9 1 0
+BITMAP
+1818
+1818
+3030
+3030
+6060
+6060
+6C60
+CCC0
+C780
+ENDCHAR
+STARTCHAR ij
+ENCODING 307
+SWIDTH 542 0
+DWIDTH 6 0
+BBX 8 12 0 -3
+BITMAP
+1B
+00
+36
+36
+6C
+6C
+6C
+D8
+D8
+18
+30
+60
+ENDCHAR
+STARTCHAR Jcircumflex
+ENCODING 308
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 9 13 0 0
+BITMAP
+0200
+0700
+0D80
+0000
+0180
+0180
+0300
+0300
+0600
+0600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR jcircumflex
+ENCODING 309
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 7 14 -2 -3
+BITMAP
+08
+1C
+36
+00
+0C
+0C
+18
+18
+18
+30
+30
+30
+60
+C0
+ENDCHAR
+STARTCHAR Kcommaaccent
+ENCODING 310
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 10 14 1 -5
+BITMAP
+18C0
+1980
+3300
+3600
+3C00
+6600
+6600
+C300
+C300
+0000
+1800
+1800
+0800
+1000
+ENDCHAR
+STARTCHAR kcommaaccent
+ENCODING 311
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 14 0 -5
+BITMAP
+18
+18
+33
+36
+7C
+78
+6C
+CC
+C6
+00
+18
+18
+08
+10
+ENDCHAR
+STARTCHAR kgreenlandic
+ENCODING 312
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+33
+36
+7C
+78
+6C
+CC
+C6
+ENDCHAR
+STARTCHAR Lacute
+ENCODING 313
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 12 1 0
+BITMAP
+18
+30
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+FC
+ENDCHAR
+STARTCHAR lacute
+ENCODING 314
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 12 0 0
+BITMAP
+18
+30
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Lcommaaccent
+ENCODING 315
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 14 1 -5
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+FC
+00
+30
+30
+10
+20
+ENDCHAR
+STARTCHAR lcommaaccent
+ENCODING 316
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 14 0 -5
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+00
+60
+60
+20
+40
+ENDCHAR
+STARTCHAR Lcaron
+ENCODING 317
+SWIDTH 858 0
+DWIDTH 11 0
+BBX 12 9 1 0
+BITMAP
+1830
+1830
+3060
+3000
+6000
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR lcaron
+ENCODING 318
+SWIDTH 542 0
+DWIDTH 7 0
+BBX 9 9 0 0
+BITMAP
+1980
+1980
+3300
+3000
+6000
+6000
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR Ldot
+ENCODING 319
+SWIDTH 858 0
+DWIDTH 11 0
+BBX 10 9 1 0
+BITMAP
+1800
+1800
+3000
+3000
+60C0
+60C0
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR ldot
+ENCODING 320
+SWIDTH 542 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+18
+18
+30
+30
+66
+66
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Lslash
+ENCODING 321
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+18
+18
+30
+38
+E0
+60
+60
+C0
+FC
+ENDCHAR
+STARTCHAR lslash
+ENCODING 322
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 9 0 0
+BITMAP
+18
+18
+30
+38
+E0
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Nacute
+ENCODING 323
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 12 1 0
+BITMAP
+0300
+0600
+0000
+18C0
+18C0
+3980
+2980
+6980
+6500
+6700
+C600
+C600
+ENDCHAR
+STARTCHAR nacute
+ENCODING 324
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+0C
+18
+00
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR Ncommaaccent
+ENCODING 325
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 14 1 -5
+BITMAP
+18C0
+18C0
+3980
+2980
+6980
+6500
+6700
+C600
+C600
+0000
+1800
+1800
+0800
+1000
+ENDCHAR
+STARTCHAR ncommaaccent
+ENCODING 326
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 12 0 -5
+BITMAP
+36
+3B
+63
+66
+66
+CC
+CC
+00
+30
+30
+10
+20
+ENDCHAR
+STARTCHAR Ncaron
+ENCODING 327
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 13 1 0
+BITMAP
+1B00
+0E00
+0400
+0000
+18C0
+18C0
+3980
+2980
+6980
+6500
+6700
+C600
+C600
+ENDCHAR
+STARTCHAR ncaron
+ENCODING 328
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+36
+1C
+08
+00
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR napostrophe
+ENCODING 329
+SWIDTH 875 0
+DWIDTH 11 0
+BBX 9 9 3 0
+BITMAP
+6000
+6000
+DB00
+1D80
+3180
+3300
+3300
+6600
+6600
+ENDCHAR
+STARTCHAR Eng
+ENCODING 330
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 12 1 -3
+BITMAP
+18C0
+18C0
+3980
+2980
+6980
+6500
+6700
+C600
+C600
+0600
+0C00
+1800
+ENDCHAR
+STARTCHAR eng
+ENCODING 331
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+36
+3B
+63
+66
+66
+CC
+CC
+0C
+18
+30
+ENDCHAR
+STARTCHAR Omacron
+ENCODING 332
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 11 1 0
+BITMAP
+1E00
+0000
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR omacron
+ENCODING 333
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+1E
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR Obreve
+ENCODING 334
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+1B00
+0E00
+0000
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR obreve
+ENCODING 335
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+36
+1C
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR Ohungarumlaut
+ENCODING 336
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0D80
+1B00
+0000
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR ohungarumlaut
+ENCODING 337
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+1B
+36
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR OE
+ENCODING 338
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 13 9 1 0
+BITMAP
+0FF8
+3980
+3300
+6300
+67E0
+C600
+C600
+CC00
+7FC0
+ENDCHAR
+STARTCHAR oe
+ENCODING 339
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 12 7 0 0
+BITMAP
+1DE0
+3330
+6230
+67E0
+C600
+CCC0
+7F80
+ENDCHAR
+STARTCHAR Racute
+ENCODING 340
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0600
+0C00
+0000
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR racute
+ENCODING 341
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 10 0 0
+BITMAP
+0C
+18
+00
+36
+3C
+70
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Rcommaaccent
+ENCODING 342
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 14 1 -5
+BITMAP
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+C600
+0000
+1800
+1800
+0800
+1000
+ENDCHAR
+STARTCHAR rcommaaccent
+ENCODING 343
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 12 0 -5
+BITMAP
+36
+3C
+70
+60
+60
+C0
+C0
+00
+60
+60
+20
+40
+ENDCHAR
+STARTCHAR Rcaron
+ENCODING 344
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 13 1 0
+BITMAP
+1B00
+0E00
+0400
+0000
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR rcaron
+ENCODING 345
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 11 0 0
+BITMAP
+36
+1C
+08
+00
+36
+3C
+70
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Sacute
+ENCODING 346
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 12 1 0
+BITMAP
+0C
+18
+00
+1E
+33
+63
+70
+3C
+0E
+C6
+CC
+78
+ENDCHAR
+STARTCHAR sacute
+ENCODING 347
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+06
+0C
+00
+1E
+33
+38
+1C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR Scircumflex
+ENCODING 348
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 13 1 0
+BITMAP
+08
+1C
+36
+00
+1E
+33
+63
+70
+3C
+0E
+C6
+CC
+78
+ENDCHAR
+STARTCHAR scircumflex
+ENCODING 349
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+08
+1C
+36
+00
+1E
+33
+38
+1C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR Scedilla
+ENCODING 350
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 12 1 -3
+BITMAP
+1E
+33
+63
+70
+3C
+0E
+C6
+CC
+78
+18
+48
+70
+ENDCHAR
+STARTCHAR scedilla
+ENCODING 351
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+1E
+33
+38
+1C
+0C
+CC
+78
+18
+48
+70
+ENDCHAR
+STARTCHAR Scaron
+ENCODING 352
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 10 1 0
+BITMAP
+1B
+0E
+04
+1E
+33
+31
+1C
+86
+C6
+7C
+ENDCHAR
+STARTCHAR scaron
+ENCODING 353
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+1B
+0E
+04
+1E
+33
+38
+1C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 354
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 12 2 -3
+BITMAP
+FF
+18
+30
+30
+60
+60
+60
+C0
+E0
+30
+90
+E0
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 355
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 12 1 -3
+BITMAP
+18
+18
+7C
+30
+60
+60
+60
+C0
+E0
+30
+90
+E0
+ENDCHAR
+STARTCHAR Tcaron
+ENCODING 356
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 13 2 0
+BITMAP
+6C
+38
+10
+00
+FF
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR tcaron
+ENCODING 357
+SWIDTH 594 0
+DWIDTH 9 0
+BBX 10 9 1 0
+BITMAP
+18C0
+18C0
+7D80
+3000
+6000
+6000
+6000
+C000
+E000
+ENDCHAR
+STARTCHAR Tbar
+ENCODING 358
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 2 0
+BITMAP
+FF
+18
+30
+30
+7E
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR tbar
+ENCODING 359
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 9 1 0
+BITMAP
+18
+18
+7C
+30
+60
+7C
+60
+C0
+E0
+ENDCHAR
+STARTCHAR Utilde
+ENCODING 360
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0D00
+1600
+0000
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR utilde
+ENCODING 361
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+1A
+2C
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR Umacron
+ENCODING 362
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 11 1 0
+BITMAP
+1E00
+0000
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR umacron
+ENCODING 363
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+1E
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR Ubreve
+ENCODING 364
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+3600
+1C00
+0000
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR ubreve
+ENCODING 365
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+36
+1C
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR Uring
+ENCODING 366
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 13 1 0
+BITMAP
+1C00
+3600
+1C00
+0000
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uring
+ENCODING 367
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+1C
+36
+1C
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR Uhungarumlaut
+ENCODING 368
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+1B00
+3600
+0000
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uhungarumlaut
+ENCODING 369
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+1B
+36
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR Uogonek
+ENCODING 370
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 1 -3
+BITMAP
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+3000
+2000
+3800
+ENDCHAR
+STARTCHAR uogonek
+ENCODING 371
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+33
+33
+63
+66
+C6
+CC
+7C
+30
+20
+38
+ENDCHAR
+STARTCHAR Wcircumflex
+ENCODING 372
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 13 2 0
+BITMAP
+0800
+1C00
+3600
+0000
+CCC0
+CCC0
+CD80
+DD80
+DD00
+ED00
+EE00
+4400
+4400
+ENDCHAR
+STARTCHAR wcircumflex
+ENCODING 373
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 11 1 0
+BITMAP
+0400
+0E00
+1B00
+0000
+CCC0
+CCC0
+DD80
+DD80
+5500
+7700
+6600
+ENDCHAR
+STARTCHAR Ycircumflex
+ENCODING 374
+SWIDTH 667 0
+DWIDTH 7 0
+BBX 7 13 2 0
+BITMAP
+10
+38
+6C
+00
+C6
+C6
+6C
+6C
+38
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR ycircumflex
+ENCODING 375
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 14 1 -3
+BITMAP
+10
+38
+6C
+00
+CC
+CC
+CC
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+STARTCHAR Ydieresis
+ENCODING 376
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 9 3 0
+BITMAP
+6C
+00
+C6
+CC
+D8
+70
+60
+C0
+C0
+ENDCHAR
+STARTCHAR Zacute
+ENCODING 377
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 12 0 0
+BITMAP
+0600
+0C00
+0000
+3F80
+0300
+0600
+0C00
+1800
+3000
+6000
+C000
+FE00
+ENDCHAR
+STARTCHAR zacute
+ENCODING 378
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+0C
+18
+00
+3E
+06
+0C
+38
+60
+C0
+F8
+ENDCHAR
+STARTCHAR Zdotaccent
+ENCODING 379
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 11 0 0
+BITMAP
+0C00
+0000
+3F80
+0300
+0600
+0C00
+1800
+3000
+6000
+C000
+FE00
+ENDCHAR
+STARTCHAR zdotaccent
+ENCODING 380
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 7 9 0 0
+BITMAP
+18
+00
+3E
+06
+0C
+38
+60
+C0
+F8
+ENDCHAR
+STARTCHAR Zcaron
+ENCODING 381
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 10 0 0
+BITMAP
+1B00
+0E00
+0400
+3F80
+0300
+0600
+1C00
+3000
+6000
+FE00
+ENDCHAR
+STARTCHAR zcaron
+ENCODING 382
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 7 10 0 0
+BITMAP
+36
+1C
+08
+3E
+06
+0C
+38
+60
+C0
+F8
+ENDCHAR
+STARTCHAR uni0186
+ENCODING 390
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 9 1 0
+BITMAP
+1E
+33
+63
+03
+03
+06
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni0189
+ENCODING 393
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+1F00
+1980
+3180
+3180
+F980
+6300
+6300
+C600
+FC00
+ENDCHAR
+STARTCHAR uni018E
+ENCODING 398
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 9 1 0
+BITMAP
+1F80
+0180
+0300
+0300
+3F00
+0600
+0600
+0C00
+FC00
+ENDCHAR
+STARTCHAR florin
+ENCODING 402
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 11 0 -3
+BITMAP
+0E
+18
+18
+7C
+30
+30
+30
+60
+60
+60
+C0
+ENDCHAR
+STARTCHAR uni0197
+ENCODING 407
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 5 9 1 0
+BITMAP
+18
+18
+30
+30
+F8
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR uni019A
+ENCODING 410
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 9 0 0
+BITMAP
+18
+18
+30
+30
+F8
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR uni019D
+ENCODING 413
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 12 12 -1 -3
+BITMAP
+0630
+0630
+0E60
+0A60
+1A60
+1940
+19C0
+3080
+3080
+3000
+6000
+C000
+ENDCHAR
+STARTCHAR uni019F
+ENCODING 415
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 9 1 0
+BITMAP
+0F00
+3980
+3180
+6180
+FF80
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR Ohorn
+ENCODING 416
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 11 9 1 0
+BITMAP
+0F60
+39E0
+31C0
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR ohorn
+ENCODING 417
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 11 7 0 0
+BITMAP
+1E60
+3360
+63C0
+6600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR Uhorn
+ENCODING 431
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 11 9 1 0
+BITMAP
+31E0
+31E0
+63C0
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uhorn
+ENCODING 432
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 11 7 0 0
+BITMAP
+3360
+3360
+63C0
+6600
+C600
+CC00
+7400
+ENDCHAR
+STARTCHAR uni01B5
+ENCODING 437
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 9 0 0
+BITMAP
+3F80
+0300
+0600
+0C00
+3E00
+3000
+6000
+C000
+FE00
+ENDCHAR
+STARTCHAR uni01B6
+ENCODING 438
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 7 7 0 0
+BITMAP
+3E
+06
+0C
+7C
+60
+C0
+F8
+ENDCHAR
+STARTCHAR uni01BB
+ENCODING 443
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+3C
+66
+06
+0C
+FE
+30
+60
+C0
+F8
+ENDCHAR
+STARTCHAR uni01BC
+ENCODING 444
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 0
+BITMAP
+1E
+30
+60
+78
+0C
+0C
+0C
+D8
+70
+ENDCHAR
+STARTCHAR uni01C0
+ENCODING 448
+SWIDTH 280 0
+DWIDTH 4 0
+BBX 5 12 0 -3
+BITMAP
+18
+18
+18
+10
+30
+30
+20
+60
+60
+40
+C0
+C0
+ENDCHAR
+STARTCHAR uni01C2
+ENCODING 450
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 12 1 -2
+BITMAP
+0C
+0C
+0C
+08
+18
+7C
+10
+F8
+30
+20
+60
+60
+ENDCHAR
+STARTCHAR uni01C3
+ENCODING 451
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 5 9 1 0
+BITMAP
+18
+18
+30
+30
+60
+40
+00
+C0
+C0
+ENDCHAR
+STARTCHAR uni01CD
+ENCODING 461
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 13 0 0
+BITMAP
+1B
+0E
+04
+00
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR uni01CE
+ENCODING 462
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 11 0 0
+BITMAP
+6C
+38
+10
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR uni01CF
+ENCODING 463
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 6 13 1 0
+BITMAP
+6C
+38
+10
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR uni01D0
+ENCODING 464
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 11 0 0
+BITMAP
+D8
+70
+20
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR uni01D1
+ENCODING 465
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 13 1 0
+BITMAP
+1B00
+0E00
+0400
+0000
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni01D2
+ENCODING 466
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+36
+1C
+08
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni01D3
+ENCODING 467
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 13 1 0
+BITMAP
+3600
+1C00
+0800
+0000
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni01D4
+ENCODING 468
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+36
+1C
+08
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR uni01D5
+ENCODING 469
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 13 1 0
+BITMAP
+1E00
+0000
+1B00
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni01D6
+ENCODING 470
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+1E
+00
+1B
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR uni01D7
+ENCODING 471
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 14 1 0
+BITMAP
+0600
+0C00
+0000
+1B00
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni01D8
+ENCODING 472
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 12 0 0
+BITMAP
+06
+0C
+00
+1B
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR uni01D9
+ENCODING 473
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 15 1 0
+BITMAP
+1B00
+0E00
+0400
+0000
+1B00
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni01DA
+ENCODING 474
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+36
+1C
+08
+00
+1B
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR uni01DB
+ENCODING 475
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 14 1 0
+BITMAP
+1800
+0C00
+0000
+1B00
+0000
+3180
+3180
+3180
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni01DC
+ENCODING 476
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 12 0 0
+BITMAP
+18
+0C
+00
+1B
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR uni01DD
+ENCODING 477
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+1E
+33
+03
+7E
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni01DE
+ENCODING 478
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 13 0 0
+BITMAP
+0F00
+0000
+0D80
+0000
+0600
+0600
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR uni01DF
+ENCODING 479
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 11 0 0
+BITMAP
+3C
+00
+36
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR uni01E0
+ENCODING 480
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 13 0 0
+BITMAP
+1E
+00
+0C
+00
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR uni01E1
+ENCODING 481
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 11 0 0
+BITMAP
+3C
+00
+18
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR uni01E2
+ENCODING 482
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 14 11 0 0
+BITMAP
+03C0
+0000
+07FC
+0DC0
+0980
+1980
+33F0
+3F00
+6300
+C600
+C7E0
+ENDCHAR
+STARTCHAR uni01E3
+ENCODING 483
+SWIDTH 889 0
+DWIDTH 10 0
+BBX 11 9 0 0
+BITMAP
+0F00
+0000
+3BC0
+6660
+0460
+7FC0
+CC00
+9980
+EF00
+ENDCHAR
+STARTCHAR uni01E4
+ENCODING 484
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 10 9 1 0
+BITMAP
+0F00
+3980
+3180
+6000
+6700
+C7C0
+C600
+CE00
+7A00
+ENDCHAR
+STARTCHAR uni01E5
+ENCODING 485
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 10 -1 -3
+BITMAP
+0E80
+1B80
+3180
+3300
+6300
+6600
+3E00
+FF80
+CC00
+7800
+ENDCHAR
+STARTCHAR Gcaron
+ENCODING 486
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 13 1 0
+BITMAP
+1B00
+0E00
+0400
+0000
+0F00
+3980
+3180
+6000
+6700
+C300
+C600
+CE00
+7A00
+ENDCHAR
+STARTCHAR gcaron
+ENCODING 487
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 14 -1 -3
+BITMAP
+1B00
+0E00
+0400
+0000
+0E80
+1B80
+3180
+3300
+6300
+6600
+3E00
+0600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni01E8
+ENCODING 488
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 10 13 1 0
+BITMAP
+1B00
+0E00
+0400
+0000
+18C0
+1980
+3300
+3600
+3C00
+6600
+6600
+C300
+C300
+ENDCHAR
+STARTCHAR uni01E9
+ENCODING 489
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+36
+1C
+08
+00
+18
+18
+33
+36
+7C
+78
+6C
+CC
+C6
+ENDCHAR
+STARTCHAR uni01EA
+ENCODING 490
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 -3
+BITMAP
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+3000
+2000
+3800
+ENDCHAR
+STARTCHAR uni01EB
+ENCODING 491
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+1E
+33
+63
+66
+C6
+CC
+78
+30
+20
+38
+ENDCHAR
+STARTCHAR uni01EC
+ENCODING 492
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 14 1 -3
+BITMAP
+1E00
+0000
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+3000
+2000
+3800
+ENDCHAR
+STARTCHAR uni01ED
+ENCODING 493
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 12 0 -3
+BITMAP
+1E
+00
+1E
+33
+63
+66
+C6
+CC
+78
+30
+20
+38
+ENDCHAR
+STARTCHAR uni01F0
+ENCODING 496
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 7 14 -2 -3
+BITMAP
+36
+1C
+08
+00
+0C
+0C
+18
+18
+18
+30
+30
+30
+60
+C0
+ENDCHAR
+STARTCHAR uni01F4
+ENCODING 500
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 12 1 0
+BITMAP
+0600
+0C00
+0000
+0F00
+3980
+3180
+6000
+6700
+C300
+C600
+CE00
+7A00
+ENDCHAR
+STARTCHAR uni01F5
+ENCODING 501
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 13 -1 -3
+BITMAP
+0600
+0C00
+0000
+0E80
+1B80
+3180
+3300
+6300
+6600
+3E00
+0600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni01F8
+ENCODING 504
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 12 1 0
+BITMAP
+0C00
+0600
+0000
+18C0
+18C0
+3980
+2980
+6980
+6500
+6700
+C600
+C600
+ENDCHAR
+STARTCHAR uni01F9
+ENCODING 505
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+18
+0C
+00
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR Aringacute
+ENCODING 506
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 15 0 0
+BITMAP
+0300
+0600
+0000
+0300
+0480
+0300
+0300
+0700
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR aringacute
+ENCODING 507
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 13 0 0
+BITMAP
+0C
+18
+00
+0C
+12
+0C
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR AEacute
+ENCODING 508
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 14 12 0 0
+BITMAP
+00C0
+0180
+0000
+07FC
+0DC0
+0980
+1980
+33F0
+3F00
+6300
+C600
+C7E0
+ENDCHAR
+STARTCHAR aeacute
+ENCODING 509
+SWIDTH 889 0
+DWIDTH 10 0
+BBX 11 10 0 0
+BITMAP
+0300
+0600
+0000
+3BC0
+6660
+0460
+7FC0
+CC00
+9980
+EF00
+ENDCHAR
+STARTCHAR Oslashacute
+ENCODING 510
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 11 12 0 0
+BITMAP
+0300
+0600
+0000
+07A0
+1CC0
+19C0
+32C0
+3580
+6980
+7300
+6700
+BC00
+ENDCHAR
+STARTCHAR oslashacute
+ENCODING 511
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 11 -1 0
+BITMAP
+0300
+0600
+0000
+0080
+0F00
+1B80
+3580
+3B00
+7300
+6600
+BC00
+ENDCHAR
+STARTCHAR Scommaaccent
+ENCODING 536
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 14 1 -5
+BITMAP
+1E
+33
+63
+70
+3C
+0E
+C6
+CC
+78
+00
+30
+30
+10
+20
+ENDCHAR
+STARTCHAR scommaaccent
+ENCODING 537
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 12 0 -5
+BITMAP
+1E
+33
+38
+1C
+0C
+CC
+78
+00
+30
+30
+10
+20
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 538
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 14 2 -5
+BITMAP
+FF
+18
+30
+30
+60
+60
+60
+C0
+C0
+00
+60
+60
+20
+40
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 539
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 14 1 -5
+BITMAP
+18
+18
+7C
+30
+60
+60
+60
+C0
+E0
+00
+60
+60
+20
+40
+ENDCHAR
+STARTCHAR uni021E
+ENCODING 542
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 13 1 0
+BITMAP
+1B00
+0E00
+0400
+0000
+18C0
+18C0
+3180
+3180
+7F00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR uni021F
+ENCODING 543
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+36
+1C
+08
+00
+18
+18
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR uni0226
+ENCODING 550
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+0C
+00
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR uni0227
+ENCODING 551
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 9 0 0
+BITMAP
+18
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR uni0228
+ENCODING 552
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 -3
+BITMAP
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+1800
+4800
+7000
+ENDCHAR
+STARTCHAR uni0229
+ENCODING 553
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+1E
+33
+63
+7E
+C0
+CC
+78
+18
+48
+70
+ENDCHAR
+STARTCHAR uni022A
+ENCODING 554
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 13 1 0
+BITMAP
+0F00
+0000
+0D80
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni022B
+ENCODING 555
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+1E
+00
+1B
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni022C
+ENCODING 556
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 14 1 0
+BITMAP
+0F00
+0000
+0680
+0B00
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni022D
+ENCODING 557
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 12 0 0
+BITMAP
+1E
+00
+0D
+16
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni022E
+ENCODING 558
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 11 1 0
+BITMAP
+0C00
+0000
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni022F
+ENCODING 559
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+0C
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni0230
+ENCODING 560
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 13 1 0
+BITMAP
+1E00
+0000
+0C00
+0000
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni0231
+ENCODING 561
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+1E
+00
+0C
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni0232
+ENCODING 562
+SWIDTH 667 0
+DWIDTH 7 0
+BBX 7 11 2 0
+BITMAP
+3C
+00
+C6
+C6
+6C
+6C
+38
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR uni0233
+ENCODING 563
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 1 -3
+BITMAP
+78
+00
+CC
+CC
+CC
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+STARTCHAR uni0250
+ENCODING 592
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 7 0 0
+BITMAP
+6E
+32
+66
+7C
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni0259
+ENCODING 601
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+1E
+33
+03
+7E
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni025F
+ENCODING 607
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 7 9 1 -2
+BITMAP
+06
+06
+0C
+0C
+18
+18
+7C
+30
+E0
+ENDCHAR
+STARTCHAR uni0265
+ENCODING 613
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 -2
+BITMAP
+33
+33
+66
+66
+C6
+DC
+6C
+18
+18
+ENDCHAR
+STARTCHAR uni0275
+ENCODING 629
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+1E
+33
+63
+FF
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni0279
+ENCODING 633
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 7 0 0
+BITMAP
+06
+06
+0C
+0C
+1C
+78
+D8
+ENDCHAR
+STARTCHAR uni0287
+ENCODING 647
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 9 1 0
+BITMAP
+1C
+0C
+18
+18
+18
+30
+F8
+60
+60
+ENDCHAR
+STARTCHAR uni0289
+ENCODING 649
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 7 0 0
+BITMAP
+33
+33
+63
+FF
+C6
+CC
+74
+ENDCHAR
+STARTCHAR uni028C
+ENCODING 652
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 2 0
+BITMAP
+08
+18
+3C
+6C
+6C
+CC
+CC
+ENDCHAR
+STARTCHAR uni028D
+ENCODING 653
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 7 1 0
+BITMAP
+1980
+3B80
+2A80
+6EC0
+6EC0
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR uni028E
+ENCODING 654
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+04
+0C
+18
+18
+38
+28
+6C
+CC
+CC
+CC
+ENDCHAR
+STARTCHAR uni029E
+ENCODING 670
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 -2
+BITMAP
+63
+33
+36
+1E
+3E
+6C
+CC
+18
+18
+ENDCHAR
+STARTCHAR uni02BB
+ENCODING 699
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 3 3 3 6
+BITMAP
+60
+C0
+C0
+ENDCHAR
+STARTCHAR afii57929
+ENCODING 700
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 3 3 3 6
+BITMAP
+60
+60
+C0
+ENDCHAR
+STARTCHAR afii64937
+ENCODING 701
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 3 3 3 6
+BITMAP
+C0
+C0
+60
+ENDCHAR
+STARTCHAR circumflex
+ENCODING 710
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 3 2 7
+BITMAP
+20
+70
+D8
+ENDCHAR
+STARTCHAR caron
+ENCODING 711
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 3 3 6
+BITMAP
+D8
+70
+20
+ENDCHAR
+STARTCHAR uni02C8
+ENCODING 712
+SWIDTH 238 0
+DWIDTH 4 0
+BBX 4 3 2 6
+BITMAP
+30
+60
+C0
+ENDCHAR
+STARTCHAR macron
+ENCODING 713
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 3 8
+BITMAP
+F0
+ENDCHAR
+STARTCHAR uni02CA
+ENCODING 714
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 3 7
+BITMAP
+60
+C0
+ENDCHAR
+STARTCHAR uni02CB
+ENCODING 715
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 3 7
+BITMAP
+C0
+60
+ENDCHAR
+STARTCHAR uni02CD
+ENCODING 717
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 3 -2
+BITMAP
+F0
+ENDCHAR
+STARTCHAR uni02CE
+ENCODING 718
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 3 -3
+BITMAP
+C0
+60
+ENDCHAR
+STARTCHAR uni02CF
+ENCODING 719
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 3 -3
+BITMAP
+60
+C0
+ENDCHAR
+STARTCHAR breve
+ENCODING 728
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 5 2 2 7
+BITMAP
+D8
+70
+ENDCHAR
+STARTCHAR dotaccent
+ENCODING 729
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 2 1 3 8
+BITMAP
+C0
+ENDCHAR
+STARTCHAR ring
+ENCODING 730
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 3 2 6
+BITMAP
+70
+D8
+70
+ENDCHAR
+STARTCHAR ogonek
+ENCODING 731
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 4 0 -3
+BITMAP
+60
+C0
+80
+E0
+ENDCHAR
+STARTCHAR tilde
+ENCODING 732
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 2 3 7
+BITMAP
+68
+B0
+ENDCHAR
+STARTCHAR hungarumlaut
+ENCODING 733
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 2 2 7
+BITMAP
+6C
+D8
+ENDCHAR
+STARTCHAR uni02EE
+ENCODING 750
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 6 3 2 6
+BITMAP
+6C
+6C
+D8
+ENDCHAR
+STARTCHAR uni037E
+ENCODING 894
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 9 1 -2
+BITMAP
+30
+30
+00
+00
+00
+C0
+C0
+40
+80
+ENDCHAR
+STARTCHAR tonos
+ENCODING 900
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 2 3 7
+BITMAP
+60
+C0
+ENDCHAR
+STARTCHAR dieresistonos
+ENCODING 901
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 4 3 8
+BITMAP
+30
+60
+00
+D8
+ENDCHAR
+STARTCHAR anoteleia
+ENCODING 903
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 2 2 3
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR mu
+ENCODING 956
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 10 10 -2 -3
+BITMAP
+0CC0
+0CC0
+18C0
+1980
+3180
+3300
+6D00
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR uni1E00
+ENCODING 7680
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 13 0 -4
+BITMAP
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+00
+1C
+36
+1C
+ENDCHAR
+STARTCHAR uni1E01
+ENCODING 7681
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 11 0 -4
+BITMAP
+3C
+66
+06
+7C
+CC
+98
+EC
+00
+38
+6C
+38
+ENDCHAR
+STARTCHAR uni1E02
+ENCODING 7682
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 11 1 0
+BITMAP
+0C00
+0000
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+FC00
+ENDCHAR
+STARTCHAR uni1E03
+ENCODING 7683
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+18
+00
+18
+18
+36
+3B
+63
+66
+C6
+CC
+F8
+ENDCHAR
+STARTCHAR uni1E04
+ENCODING 7684
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 11 1 -2
+BITMAP
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+FC00
+0000
+1800
+ENDCHAR
+STARTCHAR uni1E05
+ENCODING 7685
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 -2
+BITMAP
+18
+18
+36
+3B
+63
+66
+C6
+CC
+F8
+00
+30
+ENDCHAR
+STARTCHAR uni1E06
+ENCODING 7686
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 11 1 -2
+BITMAP
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+FC00
+0000
+3C00
+ENDCHAR
+STARTCHAR uni1E07
+ENCODING 7687
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 -2
+BITMAP
+18
+18
+36
+3B
+63
+66
+C6
+CC
+F8
+00
+78
+ENDCHAR
+STARTCHAR uni1E08
+ENCODING 7688
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 1 -3
+BITMAP
+0C
+18
+00
+1E
+33
+63
+60
+C0
+C0
+C6
+CC
+78
+30
+90
+E0
+ENDCHAR
+STARTCHAR uni1E09
+ENCODING 7689
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 13 0 -3
+BITMAP
+0C
+18
+00
+1E
+33
+60
+60
+C6
+CC
+78
+30
+90
+E0
+ENDCHAR
+STARTCHAR uni1E0A
+ENCODING 7690
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 11 1 0
+BITMAP
+0C00
+0000
+1F00
+1980
+3180
+3180
+6180
+6300
+6300
+C600
+FC00
+ENDCHAR
+STARTCHAR uni1E0B
+ENCODING 7691
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 11 0 0
+BITMAP
+0600
+0000
+0180
+0180
+1B00
+3700
+6300
+6600
+C600
+CC00
+7C00
+ENDCHAR
+STARTCHAR uni1E0C
+ENCODING 7692
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 11 1 -2
+BITMAP
+1F00
+1980
+3180
+3180
+6180
+6300
+6300
+C600
+FC00
+0000
+1800
+ENDCHAR
+STARTCHAR uni1E0D
+ENCODING 7693
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 11 0 -2
+BITMAP
+0180
+0180
+1B00
+3700
+6300
+6600
+C600
+CC00
+7C00
+0000
+1800
+ENDCHAR
+STARTCHAR uni1E0E
+ENCODING 7694
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 11 1 -2
+BITMAP
+1F00
+1980
+3180
+3180
+6180
+6300
+6300
+C600
+FC00
+0000
+3C00
+ENDCHAR
+STARTCHAR uni1E0F
+ENCODING 7695
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 11 0 -2
+BITMAP
+0180
+0180
+1B00
+3700
+6300
+6600
+C600
+CC00
+7C00
+0000
+3C00
+ENDCHAR
+STARTCHAR uni1E10
+ENCODING 7696
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 12 1 -3
+BITMAP
+1F00
+1980
+3180
+3180
+6180
+6300
+6300
+C600
+FC00
+0C00
+2400
+3800
+ENDCHAR
+STARTCHAR uni1E11
+ENCODING 7697
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 12 0 -3
+BITMAP
+0180
+0180
+1B00
+3700
+6300
+6600
+C600
+CC00
+7C00
+1800
+4800
+7000
+ENDCHAR
+STARTCHAR uni1E12
+ENCODING 7698
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 13 1 -4
+BITMAP
+1F00
+1980
+3180
+3180
+6180
+6300
+6300
+C600
+FC00
+0000
+1000
+3800
+6C00
+ENDCHAR
+STARTCHAR uni1E13
+ENCODING 7699
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 13 0 -4
+BITMAP
+0180
+0180
+1B00
+3700
+6300
+6600
+C600
+CC00
+7C00
+0000
+1000
+3800
+6C00
+ENDCHAR
+STARTCHAR uni1E14
+ENCODING 7700
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 14 1 0
+BITMAP
+1800
+0C00
+0000
+1E00
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR uni1E15
+ENCODING 7701
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 12 0 0
+BITMAP
+18
+0C
+00
+1E
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1E16
+ENCODING 7702
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 14 1 0
+BITMAP
+0600
+0C00
+0000
+1E00
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR uni1E17
+ENCODING 7703
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 12 0 0
+BITMAP
+06
+0C
+00
+1E
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1E18
+ENCODING 7704
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 13 1 -4
+BITMAP
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+0000
+1000
+3800
+6C00
+ENDCHAR
+STARTCHAR uni1E19
+ENCODING 7705
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 11 0 -4
+BITMAP
+1E
+33
+63
+7E
+C0
+CC
+78
+00
+10
+38
+6C
+ENDCHAR
+STARTCHAR uni1E1A
+ENCODING 7706
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 -3
+BITMAP
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+0000
+6800
+B000
+ENDCHAR
+STARTCHAR uni1E1B
+ENCODING 7707
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+1E
+33
+63
+7E
+C0
+CC
+78
+00
+34
+58
+ENDCHAR
+STARTCHAR uni1E1C
+ENCODING 7708
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 15 1 -3
+BITMAP
+3600
+1C00
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+1800
+4800
+7000
+ENDCHAR
+STARTCHAR uni1E1D
+ENCODING 7709
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 13 0 -3
+BITMAP
+36
+1C
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+18
+48
+70
+ENDCHAR
+STARTCHAR uni1E1E
+ENCODING 7710
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 11 1 0
+BITMAP
+0C00
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR uni1E1F
+ENCODING 7711
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 7 11 1 0
+BITMAP
+18
+00
+0E
+18
+7C
+30
+30
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E20
+ENCODING 7712
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 11 1 0
+BITMAP
+1E00
+0000
+0F00
+3980
+3180
+6000
+6700
+C300
+C600
+CE00
+7A00
+ENDCHAR
+STARTCHAR uni1E21
+ENCODING 7713
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 12 -1 -3
+BITMAP
+1E00
+0000
+0E80
+1B80
+3180
+3300
+6300
+6600
+3E00
+0600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni1E22
+ENCODING 7714
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 11 1 0
+BITMAP
+0600
+0000
+18C0
+18C0
+3180
+3180
+7F00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR uni1E23
+ENCODING 7715
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+18
+00
+18
+18
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR uni1E24
+ENCODING 7716
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 11 1 -2
+BITMAP
+18C0
+18C0
+3180
+3180
+7F00
+6300
+6300
+C600
+C600
+0000
+1800
+ENDCHAR
+STARTCHAR uni1E25
+ENCODING 7717
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 -2
+BITMAP
+18
+18
+36
+3B
+63
+66
+66
+CC
+CC
+00
+18
+ENDCHAR
+STARTCHAR uni1E26
+ENCODING 7718
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 11 1 0
+BITMAP
+1B00
+0000
+18C0
+18C0
+3180
+3180
+7F00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR uni1E27
+ENCODING 7719
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+36
+00
+18
+18
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR uni1E28
+ENCODING 7720
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 12 1 -3
+BITMAP
+18C0
+18C0
+3180
+3180
+7F00
+6300
+6300
+C600
+DE00
+0C00
+2400
+3800
+ENDCHAR
+STARTCHAR uni1E29
+ENCODING 7721
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 12 0 -3
+BITMAP
+18
+18
+36
+3B
+63
+66
+66
+CC
+FC
+18
+48
+70
+ENDCHAR
+STARTCHAR uni1E2A
+ENCODING 7722
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 12 1 -3
+BITMAP
+18C0
+18C0
+3180
+3180
+7F00
+6300
+6300
+C600
+C600
+0000
+3600
+1C00
+ENDCHAR
+STARTCHAR uni1E2B
+ENCODING 7723
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 12 0 -3
+BITMAP
+18
+18
+36
+3B
+63
+66
+66
+CC
+CC
+00
+6C
+38
+ENDCHAR
+STARTCHAR uni1E2C
+ENCODING 7724
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 6 12 0 -3
+BITMAP
+0C
+0C
+18
+18
+30
+30
+30
+60
+60
+00
+68
+B0
+ENDCHAR
+STARTCHAR uni1E2D
+ENCODING 7725
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 6 12 -1 -3
+BITMAP
+0C
+00
+18
+18
+30
+30
+30
+60
+60
+00
+68
+B0
+ENDCHAR
+STARTCHAR uni1E2E
+ENCODING 7726
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 7 14 1 0
+BITMAP
+0C
+18
+00
+36
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E2F
+ENCODING 7727
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 6 12 0 0
+BITMAP
+18
+30
+00
+6C
+00
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E30
+ENCODING 7728
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 10 12 1 0
+BITMAP
+0600
+0C00
+0000
+18C0
+1980
+3300
+3600
+3C00
+6600
+6600
+C300
+C300
+ENDCHAR
+STARTCHAR uni1E31
+ENCODING 7729
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 12 0 0
+BITMAP
+0C
+18
+00
+18
+18
+33
+36
+7C
+78
+6C
+CC
+C6
+ENDCHAR
+STARTCHAR uni1E32
+ENCODING 7730
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 10 11 1 -2
+BITMAP
+18C0
+1980
+3300
+3600
+3C00
+6600
+6600
+C300
+C300
+0000
+1800
+ENDCHAR
+STARTCHAR uni1E33
+ENCODING 7731
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 11 0 -2
+BITMAP
+18
+18
+33
+36
+7C
+78
+6C
+CC
+C6
+00
+18
+ENDCHAR
+STARTCHAR uni1E34
+ENCODING 7732
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 10 11 1 -2
+BITMAP
+18C0
+1980
+3300
+3600
+3C00
+6600
+6600
+C300
+C300
+0000
+3C00
+ENDCHAR
+STARTCHAR uni1E35
+ENCODING 7733
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 11 0 -2
+BITMAP
+18
+18
+33
+36
+7C
+78
+6C
+CC
+C6
+00
+3C
+ENDCHAR
+STARTCHAR uni1E36
+ENCODING 7734
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 1 -2
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+FC
+00
+30
+ENDCHAR
+STARTCHAR uni1E37
+ENCODING 7735
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 11 0 -2
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+00
+60
+ENDCHAR
+STARTCHAR uni1E38
+ENCODING 7736
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 1 -2
+BITMAP
+78
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+FC
+00
+30
+ENDCHAR
+STARTCHAR uni1E39
+ENCODING 7737
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 13 0 -2
+BITMAP
+78
+00
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+00
+60
+ENDCHAR
+STARTCHAR uni1E3A
+ENCODING 7738
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 11 1 -2
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+FC
+00
+78
+ENDCHAR
+STARTCHAR uni1E3B
+ENCODING 7739
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 11 0 -2
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+00
+F0
+ENDCHAR
+STARTCHAR uni1E3C
+ENCODING 7740
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 6 13 1 -4
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+FC
+00
+20
+70
+D8
+ENDCHAR
+STARTCHAR uni1E3D
+ENCODING 7741
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 6 13 -1 -4
+BITMAP
+0C
+0C
+18
+18
+30
+30
+30
+60
+60
+00
+20
+70
+D8
+ENDCHAR
+STARTCHAR uni1E3E
+ENCODING 7742
+SWIDTH 833 0
+DWIDTH 12 0
+BBX 12 12 1 0
+BITMAP
+0180
+0300
+0000
+1830
+1870
+38E0
+38E0
+6940
+6AC0
+6EC0
+CD80
+C980
+ENDCHAR
+STARTCHAR uni1E3F
+ENCODING 7743
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 12 10 0 0
+BITMAP
+0300
+0600
+0000
+2EE0
+3330
+3330
+6660
+6660
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR uni1E40
+ENCODING 7744
+SWIDTH 833 0
+DWIDTH 12 0
+BBX 12 11 1 0
+BITMAP
+0300
+0000
+1830
+1870
+38E0
+38E0
+6940
+6AC0
+6EC0
+CD80
+C980
+ENDCHAR
+STARTCHAR uni1E41
+ENCODING 7745
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 12 9 0 0
+BITMAP
+0300
+0000
+2EE0
+3330
+3330
+6660
+6660
+CCC0
+CCC0
+ENDCHAR
+STARTCHAR uni1E42
+ENCODING 7746
+SWIDTH 833 0
+DWIDTH 12 0
+BBX 12 11 1 -2
+BITMAP
+1830
+1870
+38E0
+38E0
+6940
+6AC0
+6EC0
+CD80
+C980
+0000
+0C00
+ENDCHAR
+STARTCHAR uni1E43
+ENCODING 7747
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 12 9 0 -2
+BITMAP
+2EE0
+3330
+3330
+6660
+6660
+CCC0
+CCC0
+0000
+0C00
+ENDCHAR
+STARTCHAR uni1E44
+ENCODING 7748
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 11 1 0
+BITMAP
+0600
+0000
+18C0
+18C0
+3980
+2980
+6980
+6500
+6700
+C600
+C600
+ENDCHAR
+STARTCHAR uni1E45
+ENCODING 7749
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+18
+00
+36
+3B
+63
+66
+66
+CC
+CC
+ENDCHAR
+STARTCHAR uni1E46
+ENCODING 7750
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 11 1 -2
+BITMAP
+18C0
+18C0
+3980
+2980
+6980
+6500
+6700
+C600
+C600
+0000
+1800
+ENDCHAR
+STARTCHAR uni1E47
+ENCODING 7751
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 -2
+BITMAP
+36
+3B
+63
+66
+66
+CC
+CC
+00
+30
+ENDCHAR
+STARTCHAR uni1E48
+ENCODING 7752
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 11 1 -2
+BITMAP
+18C0
+18C0
+3980
+2980
+6980
+6500
+6700
+C600
+C600
+0000
+3C00
+ENDCHAR
+STARTCHAR uni1E49
+ENCODING 7753
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 -2
+BITMAP
+36
+3B
+63
+66
+66
+CC
+CC
+00
+78
+ENDCHAR
+STARTCHAR uni1E4A
+ENCODING 7754
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 13 1 -4
+BITMAP
+18C0
+18C0
+3980
+2980
+6980
+6500
+6700
+C600
+C600
+0000
+0800
+1C00
+3600
+ENDCHAR
+STARTCHAR uni1E4B
+ENCODING 7755
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 -4
+BITMAP
+36
+3B
+63
+66
+66
+CC
+CC
+00
+10
+38
+6C
+ENDCHAR
+STARTCHAR uni1E4C
+ENCODING 7756
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 15 1 0
+BITMAP
+0300
+0600
+0000
+0680
+0B00
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni1E4D
+ENCODING 7757
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+06
+0C
+00
+0D
+16
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni1E4E
+ENCODING 7758
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 14 1 0
+BITMAP
+1B00
+0000
+0680
+0B00
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni1E4F
+ENCODING 7759
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 12 0 0
+BITMAP
+1B
+00
+0D
+16
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni1E50
+ENCODING 7760
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 14 1 0
+BITMAP
+1800
+0C00
+0000
+1E00
+0000
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni1E51
+ENCODING 7761
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 12 0 0
+BITMAP
+18
+0C
+00
+1E
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni1E52
+ENCODING 7762
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 14 1 0
+BITMAP
+0600
+0C00
+0000
+1E00
+0000
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni1E53
+ENCODING 7763
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 12 0 0
+BITMAP
+06
+0C
+00
+1E
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni1E54
+ENCODING 7764
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0600
+0C00
+0000
+1F00
+1980
+3180
+3300
+7E00
+6000
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR uni1E55
+ENCODING 7765
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 13 -1 -3
+BITMAP
+0600
+0C00
+0000
+1B00
+1D80
+3180
+3300
+6300
+6600
+7C00
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR uni1E56
+ENCODING 7766
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 11 1 0
+BITMAP
+0C00
+0000
+1F00
+1980
+3180
+3300
+7E00
+6000
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR uni1E57
+ENCODING 7767
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 12 -1 -3
+BITMAP
+0C00
+0000
+1B00
+1D80
+3180
+3300
+6300
+6600
+7C00
+6000
+C000
+C000
+ENDCHAR
+STARTCHAR uni1E58
+ENCODING 7768
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 11 1 0
+BITMAP
+0C00
+0000
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+C600
+ENDCHAR
+STARTCHAR uni1E59
+ENCODING 7769
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 9 0 0
+BITMAP
+18
+00
+36
+3C
+70
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E5A
+ENCODING 7770
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 11 1 -2
+BITMAP
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+C600
+0000
+1800
+ENDCHAR
+STARTCHAR uni1E5B
+ENCODING 7771
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 9 0 -2
+BITMAP
+36
+3C
+70
+60
+60
+C0
+C0
+00
+60
+ENDCHAR
+STARTCHAR uni1E5C
+ENCODING 7772
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 13 1 -2
+BITMAP
+1E00
+0000
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+C600
+0000
+1800
+ENDCHAR
+STARTCHAR uni1E5D
+ENCODING 7773
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 11 0 -2
+BITMAP
+3C
+00
+36
+3C
+70
+60
+60
+C0
+C0
+00
+60
+ENDCHAR
+STARTCHAR uni1E5E
+ENCODING 7774
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 11 1 -2
+BITMAP
+1F00
+1980
+3180
+3300
+7E00
+6300
+6300
+C600
+C600
+0000
+3C00
+ENDCHAR
+STARTCHAR uni1E5F
+ENCODING 7775
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 7 9 0 -2
+BITMAP
+36
+3C
+70
+60
+60
+C0
+C0
+00
+F0
+ENDCHAR
+STARTCHAR uni1E60
+ENCODING 7776
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 11 1 0
+BITMAP
+0C
+00
+1E
+33
+63
+70
+3C
+0E
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni1E61
+ENCODING 7777
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+0C
+00
+1E
+33
+38
+1C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR uni1E62
+ENCODING 7778
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 11 1 -2
+BITMAP
+1E
+33
+63
+70
+3C
+0E
+C6
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1E63
+ENCODING 7779
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 -2
+BITMAP
+1E
+33
+38
+1C
+0C
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1E64
+ENCODING 7780
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 14 1 0
+BITMAP
+0C
+00
+0C
+18
+00
+1E
+33
+63
+70
+3C
+0E
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni1E65
+ENCODING 7781
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 12 0 0
+BITMAP
+0C
+00
+06
+0C
+00
+1E
+33
+38
+1C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR uni1E66
+ENCODING 7782
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 12 1 0
+BITMAP
+0C
+00
+1B
+0E
+04
+1E
+33
+31
+1C
+86
+C6
+7C
+ENDCHAR
+STARTCHAR uni1E67
+ENCODING 7783
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 12 0 0
+BITMAP
+0C
+00
+1B
+0E
+04
+1E
+33
+38
+1C
+0C
+CC
+78
+ENDCHAR
+STARTCHAR uni1E68
+ENCODING 7784
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 8 13 1 -2
+BITMAP
+0C
+00
+1E
+33
+63
+70
+3C
+0E
+C6
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1E69
+ENCODING 7785
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 11 0 -2
+BITMAP
+18
+00
+1E
+33
+38
+1C
+0C
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1E6A
+ENCODING 7786
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 2 0
+BITMAP
+18
+00
+FF
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR uni1E6B
+ENCODING 7787
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 11 1 0
+BITMAP
+30
+00
+18
+18
+7C
+30
+60
+60
+60
+C0
+E0
+ENDCHAR
+STARTCHAR uni1E6C
+ENCODING 7788
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 2 -2
+BITMAP
+FF
+18
+30
+30
+60
+60
+60
+C0
+C0
+00
+60
+ENDCHAR
+STARTCHAR uni1E6D
+ENCODING 7789
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 11 1 -2
+BITMAP
+18
+18
+7C
+30
+60
+60
+60
+C0
+E0
+00
+60
+ENDCHAR
+STARTCHAR uni1E6E
+ENCODING 7790
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 2 -2
+BITMAP
+FF
+18
+30
+30
+60
+60
+60
+C0
+C0
+00
+F0
+ENDCHAR
+STARTCHAR uni1E6F
+ENCODING 7791
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 11 1 -2
+BITMAP
+18
+18
+7C
+30
+60
+60
+60
+C0
+E0
+00
+F0
+ENDCHAR
+STARTCHAR uni1E70
+ENCODING 7792
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 13 2 -4
+BITMAP
+FF
+18
+30
+30
+60
+60
+60
+C0
+C0
+00
+20
+70
+D8
+ENDCHAR
+STARTCHAR uni1E71
+ENCODING 7793
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 13 1 -4
+BITMAP
+18
+18
+7C
+30
+60
+60
+60
+C0
+E0
+00
+20
+70
+D8
+ENDCHAR
+STARTCHAR uni1E72
+ENCODING 7794
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 11 1 -2
+BITMAP
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+0000
+6C00
+ENDCHAR
+STARTCHAR uni1E73
+ENCODING 7795
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 -2
+BITMAP
+33
+33
+63
+66
+C6
+CC
+74
+00
+6C
+ENDCHAR
+STARTCHAR uni1E74
+ENCODING 7796
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 1 -3
+BITMAP
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+0000
+3400
+5800
+ENDCHAR
+STARTCHAR uni1E75
+ENCODING 7797
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 10 0 -3
+BITMAP
+33
+33
+63
+66
+C6
+CC
+74
+00
+34
+58
+ENDCHAR
+STARTCHAR uni1E76
+ENCODING 7798
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 13 1 -4
+BITMAP
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+0000
+1000
+3800
+6C00
+ENDCHAR
+STARTCHAR uni1E77
+ENCODING 7799
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 -4
+BITMAP
+33
+33
+63
+66
+C6
+CC
+74
+00
+10
+38
+6C
+ENDCHAR
+STARTCHAR uni1E78
+ENCODING 7800
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 15 1 0
+BITMAP
+0600
+0C00
+0000
+0D00
+1600
+0000
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni1E79
+ENCODING 7801
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+0C
+18
+00
+1A
+2C
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR uni1E7A
+ENCODING 7802
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 13 1 0
+BITMAP
+1B00
+0000
+1E00
+0000
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni1E7B
+ENCODING 7803
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 0
+BITMAP
+36
+00
+1E
+00
+33
+33
+63
+66
+C6
+CC
+74
+ENDCHAR
+STARTCHAR uni1E7C
+ENCODING 7804
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 8 12 3 0
+BITMAP
+1A
+2C
+00
+C3
+C3
+C6
+C6
+CC
+CC
+58
+70
+60
+ENDCHAR
+STARTCHAR uni1E7D
+ENCODING 7805
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 2 0
+BITMAP
+34
+58
+00
+CC
+CC
+D8
+D8
+F0
+60
+40
+ENDCHAR
+STARTCHAR uni1E7E
+ENCODING 7806
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 8 11 3 -2
+BITMAP
+C3
+C3
+C6
+C6
+CC
+CC
+58
+70
+60
+00
+30
+ENDCHAR
+STARTCHAR uni1E7F
+ENCODING 7807
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 2 -2
+BITMAP
+CC
+CC
+D8
+D8
+F0
+60
+40
+00
+60
+ENDCHAR
+STARTCHAR Wgrave
+ENCODING 7808
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 12 2 0
+BITMAP
+1800
+0C00
+0000
+CCC0
+CCC0
+CD80
+DD80
+DD00
+ED00
+EE00
+4400
+4400
+ENDCHAR
+STARTCHAR wgrave
+ENCODING 7809
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 10 1 0
+BITMAP
+1800
+0C00
+0000
+CCC0
+CCC0
+DD80
+DD80
+5500
+7700
+6600
+ENDCHAR
+STARTCHAR Wacute
+ENCODING 7810
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 12 2 0
+BITMAP
+0600
+0C00
+0000
+CCC0
+CCC0
+CD80
+DD80
+DD00
+ED00
+EE00
+4400
+4400
+ENDCHAR
+STARTCHAR wacute
+ENCODING 7811
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 10 1 0
+BITMAP
+0600
+0C00
+0000
+CCC0
+CCC0
+DD80
+DD80
+5500
+7700
+6600
+ENDCHAR
+STARTCHAR Wdieresis
+ENCODING 7812
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 11 2 0
+BITMAP
+3600
+0000
+CCC0
+CCC0
+CD80
+DD80
+DD00
+ED00
+EE00
+4400
+4400
+ENDCHAR
+STARTCHAR wdieresis
+ENCODING 7813
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+1B00
+0000
+CCC0
+CCC0
+DD80
+DD80
+5500
+7700
+6600
+ENDCHAR
+STARTCHAR uni1E86
+ENCODING 7814
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 11 2 0
+BITMAP
+0C00
+0000
+CCC0
+CCC0
+CD80
+DD80
+DD00
+ED00
+EE00
+4400
+4400
+ENDCHAR
+STARTCHAR uni1E87
+ENCODING 7815
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+0C00
+0000
+CCC0
+CCC0
+DD80
+DD80
+5500
+7700
+6600
+ENDCHAR
+STARTCHAR uni1E88
+ENCODING 7816
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 11 2 -2
+BITMAP
+CCC0
+CCC0
+CD80
+DD80
+DD00
+ED00
+EE00
+4400
+4400
+0000
+1800
+ENDCHAR
+STARTCHAR uni1E89
+ENCODING 7817
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 9 1 -2
+BITMAP
+CCC0
+CCC0
+DD80
+DD80
+5500
+7700
+6600
+0000
+0C00
+ENDCHAR
+STARTCHAR uni1E8A
+ENCODING 7818
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 10 11 1 0
+BITMAP
+0C00
+0000
+30C0
+3180
+1B00
+1E00
+0C00
+1E00
+3600
+6300
+C300
+ENDCHAR
+STARTCHAR uni1E8B
+ENCODING 7819
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+0C
+00
+33
+36
+1C
+18
+38
+6C
+CC
+ENDCHAR
+STARTCHAR uni1E8C
+ENCODING 7820
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 10 11 1 0
+BITMAP
+1B00
+0000
+30C0
+3180
+1B00
+1E00
+0C00
+1E00
+3600
+6300
+C300
+ENDCHAR
+STARTCHAR uni1E8D
+ENCODING 7821
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 0
+BITMAP
+36
+00
+33
+36
+1C
+18
+38
+6C
+CC
+ENDCHAR
+STARTCHAR uni1E8E
+ENCODING 7822
+SWIDTH 667 0
+DWIDTH 7 0
+BBX 7 11 2 0
+BITMAP
+18
+00
+C6
+C6
+6C
+6C
+38
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR uni1E8F
+ENCODING 7823
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 1 -3
+BITMAP
+30
+00
+CC
+CC
+CC
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+STARTCHAR uni1E90
+ENCODING 7824
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 13 0 0
+BITMAP
+0400
+0E00
+1B00
+0000
+3F80
+0300
+0600
+0C00
+1800
+3000
+6000
+C000
+FE00
+ENDCHAR
+STARTCHAR uni1E91
+ENCODING 7825
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 7 11 0 0
+BITMAP
+08
+1C
+36
+00
+3E
+06
+0C
+38
+60
+C0
+F8
+ENDCHAR
+STARTCHAR uni1E92
+ENCODING 7826
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 11 0 -2
+BITMAP
+3F80
+0300
+0600
+0C00
+1800
+3000
+6000
+C000
+FE00
+0000
+3000
+ENDCHAR
+STARTCHAR uni1E93
+ENCODING 7827
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 7 9 0 -2
+BITMAP
+3E
+06
+0C
+38
+60
+C0
+F8
+00
+30
+ENDCHAR
+STARTCHAR uni1E94
+ENCODING 7828
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 11 0 -2
+BITMAP
+3F80
+0300
+0600
+0C00
+1800
+3000
+6000
+C000
+FE00
+0000
+7800
+ENDCHAR
+STARTCHAR uni1E95
+ENCODING 7829
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 7 9 0 -2
+BITMAP
+3E
+06
+0C
+38
+60
+C0
+F8
+00
+78
+ENDCHAR
+STARTCHAR uni1E96
+ENCODING 7830
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 11 0 -2
+BITMAP
+18
+18
+36
+3B
+63
+66
+66
+CC
+CC
+00
+3C
+ENDCHAR
+STARTCHAR uni1E97
+ENCODING 7831
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 6 11 1 0
+BITMAP
+6C
+00
+18
+18
+7C
+30
+60
+60
+60
+C0
+E0
+ENDCHAR
+STARTCHAR uni1E98
+ENCODING 7832
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 11 1 0
+BITMAP
+0E00
+1B00
+0E00
+0000
+CCC0
+CCC0
+DD80
+DD80
+5500
+7700
+6600
+ENDCHAR
+STARTCHAR uni1E99
+ENCODING 7833
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 14 1 -3
+BITMAP
+38
+6C
+38
+00
+CC
+CC
+CC
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+STARTCHAR uni1EA0
+ENCODING 7840
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 11 0 -2
+BITMAP
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+00
+18
+ENDCHAR
+STARTCHAR uni1EA1
+ENCODING 7841
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 9 0 -2
+BITMAP
+3C
+66
+06
+7C
+CC
+98
+EC
+00
+30
+ENDCHAR
+STARTCHAR uni1EA4
+ENCODING 7844
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 15 0 0
+BITMAP
+0300
+0600
+0000
+0700
+0D80
+0000
+0600
+0600
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR uni1EA5
+ENCODING 7845
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 13 0 0
+BITMAP
+0C
+18
+00
+1C
+36
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR uni1EA6
+ENCODING 7846
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 15 0 0
+BITMAP
+0C00
+0600
+0000
+0700
+0D80
+0000
+0600
+0600
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR uni1EA7
+ENCODING 7847
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 13 0 0
+BITMAP
+30
+18
+00
+1C
+36
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR uni1EAA
+ENCODING 7850
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 15 0 0
+BITMAP
+0D00
+1600
+0000
+0700
+0D80
+0000
+0600
+0600
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR uni1EAB
+ENCODING 7851
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 13 0 0
+BITMAP
+1A
+2C
+00
+1C
+36
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR uni1EAC
+ENCODING 7852
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 0 -2
+BITMAP
+04
+0E
+1B
+00
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+00
+18
+ENDCHAR
+STARTCHAR uni1EAD
+ENCODING 7853
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 13 0 -2
+BITMAP
+08
+1C
+36
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+00
+30
+ENDCHAR
+STARTCHAR uni1EAE
+ENCODING 7854
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 0 0
+BITMAP
+06
+0C
+00
+1B
+0E
+00
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR uni1EAF
+ENCODING 7855
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 13 0 0
+BITMAP
+18
+30
+00
+6C
+38
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR uni1EB0
+ENCODING 7856
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 0 0
+BITMAP
+18
+0C
+00
+1B
+0E
+00
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR uni1EB1
+ENCODING 7857
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 13 0 0
+BITMAP
+30
+18
+00
+6C
+38
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR uni1EB4
+ENCODING 7860
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 15 0 0
+BITMAP
+0D
+16
+00
+1B
+0E
+00
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+ENDCHAR
+STARTCHAR uni1EB5
+ENCODING 7861
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 13 0 0
+BITMAP
+34
+58
+00
+6C
+38
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+ENDCHAR
+STARTCHAR uni1EB6
+ENCODING 7862
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 14 0 -2
+BITMAP
+1B
+0E
+00
+06
+0E
+0B
+1B
+33
+3F
+63
+C3
+C3
+00
+18
+ENDCHAR
+STARTCHAR uni1EB7
+ENCODING 7863
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 7 12 0 -2
+BITMAP
+36
+1C
+00
+3C
+66
+06
+7C
+CC
+98
+EC
+00
+30
+ENDCHAR
+STARTCHAR uni1EB8
+ENCODING 7864
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 11 1 -2
+BITMAP
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+0000
+3000
+ENDCHAR
+STARTCHAR uni1EB9
+ENCODING 7865
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 9 0 -2
+BITMAP
+1E
+33
+63
+7E
+C0
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1EBC
+ENCODING 7868
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 12 1 0
+BITMAP
+0D00
+1600
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR uni1EBD
+ENCODING 7869
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 10 0 0
+BITMAP
+1A
+2C
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1EBE
+ENCODING 7870
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 15 1 0
+BITMAP
+0300
+0600
+0000
+0700
+0D80
+0000
+1F80
+1000
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR uni1EBF
+ENCODING 7871
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+06
+0C
+00
+0E
+1B
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1EC0
+ENCODING 7872
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 15 1 0
+BITMAP
+0C00
+0600
+0000
+0700
+0D80
+0000
+1F80
+1000
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR uni1EC1
+ENCODING 7873
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+18
+0C
+00
+0E
+1B
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1EC4
+ENCODING 7876
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 15 1 0
+BITMAP
+0D00
+1600
+0000
+0700
+0D80
+0000
+1F80
+1000
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+ENDCHAR
+STARTCHAR uni1EC5
+ENCODING 7877
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+0D
+16
+00
+0E
+1B
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+ENDCHAR
+STARTCHAR uni1EC6
+ENCODING 7878
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 9 15 1 -2
+BITMAP
+0800
+1C00
+3600
+0000
+1F80
+1800
+3000
+3000
+7E00
+6000
+6000
+C000
+FC00
+0000
+3000
+ENDCHAR
+STARTCHAR uni1EC7
+ENCODING 7879
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 13 0 -2
+BITMAP
+08
+1C
+36
+00
+1E
+33
+63
+7E
+C0
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1ECA
+ENCODING 7882
+SWIDTH 278 0
+DWIDTH 5 0
+BBX 5 11 1 -2
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+C0
+C0
+00
+60
+ENDCHAR
+STARTCHAR uni1ECB
+ENCODING 7883
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 5 11 0 -2
+BITMAP
+18
+00
+30
+30
+60
+60
+60
+C0
+C0
+00
+60
+ENDCHAR
+STARTCHAR uni1ECC
+ENCODING 7884
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 11 1 -2
+BITMAP
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+0000
+1800
+ENDCHAR
+STARTCHAR uni1ECD
+ENCODING 7885
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 -2
+BITMAP
+1E
+33
+63
+66
+C6
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1ED0
+ENCODING 7888
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 15 1 0
+BITMAP
+0300
+0600
+0000
+0700
+0D80
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni1ED1
+ENCODING 7889
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+06
+0C
+00
+0E
+1B
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni1ED2
+ENCODING 7890
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 15 1 0
+BITMAP
+0C00
+0600
+0000
+0700
+0D80
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni1ED3
+ENCODING 7891
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+18
+0C
+00
+0E
+1B
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni1ED6
+ENCODING 7894
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 15 1 0
+BITMAP
+0D00
+1600
+0000
+0700
+0D80
+0000
+0F00
+3980
+3180
+6180
+C300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni1ED7
+ENCODING 7895
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 13 0 0
+BITMAP
+0D
+16
+00
+0E
+1B
+00
+1E
+33
+63
+66
+C6
+CC
+78
+ENDCHAR
+STARTCHAR uni1ED8
+ENCODING 7896
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 9 15 1 -2
+BITMAP
+0400
+0E00
+1B00
+0000
+0F00
+3980
+3180
+6180
+6300
+C300
+C600
+CE00
+7800
+0000
+1800
+ENDCHAR
+STARTCHAR uni1ED9
+ENCODING 7897
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 13 0 -2
+BITMAP
+08
+1C
+36
+00
+1E
+33
+63
+66
+C6
+CC
+78
+00
+30
+ENDCHAR
+STARTCHAR uni1EDA
+ENCODING 7898
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 11 12 1 0
+BITMAP
+0300
+0600
+0000
+0F60
+39E0
+31C0
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni1EDB
+ENCODING 7899
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 11 10 0 0
+BITMAP
+0300
+0600
+0000
+1E60
+3360
+63C0
+6600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni1EDC
+ENCODING 7900
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 11 12 1 0
+BITMAP
+0600
+0300
+0000
+0F60
+39E0
+31C0
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni1EDD
+ENCODING 7901
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 11 10 0 0
+BITMAP
+0C00
+0600
+0000
+1E60
+3360
+63C0
+6600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni1EE0
+ENCODING 7904
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 11 12 1 0
+BITMAP
+0680
+0B00
+0000
+0F60
+39E0
+31C0
+6180
+6300
+C300
+C600
+CE00
+7800
+ENDCHAR
+STARTCHAR uni1EE1
+ENCODING 7905
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 11 10 0 0
+BITMAP
+0680
+0B00
+0000
+1E60
+3360
+63C0
+6600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni1EE2
+ENCODING 7906
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 11 11 1 -2
+BITMAP
+0F60
+39E0
+31C0
+6180
+6300
+C300
+C600
+CE00
+7800
+0000
+1800
+ENDCHAR
+STARTCHAR uni1EE3
+ENCODING 7907
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 11 9 0 -2
+BITMAP
+1E60
+3360
+63C0
+6600
+C600
+CC00
+7800
+0000
+1800
+ENDCHAR
+STARTCHAR uni1EE4
+ENCODING 7908
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 11 1 -2
+BITMAP
+3180
+3180
+6300
+6300
+6300
+C600
+C600
+CC00
+7800
+0000
+1800
+ENDCHAR
+STARTCHAR uni1EE5
+ENCODING 7909
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 8 9 0 -2
+BITMAP
+33
+33
+63
+66
+C6
+CC
+74
+00
+30
+ENDCHAR
+STARTCHAR uni1EE8
+ENCODING 7912
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 11 12 1 0
+BITMAP
+0300
+0600
+0000
+31E0
+31E0
+63C0
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni1EE9
+ENCODING 7913
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 11 10 0 0
+BITMAP
+0300
+0600
+0000
+3360
+3360
+63C0
+6600
+C600
+CC00
+7400
+ENDCHAR
+STARTCHAR uni1EEA
+ENCODING 7914
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 11 12 1 0
+BITMAP
+0C00
+0600
+0000
+31E0
+31E0
+63C0
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni1EEB
+ENCODING 7915
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 11 10 0 0
+BITMAP
+0C00
+0600
+0000
+3360
+3360
+63C0
+6600
+C600
+CC00
+7400
+ENDCHAR
+STARTCHAR uni1EEE
+ENCODING 7918
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 11 12 1 0
+BITMAP
+0680
+0B00
+0000
+31E0
+31E0
+63C0
+6300
+6300
+C600
+C600
+CC00
+7800
+ENDCHAR
+STARTCHAR uni1EEF
+ENCODING 7919
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 11 10 0 0
+BITMAP
+0680
+0B00
+0000
+3360
+3360
+63C0
+6600
+C600
+CC00
+7400
+ENDCHAR
+STARTCHAR uni1EF0
+ENCODING 7920
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 11 11 1 -2
+BITMAP
+31E0
+31E0
+63C0
+6300
+6300
+C600
+C600
+CC00
+7800
+0000
+1800
+ENDCHAR
+STARTCHAR uni1EF1
+ENCODING 7921
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 11 9 0 -2
+BITMAP
+3360
+3360
+63C0
+6600
+C600
+CC00
+7400
+0000
+1800
+ENDCHAR
+STARTCHAR Ygrave
+ENCODING 7922
+SWIDTH 667 0
+DWIDTH 7 0
+BBX 7 12 2 0
+BITMAP
+30
+18
+00
+C6
+C6
+6C
+6C
+38
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR ygrave
+ENCODING 7923
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 1 -3
+BITMAP
+60
+30
+00
+CC
+CC
+CC
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+STARTCHAR uni1EF4
+ENCODING 7924
+SWIDTH 667 0
+DWIDTH 7 0
+BBX 7 11 2 -2
+BITMAP
+C6
+C6
+6C
+6C
+38
+30
+30
+60
+60
+00
+30
+ENDCHAR
+STARTCHAR uni1EF5
+ENCODING 7925
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 1 -5
+BITMAP
+CC
+CC
+CC
+D8
+50
+70
+60
+60
+C0
+80
+00
+60
+ENDCHAR
+STARTCHAR uni1EF8
+ENCODING 7928
+SWIDTH 667 0
+DWIDTH 7 0
+BBX 7 12 2 0
+BITMAP
+34
+58
+00
+C6
+C6
+6C
+6C
+38
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR uni1EF9
+ENCODING 7929
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 1 -3
+BITMAP
+34
+58
+00
+CC
+CC
+CC
+D8
+50
+70
+60
+60
+C0
+80
+ENDCHAR
+STARTCHAR uni2000
+ENCODING 8192
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2001
+ENCODING 8193
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2002
+ENCODING 8194
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2003
+ENCODING 8195
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2004
+ENCODING 8196
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2005
+ENCODING 8197
+SWIDTH 250 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2006
+ENCODING 8198
+SWIDTH 167 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2007
+ENCODING 8199
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2008
+ENCODING 8200
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2009
+ENCODING 8201
+SWIDTH 200 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni200A
+ENCODING 8202
+SWIDTH 100 0
+DWIDTH 1 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni200B
+ENCODING 8203
+SWIDTH 0 0
+DWIDTH 0 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2010
+ENCODING 8208
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 1 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR uni2011
+ENCODING 8209
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 1 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR figuredash
+ENCODING 8210
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 1 3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR endash
+ENCODING 8211
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 1 3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR emdash
+ENCODING 8212
+SWIDTH 1000 0
+DWIDTH 12 0
+BBX 12 1 1 3
+BITMAP
+FFF0
+ENDCHAR
+STARTCHAR afii00208
+ENCODING 8213
+SWIDTH 1000 0
+DWIDTH 12 0
+BBX 12 1 1 3
+BITMAP
+FFF0
+ENDCHAR
+STARTCHAR quoteleft
+ENCODING 8216
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 3 3 3 6
+BITMAP
+60
+C0
+C0
+ENDCHAR
+STARTCHAR quoteright
+ENCODING 8217
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 3 3 3 6
+BITMAP
+60
+60
+C0
+ENDCHAR
+STARTCHAR quotesinglbase
+ENCODING 8218
+SWIDTH 278 0
+DWIDTH 2 0
+BBX 3 3 -1 -1
+BITMAP
+60
+60
+C0
+ENDCHAR
+STARTCHAR quotereversed
+ENCODING 8219
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 3 3 3 6
+BITMAP
+C0
+C0
+60
+ENDCHAR
+STARTCHAR quotedblleft
+ENCODING 8220
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 6 3 2 6
+BITMAP
+6C
+D8
+D8
+ENDCHAR
+STARTCHAR quotedblright
+ENCODING 8221
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 6 3 2 6
+BITMAP
+6C
+6C
+D8
+ENDCHAR
+STARTCHAR quotedblbase
+ENCODING 8222
+SWIDTH 500 0
+DWIDTH 5 0
+BBX 6 3 -1 -1
+BITMAP
+6C
+6C
+D8
+ENDCHAR
+STARTCHAR uni201F
+ENCODING 8223
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 6 3 2 6
+BITMAP
+D8
+D8
+6C
+ENDCHAR
+STARTCHAR dagger
+ENCODING 8224
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 12 1 -3
+BITMAP
+0C
+0C
+18
+7E
+18
+30
+30
+60
+60
+60
+C0
+C0
+ENDCHAR
+STARTCHAR daggerdbl
+ENCODING 8225
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 8 12 0 -3
+BITMAP
+06
+06
+0C
+3F
+0C
+18
+18
+30
+FC
+30
+60
+60
+ENDCHAR
+STARTCHAR bullet
+ENCODING 8226
+SWIDTH 350 0
+DWIDTH 6 0
+BBX 4 3 1 2
+BITMAP
+70
+F0
+E0
+ENDCHAR
+STARTCHAR ellipsis
+ENCODING 8230
+SWIDTH 1000 0
+DWIDTH 12 0
+BBX 10 1 1 0
+BITMAP
+CCC0
+ENDCHAR
+STARTCHAR perthousand
+ENCODING 8240
+SWIDTH 1000 0
+DWIDTH 14 0
+BBX 13 8 1 0
+BITMAP
+3180
+6B00
+3600
+0C00
+1800
+3630
+6D68
+C630
+ENDCHAR
+STARTCHAR guilsinglleft
+ENCODING 8249
+SWIDTH 333 0
+DWIDTH 6 0
+BBX 5 5 1 1
+BITMAP
+18
+70
+C0
+60
+30
+ENDCHAR
+STARTCHAR guilsinglright
+ENCODING 8250
+SWIDTH 333 0
+DWIDTH 6 0
+BBX 5 5 1 1
+BITMAP
+60
+30
+18
+70
+C0
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8260
+SWIDTH 167 0
+DWIDTH 5 0
+BBX 8 8 -1 0
+BITMAP
+03
+06
+0C
+18
+10
+30
+60
+C0
+ENDCHAR
+STARTCHAR oneinferior
+ENCODING 8321
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 5 1 -3
+BITMAP
+20
+E0
+20
+40
+40
+ENDCHAR
+STARTCHAR twoinferior
+ENCODING 8322
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 1 -3
+BITMAP
+60
+B0
+20
+40
+F0
+ENDCHAR
+STARTCHAR threeinferior
+ENCODING 8323
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 1 -3
+BITMAP
+70
+30
+60
+30
+E0
+ENDCHAR
+STARTCHAR uni20A5
+ENCODING 8357
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 12 9 0 -1
+BITMAP
+0040
+2EE0
+33B0
+3330
+6660
+6660
+CCC0
+DCC0
+1000
+ENDCHAR
+STARTCHAR uni20A6
+ENCODING 8358
+SWIDTH 722 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+18C0
+18C0
+3980
+3F80
+6980
+7F00
+6700
+C600
+C600
+ENDCHAR
+STARTCHAR uni20A9
+ENCODING 8361
+SWIDTH 944 0
+DWIDTH 10 0
+BBX 10 9 2 0
+BITMAP
+CCC0
+CCC0
+CD80
+DF80
+DD00
+FF00
+EE00
+4400
+4400
+ENDCHAR
+STARTCHAR Euro
+ENCODING 8364
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 9 0 0
+BITMAP
+0F00
+1980
+3180
+7C00
+6000
+F800
+6300
+6600
+3C00
+ENDCHAR
+STARTCHAR uni20AD
+ENCODING 8365
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 10 9 1 0
+BITMAP
+18C0
+1980
+3300
+3600
+FFC0
+6600
+6600
+C300
+C300
+ENDCHAR
+STARTCHAR uni2103
+ENCODING 8451
+SWIDTH 1102 0
+DWIDTH 13 0
+BBX 12 9 2 0
+BITMAP
+01E0
+6330
+9630
+9600
+6C00
+0C00
+0C60
+0CC0
+0780
+ENDCHAR
+STARTCHAR uni2109
+ENCODING 8457
+SWIDTH 991 0
+DWIDTH 12 0
+BBX 13 9 2 0
+BITMAP
+01F8
+6180
+9300
+9300
+67E0
+0600
+0600
+0C00
+0C00
+ENDCHAR
+STARTCHAR trademark
+ENCODING 8482
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 9 5 3 3
+BITMAP
+E880
+4D80
+4A80
+9500
+9500
+ENDCHAR
+STARTCHAR uni212A
+ENCODING 8490
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 10 9 1 0
+BITMAP
+18C0
+1980
+3300
+3600
+3C00
+6600
+6600
+C300
+C300
+ENDCHAR
+STARTCHAR uni212B
+ENCODING 8491
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 9 12 0 0
+BITMAP
+0300
+0480
+0300
+0300
+0700
+0F00
+1B00
+3300
+3F00
+6300
+C300
+C300
+ENDCHAR
+STARTCHAR uni2132
+ENCODING 8498
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 9 9 1 0
+BITMAP
+0180
+0180
+0300
+0300
+3F00
+0600
+0600
+0C00
+FC00
+ENDCHAR
+STARTCHAR minus
+ENCODING 8722
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 6 1 2 3
+BITMAP
+FC
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8725
+SWIDTH 167 0
+DWIDTH 5 0
+BBX 8 8 -1 0
+BITMAP
+03
+06
+0C
+18
+10
+30
+60
+C0
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 8729
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 2 2 3
+BITMAP
+C0
+C0
+ENDCHAR
+STARTCHAR uni2236
+ENCODING 8758
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 7 1 0
+BITMAP
+30
+30
+00
+00
+00
+C0
+C0
+ENDCHAR
+STARTCHAR uni2259
+ENCODING 8793
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 7 1 2
+BITMAP
+10
+38
+6C
+00
+7C
+00
+F8
+ENDCHAR
+STARTCHAR uni225A
+ENCODING 8794
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 7 1 2
+BITMAP
+6C
+38
+10
+00
+7C
+00
+F8
+ENDCHAR
+STARTCHAR notequal
+ENCODING 8800
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 9 1 -1
+BITMAP
+02
+06
+0C
+7C
+10
+F8
+60
+C0
+80
+ENDCHAR
+STARTCHAR equivalence
+ENCODING 8801
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+FC
+00
+FC
+00
+FC
+ENDCHAR
+STARTCHAR uni2262
+ENCODING 8802
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 9 0 -1
+BITMAP
+02
+06
+FC
+18
+FC
+30
+FC
+C0
+80
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 8804
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 7 2 -1
+BITMAP
+1C
+70
+C0
+60
+30
+00
+FC
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 8805
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 7 1 -1
+BITMAP
+30
+18
+0C
+38
+E0
+00
+FC
+ENDCHAR
+STARTCHAR uni226E
+ENCODING 8814
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 9 2 -1
+BITMAP
+02
+06
+1C
+78
+D0
+70
+70
+C0
+80
+ENDCHAR
+STARTCHAR uni226F
+ENCODING 8815
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 9 1 -1
+BITMAP
+02
+06
+3C
+18
+1C
+38
+E0
+C0
+80
+ENDCHAR
+STARTCHAR uni2270
+ENCODING 8816
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 9 2 -2
+BITMAP
+02
+1E
+7C
+D8
+70
+30
+60
+FC
+80
+ENDCHAR
+STARTCHAR uni2271
+ENCODING 8817
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 7 9 1 -2
+BITMAP
+02
+36
+1C
+1C
+38
+F0
+60
+FC
+80
+ENDCHAR
+STARTCHAR fi
+ENCODING -1
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 10 9 0 0
+BITMAP
+0EC0
+1800
+7D80
+3300
+3300
+6600
+6600
+CC00
+CC00
+ENDCHAR
+STARTCHAR fl
+ENCODING -1
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 10 9 0 0
+BITMAP
+0EC0
+1980
+7D80
+3300
+3300
+6600
+6600
+CC00
+CC00
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/helvR12-iso-8859-1.bdf b/gui/themes/fonts/helvR12-iso-8859-1.bdf
new file mode 100644
index 0000000000..1f27c247db
--- /dev/null
+++ b/gui/themes/fonts/helvR12-iso-8859-1.bdf
@@ -0,0 +1,3048 @@
+STARTFONT 2.1
+COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT!
+COMMENT Generated with 'ucs2any.pl helvR12.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1'
+COMMENT from an ISO10646-1 encoded source BDF font.
+COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000.
+FONT -Adobe-Helvetica-Medium-R-Normal--12-120-75-75-P-67-ISO8859-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 11 15 0 -3
+COMMENT $Xorg: $
+COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20
+COMMENT
+COMMENT +
+COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated.
+COMMENT Copyright 1988, 1994 Digital Equipment Corporation.
+COMMENT
+COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be
+COMMENT registered in certain jurisdictions.
+COMMENT Permission to use these trademarks is hereby granted only in
+COMMENT association with the images described in this file.
+COMMENT
+COMMENT Permission to use, copy, modify, distribute and sell this software
+COMMENT and its documentation for any purpose and without fee is hereby
+COMMENT granted, provided that the above copyright notices appear in all
+COMMENT copies and that both those copyright notices and this permission
+COMMENT notice appear in supporting documentation, and that the names of
+COMMENT Adobe Systems and Digital Equipment Corporation not be used in
+COMMENT advertising or publicity pertaining to distribution of the software
+COMMENT without specific, written prior permission. Adobe Systems and
+COMMENT Digital Equipment Corporation make no representations about the
+COMMENT suitability of this software for any purpose. It is provided "as
+COMMENT is" without express or implied warranty.
+COMMENT -
+STARTPROPERTIES 26
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 67
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 7
+FONT_ASCENT 11
+FONT_DESCENT 3
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+DEFAULT_CHAR 0
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Helvetica"
+ENDPROPERTIES
+CHARS 192
+STARTCHAR defaultchar
+ENCODING 0
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+AA
+00
+82
+00
+82
+00
+82
+00
+AA
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 355 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+28
+28
+FC
+28
+FC
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -1
+BITMAP
+20
+70
+A8
+A0
+70
+28
+A8
+A8
+70
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+6200
+9400
+9400
+6800
+0800
+1300
+1480
+1480
+2300
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+30
+48
+48
+30
+50
+8A
+84
+8C
+72
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 191 0
+DWIDTH 3 0
+BBX 1 3 1 6
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 12 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 12 0 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+A0
+40
+A0
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+20
+F8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 3 1 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+10
+10
+20
+20
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 3 9 1 0
+BITMAP
+20
+E0
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+10
+20
+40
+80
+80
+F8
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+30
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+08
+18
+28
+28
+48
+88
+FC
+08
+08
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+F8
+80
+80
+F0
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+80
+B0
+C8
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+F8
+08
+10
+10
+20
+20
+20
+40
+40
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+78
+08
+08
+88
+70
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 6 1 0
+BITMAP
+80
+00
+00
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 8 0 -2
+BITMAP
+40
+00
+00
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+0C
+30
+C0
+30
+0C
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 3 1 2
+BITMAP
+F8
+00
+F8
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 1 1
+BITMAP
+C0
+30
+0C
+30
+C0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+10
+10
+20
+20
+00
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 1015 0
+DWIDTH 12 0
+BBX 10 10 1 -1
+BITMAP
+1F00
+6080
+4D40
+9240
+A240
+A240
+A680
+9B00
+4000
+3E00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+F8
+84
+84
+84
+F8
+84
+84
+84
+F8
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3C
+42
+80
+80
+80
+80
+80
+42
+3C
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+F8
+84
+82
+82
+82
+82
+82
+84
+F8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+80
+80
+80
+F8
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3C
+42
+80
+80
+8E
+82
+82
+46
+3A
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+82
+82
+FE
+82
+82
+82
+82
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+08
+08
+08
+08
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+84
+88
+90
+A0
+E0
+90
+88
+84
+82
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+F8
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 833 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+8080
+C180
+C180
+A280
+A280
+9480
+9480
+8880
+8880
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+F8
+84
+84
+84
+F8
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+42
+81
+81
+81
+89
+85
+42
+3D
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+F8
+84
+84
+84
+F8
+88
+84
+84
+84
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+84
+80
+60
+18
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+44
+44
+44
+28
+28
+10
+10
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+8880
+8880
+8880
+4900
+5500
+5500
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+44
+44
+28
+10
+28
+44
+44
+82
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 611 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FE
+02
+04
+08
+10
+20
+40
+80
+FE
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 12 1 -3
+BITMAP
+C0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+C0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+80
+80
+40
+40
+20
+20
+20
+10
+10
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 12 0 -3
+BITMAP
+C0
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+C0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 469 0
+DWIDTH 6 0
+BBX 5 3 0 5
+BITMAP
+20
+50
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 0 -2
+BITMAP
+FE
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 333 0
+DWIDTH 2 0
+BBX 2 2 0 8
+BITMAP
+80
+40
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+C8
+B0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+80
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+08
+08
+68
+98
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 9 0 0
+BITMAP
+30
+40
+E0
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 2 12 0 -3
+BITMAP
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+90
+A0
+C0
+C0
+A0
+90
+88
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 833 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+A4
+DA
+92
+92
+92
+92
+92
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+B0
+C8
+88
+88
+88
+C8
+B0
+80
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+68
+98
+88
+88
+88
+98
+68
+08
+08
+08
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+A0
+C0
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+60
+90
+80
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+40
+E0
+40
+40
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+88
+88
+88
+50
+50
+20
+20
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 7 0 0
+BITMAP
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+84
+48
+30
+30
+48
+84
+84
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+F0
+10
+20
+40
+40
+80
+F0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 334 0
+DWIDTH 4 0
+BBX 4 12 0 -3
+BITMAP
+30
+40
+40
+40
+40
+80
+40
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 260 0
+DWIDTH 3 0
+BBX 1 12 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 334 0
+DWIDTH 4 0
+BBX 4 12 0 -3
+BITMAP
+C0
+20
+20
+20
+20
+10
+20
+20
+20
+20
+20
+C0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 2 0 3
+BITMAP
+64
+98
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 1 10 1 -3
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 -1
+BITMAP
+10
+70
+A8
+A0
+A0
+A0
+C8
+70
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+30
+48
+40
+40
+F0
+20
+20
+48
+B0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 6 0 1
+BITMAP
+84
+78
+48
+48
+78
+84
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+88
+88
+50
+20
+F8
+20
+F8
+20
+20
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 260 0
+DWIDTH 3 0
+BBX 1 11 1 -2
+BITMAP
+80
+80
+80
+80
+00
+00
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 5 12 0 -3
+BITMAP
+70
+88
+80
+60
+90
+88
+88
+48
+30
+08
+88
+70
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 3 1 0 8
+BITMAP
+A0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3E00
+4100
+9C80
+A280
+A080
+A280
+9C80
+4100
+3E00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 370 0
+DWIDTH 5 0
+BBX 3 5 1 4
+BITMAP
+E0
+20
+A0
+00
+E0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+28
+50
+A0
+50
+28
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 6 4 1 2
+BITMAP
+FC
+04
+04
+04
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3E00
+4100
+9C80
+9480
+9880
+9480
+9480
+4100
+3E00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 0 8
+BITMAP
+F0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 0 4
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+20
+20
+F8
+20
+20
+00
+F8
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 0 3
+BITMAP
+60
+90
+20
+40
+F0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 5 0 3
+BITMAP
+E0
+20
+40
+20
+C0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 333 0
+DWIDTH 2 0
+BBX 2 2 0 8
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+88
+88
+98
+E8
+80
+80
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 537 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+3C
+68
+E8
+E8
+E8
+68
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 1 1 3
+BITMAP
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 3 4 0 -3
+BITMAP
+40
+20
+20
+C0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 5 1 3
+BITMAP
+40
+C0
+40
+40
+40
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 365 0
+DWIDTH 5 0
+BBX 3 5 1 4
+BITMAP
+E0
+A0
+E0
+00
+E0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+A0
+50
+28
+50
+A0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+4100
+C200
+4400
+4400
+4900
+1300
+1500
+2780
+4100
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+4100
+C200
+4400
+4800
+4B00
+1480
+1100
+2200
+4780
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+E100
+2200
+4400
+2400
+C900
+0B00
+1500
+1780
+2100
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 5 9 1 -3
+BITMAP
+20
+00
+20
+20
+40
+40
+88
+88
+70
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+20
+10
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+14
+28
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+28
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+10
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+1F80
+2800
+2800
+4800
+4F80
+7800
+8800
+8800
+8F80
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+3C
+42
+80
+80
+80
+80
+80
+42
+3C
+08
+08
+30
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+20
+10
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+08
+10
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+10
+28
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+28
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 12 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 12 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 0 0
+BITMAP
+40
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+7C
+42
+41
+41
+F1
+41
+41
+42
+7C
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+14
+28
+00
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+10
+08
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+04
+08
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+08
+14
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+14
+28
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+24
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+88
+50
+20
+50
+88
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 11 0 -1
+BITMAP
+0040
+1E80
+2100
+4280
+4480
+4480
+4880
+5080
+2100
+5E00
+8000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+20
+10
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+08
+10
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+10
+28
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+48
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+80
+80
+F8
+84
+84
+84
+F8
+80
+80
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+B0
+88
+88
+88
+B0
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+20
+10
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+28
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+30
+48
+30
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 9 7 1 0
+BITMAP
+7700
+8880
+0880
+7F80
+8800
+8880
+7700
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+70
+88
+80
+80
+80
+88
+70
+20
+10
+60
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 10 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 10 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+40
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+68
+30
+50
+08
+78
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+00
+F8
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+3A
+44
+4C
+54
+64
+44
+B8
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+10
+20
+00
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+C8
+B0
+80
+80
+80
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+50
+00
+88
+88
+48
+50
+50
+30
+20
+20
+20
+C0
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/helvR12.bdf b/gui/themes/fonts/helvR12.bdf
new file mode 100644
index 0000000000..2e7abc680b
--- /dev/null
+++ b/gui/themes/fonts/helvR12.bdf
@@ -0,0 +1,12688 @@
+STARTFONT 2.1
+FONT -Adobe-Helvetica-Medium-R-Normal--12-120-75-75-P-67-ISO10646-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 14 20 -1 -5
+COMMENT $Xorg: $
+COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20
+COMMENT
+COMMENT +
+COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated.
+COMMENT Copyright 1988, 1994 Digital Equipment Corporation.
+COMMENT
+COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be
+COMMENT registered in certain jurisdictions.
+COMMENT Permission to use these trademarks is hereby granted only in
+COMMENT association with the images described in this file.
+COMMENT
+COMMENT Permission to use, copy, modify, distribute and sell this software
+COMMENT and its documentation for any purpose and without fee is hereby
+COMMENT granted, provided that the above copyright notices appear in all
+COMMENT copies and that both those copyright notices and this permission
+COMMENT notice appear in supporting documentation, and that the names of
+COMMENT Adobe Systems and Digital Equipment Corporation not be used in
+COMMENT advertising or publicity pertaining to distribution of the software
+COMMENT without specific, written prior permission. Adobe Systems and
+COMMENT Digital Equipment Corporation make no representations about the
+COMMENT suitability of this software for any purpose. It is provided "as
+COMMENT is" without express or implied warranty.
+COMMENT -
+STARTPROPERTIES 26
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 67
+CHARSET_REGISTRY "ISO10646"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 7
+FONT_ASCENT 11
+FONT_DESCENT 3
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+DEFAULT_CHAR 0
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Helvetica"
+ENDPROPERTIES
+CHARS 756
+STARTCHAR char0
+ENCODING 0
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+AA
+00
+82
+00
+82
+00
+82
+00
+AA
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 355 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+28
+28
+FC
+28
+FC
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -1
+BITMAP
+20
+70
+A8
+A0
+70
+28
+A8
+A8
+70
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+6200
+9400
+9400
+6800
+0800
+1300
+1480
+1480
+2300
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+30
+48
+48
+30
+50
+8A
+84
+8C
+72
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 191 0
+DWIDTH 3 0
+BBX 1 3 1 6
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 12 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 12 0 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 389 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+A0
+40
+A0
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+20
+F8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 2 3 1 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+10
+10
+20
+20
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 3 9 1 0
+BITMAP
+20
+E0
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+10
+20
+40
+80
+80
+F8
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+30
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+08
+18
+28
+28
+48
+88
+FC
+08
+08
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+F8
+80
+80
+F0
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+80
+B0
+C8
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+F8
+08
+10
+10
+20
+20
+20
+40
+40
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+78
+08
+08
+88
+70
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 6 1 0
+BITMAP
+80
+00
+00
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 8 0 -2
+BITMAP
+40
+00
+00
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+0C
+30
+C0
+30
+0C
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 3 1 2
+BITMAP
+F8
+00
+F8
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 5 1 1
+BITMAP
+C0
+30
+0C
+30
+C0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+10
+10
+20
+20
+00
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 1015 0
+DWIDTH 12 0
+BBX 10 10 1 -1
+BITMAP
+1F00
+6080
+4D40
+9240
+A240
+A240
+A680
+9B00
+4000
+3E00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+F8
+84
+84
+84
+F8
+84
+84
+84
+F8
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3C
+42
+80
+80
+80
+80
+80
+42
+3C
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+F8
+84
+82
+82
+82
+82
+82
+84
+F8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+80
+80
+80
+F8
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3C
+42
+80
+80
+8E
+82
+82
+46
+3A
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+82
+82
+FE
+82
+82
+82
+82
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+08
+08
+08
+08
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+84
+88
+90
+A0
+E0
+90
+88
+84
+82
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+F8
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 833 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+8080
+C180
+C180
+A280
+A280
+9480
+9480
+8880
+8880
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+F8
+84
+84
+84
+F8
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+42
+81
+81
+81
+89
+85
+42
+3D
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+F8
+84
+84
+84
+F8
+88
+84
+84
+84
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+84
+80
+60
+18
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+44
+44
+44
+28
+28
+10
+10
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+8880
+8880
+8880
+4900
+5500
+5500
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+44
+44
+28
+10
+28
+44
+44
+82
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 611 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FE
+02
+04
+08
+10
+20
+40
+80
+FE
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 12 1 -3
+BITMAP
+C0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+C0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+80
+80
+40
+40
+20
+20
+20
+10
+10
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 12 0 -3
+BITMAP
+C0
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+C0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 469 0
+DWIDTH 6 0
+BBX 5 3 0 5
+BITMAP
+20
+50
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 0 -2
+BITMAP
+FE
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 333 0
+DWIDTH 2 0
+BBX 2 2 0 8
+BITMAP
+80
+40
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+C8
+B0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+80
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+08
+08
+68
+98
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 9 0 0
+BITMAP
+30
+40
+E0
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 2 12 0 -3
+BITMAP
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+90
+A0
+C0
+C0
+A0
+90
+88
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 833 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+A4
+DA
+92
+92
+92
+92
+92
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+B0
+C8
+88
+88
+88
+C8
+B0
+80
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+68
+98
+88
+88
+88
+98
+68
+08
+08
+08
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+A0
+C0
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+60
+90
+80
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+40
+E0
+40
+40
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+88
+88
+88
+50
+50
+20
+20
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 7 0 0
+BITMAP
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+84
+48
+30
+30
+48
+84
+84
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+F0
+10
+20
+40
+40
+80
+F0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 334 0
+DWIDTH 4 0
+BBX 4 12 0 -3
+BITMAP
+30
+40
+40
+40
+40
+80
+40
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 260 0
+DWIDTH 3 0
+BBX 1 12 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 334 0
+DWIDTH 4 0
+BBX 4 12 0 -3
+BITMAP
+C0
+20
+20
+20
+20
+10
+20
+20
+20
+20
+20
+C0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 2 0 3
+BITMAP
+64
+98
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 278 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 1 10 1 -3
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 -1
+BITMAP
+10
+70
+A8
+A0
+A0
+A0
+C8
+70
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+30
+48
+40
+40
+F0
+20
+20
+48
+B0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 6 0 1
+BITMAP
+84
+78
+48
+48
+78
+84
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+88
+88
+50
+20
+F8
+20
+F8
+20
+20
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 260 0
+DWIDTH 3 0
+BBX 1 11 1 -2
+BITMAP
+80
+80
+80
+80
+00
+00
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 5 12 0 -3
+BITMAP
+70
+88
+80
+60
+90
+88
+88
+48
+30
+08
+88
+70
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 3 1 0 8
+BITMAP
+A0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3E00
+4100
+9C80
+A280
+A080
+A280
+9C80
+4100
+3E00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 370 0
+DWIDTH 5 0
+BBX 3 5 1 4
+BITMAP
+E0
+20
+A0
+00
+E0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+28
+50
+A0
+50
+28
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 6 4 1 2
+BITMAP
+FC
+04
+04
+04
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 737 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3E00
+4100
+9C80
+9480
+9880
+9480
+9480
+4100
+3E00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 0 8
+BITMAP
+F0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 0 4
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+20
+20
+F8
+20
+20
+00
+F8
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 0 3
+BITMAP
+60
+90
+20
+40
+F0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 5 0 3
+BITMAP
+E0
+20
+40
+20
+C0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 333 0
+DWIDTH 2 0
+BBX 2 2 0 8
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+88
+88
+98
+E8
+80
+80
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 537 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+3C
+68
+E8
+E8
+E8
+68
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 1 1 3
+BITMAP
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 3 4 0 -3
+BITMAP
+40
+20
+20
+C0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 5 1 3
+BITMAP
+40
+C0
+40
+40
+40
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 365 0
+DWIDTH 5 0
+BBX 3 5 1 4
+BITMAP
+E0
+A0
+E0
+00
+E0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+A0
+50
+28
+50
+A0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+4100
+C200
+4400
+4400
+4900
+1300
+1500
+2780
+4100
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+4100
+C200
+4400
+4800
+4B00
+1480
+1100
+2200
+4780
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 834 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+E100
+2200
+4400
+2400
+C900
+0B00
+1500
+1780
+2100
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 5 9 1 -3
+BITMAP
+20
+00
+20
+20
+40
+40
+88
+88
+70
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+20
+10
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+14
+28
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+28
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+10
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+1F80
+2800
+2800
+4800
+4F80
+7800
+8800
+8800
+8F80
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+3C
+42
+80
+80
+80
+80
+80
+42
+3C
+08
+08
+30
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+20
+10
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+08
+10
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+10
+28
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+28
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 12 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 12 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 0 0
+BITMAP
+40
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+7C
+42
+41
+41
+F1
+41
+41
+42
+7C
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+14
+28
+00
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+10
+08
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+04
+08
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+08
+14
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+14
+28
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+24
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+88
+50
+20
+50
+88
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 11 0 -1
+BITMAP
+0040
+1E80
+2100
+4280
+4480
+4480
+4880
+5080
+2100
+5E00
+8000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+20
+10
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+08
+10
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+10
+28
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+48
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+80
+80
+F8
+84
+84
+84
+F8
+80
+80
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+B0
+88
+88
+88
+B0
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+20
+10
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+28
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+30
+48
+30
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 9 7 1 0
+BITMAP
+7700
+8880
+0880
+7F80
+8800
+8880
+7700
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+70
+88
+80
+80
+80
+88
+70
+20
+10
+60
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 10 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 10 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+40
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+68
+30
+50
+08
+78
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+00
+F8
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+3A
+44
+4C
+54
+64
+44
+B8
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+10
+20
+00
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+C8
+B0
+80
+80
+80
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+50
+00
+88
+88
+48
+50
+50
+30
+20
+20
+20
+C0
+ENDCHAR
+STARTCHAR Amacron
+ENCODING 256
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+3C
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR amacron
+ENCODING 257
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+78
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR Abreve
+ENCODING 258
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+24
+18
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR abreve
+ENCODING 259
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+48
+30
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR Aogonek
+ENCODING 260
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+10
+28
+28
+44
+44
+7C
+82
+82
+92
+20
+20
+18
+ENDCHAR
+STARTCHAR aogonek
+ENCODING 261
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 -3
+BITMAP
+70
+88
+08
+78
+88
+88
+74
+20
+20
+18
+ENDCHAR
+STARTCHAR Cacute
+ENCODING 262
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+3C
+42
+80
+80
+80
+80
+80
+42
+3C
+ENDCHAR
+STARTCHAR cacute
+ENCODING 263
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+80
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR Ccircumflex
+ENCODING 264
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+00
+3C
+42
+80
+80
+80
+80
+80
+42
+3C
+ENDCHAR
+STARTCHAR ccircumflex
+ENCODING 265
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+80
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR Cdotaccent
+ENCODING 266
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+10
+00
+3C
+42
+80
+80
+80
+80
+80
+42
+3C
+ENDCHAR
+STARTCHAR cdotaccent
+ENCODING 267
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+20
+00
+70
+88
+80
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR Ccaron
+ENCODING 268
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+28
+10
+00
+3C
+42
+80
+80
+80
+80
+80
+42
+3C
+ENDCHAR
+STARTCHAR ccaron
+ENCODING 269
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+50
+20
+00
+70
+88
+80
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR Dcaron
+ENCODING 270
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+28
+10
+00
+F8
+84
+82
+82
+82
+82
+82
+84
+F8
+ENDCHAR
+STARTCHAR dcaron
+ENCODING 271
+SWIDTH 750 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+0980
+0880
+6900
+9800
+8800
+8800
+8800
+9800
+6800
+ENDCHAR
+STARTCHAR Dcroat
+ENCODING 272
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+7C
+42
+41
+41
+F1
+41
+41
+42
+7C
+ENDCHAR
+STARTCHAR dcroat
+ENCODING 273
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+08
+38
+68
+98
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR Emacron
+ENCODING 274
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR emacron
+ENCODING 275
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+78
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR Ebreve
+ENCODING 276
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+48
+30
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR ebreve
+ENCODING 277
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+48
+30
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR Edotaccent
+ENCODING 278
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR edotaccent
+ENCODING 279
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+20
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR Eogonek
+ENCODING 280
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+40
+40
+30
+ENDCHAR
+STARTCHAR eogonek
+ENCODING 281
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+70
+88
+88
+F8
+80
+88
+70
+40
+40
+30
+ENDCHAR
+STARTCHAR Ecaron
+ENCODING 282
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+50
+20
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR ecaron
+ENCODING 283
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+50
+20
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR Gcircumflex
+ENCODING 284
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+00
+3C
+42
+80
+80
+8E
+82
+82
+46
+3A
+ENDCHAR
+STARTCHAR gcircumflex
+ENCODING 285
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+20
+50
+00
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR Gbreve
+ENCODING 286
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+24
+18
+00
+3C
+42
+80
+80
+8E
+82
+82
+46
+3A
+ENDCHAR
+STARTCHAR gbreve
+ENCODING 287
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+48
+30
+00
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR Gdotaccent
+ENCODING 288
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+10
+00
+3C
+42
+80
+80
+8E
+82
+82
+46
+3A
+ENDCHAR
+STARTCHAR gdotaccent
+ENCODING 289
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+20
+00
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR Gcommaaccent
+ENCODING 290
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 7 13 1 -4
+BITMAP
+3C
+42
+80
+80
+8E
+82
+82
+46
+3A
+00
+08
+08
+10
+ENDCHAR
+STARTCHAR gcommaaccent
+ENCODING 291
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 14 1 -3
+BITMAP
+10
+20
+30
+00
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR Hcircumflex
+ENCODING 292
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+00
+82
+82
+82
+82
+FE
+82
+82
+82
+82
+ENDCHAR
+STARTCHAR hcircumflex
+ENCODING 293
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+40
+A0
+00
+80
+80
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR Hbar
+ENCODING 294
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+FE
+82
+82
+FE
+82
+82
+82
+82
+ENDCHAR
+STARTCHAR hbar
+ENCODING 295
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+E0
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR Itilde
+ENCODING 296
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 12 0 0
+BITMAP
+50
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR itilde
+ENCODING 297
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 10 0 0
+BITMAP
+50
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Imacron
+ENCODING 298
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 11 0 0
+BITMAP
+F0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR imacron
+ENCODING 299
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 9 0 0
+BITMAP
+F0
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Ibreve
+ENCODING 300
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 12 0 0
+BITMAP
+90
+60
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR ibreve
+ENCODING 301
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 10 0 0
+BITMAP
+90
+60
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Iogonek
+ENCODING 302
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 0 -3
+BITMAP
+40
+40
+40
+40
+40
+40
+40
+40
+40
+80
+80
+60
+ENDCHAR
+STARTCHAR iogonek
+ENCODING 303
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 3 12 0 -3
+BITMAP
+40
+00
+40
+40
+40
+40
+40
+40
+40
+80
+80
+60
+ENDCHAR
+STARTCHAR Idotaccent
+ENCODING 304
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 11 1 0
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR dotlessi
+ENCODING 305
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 7 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR IJ
+ENCODING 306
+SWIDTH 764 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+81
+81
+81
+81
+81
+81
+91
+91
+8E
+ENDCHAR
+STARTCHAR ij
+ENCODING 307
+SWIDTH 433 0
+DWIDTH 6 0
+BBX 4 12 1 -3
+BITMAP
+90
+00
+90
+90
+90
+90
+90
+90
+90
+10
+10
+20
+ENDCHAR
+STARTCHAR Jcircumflex
+ENCODING 308
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+10
+28
+00
+08
+08
+08
+08
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR jcircumflex
+ENCODING 309
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 3 13 0 -3
+BITMAP
+40
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR Kcommaaccent
+ENCODING 310
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 13 1 -4
+BITMAP
+84
+88
+90
+A0
+E0
+90
+88
+84
+82
+00
+10
+10
+20
+ENDCHAR
+STARTCHAR kcommaaccent
+ENCODING 311
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 13 1 -4
+BITMAP
+80
+80
+90
+A0
+C0
+C0
+A0
+90
+88
+00
+20
+20
+40
+ENDCHAR
+STARTCHAR kgreenlandic
+ENCODING 312
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 7 1 0
+BITMAP
+90
+A0
+C0
+C0
+A0
+90
+88
+ENDCHAR
+STARTCHAR Lacute
+ENCODING 313
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+20
+40
+00
+80
+80
+80
+80
+80
+80
+80
+80
+F8
+ENDCHAR
+STARTCHAR lacute
+ENCODING 314
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 2 12 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Lcommaaccent
+ENCODING 315
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+F8
+00
+20
+20
+40
+ENDCHAR
+STARTCHAR lcommaaccent
+ENCODING 316
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 2 13 0 -4
+BITMAP
+40
+40
+40
+40
+40
+40
+40
+40
+40
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR Lcaron
+ENCODING 317
+SWIDTH 750 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+8180
+8080
+8100
+8000
+8000
+8000
+8000
+8000
+F800
+ENDCHAR
+STARTCHAR lcaron
+ENCODING 318
+SWIDTH 433 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+98
+88
+90
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Ldot
+ENCODING 319
+SWIDTH 806 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+81
+80
+80
+F8
+ENDCHAR
+STARTCHAR ldot
+ENCODING 320
+SWIDTH 489 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+90
+80
+80
+80
+ENDCHAR
+STARTCHAR Lslash
+ENCODING 321
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+40
+40
+50
+60
+C0
+40
+40
+40
+7C
+ENDCHAR
+STARTCHAR lslash
+ENCODING 322
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+40
+40
+60
+C0
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Nacute
+ENCODING 323
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+ENDCHAR
+STARTCHAR nacute
+ENCODING 324
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR Ncommaaccent
+ENCODING 325
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 13 1 -4
+BITMAP
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+00
+10
+10
+20
+ENDCHAR
+STARTCHAR ncommaaccent
+ENCODING 326
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 -4
+BITMAP
+B0
+C8
+88
+88
+88
+88
+88
+00
+20
+20
+40
+ENDCHAR
+STARTCHAR Ncaron
+ENCODING 327
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+28
+10
+00
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+ENDCHAR
+STARTCHAR ncaron
+ENCODING 328
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+50
+20
+00
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR napostrophe
+ENCODING 329
+SWIDTH 767 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+C0
+40
+96
+19
+11
+11
+11
+11
+11
+ENDCHAR
+STARTCHAR Eng
+ENCODING 330
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+02
+02
+04
+ENDCHAR
+STARTCHAR eng
+ENCODING 331
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+B0
+C8
+88
+88
+88
+88
+88
+08
+08
+10
+ENDCHAR
+STARTCHAR Omacron
+ENCODING 332
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+3C
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR omacron
+ENCODING 333
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+78
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Obreve
+ENCODING 334
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+24
+18
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR obreve
+ENCODING 335
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+48
+30
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Ohungarumlaut
+ENCODING 336
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+14
+28
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR ohungarumlaut
+ENCODING 337
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR OE
+ENCODING 338
+SWIDTH 1000 0
+DWIDTH 12 0
+BBX 10 9 1 0
+BITMAP
+3FC0
+4400
+8400
+8400
+87C0
+8400
+8400
+4400
+3FC0
+ENDCHAR
+STARTCHAR oe
+ENCODING 339
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 9 7 1 0
+BITMAP
+7700
+8880
+8880
+8F80
+8800
+8880
+7700
+ENDCHAR
+STARTCHAR Racute
+ENCODING 340
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+10
+20
+00
+F8
+84
+84
+84
+F8
+88
+84
+84
+84
+ENDCHAR
+STARTCHAR racute
+ENCODING 341
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 10 1 0
+BITMAP
+20
+40
+00
+A0
+C0
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Rcommaaccent
+ENCODING 342
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 13 1 -4
+BITMAP
+F8
+84
+84
+84
+F8
+88
+84
+84
+84
+00
+10
+10
+20
+ENDCHAR
+STARTCHAR rcommaaccent
+ENCODING 343
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 11 1 -4
+BITMAP
+A0
+C0
+80
+80
+80
+80
+80
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR Rcaron
+ENCODING 344
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+50
+20
+00
+F8
+84
+84
+84
+F8
+88
+84
+84
+84
+ENDCHAR
+STARTCHAR rcaron
+ENCODING 345
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 10 1 0
+BITMAP
+A0
+40
+00
+A0
+C0
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Sacute
+ENCODING 346
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+10
+20
+00
+78
+84
+80
+60
+18
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR sacute
+ENCODING 347
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 10 1 0
+BITMAP
+20
+40
+00
+60
+90
+80
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR Scircumflex
+ENCODING 348
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+20
+50
+00
+78
+84
+80
+60
+18
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR scircumflex
+ENCODING 349
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 10 1 0
+BITMAP
+20
+50
+00
+60
+90
+80
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR Scedilla
+ENCODING 350
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+78
+84
+80
+60
+18
+04
+84
+84
+78
+10
+10
+60
+ENDCHAR
+STARTCHAR scedilla
+ENCODING 351
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 10 1 -3
+BITMAP
+60
+90
+80
+60
+10
+90
+60
+20
+20
+C0
+ENDCHAR
+STARTCHAR Scaron
+ENCODING 352
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+28
+10
+00
+78
+84
+80
+60
+18
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR scaron
+ENCODING 353
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 10 1 0
+BITMAP
+A0
+40
+00
+60
+90
+80
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 354
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 12 0 -3
+BITMAP
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+08
+08
+30
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 355
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 0 -3
+BITMAP
+40
+40
+E0
+40
+40
+40
+40
+40
+60
+20
+20
+C0
+ENDCHAR
+STARTCHAR Tcaron
+ENCODING 356
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 12 0 0
+BITMAP
+28
+10
+00
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR tcaron
+ENCODING 357
+SWIDTH 486 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+4C
+44
+E8
+40
+40
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR Tbar
+ENCODING 358
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+FE
+10
+10
+10
+38
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR tbar
+ENCODING 359
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+40
+E0
+40
+40
+E0
+40
+40
+60
+ENDCHAR
+STARTCHAR Utilde
+ENCODING 360
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+28
+50
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR utilde
+ENCODING 361
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR Umacron
+ENCODING 362
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR umacron
+ENCODING 363
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+78
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR Ubreve
+ENCODING 364
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+48
+30
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR ubreve
+ENCODING 365
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+48
+30
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR Uring
+ENCODING 366
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 13 1 0
+BITMAP
+30
+48
+30
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uring
+ENCODING 367
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+30
+48
+30
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR Uhungarumlaut
+ENCODING 368
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+28
+50
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uhungarumlaut
+ENCODING 369
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR Uogonek
+ENCODING 370
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+84
+84
+84
+84
+84
+84
+84
+84
+78
+20
+20
+18
+ENDCHAR
+STARTCHAR uogonek
+ENCODING 371
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+88
+88
+98
+78
+20
+20
+18
+ENDCHAR
+STARTCHAR Wcircumflex
+ENCODING 372
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0800
+1400
+0000
+8880
+8880
+8880
+4900
+5500
+5500
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR wcircumflex
+ENCODING 373
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+0800
+1400
+0000
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR Ycircumflex
+ENCODING 374
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+00
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR ycircumflex
+ENCODING 375
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+20
+50
+00
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR Ydieresis
+ENCODING 376
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+28
+00
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR Zacute
+ENCODING 377
+SWIDTH 611 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+FE
+02
+04
+08
+10
+20
+40
+80
+FE
+ENDCHAR
+STARTCHAR zacute
+ENCODING 378
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 10 1 0
+BITMAP
+10
+20
+00
+F0
+10
+20
+40
+40
+80
+F0
+ENDCHAR
+STARTCHAR Zdotaccent
+ENCODING 379
+SWIDTH 611 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+10
+00
+FE
+02
+04
+08
+10
+20
+40
+80
+FE
+ENDCHAR
+STARTCHAR zdotaccent
+ENCODING 380
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+20
+00
+F0
+10
+20
+40
+40
+80
+F0
+ENDCHAR
+STARTCHAR Zcaron
+ENCODING 381
+SWIDTH 611 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+28
+10
+00
+FE
+02
+04
+08
+10
+20
+40
+80
+FE
+ENDCHAR
+STARTCHAR zcaron
+ENCODING 382
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 10 0 0
+BITMAP
+50
+20
+00
+F8
+08
+10
+20
+40
+80
+F8
+ENDCHAR
+STARTCHAR uni0186
+ENCODING 390
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+78
+84
+02
+02
+02
+02
+02
+84
+78
+ENDCHAR
+STARTCHAR uni0189
+ENCODING 393
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+7C
+42
+41
+41
+F1
+41
+41
+42
+7C
+ENDCHAR
+STARTCHAR uni018E
+ENCODING 398
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+04
+04
+04
+FC
+04
+04
+04
+FC
+ENDCHAR
+STARTCHAR florin
+ENCODING 402
+SWIDTH 556 0
+DWIDTH 6 0
+BBX 4 11 1 -2
+BITMAP
+30
+40
+40
+E0
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR uni0197
+ENCODING 407
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+40
+40
+40
+E0
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni019A
+ENCODING 410
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+40
+40
+40
+E0
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni019D
+ENCODING 413
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 12 0 -3
+BITMAP
+41
+61
+51
+51
+49
+45
+45
+43
+41
+40
+40
+80
+ENDCHAR
+STARTCHAR uni019F
+ENCODING 415
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3C
+42
+81
+81
+FF
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR Ohorn
+ENCODING 416
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 9 1 0
+BITMAP
+3CC0
+4240
+8180
+8100
+8100
+8100
+8100
+4200
+3C00
+ENDCHAR
+STARTCHAR ohorn
+ENCODING 417
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 7 1 0
+BITMAP
+76
+8A
+8C
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni01A7
+ENCODING 423
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+84
+04
+18
+60
+80
+84
+84
+78
+ENDCHAR
+STARTCHAR uni01A8
+ENCODING 424
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+60
+90
+10
+60
+80
+90
+60
+ENDCHAR
+STARTCHAR uni01AE
+ENCODING 430
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 12 0 -3
+BITMAP
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+08
+ENDCHAR
+STARTCHAR Uhorn
+ENCODING 431
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 9 1 0
+BITMAP
+87
+85
+86
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uhorn
+ENCODING 432
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 7 1 0
+BITMAP
+8E
+8A
+8C
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni01B5
+ENCODING 437
+SWIDTH 611 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+FE
+02
+04
+08
+38
+20
+40
+80
+FE
+ENDCHAR
+STARTCHAR uni01B6
+ENCODING 438
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+F0
+10
+20
+70
+40
+80
+F0
+ENDCHAR
+STARTCHAR uni01BB
+ENCODING 443
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+10
+F8
+40
+80
+80
+F8
+ENDCHAR
+STARTCHAR uni01BC
+ENCODING 444
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+F8
+80
+80
+F0
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR uni01C0
+ENCODING 448
+SWIDTH 260 0
+DWIDTH 3 0
+BBX 1 12 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uni01C2
+ENCODING 450
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 12 1 -2
+BITMAP
+20
+20
+20
+20
+20
+F8
+20
+F8
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni01C3
+ENCODING 451
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR uni01CD
+ENCODING 461
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+28
+10
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni01CE
+ENCODING 462
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+50
+20
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni01CF
+ENCODING 463
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 0 0
+BITMAP
+A0
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni01D0
+ENCODING 464
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+A0
+40
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni01D1
+ENCODING 465
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+14
+08
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni01D2
+ENCODING 466
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+50
+20
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni01D3
+ENCODING 467
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+28
+10
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni01D4
+ENCODING 468
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+50
+20
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni01D5
+ENCODING 469
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 13 1 0
+BITMAP
+78
+00
+48
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni01D6
+ENCODING 470
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+78
+00
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni01D7
+ENCODING 471
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 14 1 0
+BITMAP
+10
+20
+00
+48
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni01D8
+ENCODING 472
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+10
+20
+00
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni01D9
+ENCODING 473
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 14 1 0
+BITMAP
+28
+10
+00
+48
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni01DA
+ENCODING 474
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+50
+20
+00
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni01DB
+ENCODING 475
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 14 1 0
+BITMAP
+20
+10
+00
+48
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni01DC
+ENCODING 476
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+40
+20
+00
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni01DD
+ENCODING 477
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+08
+F8
+88
+88
+70
+ENDCHAR
+STARTCHAR uni01DE
+ENCODING 478
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+3C
+00
+28
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni01DF
+ENCODING 479
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+78
+00
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni01E0
+ENCODING 480
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+3C
+00
+10
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni01E1
+ENCODING 481
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+78
+00
+20
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni01E2
+ENCODING 482
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1E00
+0000
+1F80
+2800
+2800
+4800
+4F80
+7800
+8800
+8800
+8F80
+ENDCHAR
+STARTCHAR uni01E3
+ENCODING 483
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+1E00
+0000
+7700
+8880
+0880
+7F80
+8800
+8880
+7700
+ENDCHAR
+STARTCHAR uni01E4
+ENCODING 484
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3C
+42
+80
+80
+8E
+8E
+82
+46
+3A
+ENDCHAR
+STARTCHAR uni01E5
+ENCODING 485
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+68
+98
+88
+88
+88
+98
+68
+F8
+88
+70
+ENDCHAR
+STARTCHAR Gcaron
+ENCODING 486
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+28
+10
+00
+3C
+42
+80
+80
+8E
+82
+82
+46
+3A
+ENDCHAR
+STARTCHAR gcaron
+ENCODING 487
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+50
+20
+00
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR uni01E8
+ENCODING 488
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 12 1 0
+BITMAP
+50
+20
+00
+84
+88
+90
+A0
+E0
+90
+88
+84
+82
+ENDCHAR
+STARTCHAR uni01E9
+ENCODING 489
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 12 1 0
+BITMAP
+A0
+40
+00
+80
+80
+90
+A0
+C0
+C0
+A0
+90
+88
+ENDCHAR
+STARTCHAR uni01EA
+ENCODING 490
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 -3
+BITMAP
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+10
+10
+0C
+ENDCHAR
+STARTCHAR uni01EB
+ENCODING 491
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+70
+88
+88
+88
+88
+88
+70
+40
+40
+30
+ENDCHAR
+STARTCHAR uni01EC
+ENCODING 492
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 -3
+BITMAP
+3C
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+10
+10
+0C
+ENDCHAR
+STARTCHAR uni01ED
+ENCODING 493
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+78
+00
+70
+88
+88
+88
+88
+88
+70
+40
+40
+30
+ENDCHAR
+STARTCHAR uni01F0
+ENCODING 496
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 3 13 0 -3
+BITMAP
+A0
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR uni01F4
+ENCODING 500
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+3C
+42
+80
+80
+8E
+82
+82
+46
+3A
+ENDCHAR
+STARTCHAR uni01F5
+ENCODING 501
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+10
+20
+00
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR uni01F8
+ENCODING 504
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+20
+10
+00
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+ENDCHAR
+STARTCHAR uni01F9
+ENCODING 505
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR Aringacute
+ENCODING 506
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 15 1 0
+BITMAP
+08
+10
+00
+10
+28
+10
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR aringacute
+ENCODING 507
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 1 0
+BITMAP
+10
+20
+00
+30
+48
+30
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR AEacute
+ENCODING 508
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0400
+0800
+0000
+1F80
+2800
+2800
+4800
+4F80
+7800
+8800
+8800
+8F80
+ENDCHAR
+STARTCHAR aeacute
+ENCODING 509
+SWIDTH 889 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+0400
+0800
+0000
+7700
+8880
+0880
+7F80
+8800
+8880
+7700
+ENDCHAR
+STARTCHAR Oslashacute
+ENCODING 510
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 14 0 -1
+BITMAP
+0200
+0400
+0000
+0040
+1E80
+2100
+4280
+4480
+4480
+4880
+5080
+2100
+5E00
+8000
+ENDCHAR
+STARTCHAR oslashacute
+ENCODING 511
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+08
+10
+00
+3A
+44
+4C
+54
+64
+44
+B8
+ENDCHAR
+STARTCHAR uni0200
+ENCODING 512
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+50
+28
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni0201
+ENCODING 513
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+A0
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni0202
+ENCODING 514
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+18
+24
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni0203
+ENCODING 515
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+30
+48
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni0204
+ENCODING 516
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+A0
+50
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR uni0205
+ENCODING 517
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+A0
+50
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR uni0206
+ENCODING 518
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+30
+48
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR uni0207
+ENCODING 519
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+30
+48
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR uni0208
+ENCODING 520
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 12 -1 0
+BITMAP
+A0
+50
+00
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni0209
+ENCODING 521
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 10 -1 0
+BITMAP
+A0
+50
+00
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR uni020A
+ENCODING 522
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 12 0 0
+BITMAP
+60
+90
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni020B
+ENCODING 523
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 10 0 0
+BITMAP
+60
+90
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni020C
+ENCODING 524
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+28
+14
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni020D
+ENCODING 525
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+A0
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni020E
+ENCODING 526
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+18
+24
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni020F
+ENCODING 527
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+30
+48
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni0210
+ENCODING 528
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+A0
+50
+00
+F8
+84
+84
+84
+F8
+88
+84
+84
+84
+ENDCHAR
+STARTCHAR uni0211
+ENCODING 529
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+A0
+50
+00
+50
+60
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni0212
+ENCODING 530
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+30
+48
+00
+F8
+84
+84
+84
+F8
+88
+84
+84
+84
+ENDCHAR
+STARTCHAR uni0213
+ENCODING 531
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+60
+90
+00
+50
+60
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni0214
+ENCODING 532
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+50
+28
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni0215
+ENCODING 533
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+A0
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni0216
+ENCODING 534
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+30
+48
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni0217
+ENCODING 535
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+30
+48
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR Scommaaccent
+ENCODING 536
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 13 1 -4
+BITMAP
+78
+84
+80
+60
+18
+04
+84
+84
+78
+00
+10
+10
+20
+ENDCHAR
+STARTCHAR scommaaccent
+ENCODING 537
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 11 1 -4
+BITMAP
+60
+90
+80
+60
+10
+90
+60
+00
+20
+20
+40
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 538
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 13 0 -4
+BITMAP
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+00
+10
+10
+20
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 539
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 13 0 -4
+BITMAP
+40
+40
+E0
+40
+40
+40
+40
+40
+60
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR uni021E
+ENCODING 542
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+28
+10
+00
+82
+82
+82
+82
+FE
+82
+82
+82
+82
+ENDCHAR
+STARTCHAR uni021F
+ENCODING 543
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+A0
+40
+00
+80
+80
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR uni0226
+ENCODING 550
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+10
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni0227
+ENCODING 551
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+20
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni0228
+ENCODING 552
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+10
+10
+60
+ENDCHAR
+STARTCHAR uni0229
+ENCODING 553
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+70
+88
+88
+F8
+80
+88
+70
+10
+10
+60
+ENDCHAR
+STARTCHAR uni022A
+ENCODING 554
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3C
+00
+24
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni022B
+ENCODING 555
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+78
+00
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni022C
+ENCODING 556
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+3C
+00
+14
+28
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni022D
+ENCODING 557
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+78
+00
+28
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni022E
+ENCODING 558
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+08
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni022F
+ENCODING 559
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+20
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni0230
+ENCODING 560
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3C
+00
+08
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni0231
+ENCODING 561
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+78
+00
+20
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni0232
+ENCODING 562
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+3C
+00
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR uni0233
+ENCODING 563
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+78
+00
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR uni0250
+ENCODING 592
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+B8
+44
+44
+78
+40
+44
+38
+ENDCHAR
+STARTCHAR uni0254
+ENCODING 596
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+08
+08
+08
+88
+70
+ENDCHAR
+STARTCHAR uni0258
+ENCODING 600
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+F8
+08
+88
+70
+ENDCHAR
+STARTCHAR uni0259
+ENCODING 601
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+08
+F8
+88
+88
+70
+ENDCHAR
+STARTCHAR uni025F
+ENCODING 607
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 9 0 -2
+BITMAP
+20
+20
+20
+20
+20
+20
+70
+20
+C0
+ENDCHAR
+STARTCHAR uni0265
+ENCODING 613
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 -2
+BITMAP
+88
+88
+88
+88
+88
+98
+68
+08
+08
+ENDCHAR
+STARTCHAR uni0275
+ENCODING 629
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+F8
+88
+88
+70
+ENDCHAR
+STARTCHAR uni0279
+ENCODING 633
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+20
+20
+20
+20
+20
+60
+A0
+ENDCHAR
+STARTCHAR uni0287
+ENCODING 647
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+C0
+40
+40
+40
+40
+40
+E0
+40
+40
+ENDCHAR
+STARTCHAR uni0288
+ENCODING 648
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 0 -3
+BITMAP
+40
+40
+E0
+40
+40
+40
+40
+40
+40
+40
+40
+20
+ENDCHAR
+STARTCHAR uni0289
+ENCODING 649
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+88
+88
+88
+F8
+88
+98
+68
+ENDCHAR
+STARTCHAR uni028C
+ENCODING 652
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+20
+20
+50
+50
+88
+88
+88
+ENDCHAR
+STARTCHAR uni028D
+ENCODING 653
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 7 0 0
+BITMAP
+2200
+2200
+5500
+4900
+4900
+8880
+8880
+ENDCHAR
+STARTCHAR uni028E
+ENCODING 654
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+08
+10
+20
+20
+50
+50
+48
+88
+88
+88
+ENDCHAR
+STARTCHAR uni029E
+ENCODING 670
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 9 1 -2
+BITMAP
+88
+48
+28
+18
+18
+28
+48
+08
+08
+ENDCHAR
+STARTCHAR uni02BB
+ENCODING 699
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 2 3 0 6
+BITMAP
+40
+80
+C0
+ENDCHAR
+STARTCHAR afii57929
+ENCODING 700
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 2 3 1 6
+BITMAP
+C0
+40
+80
+ENDCHAR
+STARTCHAR afii64937
+ENCODING 701
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 2 3 1 6
+BITMAP
+C0
+80
+40
+ENDCHAR
+STARTCHAR circumflex
+ENCODING 710
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 3 2 0 8
+BITMAP
+40
+A0
+ENDCHAR
+STARTCHAR caron
+ENCODING 711
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 3 2 0 8
+BITMAP
+A0
+40
+ENDCHAR
+STARTCHAR uni02C8
+ENCODING 712
+SWIDTH 191 0
+DWIDTH 3 0
+BBX 1 3 1 6
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR macron
+ENCODING 713
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 0 8
+BITMAP
+F0
+ENDCHAR
+STARTCHAR uni02CA
+ENCODING 714
+SWIDTH 333 0
+DWIDTH 2 0
+BBX 2 2 0 8
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR uni02CB
+ENCODING 715
+SWIDTH 333 0
+DWIDTH 2 0
+BBX 2 2 0 8
+BITMAP
+80
+40
+ENDCHAR
+STARTCHAR uni02CD
+ENCODING 717
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 1 0 -2
+BITMAP
+F0
+ENDCHAR
+STARTCHAR uni02CE
+ENCODING 718
+SWIDTH 333 0
+DWIDTH 2 0
+BBX 2 2 0 -3
+BITMAP
+80
+40
+ENDCHAR
+STARTCHAR uni02CF
+ENCODING 719
+SWIDTH 333 0
+DWIDTH 2 0
+BBX 2 2 0 -3
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR breve
+ENCODING 728
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 2 0 8
+BITMAP
+90
+60
+ENDCHAR
+STARTCHAR dotaccent
+ENCODING 729
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 1 1 1 8
+BITMAP
+80
+ENDCHAR
+STARTCHAR ring
+ENCODING 730
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 3 0 7
+BITMAP
+60
+90
+60
+ENDCHAR
+STARTCHAR ogonek
+ENCODING 731
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 3 4 0 -3
+BITMAP
+40
+80
+80
+60
+ENDCHAR
+STARTCHAR tilde
+ENCODING 732
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 2 0 8
+BITMAP
+50
+A0
+ENDCHAR
+STARTCHAR hungarumlaut
+ENCODING 733
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 2 0 8
+BITMAP
+50
+A0
+ENDCHAR
+STARTCHAR uni02EE
+ENCODING 750
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 3 0 6
+BITMAP
+D8
+48
+90
+ENDCHAR
+STARTCHAR uni037E
+ENCODING 894
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 2 8 0 -2
+BITMAP
+40
+00
+00
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR tonos
+ENCODING 900
+SWIDTH 333 0
+DWIDTH 2 0
+BBX 2 2 0 8
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR dieresistonos
+ENCODING 901
+SWIDTH 333 0
+DWIDTH 3 0
+BBX 3 4 0 8
+BITMAP
+20
+40
+00
+A0
+ENDCHAR
+STARTCHAR anoteleia
+ENCODING 903
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 1 1 3
+BITMAP
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 956
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+88
+88
+98
+E8
+80
+80
+80
+ENDCHAR
+STARTCHAR uni1E00
+ENCODING 7680
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 13 1 -4
+BITMAP
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+00
+18
+24
+18
+ENDCHAR
+STARTCHAR uni1E01
+ENCODING 7681
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 11 1 -4
+BITMAP
+70
+88
+08
+78
+88
+88
+74
+00
+30
+48
+30
+ENDCHAR
+STARTCHAR uni1E02
+ENCODING 7682
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+00
+F8
+84
+84
+84
+F8
+84
+84
+84
+F8
+ENDCHAR
+STARTCHAR uni1E03
+ENCODING 7683
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+40
+00
+80
+80
+B0
+C8
+88
+88
+88
+C8
+B0
+ENDCHAR
+STARTCHAR uni1E04
+ENCODING 7684
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 -2
+BITMAP
+F8
+84
+84
+84
+F8
+84
+84
+84
+F8
+00
+20
+ENDCHAR
+STARTCHAR uni1E05
+ENCODING 7685
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 -2
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+C8
+B0
+00
+20
+ENDCHAR
+STARTCHAR uni1E06
+ENCODING 7686
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 -2
+BITMAP
+F8
+84
+84
+84
+F8
+84
+84
+84
+F8
+00
+78
+ENDCHAR
+STARTCHAR uni1E07
+ENCODING 7687
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 -2
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+C8
+B0
+00
+F0
+ENDCHAR
+STARTCHAR uni1E08
+ENCODING 7688
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 15 1 -3
+BITMAP
+08
+10
+00
+3C
+42
+80
+80
+80
+80
+80
+42
+3C
+08
+08
+30
+ENDCHAR
+STARTCHAR uni1E09
+ENCODING 7689
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+10
+20
+00
+70
+88
+80
+80
+80
+88
+70
+20
+10
+60
+ENDCHAR
+STARTCHAR uni1E0A
+ENCODING 7690
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+10
+00
+F8
+84
+82
+82
+82
+82
+82
+84
+F8
+ENDCHAR
+STARTCHAR uni1E0B
+ENCODING 7691
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+10
+00
+08
+08
+68
+98
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni1E0C
+ENCODING 7692
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+F8
+84
+82
+82
+82
+82
+82
+84
+F8
+00
+10
+ENDCHAR
+STARTCHAR uni1E0D
+ENCODING 7693
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 -2
+BITMAP
+08
+08
+68
+98
+88
+88
+88
+98
+68
+00
+20
+ENDCHAR
+STARTCHAR uni1E0E
+ENCODING 7694
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+F8
+84
+82
+82
+82
+82
+82
+84
+F8
+00
+78
+ENDCHAR
+STARTCHAR uni1E0F
+ENCODING 7695
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 -2
+BITMAP
+08
+08
+68
+98
+88
+88
+88
+98
+68
+00
+78
+ENDCHAR
+STARTCHAR uni1E10
+ENCODING 7696
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+F8
+84
+82
+82
+82
+82
+82
+84
+F8
+10
+10
+60
+ENDCHAR
+STARTCHAR uni1E11
+ENCODING 7697
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+08
+08
+68
+98
+88
+88
+88
+98
+68
+10
+10
+60
+ENDCHAR
+STARTCHAR uni1E12
+ENCODING 7698
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+F8
+84
+82
+82
+82
+82
+82
+84
+F8
+00
+10
+28
+ENDCHAR
+STARTCHAR uni1E13
+ENCODING 7699
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+08
+08
+68
+98
+88
+88
+88
+98
+68
+00
+20
+50
+ENDCHAR
+STARTCHAR uni1E14
+ENCODING 7700
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 14 1 0
+BITMAP
+20
+10
+00
+78
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR uni1E15
+ENCODING 7701
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+40
+20
+00
+78
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR uni1E16
+ENCODING 7702
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 14 1 0
+BITMAP
+10
+20
+00
+78
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR uni1E17
+ENCODING 7703
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+10
+20
+00
+78
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR uni1E18
+ENCODING 7704
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+00
+20
+50
+ENDCHAR
+STARTCHAR uni1E19
+ENCODING 7705
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+70
+88
+88
+F8
+80
+88
+70
+00
+20
+50
+ENDCHAR
+STARTCHAR uni1E1A
+ENCODING 7706
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+00
+50
+A0
+ENDCHAR
+STARTCHAR uni1E1B
+ENCODING 7707
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+70
+88
+88
+F8
+80
+88
+70
+00
+50
+A0
+ENDCHAR
+STARTCHAR uni1E1C
+ENCODING 7708
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 15 1 -3
+BITMAP
+90
+60
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+10
+10
+60
+ENDCHAR
+STARTCHAR uni1E1D
+ENCODING 7709
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+48
+30
+00
+70
+88
+88
+F8
+80
+88
+70
+10
+10
+60
+ENDCHAR
+STARTCHAR uni1E1E
+ENCODING 7710
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+00
+FC
+80
+80
+80
+F8
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uni1E1F
+ENCODING 7711
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 11 0 0
+BITMAP
+20
+00
+30
+40
+E0
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni1E20
+ENCODING 7712
+SWIDTH 778 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+3C
+00
+3C
+42
+80
+80
+8E
+82
+82
+46
+3A
+ENDCHAR
+STARTCHAR uni1E21
+ENCODING 7713
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+78
+00
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR uni1E22
+ENCODING 7714
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+10
+00
+82
+82
+82
+82
+FE
+82
+82
+82
+82
+ENDCHAR
+STARTCHAR uni1E23
+ENCODING 7715
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+40
+00
+80
+80
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR uni1E24
+ENCODING 7716
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+82
+82
+82
+82
+FE
+82
+82
+82
+82
+00
+10
+ENDCHAR
+STARTCHAR uni1E25
+ENCODING 7717
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 -2
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+88
+88
+00
+20
+ENDCHAR
+STARTCHAR uni1E26
+ENCODING 7718
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+28
+00
+82
+82
+82
+82
+FE
+82
+82
+82
+82
+ENDCHAR
+STARTCHAR uni1E27
+ENCODING 7719
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+A0
+00
+80
+80
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR uni1E28
+ENCODING 7720
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+82
+82
+82
+82
+FE
+82
+82
+82
+92
+08
+08
+30
+ENDCHAR
+STARTCHAR uni1E29
+ENCODING 7721
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+88
+A8
+10
+10
+60
+ENDCHAR
+STARTCHAR uni1E2A
+ENCODING 7722
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+82
+82
+82
+82
+FE
+82
+82
+82
+82
+00
+24
+18
+ENDCHAR
+STARTCHAR uni1E2B
+ENCODING 7723
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+88
+88
+00
+48
+30
+ENDCHAR
+STARTCHAR uni1E2C
+ENCODING 7724
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 12 -1 -3
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+20
+20
+00
+50
+A0
+ENDCHAR
+STARTCHAR uni1E2D
+ENCODING 7725
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 4 12 -1 -3
+BITMAP
+20
+00
+20
+20
+20
+20
+20
+20
+20
+00
+50
+A0
+ENDCHAR
+STARTCHAR uni1E2E
+ENCODING 7726
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 14 0 0
+BITMAP
+20
+40
+00
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni1E2F
+ENCODING 7727
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 0 0
+BITMAP
+20
+40
+00
+A0
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni1E30
+ENCODING 7728
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 12 1 0
+BITMAP
+10
+20
+00
+84
+88
+90
+A0
+E0
+90
+88
+84
+82
+ENDCHAR
+STARTCHAR uni1E31
+ENCODING 7729
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 12 1 0
+BITMAP
+20
+40
+00
+80
+80
+90
+A0
+C0
+C0
+A0
+90
+88
+ENDCHAR
+STARTCHAR uni1E32
+ENCODING 7730
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 11 1 -2
+BITMAP
+84
+88
+90
+A0
+E0
+90
+88
+84
+82
+00
+10
+ENDCHAR
+STARTCHAR uni1E33
+ENCODING 7731
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 11 1 -2
+BITMAP
+80
+80
+90
+A0
+C0
+C0
+A0
+90
+88
+00
+20
+ENDCHAR
+STARTCHAR uni1E34
+ENCODING 7732
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 11 1 -2
+BITMAP
+84
+88
+90
+A0
+E0
+90
+88
+84
+82
+00
+78
+ENDCHAR
+STARTCHAR uni1E35
+ENCODING 7733
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 11 1 -2
+BITMAP
+80
+80
+90
+A0
+C0
+C0
+A0
+90
+88
+00
+F0
+ENDCHAR
+STARTCHAR uni1E36
+ENCODING 7734
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+F8
+00
+20
+ENDCHAR
+STARTCHAR uni1E37
+ENCODING 7735
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 1 11 1 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR uni1E38
+ENCODING 7736
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 0 -2
+BITMAP
+F0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+7C
+00
+10
+ENDCHAR
+STARTCHAR uni1E39
+ENCODING 7737
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 4 13 0 -2
+BITMAP
+F0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+00
+40
+ENDCHAR
+STARTCHAR uni1E3A
+ENCODING 7738
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+F8
+00
+F0
+ENDCHAR
+STARTCHAR uni1E3B
+ENCODING 7739
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 4 11 0 -2
+BITMAP
+40
+40
+40
+40
+40
+40
+40
+40
+40
+00
+F0
+ENDCHAR
+STARTCHAR uni1E3C
+ENCODING 7740
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+F8
+00
+20
+50
+ENDCHAR
+STARTCHAR uni1E3D
+ENCODING 7741
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 3 12 0 -3
+BITMAP
+40
+40
+40
+40
+40
+40
+40
+40
+40
+00
+40
+A0
+ENDCHAR
+STARTCHAR uni1E3E
+ENCODING 7742
+SWIDTH 833 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0400
+0800
+0000
+8080
+C180
+C180
+A280
+A280
+9480
+9480
+8880
+8880
+ENDCHAR
+STARTCHAR uni1E3F
+ENCODING 7743
+SWIDTH 833 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+08
+10
+00
+A4
+DA
+92
+92
+92
+92
+92
+ENDCHAR
+STARTCHAR uni1E40
+ENCODING 7744
+SWIDTH 833 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+0800
+0000
+8080
+C180
+C180
+A280
+A280
+9480
+9480
+8880
+8880
+ENDCHAR
+STARTCHAR uni1E41
+ENCODING 7745
+SWIDTH 833 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+10
+00
+A4
+DA
+92
+92
+92
+92
+92
+ENDCHAR
+STARTCHAR uni1E42
+ENCODING 7746
+SWIDTH 833 0
+DWIDTH 11 0
+BBX 9 11 1 -2
+BITMAP
+8080
+C180
+C180
+A280
+A280
+9480
+9480
+8880
+8880
+0000
+0800
+ENDCHAR
+STARTCHAR uni1E43
+ENCODING 7747
+SWIDTH 833 0
+DWIDTH 9 0
+BBX 7 9 1 -2
+BITMAP
+A4
+DA
+92
+92
+92
+92
+92
+00
+10
+ENDCHAR
+STARTCHAR uni1E44
+ENCODING 7748
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+10
+00
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+ENDCHAR
+STARTCHAR uni1E45
+ENCODING 7749
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+20
+00
+B0
+C8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR uni1E46
+ENCODING 7750
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+00
+10
+ENDCHAR
+STARTCHAR uni1E47
+ENCODING 7751
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 -2
+BITMAP
+B0
+C8
+88
+88
+88
+88
+88
+00
+20
+ENDCHAR
+STARTCHAR uni1E48
+ENCODING 7752
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+00
+3C
+ENDCHAR
+STARTCHAR uni1E49
+ENCODING 7753
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 -2
+BITMAP
+B0
+C8
+88
+88
+88
+88
+88
+00
+78
+ENDCHAR
+STARTCHAR uni1E4A
+ENCODING 7754
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+82
+C2
+A2
+A2
+92
+8A
+8A
+86
+82
+00
+10
+28
+ENDCHAR
+STARTCHAR uni1E4B
+ENCODING 7755
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+B0
+C8
+88
+88
+88
+88
+88
+00
+20
+50
+ENDCHAR
+STARTCHAR uni1E4C
+ENCODING 7756
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 15 1 0
+BITMAP
+08
+10
+00
+14
+28
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni1E4D
+ENCODING 7757
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 0
+BITMAP
+10
+20
+00
+28
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni1E4E
+ENCODING 7758
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+14
+00
+14
+28
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni1E4F
+ENCODING 7759
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+50
+00
+28
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni1E50
+ENCODING 7760
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+10
+08
+00
+3C
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni1E51
+ENCODING 7761
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+40
+20
+00
+78
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni1E52
+ENCODING 7762
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+08
+10
+00
+3C
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni1E53
+ENCODING 7763
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 0
+BITMAP
+10
+20
+00
+78
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni1E54
+ENCODING 7764
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+10
+20
+00
+F8
+84
+84
+84
+F8
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uni1E55
+ENCODING 7765
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+10
+20
+00
+B0
+C8
+88
+88
+88
+C8
+B0
+80
+80
+80
+ENDCHAR
+STARTCHAR uni1E56
+ENCODING 7766
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+00
+F8
+84
+84
+84
+F8
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uni1E57
+ENCODING 7767
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+20
+00
+B0
+C8
+88
+88
+88
+C8
+B0
+80
+80
+80
+ENDCHAR
+STARTCHAR uni1E58
+ENCODING 7768
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+00
+F8
+84
+84
+84
+F8
+88
+84
+84
+84
+ENDCHAR
+STARTCHAR uni1E59
+ENCODING 7769
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 9 1 0
+BITMAP
+40
+00
+A0
+C0
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uni1E5A
+ENCODING 7770
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 11 1 -2
+BITMAP
+F8
+84
+84
+84
+F8
+88
+84
+84
+84
+00
+10
+ENDCHAR
+STARTCHAR uni1E5B
+ENCODING 7771
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 9 1 -2
+BITMAP
+A0
+C0
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR uni1E5C
+ENCODING 7772
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 13 1 -2
+BITMAP
+78
+00
+F8
+84
+84
+84
+F8
+88
+84
+84
+84
+00
+10
+ENDCHAR
+STARTCHAR uni1E5D
+ENCODING 7773
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 11 0 -2
+BITMAP
+F0
+00
+50
+60
+40
+40
+40
+40
+40
+00
+40
+ENDCHAR
+STARTCHAR uni1E5E
+ENCODING 7774
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 11 1 -2
+BITMAP
+F8
+84
+84
+84
+F8
+88
+84
+84
+84
+00
+78
+ENDCHAR
+STARTCHAR uni1E5F
+ENCODING 7775
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 9 0 -2
+BITMAP
+50
+60
+40
+40
+40
+40
+40
+00
+F0
+ENDCHAR
+STARTCHAR uni1E60
+ENCODING 7776
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+00
+78
+84
+80
+60
+18
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR uni1E61
+ENCODING 7777
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+20
+00
+60
+90
+80
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR uni1E62
+ENCODING 7778
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 -2
+BITMAP
+78
+84
+80
+60
+18
+04
+84
+84
+78
+00
+10
+ENDCHAR
+STARTCHAR uni1E63
+ENCODING 7779
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 9 1 -2
+BITMAP
+60
+90
+80
+60
+10
+90
+60
+00
+20
+ENDCHAR
+STARTCHAR uni1E64
+ENCODING 7780
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 14 1 0
+BITMAP
+10
+00
+10
+20
+00
+78
+84
+80
+60
+18
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR uni1E65
+ENCODING 7781
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 12 1 0
+BITMAP
+20
+00
+20
+40
+00
+60
+90
+80
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR uni1E66
+ENCODING 7782
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 14 1 0
+BITMAP
+10
+00
+28
+10
+00
+78
+84
+80
+60
+18
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR uni1E67
+ENCODING 7783
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 12 1 0
+BITMAP
+40
+00
+A0
+40
+00
+60
+90
+80
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR uni1E68
+ENCODING 7784
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 13 1 -2
+BITMAP
+20
+00
+78
+84
+80
+60
+18
+04
+84
+84
+78
+00
+10
+ENDCHAR
+STARTCHAR uni1E69
+ENCODING 7785
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 11 1 -2
+BITMAP
+40
+00
+60
+90
+80
+60
+10
+90
+60
+00
+20
+ENDCHAR
+STARTCHAR uni1E6A
+ENCODING 7786
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+10
+00
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR uni1E6B
+ENCODING 7787
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+40
+00
+40
+40
+E0
+40
+40
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR uni1E6C
+ENCODING 7788
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 11 0 -2
+BITMAP
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+00
+10
+ENDCHAR
+STARTCHAR uni1E6D
+ENCODING 7789
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 11 0 -2
+BITMAP
+40
+40
+E0
+40
+40
+40
+40
+40
+60
+00
+40
+ENDCHAR
+STARTCHAR uni1E6E
+ENCODING 7790
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 11 0 -2
+BITMAP
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+00
+3C
+ENDCHAR
+STARTCHAR uni1E6F
+ENCODING 7791
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 4 11 0 -2
+BITMAP
+40
+40
+E0
+40
+40
+40
+40
+40
+60
+00
+F0
+ENDCHAR
+STARTCHAR uni1E70
+ENCODING 7792
+SWIDTH 611 0
+DWIDTH 7 0
+BBX 7 12 0 -3
+BITMAP
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+00
+10
+28
+ENDCHAR
+STARTCHAR uni1E71
+ENCODING 7793
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 12 0 -3
+BITMAP
+40
+40
+E0
+40
+40
+40
+40
+40
+60
+00
+40
+A0
+ENDCHAR
+STARTCHAR uni1E72
+ENCODING 7794
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 11 1 -2
+BITMAP
+84
+84
+84
+84
+84
+84
+84
+84
+78
+00
+28
+ENDCHAR
+STARTCHAR uni1E73
+ENCODING 7795
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 -2
+BITMAP
+88
+88
+88
+88
+88
+98
+68
+00
+50
+ENDCHAR
+STARTCHAR uni1E74
+ENCODING 7796
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+84
+84
+84
+84
+84
+84
+84
+84
+78
+00
+28
+50
+ENDCHAR
+STARTCHAR uni1E75
+ENCODING 7797
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+88
+88
+98
+68
+00
+50
+A0
+ENDCHAR
+STARTCHAR uni1E76
+ENCODING 7798
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 12 1 -3
+BITMAP
+84
+84
+84
+84
+84
+84
+84
+84
+78
+00
+10
+28
+ENDCHAR
+STARTCHAR uni1E77
+ENCODING 7799
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+88
+88
+98
+68
+00
+20
+50
+ENDCHAR
+STARTCHAR uni1E78
+ENCODING 7800
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 15 1 0
+BITMAP
+10
+20
+00
+28
+50
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni1E79
+ENCODING 7801
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 0
+BITMAP
+10
+20
+00
+28
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni1E7A
+ENCODING 7802
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 13 1 0
+BITMAP
+28
+00
+78
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni1E7B
+ENCODING 7803
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+50
+00
+78
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni1E7C
+ENCODING 7804
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+14
+28
+00
+82
+82
+44
+44
+44
+28
+28
+10
+10
+ENDCHAR
+STARTCHAR uni1E7D
+ENCODING 7805
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+88
+88
+88
+50
+50
+20
+20
+ENDCHAR
+STARTCHAR uni1E7E
+ENCODING 7806
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+82
+82
+44
+44
+44
+28
+28
+10
+10
+00
+10
+ENDCHAR
+STARTCHAR uni1E7F
+ENCODING 7807
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 9 1 -2
+BITMAP
+88
+88
+88
+50
+50
+20
+20
+00
+20
+ENDCHAR
+STARTCHAR Wgrave
+ENCODING 7808
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+1000
+0800
+0000
+8880
+8880
+8880
+4900
+5500
+5500
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR wgrave
+ENCODING 7809
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+1000
+0800
+0000
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR Wacute
+ENCODING 7810
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0400
+0800
+0000
+8880
+8880
+8880
+4900
+5500
+5500
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR wacute
+ENCODING 7811
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+0400
+0800
+0000
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR Wdieresis
+ENCODING 7812
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1400
+0000
+8880
+8880
+8880
+4900
+5500
+5500
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR wdieresis
+ENCODING 7813
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+1400
+0000
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR uni1E86
+ENCODING 7814
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+0800
+0000
+8880
+8880
+8880
+4900
+5500
+5500
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR uni1E87
+ENCODING 7815
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+0800
+0000
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR uni1E88
+ENCODING 7816
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 9 11 1 -2
+BITMAP
+8880
+8880
+8880
+4900
+5500
+5500
+2200
+2200
+2200
+0000
+0800
+ENDCHAR
+STARTCHAR uni1E89
+ENCODING 7817
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 9 0 -2
+BITMAP
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+0000
+0800
+ENDCHAR
+STARTCHAR uni1E8A
+ENCODING 7818
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+10
+00
+82
+44
+44
+28
+10
+28
+44
+44
+82
+ENDCHAR
+STARTCHAR uni1E8B
+ENCODING 7819
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+10
+00
+84
+48
+30
+30
+48
+84
+84
+ENDCHAR
+STARTCHAR uni1E8C
+ENCODING 7820
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+28
+00
+82
+44
+44
+28
+10
+28
+44
+44
+82
+ENDCHAR
+STARTCHAR uni1E8D
+ENCODING 7821
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+28
+00
+84
+48
+30
+30
+48
+84
+84
+ENDCHAR
+STARTCHAR uni1E8E
+ENCODING 7822
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+10
+00
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR uni1E8F
+ENCODING 7823
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+20
+00
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR uni1E90
+ENCODING 7824
+SWIDTH 611 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+00
+FE
+02
+04
+08
+10
+20
+40
+80
+FE
+ENDCHAR
+STARTCHAR uni1E91
+ENCODING 7825
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 10 1 0
+BITMAP
+20
+50
+00
+F0
+10
+20
+40
+40
+80
+F0
+ENDCHAR
+STARTCHAR uni1E92
+ENCODING 7826
+SWIDTH 611 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+FE
+02
+04
+08
+10
+20
+40
+80
+FE
+00
+10
+ENDCHAR
+STARTCHAR uni1E93
+ENCODING 7827
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 9 1 -2
+BITMAP
+F0
+10
+20
+40
+40
+80
+F0
+00
+40
+ENDCHAR
+STARTCHAR uni1E94
+ENCODING 7828
+SWIDTH 611 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+FE
+02
+04
+08
+10
+20
+40
+80
+FE
+00
+78
+ENDCHAR
+STARTCHAR uni1E95
+ENCODING 7829
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 4 9 1 -2
+BITMAP
+F0
+10
+20
+40
+40
+80
+F0
+00
+F0
+ENDCHAR
+STARTCHAR uni1E96
+ENCODING 7830
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 11 1 -2
+BITMAP
+80
+80
+B0
+C8
+88
+88
+88
+88
+88
+00
+78
+ENDCHAR
+STARTCHAR uni1E97
+ENCODING 7831
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+A0
+00
+40
+40
+E0
+40
+40
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR uni1E98
+ENCODING 7832
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+0C00
+1200
+0C00
+0000
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR uni1E99
+ENCODING 7833
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 14 1 -3
+BITMAP
+30
+48
+30
+00
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR uni1EA0
+ENCODING 7840
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+00
+10
+ENDCHAR
+STARTCHAR uni1EA1
+ENCODING 7841
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 9 1 -2
+BITMAP
+70
+88
+08
+78
+88
+88
+74
+00
+10
+ENDCHAR
+STARTCHAR uni1EA4
+ENCODING 7844
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 15 1 0
+BITMAP
+08
+10
+00
+10
+28
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni1EA5
+ENCODING 7845
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 1 0
+BITMAP
+10
+20
+00
+20
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni1EA6
+ENCODING 7846
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 15 1 0
+BITMAP
+20
+10
+00
+10
+28
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni1EA7
+ENCODING 7847
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 1 0
+BITMAP
+40
+20
+00
+20
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni1EAA
+ENCODING 7850
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 15 1 0
+BITMAP
+14
+28
+00
+10
+28
+00
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni1EAB
+ENCODING 7851
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 1 0
+BITMAP
+28
+50
+00
+20
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni1EAC
+ENCODING 7852
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 14 1 -2
+BITMAP
+10
+28
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+00
+10
+ENDCHAR
+STARTCHAR uni1EAD
+ENCODING 7853
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 1 -2
+BITMAP
+20
+50
+00
+70
+88
+08
+78
+88
+88
+74
+00
+10
+ENDCHAR
+STARTCHAR uni1EAE
+ENCODING 7854
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 15 1 0
+BITMAP
+08
+10
+00
+24
+18
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni1EAF
+ENCODING 7855
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 1 0
+BITMAP
+10
+20
+00
+48
+30
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni1EB0
+ENCODING 7856
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 15 1 0
+BITMAP
+20
+10
+00
+24
+18
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni1EB1
+ENCODING 7857
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 1 0
+BITMAP
+20
+10
+00
+48
+30
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni1EB4
+ENCODING 7860
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 15 1 0
+BITMAP
+14
+28
+00
+24
+18
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni1EB5
+ENCODING 7861
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 13 1 0
+BITMAP
+28
+50
+00
+48
+30
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR uni1EB6
+ENCODING 7862
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 14 1 -2
+BITMAP
+24
+18
+00
+10
+28
+28
+44
+44
+7C
+82
+82
+82
+00
+10
+ENDCHAR
+STARTCHAR uni1EB7
+ENCODING 7863
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 6 12 1 -2
+BITMAP
+48
+30
+00
+70
+88
+08
+78
+88
+88
+74
+00
+10
+ENDCHAR
+STARTCHAR uni1EB8
+ENCODING 7864
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 11 1 -2
+BITMAP
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+00
+20
+ENDCHAR
+STARTCHAR uni1EB9
+ENCODING 7865
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 -2
+BITMAP
+70
+88
+88
+F8
+80
+88
+70
+00
+20
+ENDCHAR
+STARTCHAR uni1EBC
+ENCODING 7868
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+28
+50
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR uni1EBD
+ENCODING 7869
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR uni1EBE
+ENCODING 7870
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 15 1 0
+BITMAP
+10
+20
+00
+10
+28
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR uni1EBF
+ENCODING 7871
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 0
+BITMAP
+10
+20
+00
+20
+50
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR uni1EC0
+ENCODING 7872
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 15 1 0
+BITMAP
+20
+10
+00
+10
+28
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR uni1EC1
+ENCODING 7873
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 0
+BITMAP
+40
+20
+00
+20
+50
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR uni1EC4
+ENCODING 7876
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 15 1 0
+BITMAP
+28
+50
+00
+10
+28
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+ENDCHAR
+STARTCHAR uni1EC5
+ENCODING 7877
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 0
+BITMAP
+28
+50
+00
+20
+50
+00
+70
+88
+88
+F8
+80
+88
+70
+ENDCHAR
+STARTCHAR uni1EC6
+ENCODING 7878
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 14 1 -2
+BITMAP
+20
+50
+00
+FC
+80
+80
+80
+FC
+80
+80
+80
+FC
+00
+20
+ENDCHAR
+STARTCHAR uni1EC7
+ENCODING 7879
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -2
+BITMAP
+20
+50
+00
+70
+88
+88
+F8
+80
+88
+70
+00
+20
+ENDCHAR
+STARTCHAR uni1ECA
+ENCODING 7882
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 11 1 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR uni1ECB
+ENCODING 7883
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 1 11 1 -2
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR uni1ECC
+ENCODING 7884
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 11 1 -2
+BITMAP
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+00
+08
+ENDCHAR
+STARTCHAR uni1ECD
+ENCODING 7885
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 -2
+BITMAP
+70
+88
+88
+88
+88
+88
+70
+00
+20
+ENDCHAR
+STARTCHAR uni1ED0
+ENCODING 7888
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 15 1 0
+BITMAP
+08
+10
+00
+08
+14
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni1ED1
+ENCODING 7889
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 0
+BITMAP
+10
+20
+00
+20
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni1ED2
+ENCODING 7890
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 15 1 0
+BITMAP
+10
+08
+00
+08
+14
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni1ED3
+ENCODING 7891
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 0
+BITMAP
+40
+20
+00
+20
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni1ED6
+ENCODING 7894
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 15 1 0
+BITMAP
+14
+28
+00
+08
+14
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+ENDCHAR
+STARTCHAR uni1ED7
+ENCODING 7895
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 13 1 0
+BITMAP
+28
+50
+00
+20
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni1ED8
+ENCODING 7896
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 8 14 1 -2
+BITMAP
+08
+14
+00
+3C
+42
+81
+81
+81
+81
+81
+42
+3C
+00
+08
+ENDCHAR
+STARTCHAR uni1ED9
+ENCODING 7897
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -2
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+88
+88
+70
+00
+20
+ENDCHAR
+STARTCHAR uni1EDA
+ENCODING 7898
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 12 1 0
+BITMAP
+0200
+0400
+0000
+3CC0
+4240
+8180
+8100
+8100
+8100
+8100
+4200
+3C00
+ENDCHAR
+STARTCHAR uni1EDB
+ENCODING 7899
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 1 0
+BITMAP
+08
+10
+00
+76
+8A
+8C
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni1EDC
+ENCODING 7900
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 12 1 0
+BITMAP
+0800
+0400
+0000
+3CC0
+4240
+8180
+8100
+8100
+8100
+8100
+4200
+3C00
+ENDCHAR
+STARTCHAR uni1EDD
+ENCODING 7901
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 1 0
+BITMAP
+20
+10
+00
+76
+8A
+8C
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni1EE0
+ENCODING 7904
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 12 1 0
+BITMAP
+0500
+0A00
+0000
+3CC0
+4240
+8180
+8100
+8100
+8100
+8100
+4200
+3C00
+ENDCHAR
+STARTCHAR uni1EE1
+ENCODING 7905
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 1 0
+BITMAP
+14
+28
+00
+76
+8A
+8C
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR uni1EE2
+ENCODING 7906
+SWIDTH 778 0
+DWIDTH 10 0
+BBX 10 11 1 -2
+BITMAP
+3CC0
+4240
+8180
+8100
+8100
+8100
+8100
+4200
+3C00
+0000
+0800
+ENDCHAR
+STARTCHAR uni1EE3
+ENCODING 7907
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 -2
+BITMAP
+76
+8A
+8C
+88
+88
+88
+70
+00
+20
+ENDCHAR
+STARTCHAR uni1EE4
+ENCODING 7908
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 6 11 1 -2
+BITMAP
+84
+84
+84
+84
+84
+84
+84
+84
+78
+00
+10
+ENDCHAR
+STARTCHAR uni1EE5
+ENCODING 7909
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 9 1 -2
+BITMAP
+88
+88
+88
+88
+88
+98
+68
+00
+20
+ENDCHAR
+STARTCHAR uni1EE8
+ENCODING 7912
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 1 0
+BITMAP
+04
+08
+00
+87
+85
+86
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni1EE9
+ENCODING 7913
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 1 0
+BITMAP
+08
+10
+00
+8E
+8A
+8C
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni1EEA
+ENCODING 7914
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 1 0
+BITMAP
+10
+08
+00
+87
+85
+86
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni1EEB
+ENCODING 7915
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 1 0
+BITMAP
+10
+08
+00
+8E
+8A
+8C
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni1EEE
+ENCODING 7918
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 12 1 0
+BITMAP
+0A
+14
+00
+87
+85
+86
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR uni1EEF
+ENCODING 7919
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 10 1 0
+BITMAP
+14
+28
+00
+8E
+8A
+8C
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uni1EF0
+ENCODING 7920
+SWIDTH 722 0
+DWIDTH 8 0
+BBX 8 11 1 -2
+BITMAP
+87
+85
+86
+84
+84
+84
+84
+84
+78
+00
+10
+ENDCHAR
+STARTCHAR uni1EF1
+ENCODING 7921
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 9 1 -2
+BITMAP
+8E
+8A
+8C
+88
+88
+98
+68
+00
+10
+ENDCHAR
+STARTCHAR Ygrave
+ENCODING 7922
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+20
+10
+00
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR ygrave
+ENCODING 7923
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+40
+20
+00
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR uni1EF4
+ENCODING 7924
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 11 1 -2
+BITMAP
+82
+82
+44
+44
+28
+10
+10
+10
+10
+00
+10
+ENDCHAR
+STARTCHAR uni1EF5
+ENCODING 7925
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 12 1 -5
+BITMAP
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+00
+40
+ENDCHAR
+STARTCHAR uni1EF8
+ENCODING 7928
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+14
+28
+00
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR uni1EF9
+ENCODING 7929
+SWIDTH 500 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+28
+50
+00
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR uni2000
+ENCODING 8192
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2001
+ENCODING 8193
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2002
+ENCODING 8194
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2003
+ENCODING 8195
+SWIDTH 1000 0
+DWIDTH 13 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2004
+ENCODING 8196
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2005
+ENCODING 8197
+SWIDTH 250 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2006
+ENCODING 8198
+SWIDTH 167 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2007
+ENCODING 8199
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2008
+ENCODING 8200
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2009
+ENCODING 8201
+SWIDTH 200 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni200A
+ENCODING 8202
+SWIDTH 100 0
+DWIDTH 1 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni200B
+ENCODING 8203
+SWIDTH 0 0
+DWIDTH 0 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR uni2010
+ENCODING 8208
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR uni2011
+ENCODING 8209
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+F0
+ENDCHAR
+STARTCHAR figuredash
+ENCODING 8210
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 0 3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR endash
+ENCODING 8211
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 7 1 0 3
+BITMAP
+FE
+ENDCHAR
+STARTCHAR emdash
+ENCODING 8212
+SWIDTH 1000 0
+DWIDTH 12 0
+BBX 12 1 0 3
+BITMAP
+FFF0
+ENDCHAR
+STARTCHAR afii00208
+ENCODING 8213
+SWIDTH 1000 0
+DWIDTH 12 0
+BBX 12 1 0 3
+BITMAP
+FFF0
+ENDCHAR
+STARTCHAR quoteleft
+ENCODING 8216
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 2 3 0 6
+BITMAP
+40
+80
+C0
+ENDCHAR
+STARTCHAR quoteright
+ENCODING 8217
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 2 3 1 6
+BITMAP
+C0
+40
+80
+ENDCHAR
+STARTCHAR quotesinglbase
+ENCODING 8218
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 2 3 1 -2
+BITMAP
+C0
+40
+80
+ENDCHAR
+STARTCHAR quotereversed
+ENCODING 8219
+SWIDTH 222 0
+DWIDTH 3 0
+BBX 2 3 1 6
+BITMAP
+C0
+80
+40
+ENDCHAR
+STARTCHAR quotedblleft
+ENCODING 8220
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 3 0 6
+BITMAP
+48
+90
+D8
+ENDCHAR
+STARTCHAR quotedblright
+ENCODING 8221
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 3 0 6
+BITMAP
+D8
+48
+90
+ENDCHAR
+STARTCHAR quotedblbase
+ENCODING 8222
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 3 0 -2
+BITMAP
+D8
+48
+90
+ENDCHAR
+STARTCHAR uni201F
+ENCODING 8223
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 5 3 0 6
+BITMAP
+D8
+90
+48
+ENDCHAR
+STARTCHAR dagger
+ENCODING 8224
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+20
+20
+20
+F8
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR daggerdbl
+ENCODING 8225
+SWIDTH 556 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+20
+20
+20
+F8
+20
+20
+20
+20
+F8
+20
+20
+20
+ENDCHAR
+STARTCHAR bullet
+ENCODING 8226
+SWIDTH 350 0
+DWIDTH 5 0
+BBX 3 3 1 3
+BITMAP
+40
+E0
+40
+ENDCHAR
+STARTCHAR ellipsis
+ENCODING 8230
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 9 1 1 0
+BITMAP
+8880
+ENDCHAR
+STARTCHAR perthousand
+ENCODING 8240
+SWIDTH 1000 0
+DWIDTH 14 0
+BBX 13 8 0 0
+BITMAP
+6200
+9400
+9400
+6800
+0B30
+14C8
+14C8
+2330
+ENDCHAR
+STARTCHAR guilsinglleft
+ENCODING 8249
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 3 5 1 1
+BITMAP
+20
+40
+80
+40
+20
+ENDCHAR
+STARTCHAR guilsinglright
+ENCODING 8250
+SWIDTH 333 0
+DWIDTH 5 0
+BBX 3 5 1 1
+BITMAP
+80
+40
+20
+40
+80
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8260
+SWIDTH 167 0
+DWIDTH 4 0
+BBX 5 8 -1 0
+BITMAP
+08
+10
+10
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR oneinferior
+ENCODING 8321
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 2 5 1 -3
+BITMAP
+40
+C0
+40
+40
+40
+ENDCHAR
+STARTCHAR twoinferior
+ENCODING 8322
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 4 5 0 -3
+BITMAP
+60
+90
+20
+40
+F0
+ENDCHAR
+STARTCHAR threeinferior
+ENCODING 8323
+SWIDTH 333 0
+DWIDTH 4 0
+BBX 3 5 0 -3
+BITMAP
+E0
+20
+40
+20
+C0
+ENDCHAR
+STARTCHAR uni20A5
+ENCODING 8357
+SWIDTH 833 0
+DWIDTH 9 0
+BBX 7 9 1 -1
+BITMAP
+04
+A4
+DA
+9A
+92
+92
+92
+B2
+20
+ENDCHAR
+STARTCHAR uni20A6
+ENCODING 8358
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+C2
+A2
+FE
+92
+FE
+8A
+86
+82
+ENDCHAR
+STARTCHAR uni20A9
+ENCODING 8361
+SWIDTH 944 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+8880
+8880
+8880
+7F00
+5500
+7F00
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR Euro
+ENCODING 8364
+SWIDTH 722 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+1E
+21
+40
+F8
+40
+F8
+40
+21
+1E
+ENDCHAR
+STARTCHAR uni20AD
+ENCODING 8365
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+84
+88
+90
+A0
+FE
+90
+88
+84
+82
+ENDCHAR
+STARTCHAR uni2103
+ENCODING 8451
+SWIDTH 1102 0
+DWIDTH 14 0
+BBX 13 9 0 0
+BITMAP
+00F0
+6108
+9200
+9200
+6200
+0200
+0200
+0108
+00F0
+ENDCHAR
+STARTCHAR uni2109
+ENCODING 8457
+SWIDTH 991 0
+DWIDTH 13 0
+BBX 12 9 0 0
+BITMAP
+03F0
+6200
+9200
+9200
+63E0
+0200
+0200
+0200
+0200
+ENDCHAR
+STARTCHAR trademark
+ENCODING 8482
+SWIDTH 1000 0
+DWIDTH 11 0
+BBX 9 5 1 4
+BITMAP
+E880
+4D80
+4D80
+4A80
+4A80
+ENDCHAR
+STARTCHAR uni212A
+ENCODING 8490
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+84
+88
+90
+A0
+E0
+90
+88
+84
+82
+ENDCHAR
+STARTCHAR uni212B
+ENCODING 8491
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+10
+10
+10
+28
+44
+44
+7C
+82
+82
+82
+ENDCHAR
+STARTCHAR uni2132
+ENCODING 8498
+SWIDTH 611 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+04
+04
+04
+04
+7C
+04
+04
+04
+FC
+ENDCHAR
+STARTCHAR universal
+ENCODING 8704
+SWIDTH 667 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+82
+7C
+44
+44
+28
+28
+10
+ENDCHAR
+STARTCHAR existential
+ENCODING 8707
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+04
+04
+04
+FC
+04
+04
+04
+FC
+ENDCHAR
+STARTCHAR uni2204
+ENCODING 8708
+SWIDTH 667 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+FC
+0C
+14
+14
+FC
+24
+24
+44
+FC
+ENDCHAR
+STARTCHAR minus
+ENCODING 8722
+SWIDTH 584 0
+DWIDTH 8 0
+BBX 5 1 1 3
+BITMAP
+F8
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8725
+SWIDTH 167 0
+DWIDTH 4 0
+BBX 5 8 -1 0
+BITMAP
+08
+10
+10
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 8729
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 1 1 3
+BITMAP
+80
+ENDCHAR
+STARTCHAR uni2236
+ENCODING 8758
+SWIDTH 278 0
+DWIDTH 3 0
+BBX 1 6 1 0
+BITMAP
+80
+00
+00
+00
+00
+80
+ENDCHAR
+STARTCHAR uni2259
+ENCODING 8793
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 6 1 2
+BITMAP
+20
+50
+00
+F8
+00
+F8
+ENDCHAR
+STARTCHAR uni225A
+ENCODING 8794
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 6 1 2
+BITMAP
+50
+20
+00
+F8
+00
+F8
+ENDCHAR
+STARTCHAR notequal
+ENCODING 8800
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 9 1 -1
+BITMAP
+08
+08
+10
+F8
+20
+F8
+20
+40
+40
+ENDCHAR
+STARTCHAR equivalence
+ENCODING 8801
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 5 0 1
+BITMAP
+F8
+00
+F8
+00
+F8
+ENDCHAR
+STARTCHAR uni2262
+ENCODING 8802
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 5 9 0 -1
+BITMAP
+08
+08
+F8
+10
+F8
+20
+F8
+40
+40
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 8804
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 7 0 -1
+BITMAP
+0C
+30
+C0
+30
+0C
+00
+FC
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 8805
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 7 1 -1
+BITMAP
+C0
+30
+0C
+30
+C0
+00
+FC
+ENDCHAR
+STARTCHAR uni226E
+ENCODING 8814
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 9 0 -1
+BITMAP
+08
+08
+1C
+30
+E0
+30
+2C
+40
+40
+ENDCHAR
+STARTCHAR uni226F
+ENCODING 8815
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 9 1 -1
+BITMAP
+08
+08
+D0
+30
+2C
+30
+E0
+40
+40
+ENDCHAR
+STARTCHAR uni2270
+ENCODING 8816
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 9 0 -2
+BITMAP
+08
+0C
+30
+D0
+30
+2C
+20
+FC
+40
+ENDCHAR
+STARTCHAR uni2271
+ENCODING 8817
+SWIDTH 584 0
+DWIDTH 7 0
+BBX 6 9 1 -2
+BITMAP
+08
+C8
+30
+1C
+30
+E0
+20
+FC
+40
+ENDCHAR
+STARTCHAR fi
+ENCODING -1
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+38
+40
+E8
+48
+48
+48
+48
+48
+48
+ENDCHAR
+STARTCHAR fl
+ENCODING -1
+SWIDTH 500 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+38
+48
+E8
+48
+48
+48
+48
+48
+48
+ENDCHAR
+ENDFONT
diff --git a/gui/themes/fonts/topaz/README.ScummVM b/gui/themes/fonts/topaz/README.ScummVM
new file mode 100644
index 0000000000..3beea8a048
--- /dev/null
+++ b/gui/themes/fonts/topaz/README.ScummVM
@@ -0,0 +1,6 @@
+This package is a remake of Amiga built-in Topaz font for use with Lithuanian keyboards.
+You will find detailed information in topazLT.readme.
+
+The Parallaction engine in ScummVM uses this font's bitmap, namely file topazlt/8.
+Data has been extracted and placed in the array named _amigaTopazFont which can be found in engines/parallaction/staticres.cpp.
+
diff --git a/gui/themes/fonts/topaz/topazLT.font b/gui/themes/fonts/topaz/topazLT.font
new file mode 100644
index 0000000000..e60de8600d
--- /dev/null
+++ b/gui/themes/fonts/topaz/topazLT.font
Binary files differ
diff --git a/gui/themes/fonts/topaz/topazLT.readme b/gui/themes/fonts/topaz/topazLT.readme
new file mode 100644
index 0000000000..3c3553d6ec
--- /dev/null
+++ b/gui/themes/fonts/topaz/topazLT.readme
@@ -0,0 +1,63 @@
+Short: Topaz with Lithuanian characters
+Uploader: r.ulozas@kaunas.omnitel.net (Ricardas Ulozas)
+Author: r.ulozas@kaunas.omnitel.net (Ricardas Ulozas)
+Type: text/font
+Version: 1.0
+
+WHAT IS IT?
+This font has BalticRim layout standard for Lithuanian, Latvian,
+Estonian, Finnish, Polish, Czech and other Central European
+countries. It is very useful when browsing through different
+Lithuanian or Latvian Web sites as you may see the special
+diacritic signs, or when typing in the aforementioned languages.
+
+WHAT DO YOU NEED?
+To type in Lithuanian, please download BalticRimLT.lha on
+Aminet.
+
+HOW TO RUN IT?
+First, extract: lha x topazLT.lha fonts:
+Second, select it on your famous text editor or DTP program.
+
+WHOM I WANT TO THANK?
+Commodore-Amiga,Inc. - Steve Beats and Andy Finkel for FED
+CygnusSoft for CED
+Phase5 for PPC card (when will I get it?...)
+Duckman, Smartie, Beavis and others for being so smart.
+
+HOW YOU MAY DISTRIBUTE IT?
+Anyone, anywhere, anytime, anyway, anywise, etc. as long as you
+don't make money on it (if you do, write me, I'd like to know
+how ;) )
+
+WHAT IF YOU WANT TO KEEP IT?
+If you liked it I ask you to send me a postcard with your city
+sights. Those lazy-bones, tramps and other poor creatures may
+write me an e-mail.
+
+WHAT IF YOU WANT TO CONTACT ME?
+OK, for bug reports, excited or disappointed letters, requests
+for other versions (Hmm..), ideas please write to:
+
+ r.ulozas@kaunas.omnitel.net
+
+If you are a female, have sexy voice and want to have a good
+chat with a guy thousand miles away, make a call:
+
+ 370-7-223859
+
+And if you want to send me a postcard, money, a PPC board, a
+monitor or a stone brick, better try the slow medieval way:
+
+ Ricardas Ulozas
+ POB 2133
+ LT-3000 Kaunas
+ Lithuania
+
+WHAT IS IN THE FUTURE?
+Some new characters to make it fully BalticRim-compatible.
+Sizes 9 and 11 - fixed width.
+Vector font - huge MAYBE.
+Improved documentation.
+
+That's it. Enjoy the font and support Amiga!
diff --git a/gui/themes/fonts/topaz/topazlt/8 b/gui/themes/fonts/topaz/topazlt/8
new file mode 100644
index 0000000000..e74eeb94ef
--- /dev/null
+++ b/gui/themes/fonts/topaz/topazlt/8
Binary files differ
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 9733c7a97e..2507572e40 100644
--- a/gui/themes/scummclassic.zip
+++ b/gui/themes/scummclassic.zip
Binary files differ
diff --git a/gui/themes/scummclassic/clR6x12-iso-8859-5.fcc b/gui/themes/scummclassic/clR6x12-iso-8859-5.fcc
new file mode 100644
index 0000000000..d8e614211d
--- /dev/null
+++ b/gui/themes/scummclassic/clR6x12-iso-8859-5.fcc
Binary files differ
diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx
index cc6d7d471f..d672db2540 100644
--- a/gui/themes/scummclassic/classic_gfx.stx
+++ b/gui/themes/scummclassic/classic_gfx.stx
@@ -44,13 +44,28 @@
<fonts>
<font id = 'text_default'
- file = 'default'
+ file = 'helvb12.bdf'
+ />
+ <font resolution = '320xY, 256x240'
+ id = 'text_default'
+ file = 'clR6x12.bdf'
/>
<font id = 'text_button'
- file = 'default'
+ file = 'helvb12.bdf'
+ />
+ <font resolution = '320xY, 256x240'
+ id = 'text_button'
+ file = 'clR6x12.bdf'
/>
<font id = 'text_normal'
- file = 'default'
+ file = 'helvb12.bdf'
+ />
+ <font resolution = '320xY, 256x240'
+ id = 'text_normal'
+ file = 'clR6x12.bdf'
+ />
+ <font id = 'tooltip_normal'
+ file = 'fixed5x8.bdf'
/>
<text_color id = 'color_normal'
@@ -127,6 +142,14 @@
/>
</drawdata>
+ <drawdata id = 'tooltip_bg' cache = 'false'>
+ <drawstep func = 'bevelsq'
+ bevel = '2'
+ fill = 'foreground'
+ fg_color = 'black'
+ />
+ </drawdata>
+
<drawdata id = 'separator' cache = 'false'>
<drawstep func = 'square'
fill = 'foreground'
@@ -418,9 +441,78 @@
/>
</drawdata>
+ <!-- Idle radiobutton -->
+ <drawdata id = 'radiobutton_default' cache = 'false'>
+ <text font = 'text_default'
+ text_color = 'color_normal'
+ vertical_align = 'center'
+ horizontal_align = 'left'
+ />
+ <drawstep func = 'circle'
+ width = '7'
+ height = '7'
+ radius = '7'
+ fill = 'background'
+ bg_color = 'darkgrey'
+ xpos = '0'
+ ypos = '0'
+ />
+ </drawdata>
+
+ <!-- Selected radiobutton -->
+ <drawdata id = 'radiobutton_selected' cache = 'false'>
+ <text font = 'text_default'
+ text_color = 'color_normal'
+ vertical_align = 'center'
+ horizontal_align = 'left'
+ />
+ <drawstep func = 'circle'
+ width = '7'
+ height = '7'
+ radius = '7'
+ fg_color = 'darkgrey'
+ fill = 'none'
+ xpos = '0'
+ ypos = '0'
+ />
+ <drawstep func = 'circle'
+ width = '7'
+ height = '7'
+ radius = '5'
+ fg_color = 'green'
+ fill = 'foreground'
+ xpos = '2'
+ ypos = '2'
+ />
+ </drawdata>
+
+ <!-- Disabled radiobutton -->
+ <drawdata id = 'radiobutton_disabled' cache = 'false'>
+ <text font = 'text_default'
+ text_color = 'color_normal_disabled'
+ vertical_align = 'center'
+ horizontal_align = 'left'
+ />
+ <drawstep func = 'circle'
+ width = '7'
+ height = '7'
+ radius = '7'
+ bg_color = 'lightgrey'
+ fill = 'background'
+ xpos = '0'
+ ypos = '0'
+ />
+ </drawdata>
+
<drawdata id = 'widget_default' cache = 'false'>
<drawstep func = 'bevelsq'
bevel = '2'
/>
</drawdata>
+
+ <drawdata id = 'widget_small' cache = 'false'>
+ <drawstep func = 'square'
+ stroke = '0'
+ />
+ </drawdata>
</render_info>
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 27164673b4..78941003ef 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -23,7 +23,7 @@
- $Id$
-
-->
-<layout_info resolution = '-320xY, -256x240, -Xx272'>
+<layout_info resolution = '-320xY, -256x240, -Xx272, -Xx350'>
<globals>
<def var = 'Line.Height' value = '16' />
<def var = 'Font.Height' value = '16' />
@@ -41,6 +41,10 @@
<def var = 'KeyMapper.LabelWidth' value = '100'/>
<def var = 'KeyMapper.ButtonWidth' value = '80'/>
+ <def var = 'Tooltip.MaxWidth' value = '200'/>
+ <def var = 'Tooltip.XDelta' value = '16'/> <!-- basically cursor size -->
+ <def var = 'Tooltip.YDelta' value = '16'/>
+
<widget name = 'OptionsLabel'
size = '110, Globals.Line.Height'
textalign = 'right'
@@ -66,6 +70,9 @@
<widget name = 'Checkbox'
size = '-1, 14'
/>
+ <widget name = 'Radiobutton'
+ size = '-1, Globals.Line.Height'
+ />
<widget name = 'ListWidget'
padding = '5, 0, 8, 0'
/>
@@ -85,6 +92,9 @@
size = '75, 27'
padding = '0, 0, 8, 0'
/>
+ <widget name = 'TabWidget.Body'
+ padding = '0, 0, 0, 0'
+ />
<widget name = 'TabWidget.NavButton'
size = '15, 18'
padding = '0, 3, 4, 0'
@@ -241,9 +251,14 @@
<widget name = 'subToggleDesc'
type = 'OptionsLabel'
/>
- <widget name = 'subToggleButton'
- width = '150'
- height = 'Globals.Slider.Height'
+ <widget name = 'subToggleSpeechOnly'
+ type = 'Radiobutton'
+ />
+ <widget name = 'subToggleSubOnly'
+ type = 'Radiobutton'
+ />
+ <widget name = 'subToggleSubBoth'
+ type = 'Radiobutton'
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
@@ -308,6 +323,14 @@
<dialog name = 'GlobalOptions_MIDI' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
+ <widget name = 'auPrefGmPopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefGmPopup'
+ type = 'PopUp'
+ />
+ </layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
<widget name = 'mcFontButton'
type = 'Button'
/>
@@ -322,12 +345,6 @@
<widget name = 'mcMixedCheckbox'
type = 'Checkbox'
/>
- <widget name = 'mcMt32Checkbox'
- type = 'Checkbox'
- />
- <widget name = 'mcGSCheckbox'
- type = 'Checkbox'
- />
<layout type = 'horizontal' padding = '0, 0, 0, 0'>
<widget name = 'mcMidiGainText'
type = 'OptionsLabel'
@@ -343,6 +360,25 @@
</layout>
</dialog>
+ <dialog name = 'GlobalOptions_MT32' overlays = 'Dialog.GlobalOptions.TabWidget'>
+ <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
+ <widget name = 'auPrefMt32PopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefMt32Popup'
+ type = 'PopUp'
+ />
+ </layout>
+ <widget name = 'mcMt32Checkbox'
+ type = 'Checkbox'
+ />
+ <widget name = 'mcGSCheckbox'
+ type = 'Checkbox'
+ />
+ </layout>
+ </dialog>
+
<dialog name = 'GlobalOptions_Paths' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
@@ -406,6 +442,14 @@
type = 'PopUp'
/>
</layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
+ <widget name = 'GuiLanguagePopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'GuiLanguagePopup'
+ type = 'PopUp'
+ />
+ </layout>
<widget name='KeysButton'
type='Button'
/>
@@ -479,6 +523,15 @@
</layout>
</dialog>
+ <dialog name = 'GameOptions_MT32' overlays = 'Dialog.GlobalOptions.TabWidget'>
+ <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
+ <widget name = 'EnableTabCheckbox'
+ type = 'Checkbox'
+ />
+ <import layout = 'Dialog.GlobalOptions_MT32' />
+ </layout>
+ </dialog>
+
<dialog name = 'GameOptions_Volume' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
<widget name = 'EnableTabCheckbox'
@@ -678,9 +731,17 @@
<widget name = 'subToggleDesc'
type = 'OptionsLabel'
/>
- <widget name = 'subToggleButton'
- width = '158'
- height = 'Globals.Slider.Height'
+ <widget name = 'subToggleSpeechOnly'
+ type = 'Radiobutton'
+ width = '100'
+ />
+ <widget name = 'subToggleSubOnly'
+ type = 'Radiobutton'
+ width = '100'
+ />
+ <widget name = 'subToggleSubBoth'
+ type = 'Radiobutton'
+ width = '100'
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index c8ecb1abaf..e7cc7b6279 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -23,7 +23,7 @@
- $Id$
-
-->
-<layout_info resolution = "320xY, 256x240, Xx272">
+<layout_info resolution = "320xY, 256x240, Xx272, Xx350">
<globals>
<def var = 'Line.Height' value = '12' />
<def var = 'Font.Height' value = '10' />
@@ -42,6 +42,10 @@
<def var = 'KeyMapper.LabelWidth' value = '80'/>
<def var = 'KeyMapper.ButtonWidth' value = '60'/>
+ <def var = 'Tooltip.MaxWidth' value = '70'/>
+ <def var = 'Tooltip.XDelta' value = '8'/> <!-- basically cursor size -->
+ <def var = 'Tooltip.YDelta' value = '8'/>
+
<widget name = 'Button'
size = '72, 16'
/>
@@ -63,6 +67,9 @@
<widget name = 'Checkbox'
size = '-1, Globals.Line.Height'
/>
+ <widget name = 'Radiobutton'
+ size = '-1, Globals.Line.Height'
+ />
<widget name = 'ListWidget'
padding = '5, 0, 0, 0'
/>
@@ -82,18 +89,21 @@
size = '45, 16'
padding = '0, 0, 2, 0'
/>
+ <widget name = 'TabWidget.Body'
+ padding = '0, 0, 0, -8'
+ />
<widget name = 'TabWidget.NavButton'
size = '32, 18'
- padding = '0, 3, 4, 0'
+ padding = '0, 0, 1, 0'
/>
</globals>
<dialog name = 'Launcher' overlays = 'screen'>
- <layout type = 'vertical' center = 'true' padding = '8, 8, 4, 4'>
+ <layout type = 'vertical' center = 'true' padding = '6, 6, 2, 2'>
<widget name = 'Version'
height = 'Globals.Line.Height'
/>
- <layout type = 'horizontal' spacing = '5' padding = '10, 0, 0, 0'>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 0'>
<widget name = 'SearchDesc'
width = '50'
height = 'Globals.Line.Height'
@@ -110,7 +120,7 @@
<space />
</layout>
<widget name = 'GameList'/>
- <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'>
<widget name = 'LoadGameButton'
height = '12'
/>
@@ -124,7 +134,7 @@
height = '12'
/>
</layout>
- <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'>
<widget name = 'QuitButton'
height = '12'
/>
@@ -235,13 +245,18 @@
type = 'PopUp'
/>
</layout>
- <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '3' center = 'true'>
<widget name = 'subToggleDesc'
type = 'OptionsLabel'
/>
- <widget name = 'subToggleButton'
- width = '128'
- height = 'Globals.Slider.Height'
+ <widget name = 'subToggleSpeechOnly'
+ type = 'Radiobutton'
+ />
+ <widget name = 'subToggleSubOnly'
+ type = 'Radiobutton'
+ />
+ <widget name = 'subToggleSubBoth'
+ type = 'Radiobutton'
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
@@ -304,6 +319,14 @@
<dialog name = 'GlobalOptions_MIDI' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <widget name = 'auPrefGmPopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefGmPopup'
+ type = 'PopUp'
+ />
+ </layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'>
<widget name = 'mcFontButton'
type = 'Button'
@@ -319,12 +342,6 @@
<widget name = 'mcMixedCheckbox'
type = 'Checkbox'
/>
- <widget name = 'mcMt32Checkbox'
- type = 'Checkbox'
- />
- <widget name = 'mcGSCheckbox'
- type = 'Checkbox'
- />
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
<widget name = 'mcMidiGainText'
type = 'OptionsLabel'
@@ -340,6 +357,25 @@
</layout>
</dialog>
+ <dialog name = 'GlobalOptions_MT32' overlays = 'Dialog.GlobalOptions.TabWidget'>
+ <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <widget name = 'auPrefMt32PopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefMt32Popup'
+ type = 'PopUp'
+ />
+ </layout>
+ <widget name = 'mcMt32Checkbox'
+ type = 'Checkbox'
+ />
+ <widget name = 'mcGSCheckbox'
+ type = 'Checkbox'
+ />
+ </layout>
+ </dialog>
+
<dialog name = 'GlobalOptions_Paths' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'>
@@ -407,6 +443,16 @@
type = 'PopUp'
/>
</layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <widget name = 'GuiLanguagePopupDesc'
+ width = '80'
+ height = 'Globals.Line.Height'
+ textalign = 'right'
+ />
+ <widget name = 'GuiLanguagePopup'
+ type = 'PopUp'
+ />
+ </layout>
<widget name='KeysButton'
type='Button'
/>
@@ -480,6 +526,15 @@
</layout>
</dialog>
+ <dialog name = 'GameOptions_MT32' overlays = 'Dialog.GlobalOptions.TabWidget'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' spacing = '6'>
+ <widget name = 'EnableTabCheckbox'
+ type = 'Checkbox'
+ />
+ <import layout = 'Dialog.GlobalOptions_MT32' />
+ </layout>
+ </dialog>
+
<dialog name = 'GameOptions_Volume' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '8, 8, 8, 8' spacing = '6'>
<widget name = 'EnableTabCheckbox'
@@ -686,16 +741,26 @@
width = '80'
/>
</layout>
- <space size = '4' />
- <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <layout type = 'vertical' padding = '0, 0, 0, 0' spacing = '1' center = 'true'>
<widget name = 'subToggleDesc'
type = 'OptionsLabel'
/>
- <widget name = 'subToggleButton'
- width = '128'
- height = 'Globals.Slider.Height'
- />
- </layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <widget name = 'subToggleSpeechOnly'
+ type = 'Radiobutton'
+ width = '90'
+ />
+ <widget name = 'subToggleSubOnly'
+ type = 'Radiobutton'
+ width = '90'
+ />
+ <widget name = 'subToggleSubBoth'
+ type = 'Radiobutton'
+ width = '90'
+ />
+ </layout>
+ </layout>
+ <space size = '2' />
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
<widget name = 'subSubtitleSpeedDesc'
type = 'OptionsLabel'
@@ -707,7 +772,7 @@
type = 'SmallLabel'
/>
</layout>
- <space size = '20'/>
+ <space size = '16'/>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '4'>
<widget name = 'Keys'
type = 'Button'
diff --git a/gui/themes/scummclassic/fixed5x8-iso-8859-5.fcc b/gui/themes/scummclassic/fixed5x8-iso-8859-5.fcc
new file mode 100644
index 0000000000..e70388dd93
--- /dev/null
+++ b/gui/themes/scummclassic/fixed5x8-iso-8859-5.fcc
Binary files differ
diff --git a/gui/themes/scummclassic/helvb12-iso-8859-5.fcc b/gui/themes/scummclassic/helvb12-iso-8859-5.fcc
new file mode 100644
index 0000000000..8ad8f0eb22
--- /dev/null
+++ b/gui/themes/scummclassic/helvb12-iso-8859-5.fcc
Binary files differ
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index e6cda4ddbb..ea7ecd733c 100644
--- a/gui/themes/scummmodern.zip
+++ b/gui/themes/scummmodern.zip
Binary files differ
diff --git a/gui/themes/scummmodern/clR6x12-iso-8859-5.fcc b/gui/themes/scummmodern/clR6x12-iso-8859-5.fcc
new file mode 100644
index 0000000000..d8e614211d
--- /dev/null
+++ b/gui/themes/scummmodern/clR6x12-iso-8859-5.fcc
Binary files differ
diff --git a/gui/themes/scummmodern/fixed5x8-iso-8859-5.fcc b/gui/themes/scummmodern/fixed5x8-iso-8859-5.fcc
new file mode 100644
index 0000000000..e70388dd93
--- /dev/null
+++ b/gui/themes/scummmodern/fixed5x8-iso-8859-5.fcc
Binary files differ
diff --git a/gui/themes/scummmodern/helvr12-l1.fcc b/gui/themes/scummmodern/helvb12-iso-8859-1.fcc
index 651a25934a..651a25934a 100644
--- a/gui/themes/scummmodern/helvr12-l1.fcc
+++ b/gui/themes/scummmodern/helvb12-iso-8859-1.fcc
Binary files differ
diff --git a/gui/themes/scummmodern/helvb12-iso-8859-5.fcc b/gui/themes/scummmodern/helvb12-iso-8859-5.fcc
new file mode 100644
index 0000000000..8ad8f0eb22
--- /dev/null
+++ b/gui/themes/scummmodern/helvb12-iso-8859-5.fcc
Binary files differ
diff --git a/gui/themes/scummmodern/radiobutton.bmp b/gui/themes/scummmodern/radiobutton.bmp
new file mode 100644
index 0000000000..d3ba468321
--- /dev/null
+++ b/gui/themes/scummmodern/radiobutton.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/radiobutton_empty.bmp b/gui/themes/scummmodern/radiobutton_empty.bmp
new file mode 100644
index 0000000000..06b9f9bb70
--- /dev/null
+++ b/gui/themes/scummmodern/radiobutton_empty.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx
index 05316b516f..cfe00a7016 100644
--- a/gui/themes/scummmodern/scummmodern_gfx.stx
+++ b/gui/themes/scummmodern/scummmodern_gfx.stx
@@ -98,19 +98,36 @@
<bitmap filename = 'cursor_small.bmp'/>
<bitmap filename = 'checkbox.bmp'/>
<bitmap filename = 'checkbox_empty.bmp'/>
+ <bitmap filename = 'radiobutton.bmp'/>
+ <bitmap filename = 'radiobutton_empty.bmp'/>
<bitmap filename = 'logo_small.bmp'/>
<bitmap filename = 'search.bmp'/>
</bitmaps>
<fonts>
<font id = 'text_default'
- file = 'default'
+ file = 'helvb12.bdf'
+ />
+ <font resolution = '320xY, 256x240'
+ id = 'text_default'
+ file = 'clR6x12.bdf'
/>
<font id = 'text_button'
- file = 'default'
+ file = 'helvb12.bdf'
+ />
+ <font resolution = '320xY, 256x240'
+ id = 'text_button'
+ file = 'clR6x12.bdf'
/>
<font id = 'text_normal'
- file = 'helvr12-l1.bdf'
+ file = 'helvb12.bdf'
+ />
+ <font resolution = '320xY, 256x240'
+ id = 'text_normal'
+ file = 'clR6x12.bdf'
+ />
+ <font id = 'tooltip_normal'
+ file = 'fixed5x8.bdf'
/>
<text_color id = 'color_normal'
@@ -499,6 +516,15 @@
/>
</drawdata>
+ <!-- Tooltip -->
+ <drawdata id = 'tooltip_bg' cache = 'false'>
+ <drawstep func = 'square'
+ fill = 'foreground'
+ fg_color = 'blandyellow'
+ shadow = '3'
+ />
+ </drawdata>
+
<!-- Idle button -->
<drawdata id = 'button_idle' cache = 'false'>
<text font = 'text_button'
@@ -595,6 +621,42 @@
/>
</drawdata>
+ <!-- Idle radiobutton -->
+ <drawdata id = 'radiobutton_default' cache = 'false'>
+ <text font = 'text_default'
+ text_color = 'color_normal'
+ vertical_align = 'center'
+ horizontal_align = 'left'
+ />
+ <drawstep func = 'bitmap'
+ file = 'radiobutton_empty.bmp'
+ />
+ </drawdata>
+
+ <!-- Selected radiobutton -->
+ <drawdata id = 'radiobutton_selected' cache = 'false'>
+ <text font = 'text_default'
+ text_color = 'color_normal'
+ vertical_align = 'center'
+ horizontal_align = 'left'
+ />
+ <drawstep func = 'bitmap'
+ file = 'radiobutton.bmp'
+ />
+ </drawdata>
+
+ <!-- Disabled radiobutton -->
+ <drawdata id = 'radiobutton_disabled' cache = 'false'>
+ <text font = 'text_default'
+ text_color = 'color_normal_disabled'
+ vertical_align = 'center'
+ horizontal_align = 'left'
+ />
+ <drawstep func = 'bitmap'
+ file = 'radiobutton_empty.bmp'
+ />
+ </drawdata>
+
<!-- Background of the list widget (the games list and the list in the choosers) -->
<!-- TODO: Have separate options for the games list (with gradient background) and the list in the choosers (without gradient) -->
<drawdata id = 'widget_default' cache = 'false'>
@@ -611,10 +673,8 @@
/>
</drawdata>
- <!-- Where is it used? -->
<drawdata id = 'widget_small' cache = 'false'>
- <drawstep func = 'roundedsq'
- radius = '6'
+ <drawstep func = 'square'
stroke = '0'
gradient_start = 'blandyellow'
gradient_end = 'xtrabrightred'
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index 2fd14f37aa..3464619cf3 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -23,7 +23,7 @@
- $Id$
-
-->
-<layout_info resolution = '-320xY, -256x240, -Xx272'>
+<layout_info resolution = '-320xY, -256x240, -Xx272, -Xx350'>
<globals>
<def var = 'Line.Height' value = '16' />
<def var = 'Font.Height' value = '16' />
@@ -48,6 +48,10 @@
<def var = 'KeyMapper.LabelWidth' value = '100'/>
<def var = 'KeyMapper.ButtonWidth' value = '80'/>
+ <def var = 'Tooltip.MaxWidth' value = '200'/>
+ <def var = 'Tooltip.XDelta' value = '16'/> <!-- basically cursor size -->
+ <def var = 'Tooltip.YDelta' value = '32'/>
+
<widget name = 'OptionsLabel'
size = '110, Globals.Line.Height'
textalign = 'right'
@@ -70,6 +74,9 @@
<widget name = 'Checkbox'
size = '-1, Globals.Line.Height'
/>
+ <widget name = 'Radiobutton'
+ size = '-1, Globals.Line.Height'
+ />
<widget name = 'ListWidget'
padding = '5, 0, 8, 0'
/>
@@ -89,6 +96,11 @@
size = '75, 27'
padding = '0, 0, 8, 0'
/>
+
+ <widget name = 'TabWidget.Body'
+ padding = '0, 0, 0, 0'
+ />
+
<widget name = 'TabWidget.NavButton'
size = '15, 18'
padding = '0, 3, 4, 0'
@@ -98,7 +110,7 @@
<dialog name = 'Launcher' overlays = 'screen'>
<layout type = 'vertical' center = 'true' padding = '23, 23, 8, 23'>
<widget name = 'Logo'
- width = '283'
+ width = '287'
height = '80'
/>
<layout type = 'horizontal' spacing = '5' padding = '10, 0, 0, 0'>
@@ -254,9 +266,14 @@
<widget name = 'subToggleDesc'
type = 'OptionsLabel'
/>
- <widget name = 'subToggleButton'
- width = '150'
- height = 'Globals.Slider.Height'
+ <widget name = 'subToggleSpeechOnly'
+ type = 'Radiobutton'
+ />
+ <widget name = 'subToggleSubOnly'
+ type = 'Radiobutton'
+ />
+ <widget name = 'subToggleSubBoth'
+ type = 'Radiobutton'
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
@@ -321,6 +338,14 @@
<dialog name = 'GlobalOptions_MIDI' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
+ <widget name = 'auPrefGmPopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefGmPopup'
+ type = 'PopUp'
+ />
+ </layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
<widget name = 'mcFontButton'
type = 'Button'
/>
@@ -335,12 +360,6 @@
<widget name = 'mcMixedCheckbox'
type = 'Checkbox'
/>
- <widget name = 'mcMt32Checkbox'
- type = 'Checkbox'
- />
- <widget name = 'mcGSCheckbox'
- type = 'Checkbox'
- />
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
<widget name = 'mcMidiGainText'
type = 'OptionsLabel'
@@ -356,6 +375,25 @@
</layout>
</dialog>
+ <dialog name = 'GlobalOptions_MT32' overlays = 'Dialog.GlobalOptions.TabWidget'>
+ <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
+ <widget name = 'auPrefMt32PopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefMt32Popup'
+ type = 'PopUp'
+ />
+ </layout>
+ <widget name = 'mcMt32Checkbox'
+ type = 'Checkbox'
+ />
+ <widget name = 'mcGSCheckbox'
+ type = 'Checkbox'
+ />
+ </layout>
+ </dialog>
+
<dialog name = 'GlobalOptions_Paths' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
@@ -419,6 +457,14 @@
type = 'PopUp'
/>
</layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
+ <widget name = 'GuiLanguagePopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'GuiLanguagePopup'
+ type = 'PopUp'
+ />
+ </layout>
<widget name='KeysButton'
type='Button'
/>
@@ -492,6 +538,15 @@
</layout>
</dialog>
+ <dialog name = 'GameOptions_MT32' overlays = 'Dialog.GlobalOptions.TabWidget'>
+ <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
+ <widget name = 'EnableTabCheckbox'
+ type = 'Checkbox'
+ />
+ <import layout = 'Dialog.GlobalOptions_MT32' />
+ </layout>
+ </dialog>
+
<dialog name = 'GameOptions_Volume' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
<widget name = 'EnableTabCheckbox'
@@ -691,9 +746,17 @@
<widget name = 'subToggleDesc'
type = 'OptionsLabel'
/>
- <widget name = 'subToggleButton'
- width = '158'
- height = 'Globals.Slider.Height'
+ <widget name = 'subToggleSpeechOnly'
+ type = 'Radiobutton'
+ width = '100'
+ />
+ <widget name = 'subToggleSubOnly'
+ type = 'Radiobutton'
+ width = '100'
+ />
+ <widget name = 'subToggleSubBoth'
+ type = 'Radiobutton'
+ width = '100'
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index e837e41e82..f869956300 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -23,7 +23,7 @@
- $Id$
-
-->
-<layout_info resolution = "320xY, 256x240, Xx272">
+<layout_info resolution = "320xY, 256x240, Xx272, Xx350">
<globals>
<def var = 'Line.Height' value = '12' />
<def var = 'Font.Height' value = '10' />
@@ -48,6 +48,10 @@
<def var = 'KeyMapper.LabelWidth' value = '80'/>
<def var = 'KeyMapper.ButtonWidth' value = '60'/>
+ <def var = 'Tooltip.MaxWidth' value = '70'/>
+ <def var = 'Tooltip.XDelta' value = '9'/> <!-- basically cursor size -->
+ <def var = 'Tooltip.YDelta' value = '18'/>
+
<widget name = 'OptionsLabel'
size = '100, Globals.Line.Height'
textalign = 'right'
@@ -61,6 +65,9 @@
<widget name = 'Checkbox'
size = '-1, Globals.Line.Height'
/>
+ <widget name = 'Radiobutton'
+ size = '-1, Globals.Line.Height'
+ />
<widget name = 'ListWidget'
padding = '5, 0, 8, 0'
/>
@@ -80,18 +87,21 @@
size = '45, 16'
padding = '0, 0, 2, 0'
/>
+ <widget name = 'TabWidget.Body'
+ padding = '0, 0, 0, -8'
+ />
<widget name = 'TabWidget.NavButton'
size = '32, 18'
- padding = '0, 3, 4, 0'
+ padding = '0, 0, 2, 0'
/>
</globals>
<dialog name = 'Launcher' overlays = 'screen'>
- <layout type = 'vertical' center = 'true' padding = '8, 8, 8, 4' spacing = '8'>
+ <layout type = 'vertical' center = 'true' padding = '4, 4, 2, 2' spacing = '2'>
<widget name = 'Version'
height = 'Globals.Line.Height'
/>
- <layout type = 'horizontal' spacing = '5' padding = '10, 0, 0, 0'>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 2, 2'>
<widget name = 'SearchDesc'
width = '50'
height = 'Globals.Line.Height'
@@ -108,7 +118,7 @@
<space />
</layout>
<widget name = 'GameList'/>
- <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6'>
+ <layout type = 'horizontal' padding = '0, 0, 2, 0' spacing = '2'>
<widget name = 'LoadGameButton'
height = 'Globals.Button.Height'
/>
@@ -122,7 +132,7 @@
height = 'Globals.Button.Height'
/>
</layout>
- <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '2'>
<widget name = 'QuitButton'
height = 'Globals.Button.Height'
/>
@@ -233,13 +243,18 @@
type = 'PopUp'
/>
</layout>
- <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '3' center = 'true'>
<widget name = 'subToggleDesc'
type = 'OptionsLabel'
/>
- <widget name = 'subToggleButton'
- width = '128'
- height = 'Globals.Slider.Height'
+ <widget name = 'subToggleSpeechOnly'
+ type = 'Radiobutton'
+ />
+ <widget name = 'subToggleSubOnly'
+ type = 'Radiobutton'
+ />
+ <widget name = 'subToggleSubBoth'
+ type = 'Radiobutton'
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
@@ -302,6 +317,14 @@
<dialog name = 'GlobalOptions_MIDI' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <widget name = 'auPrefGmPopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefGmPopup'
+ type = 'PopUp'
+ />
+ </layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'>
<widget name = 'mcFontButton'
type = 'Button'
@@ -317,12 +340,6 @@
<widget name = 'mcMixedCheckbox'
type = 'Checkbox'
/>
- <widget name = 'mcMt32Checkbox'
- type = 'Checkbox'
- />
- <widget name = 'mcGSCheckbox'
- type = 'Checkbox'
- />
<layout type = 'horizontal' padding = '0, 0, 0, 0' center = 'true'>
<widget name = 'mcMidiGainText'
type = 'OptionsLabel'
@@ -338,6 +355,25 @@
</layout>
</dialog>
+ <dialog name = 'GlobalOptions_MT32' overlays = 'Dialog.GlobalOptions.TabWidget'>
+ <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <widget name = 'auPrefMt32PopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefMt32Popup'
+ type = 'PopUp'
+ />
+ </layout>
+ <widget name = 'mcMt32Checkbox'
+ type = 'Checkbox'
+ />
+ <widget name = 'mcGSCheckbox'
+ type = 'Checkbox'
+ />
+ </layout>
+ </dialog>
+
<dialog name = 'GlobalOptions_Paths' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'>
@@ -389,6 +425,7 @@
<widget name = 'RendererPopupDesc'
width = '80'
height = 'Globals.Line.Height'
+ textalign = 'right'
/>
<widget name = 'RendererPopup'
type = 'PopUp'
@@ -398,11 +435,22 @@
<widget name = 'AutosavePeriodPopupDesc'
width = '80'
height = 'Globals.Line.Height'
+ textalign = 'right'
/>
<widget name = 'AutosavePeriodPopup'
type = 'PopUp'
/>
</layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <widget name = 'GuiLanguagePopupDesc'
+ width = '80'
+ height = 'Globals.Line.Height'
+ textalign = 'right'
+ />
+ <widget name = 'GuiLanguagePopup'
+ type = 'PopUp'
+ />
+ </layout>
<widget name='KeysButton'
type='Button'
/>
@@ -476,6 +524,15 @@
</layout>
</dialog>
+ <dialog name = 'GameOptions_MT32' overlays = 'Dialog.GlobalOptions.TabWidget'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' spacing = '6'>
+ <widget name = 'EnableTabCheckbox'
+ type = 'Checkbox'
+ />
+ <import layout = 'Dialog.GlobalOptions_MT32' />
+ </layout>
+ </dialog>
+
<dialog name = 'GameOptions_Volume' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '8, 8, 8, 8' spacing = '6'>
<widget name = 'EnableTabCheckbox'
@@ -676,15 +733,26 @@
/>
</layout>
<space size = '4' />
- <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <layout type = 'vertical' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
<widget name = 'subToggleDesc'
type = 'OptionsLabel'
/>
- <widget name = 'subToggleButton'
- width = '128'
- height = 'Globals.Slider.Height'
- />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <widget name = 'subToggleSpeechOnly'
+ type = 'Radiobutton'
+ width = '90'
+ />
+ <widget name = 'subToggleSubOnly'
+ type = 'Radiobutton'
+ width = '90'
+ />
+ <widget name = 'subToggleSubBoth'
+ type = 'Radiobutton'
+ width = '90'
+ />
+ </layout>
</layout>
+ <space size = '4' />
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
<widget name = 'subSubtitleSpeedDesc'
type = 'OptionsLabel'
diff --git a/gui/widget.cpp b/gui/widget.cpp
index e4b37dc3c2..f8713a14db 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -32,14 +32,14 @@
namespace GUI {
-Widget::Widget(GuiObject *boss, int x, int y, int w, int h)
- : GuiObject(x, y, w, h), _type(0), _boss(boss),
+Widget::Widget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip)
+ : GuiObject(x, y, w, h), _type(0), _boss(boss), _tooltip(tooltip),
_id(0), _flags(0), _hasFocus(false), _state(ThemeEngine::kStateEnabled) {
init();
}
-Widget::Widget(GuiObject *boss, const Common::String &name)
- : GuiObject(name), _type(0), _boss(boss),
+Widget::Widget(GuiObject *boss, const Common::String &name, const char *tooltip)
+ : GuiObject(name), _type(0), _boss(boss), _tooltip(tooltip),
_id(0), _flags(0), _hasFocus(false), _state(ThemeEngine::kStateDisabled) {
init();
}
@@ -177,17 +177,62 @@ bool Widget::isVisible() const {
return !(_flags & WIDGET_INVISIBLE);
}
+uint8 Widget::parseHotkey(const Common::String &label) {
+ if (!label.contains('~'))
+ return 0;
+
+ int state = 0;
+ uint8 hotkey = 0;
+
+ for (uint i = 0; i < label.size() && state != 3; i++) {
+ switch (state) {
+ case 0:
+ if (label[i] == '~')
+ state = 1;
+ break;
+ case 1:
+ if (label[i] != '~') {
+ state = 2;
+ hotkey = label[i];
+ } else
+ state = 0;
+ break;
+ case 2:
+ if (label[i] == '~')
+ state = 3;
+ else
+ state = 0;
+ break;
+ }
+ }
+
+ if (state == 3)
+ return hotkey;
+
+ return 0;
+}
+
+Common::String Widget::cleanupHotkey(const Common::String &label) {
+ Common::String res;
+
+ for (uint i = 0; i < label.size() ; i++)
+ if (label[i] != '~')
+ res = res + label[i];
+
+ return res;
+}
+
#pragma mark -
-StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align)
- : Widget(boss, x, y, w, h), _align(align) {
+StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip)
+ : Widget(boss, x, y, w, h, tooltip), _align(align) {
setFlags(WIDGET_ENABLED);
_type = kStaticTextWidget;
_label = text;
}
-StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text)
- : Widget(boss, name) {
+StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip)
+ : Widget(boss, name, tooltip) {
setFlags(WIDGET_ENABLED);
_type = kStaticTextWidget;
_label = text;
@@ -227,16 +272,22 @@ void StaticTextWidget::drawWidget() {
#pragma mark -
-ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd, uint8 hotkey)
- : StaticTextWidget(boss, x, y, w, h, label, Graphics::kTextAlignCenter), CommandSender(boss),
+ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
+ : StaticTextWidget(boss, x, y, w, h, cleanupHotkey(label), Graphics::kTextAlignCenter, tooltip), CommandSender(boss),
_cmd(cmd), _hotkey(hotkey) {
+
+ if (hotkey == 0)
+ _hotkey = parseHotkey(label);
+
setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
_type = kButtonWidget;
}
-ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd, uint8 hotkey)
- : StaticTextWidget(boss, name, label), CommandSender(boss),
- _cmd(cmd), _hotkey(hotkey) {
+ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
+ : StaticTextWidget(boss, name, cleanupHotkey(label), tooltip), CommandSender(boss),
+ _cmd(cmd) {
+ if (hotkey == 0)
+ _hotkey = parseHotkey(label);
setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
_type = kButtonWidget;
}
@@ -252,14 +303,14 @@ void ButtonWidget::drawWidget() {
#pragma mark -
-CheckboxWidget::CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd, uint8 hotkey)
- : ButtonWidget(boss, x, y, w, h, label, cmd, hotkey), _state(false) {
+CheckboxWidget::CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
+ : ButtonWidget(boss, x, y, w, h, label, tooltip, cmd, hotkey), _state(false) {
setFlags(WIDGET_ENABLED);
_type = kCheckboxWidget;
}
-CheckboxWidget::CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd, uint8 hotkey)
- : ButtonWidget(boss, name, label, cmd, hotkey), _state(false) {
+CheckboxWidget::CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
+ : ButtonWidget(boss, name, label, tooltip, cmd, hotkey), _state(false) {
setFlags(WIDGET_ENABLED);
_type = kCheckboxWidget;
}
@@ -284,16 +335,84 @@ void CheckboxWidget::drawWidget() {
}
#pragma mark -
+RadiobuttonGroup::RadiobuttonGroup(GuiObject *boss, uint32 cmd) : CommandSender(boss) {
+ _value = -1;
+ _cmd = cmd;
+}
+
+void RadiobuttonGroup::setValue(int value) {
+ Common::Array<RadiobuttonWidget *>::iterator button = _buttons.begin();
+ while (button != _buttons.end()) {
+ (*button)->setState((*button)->getValue() == value, false);
+
+ button++;
+ }
+
+ _value = value;
+
+ sendCommand(_cmd, _value);
+}
+
+void RadiobuttonGroup::setEnabled(bool ena) {
+ Common::Array<RadiobuttonWidget *>::iterator button = _buttons.begin();
+ while (button != _buttons.end()) {
+ (*button)->setEnabled(ena);
+
+ button++;
+ }
+}
+
+#pragma mark -
-SliderWidget::SliderWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd)
- : Widget(boss, x, y, w, h), CommandSender(boss),
+RadiobuttonWidget::RadiobuttonWidget(GuiObject *boss, int x, int y, int w, int h, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip, uint8 hotkey)
+ : ButtonWidget(boss, x, y, w, h, label, tooltip, 0, hotkey), _state(false), _value(value), _group(group) {
+ setFlags(WIDGET_ENABLED);
+ _type = kRadiobuttonWidget;
+ _group->addButton(this);
+}
+
+RadiobuttonWidget::RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip, uint8 hotkey)
+ : ButtonWidget(boss, name, label, tooltip, 0, hotkey), _state(false), _value(value), _group(group) {
+ setFlags(WIDGET_ENABLED);
+ _type = kRadiobuttonWidget;
+ _group->addButton(this);
+}
+
+void RadiobuttonWidget::handleMouseUp(int x, int y, int button, int clickCount) {
+ if (isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h) {
+ toggleState();
+ }
+}
+
+void RadiobuttonWidget::setState(bool state, bool setGroup) {
+ if (setGroup) {
+ _group->setValue(_value);
+ return;
+ }
+
+ if (_state != state) {
+ _state = state;
+ //_flags ^= WIDGET_INV_BORDER;
+ draw();
+ }
+ sendCommand(_cmd, _state);
+}
+
+void RadiobuttonWidget::drawWidget() {
+ g_gui.theme()->drawRadiobutton(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, Widget::_state);
+}
+
+#pragma mark -
+
+SliderWidget::SliderWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd)
+ : Widget(boss, x, y, w, h, tooltip), CommandSender(boss),
_cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false) {
setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG);
_type = kSliderWidget;
}
-SliderWidget::SliderWidget(GuiObject *boss, const Common::String &name, uint32 cmd)
- : Widget(boss, name), CommandSender(boss),
+SliderWidget::SliderWidget(GuiObject *boss, const Common::String &name, const char *tooltip, uint32 cmd)
+ : Widget(boss, name, tooltip), CommandSender(boss),
_cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false) {
setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG);
_type = kSliderWidget;
@@ -365,14 +484,14 @@ int SliderWidget::posToValue(int pos) {
#pragma mark -
-GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h)
- : Widget(boss, x, y, w, h), _gfx(), _alpha(256), _transparency(false) {
+GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip)
+ : Widget(boss, x, y, w, h, tooltip), _gfx(), _alpha(256), _transparency(false) {
setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
_type = kGraphicsWidget;
}
-GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name)
- : Widget(boss, name), _gfx(), _alpha(256), _transparency(false) {
+GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name, const char *tooltip)
+ : Widget(boss, name, tooltip), _gfx(), _alpha(256), _transparency(false) {
setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
_type = kGraphicsWidget;
}
@@ -387,6 +506,11 @@ void GraphicsWidget::setGfx(const Graphics::Surface *gfx) {
if (!gfx || !gfx->pixels)
return;
+ if (gfx->w > _w || gfx->h > _h) {
+ warning("GraphicsWidget has size %dx%d, but a surface with %dx%d is to be set", _w, _h, gfx->w, gfx->h);
+ return;
+ }
+
// TODO: add conversion to OverlayColor
_gfx.copyFrom(*gfx);
}
@@ -400,7 +524,7 @@ void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
_gfx.free();
_gfx.create(w, h, sizeof(OverlayColor));
- OverlayColor *dst = (OverlayColor*)_gfx.pixels;
+ OverlayColor *dst = (OverlayColor *)_gfx.pixels;
Graphics::PixelFormat overlayFormat = g_system->getOverlayFormat();
OverlayColor fillCol = overlayFormat.RGBToColor(r, g, b);
while (h--) {
@@ -411,8 +535,12 @@ void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
}
void GraphicsWidget::drawWidget() {
- if (sizeof(OverlayColor) == _gfx.bytesPerPixel && _gfx.pixels)
- g_gui.theme()->drawSurface(Common::Rect(_x, _y, _x+_w, _y+_h), _gfx, _state, _alpha, _transparency);
+ if (sizeof(OverlayColor) == _gfx.bytesPerPixel && _gfx.pixels) {
+ const int x = _x + (_w - _gfx.w) / 2;
+ const int y = _y + (_h - _gfx.h) / 2;
+
+ g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), _gfx, _state, _alpha, _transparency);
+ }
}
#pragma mark -
diff --git a/gui/widget.h b/gui/widget.h
index ebadc53241..92bfbf8256 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -27,6 +27,7 @@
#include "common/scummsys.h"
#include "common/str.h"
+#include "common/str-array.h"
#include "common/keyboard.h"
#include "graphics/surface.h"
#include "gui/object.h"
@@ -62,6 +63,7 @@ enum {
kEditTextWidget = 'EDIT',
kButtonWidget = 'BTTN',
kCheckboxWidget = 'CHKB',
+ kRadiobuttonWidget = 'RDBT',
kSliderWidget = 'SLDE',
kListWidget = 'LIST',
kScrollBarWidget = 'SCRB',
@@ -85,6 +87,7 @@ protected:
uint16 _id;
bool _hasFocus;
ThemeEngine::WidgetStateInfo _state;
+ const char *_tooltip;
private:
uint16 _flags;
@@ -94,8 +97,8 @@ public:
static Widget *findWidgetInChain(Widget *start, const char *name);
public:
- Widget(GuiObject *boss, int x, int y, int w, int h);
- Widget(GuiObject *boss, const Common::String &name);
+ Widget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0);
+ Widget(GuiObject *boss, const Common::String &name, const char *tooltip = 0);
virtual ~Widget();
void init();
@@ -135,6 +138,11 @@ public:
void setVisible(bool e);
bool isVisible() const;
+ uint8 parseHotkey(const Common::String &label);
+ Common::String cleanupHotkey(const Common::String &label);
+
+ const char *getTooltip() const { return _tooltip; }
+
protected:
void updateState(int oldFlags, int newFlags);
@@ -157,8 +165,8 @@ protected:
Common::String _label;
Graphics::TextAlign _align;
public:
- StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align);
- StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text);
+ StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip = 0);
+ StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip = 0);
void setValue(int value);
void setLabel(const Common::String &label);
const Common::String &getLabel() const { return _label; }
@@ -176,8 +184,8 @@ protected:
uint32 _cmd;
uint8 _hotkey;
public:
- ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0);
- ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0);
+ ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0);
+ ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0);
void setCmd(uint32 cmd) { _cmd = cmd; }
uint32 getCmd() const { return _cmd; }
@@ -195,8 +203,8 @@ class CheckboxWidget : public ButtonWidget {
protected:
bool _state;
public:
- CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0);
- CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0);
+ CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0);
+ CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0);
void handleMouseUp(int x, int y, int button, int clickCount);
virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); }
@@ -210,6 +218,55 @@ protected:
void drawWidget();
};
+class RadiobuttonWidget;
+
+class RadiobuttonGroup : public CommandSender {
+public:
+ RadiobuttonGroup(GuiObject *boss, uint32 cmd = 0);
+ ~RadiobuttonGroup() {}
+
+ void addButton(RadiobuttonWidget *button) { _buttons.push_back(button); }
+ Common::Array<RadiobuttonWidget *> getButtonList() const { return _buttons; }
+
+ void setValue(int state);
+ int getValue() const { return _value; }
+
+ void setEnabled(bool ena);
+
+ void setCmd(uint32 cmd) { _cmd = cmd; }
+ uint32 getCmd() const { return _cmd; }
+
+protected:
+ Common::Array<RadiobuttonWidget *> _buttons;
+ int _value;
+ uint32 _cmd;
+};
+
+/* RadiobuttonWidget */
+class RadiobuttonWidget : public ButtonWidget {
+protected:
+ bool _state;
+ int _value;
+
+public:
+ RadiobuttonWidget(GuiObject *boss, int x, int y, int w, int h, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip = 0, uint8 hotkey = 0);
+ RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip = 0, uint8 hotkey = 0);
+
+ void handleMouseUp(int x, int y, int button, int clickCount);
+ virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); }
+ virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); }
+
+ void setState(bool state, bool setGroup = true);
+ void toggleState() { setState(!_state); }
+ bool getState() const { return _state; }
+ int getValue() const { return _value; }
+
+protected:
+ void drawWidget();
+
+ RadiobuttonGroup *_group;
+};
+
/* SliderWidget */
class SliderWidget : public Widget, public CommandSender {
protected:
@@ -219,8 +276,8 @@ protected:
bool _isDragging;
uint _labelWidth;
public:
- SliderWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd = 0);
- SliderWidget(GuiObject *boss, const Common::String &name, uint32 cmd = 0);
+ SliderWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0, uint32 cmd = 0);
+ SliderWidget(GuiObject *boss, const Common::String &name, const char *tooltip = 0, uint32 cmd = 0);
void setCmd(uint32 cmd) { _cmd = cmd; }
uint32 getCmd() const { return _cmd; }
@@ -251,8 +308,8 @@ protected:
/* GraphicsWidget */
class GraphicsWidget : public Widget {
public:
- GraphicsWidget(GuiObject *boss, int x, int y, int w, int h);
- GraphicsWidget(GuiObject *boss, const Common::String &name);
+ GraphicsWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0);
+ GraphicsWidget(GuiObject *boss, const Common::String &name, const char *tooltip = 0);
~GraphicsWidget();
void setGfx(const Graphics::Surface *gfx);
diff --git a/po/POTFILES b/po/POTFILES
new file mode 100644
index 0000000000..28ca60d31b
--- /dev/null
+++ b/po/POTFILES
@@ -0,0 +1,45 @@
+#TODO: help_string & usage_string:
+
+gui/about.cpp
+gui/browser.cpp
+gui/chooser.cpp
+gui/error.cpp
+gui/GuiManager.cpp
+gui/KeysDialog.cpp
+gui/launcher.cpp
+gui/massadd.cpp
+gui/options.cpp
+gui/saveload.cpp
+gui/themebrowser.cpp
+gui/ThemeEngine.cpp
+
+base/main.cpp
+
+common/error.cpp
+common/util.cpp
+
+engines/dialogs.cpp
+engines/scumm/dialogs.cpp
+engines/mohawk/dialogs.cpp
+
+sound/fmopl.cpp
+sound/musicplugin.cpp
+sound/null.h
+sound/null.cpp
+sound/softsynth/adlib.cpp
+sound/softsynth/mt32.cpp
+sound/softsynth/pcspk.cpp
+sound/softsynth/ym2612.cpp
+
+backends/keymapper/remap-dialog.cpp
+backends/midi/windows.cpp
+backends/platform/ds/arm9/source/dsoptions.cpp
+backends/platform/iphone/osys_events.cpp
+backends/platform/sdl/graphics.cpp
+backends/platform/symbian/src/SymbianActions.cpp
+backends/platform/symbian/src/SymbianOS.cpp
+backends/platform/wii/options.cpp
+backends/platform/wince/CEActionsPocket.cpp
+backends/platform/wince/CEActionsSmartphone.cpp
+backends/platform/wince/CELauncherDialog.cpp
+backends/platform/wince/wince-sdl.cpp
diff --git a/po/ca_ES.po b/po/ca_ES.po
new file mode 100644
index 0000000000..6647dcc837
--- /dev/null
+++ b/po/ca_ES.po
@@ -0,0 +1,1456 @@
+# Catalan translation for ScummVM.
+# Copyright (C) 2007-2010 ScummVM
+# This file is distributed under the same license as the ScummVM package.
+# Jordi Vilalta Prat <jvprat@jvprat.com>, 2007-2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ScummVM 1.2.0svn\n"
+"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
+"POT-Creation-Date: 2010-07-30 22:14+0100\n"
+"PO-Revision-Date: 2010-06-26 16:45+0100\n"
+"Last-Translator: Jordi Vilalta Prat <jvprat@gmail.com>\n"
+"Language-Team: Catalan <scummvm-devel@lists.sf.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: Catalan\n"
+
+#: gui/about.cpp:96
+#, c-format
+msgid "(built on %s)"
+msgstr "(compilat el %s)"
+
+#: gui/about.cpp:103
+msgid "Features compiled in:"
+msgstr "Característiques compilades:"
+
+#: gui/about.cpp:112
+msgid "Available engines:"
+msgstr "Motors disponibles:"
+
+#: gui/browser.cpp:69
+msgid "Go up"
+msgstr "Amunt"
+
+#: gui/browser.cpp:69
+msgid "Go to previous directory level"
+msgstr "Torna al nivell de directoris anterior"
+
+#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46
+#: gui/launcher.cpp:280 gui/massadd.cpp:95 gui/options.cpp:1029
+#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56
+#: backends/platform/wii/options.cpp:48
+msgid "Cancel"
+msgstr "Cancel·la"
+
+#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57
+msgid "Choose"
+msgstr "Escull"
+
+#: gui/GuiManager.cpp:103 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "Tanca"
+
+#: gui/GuiManager.cpp:106
+msgid "Mouse click"
+msgstr "Clic del ratolí"
+
+#: gui/GuiManager.cpp:109 base/main.cpp:285
+msgid "Display keyboard"
+msgstr "Mostra el teclat"
+
+#: gui/GuiManager.cpp:112 base/main.cpp:288
+msgid "Remap keys"
+msgstr "Remapeja les tecles"
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr "Mapeja"
+
+#: gui/KeysDialog.cpp:45 gui/launcher.cpp:281 gui/launcher.cpp:893
+#: gui/launcher.cpp:897 gui/massadd.cpp:92 gui/options.cpp:1030
+#: backends/platform/wii/options.cpp:47
+#: backends/platform/wince/CELauncherDialog.cpp:56
+msgid "OK"
+msgstr "D'acord"
+
+#: gui/KeysDialog.cpp:52
+msgid "Select an action and click 'Map'"
+msgstr "Seleccioneu una acció i cliqueu 'Mapeja'"
+
+#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144
+#, c-format
+msgid "Associated key : %s"
+msgstr "Tecla associada : %s"
+
+#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146
+#, c-format
+msgid "Associated key : none"
+msgstr "Tecla associada : cap"
+
+#: gui/KeysDialog.cpp:93
+msgid "Please select an action"
+msgstr "Seleccioneu una acció"
+
+#: gui/KeysDialog.cpp:109
+msgid "Press the key to associate"
+msgstr "Premeu la tecla a associar"
+
+#: gui/KeysDialog.cpp:148
+msgid "Choose an action to map"
+msgstr "Sel·leccioneu una acció per mapejar"
+
+#: gui/launcher.cpp:172
+msgid "Game"
+msgstr "Joc"
+
+#: gui/launcher.cpp:175
+msgid "ID:"
+msgstr "Identificador:"
+
+#: gui/launcher.cpp:175 gui/launcher.cpp:176
+msgid ""
+"Short game identifier used for referring to savegames and running the game "
+"from the command line"
+msgstr ""
+"Identificador de joc curt utilitzat per referir-se a les partides i per "
+"executar el joc des de la línia de comandes"
+
+#: gui/launcher.cpp:179
+msgid "Name:"
+msgstr "Nom:"
+
+#: gui/launcher.cpp:179 gui/launcher.cpp:180
+msgid "Full title of the game"
+msgstr "Títol complet del joc"
+
+#: gui/launcher.cpp:183
+msgid "Language:"
+msgstr "Idioma:"
+
+#: gui/launcher.cpp:183 gui/launcher.cpp:184
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+"Idioma del joc. Això no convertirà la vostra versió Espanyola del joc a "
+"Anglès"
+
+#: gui/launcher.cpp:185 gui/launcher.cpp:196 gui/options.cpp:80
+#: gui/options.cpp:635 gui/options.cpp:645 gui/options.cpp:1000
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<per defecte>"
+
+#: gui/launcher.cpp:194
+msgid "Platform:"
+msgstr "Plataforma:"
+
+#: gui/launcher.cpp:194 gui/launcher.cpp:195
+msgid "Platform the game was originally designed for"
+msgstr "Plataforma per la que el joc es va dissenyar originalment"
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "Graphics"
+msgstr "Gràfics"
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "GFX"
+msgstr "GFX"
+
+#: gui/launcher.cpp:208
+msgid "Override global graphic settings"
+msgstr "Fer canvis sobre les opcions globals de gràfics"
+
+#: gui/launcher.cpp:215 gui/options.cpp:921
+msgid "Audio"
+msgstr "Àudio"
+
+#: gui/launcher.cpp:217
+msgid "Override global audio settings"
+msgstr "Fer canvis sobre les opcions globals d'àudio"
+
+#: gui/launcher.cpp:225 gui/options.cpp:925
+msgid "Volume"
+msgstr "Volum"
+
+#: gui/launcher.cpp:227
+msgid "Override global volume settings"
+msgstr "Fer canvis sobre les opcions globals de volum"
+
+#: gui/launcher.cpp:234 gui/options.cpp:933
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:236
+msgid "Override global MIDI settings"
+msgstr "Fer canvis sobre les opcions globals de MIDI"
+
+#: gui/launcher.cpp:246 gui/options.cpp:939
+msgid "MT-32"
+msgstr ""
+
+#: gui/launcher.cpp:248
+#, fuzzy
+msgid "Override global MT-32 settings"
+msgstr "Fer canvis sobre les opcions globals de MIDI"
+
+#: gui/launcher.cpp:258 gui/options.cpp:945
+msgid "Paths"
+msgstr "Camins"
+
+#: gui/launcher.cpp:264
+msgid "Game Path:"
+msgstr "Camí del Joc:"
+
+#: gui/launcher.cpp:268 gui/options.cpp:958
+msgid "Extra Path:"
+msgstr "Camí Extra:"
+
+#: gui/launcher.cpp:268 gui/launcher.cpp:269
+msgid "Specifies path to additional data used the game"
+msgstr "Especifica el camí de dades addicionals utilitzades pel joc"
+
+#: gui/launcher.cpp:272
+msgid "Save Path:"
+msgstr "Camí de les Partides:"
+
+#: gui/launcher.cpp:272 gui/launcher.cpp:273 gui/options.cpp:952
+#: gui/options.cpp:953
+msgid "Specifies where your savegames are put"
+msgstr "Especifica on es desaran les partides"
+
+#: gui/launcher.cpp:289 gui/launcher.cpp:369 gui/launcher.cpp:418
+#: gui/options.cpp:230 gui/options.cpp:399 gui/options.cpp:497
+#: gui/options.cpp:555 gui/options.cpp:732 gui/options.cpp:956
+#: gui/options.cpp:959 gui/options.cpp:963 gui/options.cpp:1053
+#: gui/options.cpp:1059 gui/options.cpp:1065 gui/options.cpp:1073
+#: gui/options.cpp:1097 gui/options.cpp:1101 gui/options.cpp:1107
+#: gui/options.cpp:1114 gui/options.cpp:1213
+msgid "None"
+msgstr "Cap"
+
+#: gui/launcher.cpp:294 gui/launcher.cpp:373
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "Per defecte"
+
+#: gui/launcher.cpp:411 gui/options.cpp:1207
+msgid "Select SoundFont"
+msgstr "Seleccioneu el fitxer SoundFont"
+
+#: gui/launcher.cpp:430 gui/launcher.cpp:568
+msgid "Select directory with game data"
+msgstr "Seleccioneu el directori amb les dades del joc"
+
+#: gui/launcher.cpp:448
+msgid "Select additional game directory"
+msgstr "Seleccioneu el directori addicional del joc"
+
+#: gui/launcher.cpp:460
+msgid "Select directory for saved games"
+msgstr "Seleccioneu el directori de les partides desades"
+
+#: gui/launcher.cpp:479
+msgid "This game ID is already taken. Please choose another one."
+msgstr ""
+"Aquest identificador de joc ja està usat. Si us plau, trieu-ne un altre."
+
+#: gui/launcher.cpp:520 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "~T~anca"
+
+#: gui/launcher.cpp:520
+msgid "Quit ScummVM"
+msgstr "Surt de ScummVM"
+
+#: gui/launcher.cpp:521
+msgid "A~b~out..."
+msgstr "~Q~uant a..."
+
+#: gui/launcher.cpp:521
+msgid "About ScummVM"
+msgstr "Quant a ScummVM"
+
+#: gui/launcher.cpp:522
+msgid "~O~ptions..."
+msgstr "~O~pcions..."
+
+#: gui/launcher.cpp:522
+msgid "Change global ScummVM options"
+msgstr "Canvia les opcions globals de ScummVM"
+
+#: gui/launcher.cpp:524
+msgid "~S~tart"
+msgstr "~I~nicia"
+
+#: gui/launcher.cpp:524
+msgid "Start selected game"
+msgstr "Iniciant el joc seleccionat"
+
+#: gui/launcher.cpp:527
+msgid "~L~oad..."
+msgstr "~C~arrega..."
+
+#: gui/launcher.cpp:527
+msgid "Load savegame for selected game"
+msgstr "Carrega una partida pel joc seleccionat"
+
+#: gui/launcher.cpp:531
+msgid "~A~dd Game..."
+msgstr "~A~fegeix Joc..."
+
+#: gui/launcher.cpp:531
+msgid "Hold Shift for Mass Add"
+msgstr "Mantingueu premut Shift per a l'Addició Massiva"
+
+#: gui/launcher.cpp:533
+msgid "~E~dit Game..."
+msgstr "~E~dita Joc..."
+
+#: gui/launcher.cpp:533
+msgid "Change game options"
+msgstr "Canvia les opcions del joc"
+
+#: gui/launcher.cpp:535
+msgid "~R~emove Game"
+msgstr "~S~uprimeix Joc"
+
+#: gui/launcher.cpp:535
+msgid "Remove game from the list. The game data files stay intact"
+msgstr ""
+"Elimina un joc de la llista. Els fitxers de dades del joc es mantenen "
+"intactes"
+
+#: gui/launcher.cpp:542
+msgid "Search in game list"
+msgstr "Cerca a la llista de jocs"
+
+#: gui/launcher.cpp:546 gui/launcher.cpp:1057
+msgid "Search:"
+msgstr "Cerca:"
+
+#: gui/launcher.cpp:549 gui/options.cpp:733
+msgid "Clear value"
+msgstr "Neteja el valor"
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "Carrega partida:"
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "Carrega"
+
+#: gui/launcher.cpp:680
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+"Esteu segur que voleu executar el detector massiu de jocs? Això pot afegir "
+"una gran quantitat de jocs."
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Yes"
+msgstr "Sí"
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "No"
+msgstr "No"
+
+#: gui/launcher.cpp:728
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM no ha pogut obrir el directori especificat!"
+
+#: gui/launcher.cpp:740
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr "ScummVM no ha pogut trobar cap joc al directori especificat!"
+
+#: gui/launcher.cpp:754
+msgid "Pick the game:"
+msgstr "Seleccioneu el joc:"
+
+#: gui/launcher.cpp:830
+msgid "Do you really want to remove this game configuration?"
+msgstr "Realment voleu suprimir la configuració d'aquest joc?"
+
+#: gui/launcher.cpp:893
+msgid "This game does not support loading games from the launcher."
+msgstr "Aquest joc no suporta la càrrega de partides des del llançador."
+
+#: gui/launcher.cpp:897
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr ""
+"ScummVM no ha pogut trobar cap motor capaç d'executar el joc seleccionat!"
+
+#: gui/launcher.cpp:1009
+msgid "Mass Add..."
+msgstr "Addició Massiva..."
+
+#: gui/launcher.cpp:1010
+msgid "Add Game..."
+msgstr "Afegeix Joc..."
+
+#: gui/massadd.cpp:79 gui/massadd.cpp:82
+msgid "... progress ..."
+msgstr "... progrés ..."
+
+#: gui/massadd.cpp:244
+msgid "Scan complete!"
+msgstr "S'ha acabat la cerca!"
+
+#: gui/massadd.cpp:247
+#, c-format
+msgid "Discovered %d new games."
+msgstr "S'han descobert %d jocs nous."
+
+#: gui/massadd.cpp:251
+#, c-format
+msgid "Scanned %d directories ..."
+msgstr "S'han cercat %d directoris ..."
+
+#: gui/massadd.cpp:254
+#, c-format
+msgid "Discovered %d new games ..."
+msgstr "S'han descobert %d jocs nous ..."
+
+#: gui/options.cpp:78
+msgid "Never"
+msgstr "Mai"
+
+#: gui/options.cpp:78
+msgid "every 5 mins"
+msgstr "cada 5 minuts"
+
+#: gui/options.cpp:78
+msgid "every 10 mins"
+msgstr "cada 10 minuts"
+
+#: gui/options.cpp:78
+msgid "every 15 mins"
+msgstr "cada 15 minuts"
+
+#: gui/options.cpp:78
+msgid "every 30 mins"
+msgstr "cada 30 minuts"
+
+#: gui/options.cpp:80
+msgid "8 kHz"
+msgstr "8 kHz"
+
+#: gui/options.cpp:80
+msgid "11kHz"
+msgstr "11kHz"
+
+#: gui/options.cpp:80
+msgid "22 kHz"
+msgstr "22 kHz"
+
+#: gui/options.cpp:80
+msgid "44 kHz"
+msgstr "44 kHz"
+
+#: gui/options.cpp:80
+msgid "48 kHz"
+msgstr "48 kHz"
+
+#: gui/options.cpp:632
+msgid "Graphics mode:"
+msgstr "Mode gràfic:"
+
+#: gui/options.cpp:643
+msgid "Render mode:"
+msgstr "Mode de pintat:"
+
+#: gui/options.cpp:643 gui/options.cpp:644
+msgid "Special dithering modes supported by some games"
+msgstr "Modes de dispersió especials suportats per alguns jocs"
+
+#: gui/options.cpp:653
+msgid "Fullscreen mode"
+msgstr "Mode pantalla completa"
+
+#: gui/options.cpp:656
+msgid "Aspect ratio correction"
+msgstr "Correcció del rati d'aspecte"
+
+#: gui/options.cpp:656
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "Corregeix la relació d'aspecte per jocs de 320x200"
+
+#: gui/options.cpp:663
+msgid "Preferred Device:"
+msgstr "Dispositiu Preferit:"
+
+#: gui/options.cpp:663
+#, fuzzy
+msgid "Music Device:"
+msgstr "Dispositiu GM:"
+
+#: gui/options.cpp:663
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr "Especifica el dispositiu de so o l'emulador de tarja de so preferit"
+
+#: gui/options.cpp:663 gui/options.cpp:664
+msgid "Specifies output sound device or sound card emulator"
+msgstr "Especifica el dispositiu de so o l'emulador de tarja de so de sortida"
+
+#: gui/options.cpp:688
+msgid "AdLib emulator:"
+msgstr "Emulador d'AdLib:"
+
+#: gui/options.cpp:688 gui/options.cpp:689
+msgid "AdLib is used for music in many games"
+msgstr "AdLib s'utilitza per la música de molts jocs"
+
+#: gui/options.cpp:699
+msgid "Output rate:"
+msgstr "Freqüència de sortida:"
+
+#: gui/options.cpp:699 gui/options.cpp:700
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+"Valors més alts especifiquen millor qualitat de so però pot ser que la "
+"vostra tarja de so no ho suporti"
+
+#: gui/options.cpp:710
+msgid "GM Device:"
+msgstr "Dispositiu GM:"
+
+#: gui/options.cpp:710
+msgid "Specifies default sound device for General MIDI output"
+msgstr ""
+"Especifica el dispositiu de so per defecte per a la sortida General MIDI"
+
+#: gui/options.cpp:731
+msgid "SoundFont:"
+msgstr "Fitxer SoundFont:"
+
+#: gui/options.cpp:731 gui/options.cpp:732
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr "Algunes targes de so, Fluidsynth i Timidity suporten SoundFont"
+
+#: gui/options.cpp:736
+msgid "Mixed AdLib/MIDI mode"
+msgstr "Mode combinat AdLib/MIDI"
+
+#: gui/options.cpp:736
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "Utilitza MIDI i la generació de so AdLib alhora"
+
+#: gui/options.cpp:739
+msgid "MIDI gain:"
+msgstr "Guany MIDI:"
+
+#: gui/options.cpp:749
+#, fuzzy
+msgid "MT-32 Device:"
+msgstr "Dispositiu MT32:"
+
+#: gui/options.cpp:749
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr ""
+"Especifica el dispositiu de so per defecte per a la sortida de Roland MT-32/"
+"LAPC1/CM32l/CM64"
+
+#: gui/options.cpp:753
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Roland MT-32 real (desactiva l'emulació GM)"
+
+#: gui/options.cpp:753
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+"Marqueu si voleu utilitzar el vostre dispositiu hardware real de so "
+"compatible amb Roland connectat al vostre ordinador"
+
+#: gui/options.cpp:756
+msgid "Enable Roland GS Mode"
+msgstr "Activa el Mode Roland GS"
+
+#: gui/options.cpp:756
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr ""
+"Desactiva la conversió General MIDI pels jocs que tenen banda sonora per a "
+"Roland MT-32"
+
+#: gui/options.cpp:780
+msgid "Text and Speech:"
+msgstr "Text i Veus:"
+
+#: gui/options.cpp:785 gui/options.cpp:791
+msgid "Speech"
+msgstr "Veus"
+
+#: gui/options.cpp:786 gui/options.cpp:792
+msgid "Subtitles"
+msgstr "Subtítols"
+
+#: gui/options.cpp:787 gui/options.cpp:793
+msgid "Both"
+msgstr "Ambdós"
+
+#: gui/options.cpp:791
+msgid "Spch"
+msgstr "Veus"
+
+#: gui/options.cpp:792
+msgid "Subs"
+msgstr "Subt"
+
+#: gui/options.cpp:793
+msgid "Show subtitles and play speech"
+msgstr "Mostra els subtítols i reprodueix la veu"
+
+#: gui/options.cpp:797
+msgid "Subtitle speed:"
+msgstr "Velocitat dels subtítols:"
+
+#: gui/options.cpp:809
+msgid "Music volume:"
+msgstr "Volum de la música:"
+
+#: gui/options.cpp:816
+msgid "Mute All"
+msgstr "Silenciar tot"
+
+#: gui/options.cpp:819
+msgid "SFX volume:"
+msgstr "Volum dels efectes:"
+
+#: gui/options.cpp:819 gui/options.cpp:820
+msgid "Special sound effects volume"
+msgstr "Volum dels sons d'efectes especials"
+
+#: gui/options.cpp:826
+msgid "Speech volume:"
+msgstr "Volum de la veu:"
+
+#: gui/options.cpp:952
+msgid "Save Path: "
+msgstr "Camí de les Partides: "
+
+#: gui/options.cpp:955
+msgid "Theme Path:"
+msgstr "Camí dels Temes:"
+
+#: gui/options.cpp:958 gui/options.cpp:959
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr ""
+"Especifica el camí de les dades addicionals utilitzades per tots els jocs o "
+"pel ScummVM"
+
+#: gui/options.cpp:962
+msgid "Plugins Path:"
+msgstr "Camí dels connectors:"
+
+#: gui/options.cpp:970
+msgid "Misc"
+msgstr "Misc"
+
+#: gui/options.cpp:972
+msgid "Theme:"
+msgstr "Tema:"
+
+#: gui/options.cpp:976
+msgid "GUI Renderer:"
+msgstr "Mode de pintat de la interfície d'usuari:"
+
+#: gui/options.cpp:982
+msgid "Autosave:"
+msgstr "Desat automàtic:"
+
+#: gui/options.cpp:990
+msgid "Keys"
+msgstr "Tecles"
+
+#: gui/options.cpp:997
+msgid "GUI Language:"
+msgstr "Idioma de la interfície d'usuari:"
+
+#: gui/options.cpp:997
+msgid "Language of ScummVM GUI"
+msgstr "Idioma de la interfície d'usuari de ScummVM"
+
+#: gui/options.cpp:1002
+msgid "English"
+msgstr "Anglès"
+
+#: gui/options.cpp:1146
+msgid "You have to restart ScummVM to take the effect."
+msgstr "Heu de reiniciar ScummVM perquè tots els canvis tingui efecte."
+
+#: gui/options.cpp:1159
+msgid "Select directory for savegames"
+msgstr "Seleccioneu el directori de les partides desades"
+
+#: gui/options.cpp:1166
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr ""
+"No es pot escriure al directori seleccionat. Si us plau, escolliu-ne un "
+"altre."
+
+#: gui/options.cpp:1175
+msgid "Select directory for GUI themes"
+msgstr "Seleccioneu el directori dels temes de la Interfície d'Usuari"
+
+#: gui/options.cpp:1185
+msgid "Select directory for extra files"
+msgstr "Seleccioneu el directori dels fitxers extra"
+
+#: gui/options.cpp:1196
+msgid "Select directory for plugins"
+msgstr "Seleccioneu el directori dels connectors"
+
+#: gui/saveload.cpp:60 gui/saveload.cpp:241
+msgid "No date saved"
+msgstr "No hi ha data desada"
+
+#: gui/saveload.cpp:61 gui/saveload.cpp:242
+msgid "No time saved"
+msgstr "No hi ha hora desada"
+
+#: gui/saveload.cpp:62 gui/saveload.cpp:243
+msgid "No playtime saved"
+msgstr "No hi ha temps de joc desat"
+
+#: gui/saveload.cpp:69 gui/saveload.cpp:157
+msgid "Delete"
+msgstr "Suprimeix"
+
+#: gui/saveload.cpp:156
+msgid "Do you really want to delete this savegame?"
+msgstr "Realment voleu suprimir aquesta partida?"
+
+#: gui/saveload.cpp:265
+msgid "Date: "
+msgstr "Data: "
+
+#: gui/saveload.cpp:268
+msgid "Time: "
+msgstr "Hora: "
+
+#: gui/saveload.cpp:273
+msgid "Playtime: "
+msgstr "Temps de joc: "
+
+#: gui/saveload.cpp:286 gui/saveload.cpp:353
+msgid "Untitled savestate"
+msgstr "Partida sense títol"
+
+#: gui/themebrowser.cpp:46
+msgid "Select a Theme"
+msgstr "Seleccioneu un Tema"
+
+#: gui/ThemeEngine.cpp:334
+msgid "Disabled GFX"
+msgstr "GFX desactivats"
+
+#: gui/ThemeEngine.cpp:335
+msgid "Standard Renderer (16bpp)"
+msgstr "Pintat estàndard (16bpp)"
+
+#: gui/ThemeEngine.cpp:337
+msgid "Antialiased Renderer (16bpp)"
+msgstr "Pintat amb antialias (16bpp)"
+
+#: base/main.cpp:205
+#, c-format
+msgid "Engine does not support debug level '%s'"
+msgstr "El motor no suporta el nivell de depuració '%s'"
+
+#: base/main.cpp:273
+msgid "Menu"
+msgstr "Menú"
+
+#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48
+#: backends/platform/wince/CEActionsPocket.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:45
+msgid "Skip"
+msgstr "Salta"
+
+#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53
+#: backends/platform/wince/CEActionsPocket.cpp:41
+msgid "Pause"
+msgstr "Pausa"
+
+#: base/main.cpp:282
+msgid "Skip line"
+msgstr "Salta la línia"
+
+#: base/main.cpp:404
+msgid "Error running game:"
+msgstr "Error al executar el joc:"
+
+#: base/main.cpp:430 base/main.cpp:431
+msgid "Could not find any engine capable of running the selected game"
+msgstr "No s'ha pogut trobar cap motor capaç d'executar el joc seleccionat"
+
+#: common/error.cpp:43
+msgid "Invalid Path"
+msgstr "Camí incorrecte"
+
+#: common/error.cpp:44
+msgid "Game Data not found"
+msgstr "No s'han trobat les dades del joc"
+
+#: common/error.cpp:45
+msgid "Game Id not supported"
+msgstr "Identificador de joc no suportat"
+
+#: common/error.cpp:46
+msgid "Unsupported Color Mode"
+msgstr "Mode de color no suportat"
+
+#: common/error.cpp:48
+msgid "Read permission denied"
+msgstr "S'ha denegat el permís de lectura"
+
+#: common/error.cpp:49
+msgid "Write permission denied"
+msgstr "S'ha denegat el permís d'escriptura"
+
+#: common/error.cpp:52
+msgid "Path not exists"
+msgstr "El camí no existeix"
+
+#: common/error.cpp:53
+msgid "Path not a directory"
+msgstr "El camí no és un directori"
+
+#: common/error.cpp:54
+msgid "Path not a file"
+msgstr "El camí no és un fitxer"
+
+#: common/error.cpp:56
+msgid "Cannot create file"
+msgstr "No s'ha pogut crear el fitxer"
+
+#: common/error.cpp:57
+msgid "Reading failed"
+msgstr "Ha fallat la lectura"
+
+#: common/error.cpp:58
+msgid "Writing data failed"
+msgstr "Ha fallat l'escriptura de dades"
+
+#: common/error.cpp:60 common/error.cpp:71
+msgid "Unknown Error"
+msgstr "Error desconegut"
+
+#: common/util.cpp:254
+msgid "Hercules Green"
+msgstr "Hercules Verd"
+
+#: common/util.cpp:255
+msgid "Hercules Amber"
+msgstr "Hercules Àmbar"
+
+#: engines/dialogs.cpp:89
+msgid "~R~esume"
+msgstr "~C~ontinua"
+
+#: engines/dialogs.cpp:91
+msgid "~L~oad"
+msgstr "C~a~rrega"
+
+#: engines/dialogs.cpp:95
+msgid "~S~ave"
+msgstr "~D~esa"
+
+#: engines/dialogs.cpp:99
+msgid "~O~ptions"
+msgstr "~O~pcions"
+
+#: engines/dialogs.cpp:104
+msgid "~H~elp"
+msgstr "~A~juda"
+
+#: engines/dialogs.cpp:107
+msgid "~A~bout"
+msgstr "~Q~uant a"
+
+#: engines/dialogs.cpp:109
+msgid "~R~eturn to Launcher"
+msgstr "~R~etorna al Llançador"
+
+#: engines/dialogs.cpp:119
+msgid "Save game:"
+msgstr "Desa la partida:"
+
+#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47
+#: backends/platform/wince/CEActionsPocket.cpp:42
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Save"
+msgstr "Desa"
+
+#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84
+#: engines/mohawk/dialogs.cpp:118
+msgid "~O~K"
+msgstr "~D~'acord"
+
+#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85
+#: engines/mohawk/dialogs.cpp:119
+msgid "~C~ancel"
+msgstr "~C~ancel·la"
+
+#: engines/dialogs.cpp:305
+msgid "~K~eys"
+msgstr "~T~ecles"
+
+#: engines/scumm/dialogs.cpp:287
+msgid "~P~revious"
+msgstr "~A~nterior"
+
+#: engines/scumm/dialogs.cpp:288
+msgid "~N~ext"
+msgstr "~S~egüent"
+
+#: engines/scumm/dialogs.cpp:289
+#: backends/platform/ds/arm9/source/dsoptions.cpp:59
+msgid "~C~lose"
+msgstr "~T~anca"
+
+#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115
+msgid "~Z~ip Mode Activated"
+msgstr "Mode ~Z~ip activat"
+
+#: engines/mohawk/dialogs.cpp:82
+msgid "~T~ransitions Enabled"
+msgstr "~T~ransicions activades"
+
+#: engines/mohawk/dialogs.cpp:116
+msgid "~W~ater Effect Enabled"
+msgstr "~E~fecte de l'aigua activat"
+
+#: sound/fmopl.cpp:51
+msgid "MAME OPL emulator"
+msgstr "Emulador OPL de MAME"
+
+#: sound/fmopl.cpp:53
+msgid "DOSBox OPL emulator"
+msgstr "Emulador OPL de DOSBox"
+
+#: sound/null.h:45
+msgid "No music"
+msgstr "Sense música"
+
+#: sound/softsynth/adlib.cpp:1590
+msgid "AdLib Emulator"
+msgstr "Emulador d'AdLib"
+
+#: sound/softsynth/mt32.cpp:327
+msgid "Initialising MT-32 Emulator"
+msgstr "Iniciant l'Emulador de MT-32"
+
+#: sound/softsynth/mt32.cpp:541
+msgid "MT-32 Emulator"
+msgstr "Emulador de MT-32"
+
+#: sound/softsynth/pcspk.cpp:142
+msgid "PC Speaker Emulator"
+msgstr "Emulador d'Altaveu de PC"
+
+#: sound/softsynth/pcspk.cpp:161
+msgid "IBM PCjr Emulator"
+msgstr "Emulador d'IBM PCjr"
+
+#: sound/softsynth/ym2612.cpp:762
+msgid "FM Towns Emulator"
+msgstr "Emulador de FM Towns"
+
+#: backends/keymapper/remap-dialog.cpp:49
+msgid "Keymap:"
+msgstr "Mapa de teclat:"
+
+#: backends/keymapper/remap-dialog.cpp:66
+msgid " (Active)"
+msgstr " (Actiu)"
+
+#: backends/keymapper/remap-dialog.cpp:100
+msgid " (Global)"
+msgstr " (Global)"
+
+#: backends/keymapper/remap-dialog.cpp:110
+msgid " (Game)"
+msgstr " (Joc)"
+
+#: backends/midi/windows.cpp:157
+msgid "Windows MIDI"
+msgstr "MIDI de Windows"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:60
+msgid "ScummVM Main Menu"
+msgstr "Menú Principal de ScummVM"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:66
+msgid "~L~eft handed mode"
+msgstr "Mode ~e~squerrà"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:67
+msgid "~I~ndy fight controls"
+msgstr "Controls de lluita de l'~I~ndy"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:68
+msgid "Show mouse cursor"
+msgstr "Mostra el cursor del ratolí"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:69
+msgid "Snap to edges"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:71
+msgid "Touch X Offset"
+msgstr "Desplaçament X del toc"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:78
+msgid "Touch Y Offset"
+msgstr "Desplaçament Y del toc"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:90
+msgid "Use laptop trackpad-style cursor control"
+msgstr "Utilitza el control del cursor a l'estil del trackpad dels portàtils"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:91
+msgid "Tap for left click, double tap right click"
+msgstr "Toc per a clic esquerre, doble toc per a clic dret"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:93
+msgid "Sensitivity"
+msgstr "Sensibilitat"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:102
+msgid "Initial top screen scale:"
+msgstr "Escalat inicial de la pantalla superior:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:108
+msgid "Main screen scaling:"
+msgstr "Escalat de la pantalla principal:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:110
+msgid "Hardware scale (fast, but low quality)"
+msgstr "Escalat per hardware (ràpid, però de baixa qualitat)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:111
+msgid "Software scale (good quality, but slower)"
+msgstr "Escalat per software (bona qualitat, però més lent)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:112
+msgid "Unscaled (you must scroll left and right)"
+msgstr "Sense escalar (haureu de desplaçar-vos a esquerra i dreta)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:114
+msgid "Brightness:"
+msgstr "Brillantor:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:124
+msgid "High quality audio (slower) (reboot)"
+msgstr "Alta qualitat d'àudio (més lent) (reiniciar)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:125
+msgid "Disable power off"
+msgstr "Desactiva l'apagat automàtic"
+
+#: backends/platform/iphone/osys_events.cpp:339
+msgid "Touchpad mode enabled."
+msgstr "Mode Touchpad activat."
+
+#: backends/platform/iphone/osys_events.cpp:341
+msgid "Touchpad mode disabled."
+msgstr "Mode Touchpad desactivat."
+
+#: backends/platform/sdl/graphics.cpp:40
+#: backends/platform/wince/wince-sdl.cpp:111
+#: backends/platform/wince/wince-sdl.cpp:118
+msgid "Normal (no scaling)"
+msgstr "Normal (sense escalar)"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:41
+#: backends/platform/wince/CEActionsSmartphone.cpp:38
+msgid "Up"
+msgstr "Amunt"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:42
+#: backends/platform/wince/CEActionsSmartphone.cpp:39
+msgid "Down"
+msgstr "Avall"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:40
+msgid "Left"
+msgstr "Esquerra"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:41
+msgid "Right"
+msgstr "Dreta"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:45
+#: backends/platform/wince/CEActionsPocket.cpp:59
+#: backends/platform/wince/CEActionsSmartphone.cpp:42
+msgid "Left Click"
+msgstr "Clic esquerre"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:46
+#: backends/platform/wince/CEActionsSmartphone.cpp:43
+msgid "Right Click"
+msgstr "Clic dret"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:49
+#: backends/platform/wince/CEActionsSmartphone.cpp:46
+msgid "Zone"
+msgstr "Zona"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:50
+#: backends/platform/wince/CEActionsPocket.cpp:53
+#: backends/platform/wince/CEActionsSmartphone.cpp:47
+msgid "Multi Function"
+msgstr "Funció Múltiple"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:51
+msgid "Swap character"
+msgstr "Commuta el personatge"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:52
+msgid "Skip text"
+msgstr "Salta el text"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:54
+msgid "Fast mode"
+msgstr "Mode ràpid"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:55
+#: backends/platform/wince/CEActionsPocket.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:51
+msgid "Quit"
+msgstr "Surt"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:56
+msgid "Debugger"
+msgstr "Depurador"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:57
+msgid "Global menu"
+msgstr "Menú global"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:58
+msgid "Virtual keyboard"
+msgstr "Teclat virtual"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:59
+msgid "Key mapper"
+msgstr "Mapejador de tecles"
+
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+msgid "Do you want to quit ?"
+msgstr "Vols sortir?"
+
+#: backends/platform/wii/options.cpp:51
+msgid "Video"
+msgstr "Vídeo"
+
+#: backends/platform/wii/options.cpp:54
+msgid "Current video mode:"
+msgstr "Mode de vídeo actual:"
+
+#: backends/platform/wii/options.cpp:56
+msgid "Double-strike"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:60
+msgid "Horizontal underscan:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:66
+msgid "Vertical underscan:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:71
+msgid "Input"
+msgstr "Entrada"
+
+#: backends/platform/wii/options.cpp:74
+msgid "GC Pad sensitivity:"
+msgstr "Sensibilitat del Pad GC:"
+
+#: backends/platform/wii/options.cpp:80
+msgid "GC Pad acceleration:"
+msgstr "Acceleració del Pad GC:"
+
+#: backends/platform/wii/options.cpp:86
+msgid "DVD"
+msgstr "DVD"
+
+#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101
+msgid "Status:"
+msgstr "Estat:"
+
+#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102
+msgid "Unknown"
+msgstr "Desconegut"
+
+#: backends/platform/wii/options.cpp:93
+msgid "Mount DVD"
+msgstr "Munta el DVD"
+
+#: backends/platform/wii/options.cpp:94
+msgid "Unmount DVD"
+msgstr "Desmunta el DVD"
+
+#: backends/platform/wii/options.cpp:98
+msgid "SMB"
+msgstr "SMB"
+
+#: backends/platform/wii/options.cpp:106
+msgid "Server:"
+msgstr "Servidor:"
+
+#: backends/platform/wii/options.cpp:110
+msgid "Share:"
+msgstr "Compartició:"
+
+#: backends/platform/wii/options.cpp:114
+msgid "Username:"
+msgstr "Nom d'usuari:"
+
+#: backends/platform/wii/options.cpp:118
+msgid "Password:"
+msgstr "Contrasenya:"
+
+#: backends/platform/wii/options.cpp:121
+msgid "Init network"
+msgstr "Inicia la xarxa"
+
+#: backends/platform/wii/options.cpp:123
+msgid "Mount SMB"
+msgstr "Munta SMB"
+
+#: backends/platform/wii/options.cpp:124
+msgid "Unmount SMB"
+msgstr "Desmunta SMB"
+
+#: backends/platform/wii/options.cpp:145
+msgid "DVD Mounted successfully"
+msgstr "El DVD s'ha muntat satisfactòriament"
+
+#: backends/platform/wii/options.cpp:148
+msgid "Error while mounting the DVD"
+msgstr "Error al muntar el DVD"
+
+#: backends/platform/wii/options.cpp:150
+msgid "DVD not mounted"
+msgstr "El DVD no està muntat"
+
+#: backends/platform/wii/options.cpp:163
+msgid "Network up, share mounted"
+msgstr "Xarxa activa, compartició muntada"
+
+#: backends/platform/wii/options.cpp:165
+msgid "Network up"
+msgstr "Xarxa activa"
+
+#: backends/platform/wii/options.cpp:168
+msgid ", error while mounting the share"
+msgstr ", error al muntar la compartició"
+
+#: backends/platform/wii/options.cpp:170
+msgid ", share not mounted"
+msgstr ", compartició no muntada"
+
+#: backends/platform/wii/options.cpp:176
+msgid "Network down"
+msgstr "Xarxa inactiva"
+
+#: backends/platform/wii/options.cpp:180
+msgid "Initialising network"
+msgstr "Iniciant la xarxa"
+
+#: backends/platform/wii/options.cpp:184
+msgid "Timeout while initialising network"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:188
+#, c-format
+msgid "Network not initialsed (%d)"
+msgstr "Xarxa no iniciada (%d)"
+
+#: backends/platform/wince/CEActionsPocket.cpp:45
+msgid "Hide Toolbar"
+msgstr "Oculta la barra d'eines"
+
+#: backends/platform/wince/CEActionsPocket.cpp:46
+msgid "Show Keyboard"
+msgstr "Mostra el teclat"
+
+#: backends/platform/wince/CEActionsPocket.cpp:47
+msgid "Sound on/off"
+msgstr "So engegat/parat"
+
+#: backends/platform/wince/CEActionsPocket.cpp:48
+msgid "Right click"
+msgstr "Clic dret"
+
+#: backends/platform/wince/CEActionsPocket.cpp:49
+msgid "Show/Hide Cursor"
+msgstr "Mostra/Oculta el cursor"
+
+#: backends/platform/wince/CEActionsPocket.cpp:50
+msgid "Free look"
+msgstr "Vista lliure"
+
+#: backends/platform/wince/CEActionsPocket.cpp:51
+msgid "Zoom up"
+msgstr "Amplia"
+
+#: backends/platform/wince/CEActionsPocket.cpp:52
+msgid "Zoom down"
+msgstr "Redueix"
+
+#: backends/platform/wince/CEActionsPocket.cpp:54
+#: backends/platform/wince/CEActionsSmartphone.cpp:48
+msgid "Bind Keys"
+msgstr "Mapeja tecles"
+
+#: backends/platform/wince/CEActionsPocket.cpp:55
+msgid "Cursor Up"
+msgstr "Cursor Amunt"
+
+#: backends/platform/wince/CEActionsPocket.cpp:56
+msgid "Cursor Down"
+msgstr "Cursor Avall"
+
+#: backends/platform/wince/CEActionsPocket.cpp:57
+msgid "Cursor Left"
+msgstr "Cursor Esquerra"
+
+#: backends/platform/wince/CEActionsPocket.cpp:58
+msgid "Cursor Right"
+msgstr "Cursor Dreta"
+
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Do you want to load or save the game?"
+msgstr "Voleu carregar o desar el joc?"
+
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+msgid " Are you sure you want to quit ? "
+msgstr ""
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:49
+msgid "Keyboard"
+msgstr "Teclat"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:50
+msgid "Rotate"
+msgstr "Rotar"
+
+#: backends/platform/wince/CELauncherDialog.cpp:58
+msgid "Using SDL driver "
+msgstr "Utilitzant el controlador SDL "
+
+#: backends/platform/wince/CELauncherDialog.cpp:62
+msgid "Display "
+msgstr "Pantalla"
+
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Do you want to perform an automatic scan ?"
+msgstr "Voleu fer una cerca automàtica?"
+
+#~ msgid "Failed to load any GUI theme, aborting"
+#~ msgstr "No s'ha pogut carregar cap tema de la interfície d'usuari, avortant"
+
+#, fuzzy
+#~ msgid "User picked target '%s' (gameid '%s')...\n"
+#~ msgstr ""
+#~ "L'usuari ha seleccionat el target '%s' (identificador de joc '%s')...\n"
+
+#~ msgid " Looking for a plugin supporting this gameid... "
+#~ msgstr " Cercant un connector que suporti aquest identificador de joc... "
+
+#~ msgid "failed\n"
+#~ msgstr "ha fallat\n"
+
+#~ msgid ""
+#~ "%s is an invalid gameid. Use the --list-games option to list supported "
+#~ "gameid"
+#~ msgstr ""
+#~ "%s és un identificador de joc invàlid. Utilitzeu l'opció --list-games per "
+#~ "llistar els identificadors de joc suportats"
+
+#~ msgid " Starting '%s'\n"
+#~ msgstr " Iniciant '%s'\n"
+
+#, fuzzy
+#~ msgid "%s failed to instantiate engine: %s (target '%s', path '%s')"
+#~ msgstr "%s ha fallat l'iniciat del motor: %s (target '%s', camí '%s')"
+
+#~ msgid "Chinese (Taiwan)"
+#~ msgstr "Xinès (Taiwan)"
+
+#~ msgid "Czech"
+#~ msgstr "Txec"
+
+#~ msgid "Dutch"
+#~ msgstr "Danès"
+
+#~ msgid "English (GB)"
+#~ msgstr "Anglès (GB)"
+
+#~ msgid "English (US)"
+#~ msgstr "Anglès (EUA)"
+
+#~ msgid "French"
+#~ msgstr "Francès"
+
+#~ msgid "German"
+#~ msgstr "Alemany"
+
+#~ msgid "Hebrew"
+#~ msgstr "Hebreu"
+
+#~ msgid "Italian"
+#~ msgstr "Italià"
+
+#~ msgid "Japanese"
+#~ msgstr "Japonès"
+
+#~ msgid "Korean"
+#~ msgstr "Coreà"
+
+#~ msgid "Polish"
+#~ msgstr "Polac"
+
+#~ msgid "Portuguese"
+#~ msgstr "Portuguès"
+
+#~ msgid "Russian"
+#~ msgstr "Rus"
+
+#~ msgid "Spanish"
+#~ msgstr "Espanyol"
+
+#~ msgid "Swedish"
+#~ msgstr "Suís"
+
+#~ msgid "Failed to load MT32_CONTROL.ROM"
+#~ msgstr "No s'ha pogut carregar el fitxer MT32_CONTROL.ROM"
+
+#~ msgid "Failed to load MT32_PCM.ROM"
+#~ msgstr "No s'ha pogut carregar el fitxer MT32_PCM.ROM"
diff --git a/po/de_DE.po b/po/de_DE.po
new file mode 100644
index 0000000000..63e2307b43
--- /dev/null
+++ b/po/de_DE.po
@@ -0,0 +1,1451 @@
+# LANGUAGE translation for ScummVM.
+# Copyright (C) 2010 ScummVM Team
+# This file is distributed under the same license as the ScummVM package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ScummVM 1.2.0svn\n"
+"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
+"POT-Creation-Date: 2010-07-30 22:14+0100\n"
+"PO-Revision-Date: 2010-07-09 20:37+0100\n"
+"Last-Translator: Simon Sawatzki\n"
+"Language-Team: Lothar Serra Mari <Lothar@Windowsbase.de> & Simon Sawatzki "
+"<SimSaw@gmx.de>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: Deutsch\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: gui/about.cpp:96
+#, c-format
+msgid "(built on %s)"
+msgstr "(erstellt am %s)"
+
+#: gui/about.cpp:103
+msgid "Features compiled in:"
+msgstr "Verwendete Funktionen:"
+
+#: gui/about.cpp:112
+msgid "Available engines:"
+msgstr "Verfügbare Spiele-Engines:"
+
+#: gui/browser.cpp:69
+msgid "Go up"
+msgstr "Pfad hoch"
+
+#: gui/browser.cpp:69
+msgid "Go to previous directory level"
+msgstr "Zu höherer Pfadebene wechseln"
+
+#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46
+#: gui/launcher.cpp:280 gui/massadd.cpp:95 gui/options.cpp:1029
+#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56
+#: backends/platform/wii/options.cpp:48
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57
+msgid "Choose"
+msgstr "Auswählen"
+
+#: gui/GuiManager.cpp:103 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "Schließen"
+
+#: gui/GuiManager.cpp:106
+msgid "Mouse click"
+msgstr "Mausklick"
+
+#: gui/GuiManager.cpp:109 base/main.cpp:285
+msgid "Display keyboard"
+msgstr "Tastatur anzeigen"
+
+#: gui/GuiManager.cpp:112 base/main.cpp:288
+msgid "Remap keys"
+msgstr "Tasten neu zuweisen"
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr "Zuweisen"
+
+#: gui/KeysDialog.cpp:45 gui/launcher.cpp:281 gui/launcher.cpp:893
+#: gui/launcher.cpp:897 gui/massadd.cpp:92 gui/options.cpp:1030
+#: backends/platform/wii/options.cpp:47
+#: backends/platform/wince/CELauncherDialog.cpp:56
+msgid "OK"
+msgstr "OK"
+
+#: gui/KeysDialog.cpp:52
+msgid "Select an action and click 'Map'"
+msgstr "Aktion auswählen und \"Zuweisen\" klicken"
+
+#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144
+#, c-format
+msgid "Associated key : %s"
+msgstr "Zugewiesene Taste: %s"
+
+#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146
+#, c-format
+msgid "Associated key : none"
+msgstr "Zugewiesene Taste: keine"
+
+#: gui/KeysDialog.cpp:93
+msgid "Please select an action"
+msgstr "Bitte eine Aktion auswählen"
+
+#: gui/KeysDialog.cpp:109
+msgid "Press the key to associate"
+msgstr "Taste drücken, um sie zuzuweisen"
+
+#: gui/KeysDialog.cpp:148
+msgid "Choose an action to map"
+msgstr "Eine Aktion zum Zuweisen auswählen"
+
+#: gui/launcher.cpp:172
+msgid "Game"
+msgstr "Spiel"
+
+#: gui/launcher.cpp:175
+msgid "ID:"
+msgstr "Kennung:"
+
+#: gui/launcher.cpp:175 gui/launcher.cpp:176
+msgid ""
+"Short game identifier used for referring to savegames and running the game "
+"from the command line"
+msgstr ""
+"Kurzer Spielname, um die Spielstände zuzuordnen und das Spiel von der "
+"Kommandozeile aus starten zu können"
+
+#: gui/launcher.cpp:179
+msgid "Name:"
+msgstr "Name:"
+
+#: gui/launcher.cpp:179 gui/launcher.cpp:180
+msgid "Full title of the game"
+msgstr "Voller Name des Spiels"
+
+#: gui/launcher.cpp:183
+msgid "Language:"
+msgstr "Sprache:"
+
+#: gui/launcher.cpp:183 gui/launcher.cpp:184
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+"Sprache des Spiels. Diese Funktion wird nicht eine spanische Version des "
+"Spiels in eine deutsche verwandeln."
+
+#: gui/launcher.cpp:185 gui/launcher.cpp:196 gui/options.cpp:80
+#: gui/options.cpp:635 gui/options.cpp:645 gui/options.cpp:1000
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<Standard>"
+
+#: gui/launcher.cpp:194
+msgid "Platform:"
+msgstr "Plattform:"
+
+#: gui/launcher.cpp:194 gui/launcher.cpp:195
+msgid "Platform the game was originally designed for"
+msgstr "Plattform, für die das Spiel ursprünglich erstellt wurde"
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "Graphics"
+msgstr "Grafik"
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "GFX"
+msgstr "GFX"
+
+#: gui/launcher.cpp:208
+msgid "Override global graphic settings"
+msgstr "Globale Grafikeinstellungen übergehen"
+
+#: gui/launcher.cpp:215 gui/options.cpp:921
+msgid "Audio"
+msgstr "Audio"
+
+#: gui/launcher.cpp:217
+msgid "Override global audio settings"
+msgstr "Globale Audioeinstellungen übergehen"
+
+#: gui/launcher.cpp:225 gui/options.cpp:925
+msgid "Volume"
+msgstr "Lautstärke"
+
+#: gui/launcher.cpp:227
+msgid "Override global volume settings"
+msgstr "Globale Lautstärke-Einstellungen übergehen"
+
+#: gui/launcher.cpp:234 gui/options.cpp:933
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:236
+msgid "Override global MIDI settings"
+msgstr "Globale MIDI-Einstellungen übergehen"
+
+#: gui/launcher.cpp:246 gui/options.cpp:939
+msgid "MT-32"
+msgstr ""
+
+#: gui/launcher.cpp:248
+#, fuzzy
+msgid "Override global MT-32 settings"
+msgstr "Globale MIDI-Einstellungen übergehen"
+
+#: gui/launcher.cpp:258 gui/options.cpp:945
+msgid "Paths"
+msgstr "Pfade"
+
+#: gui/launcher.cpp:264
+msgid "Game Path:"
+msgstr "Spielpfad:"
+
+#: gui/launcher.cpp:268 gui/options.cpp:958
+msgid "Extra Path:"
+msgstr "Extrapfad:"
+
+#: gui/launcher.cpp:268 gui/launcher.cpp:269
+msgid "Specifies path to additional data used the game"
+msgstr "Legt das Verzeichnis für zusätzliche Spieldateien fest."
+
+#: gui/launcher.cpp:272
+msgid "Save Path:"
+msgstr "Spielstände:"
+
+#: gui/launcher.cpp:272 gui/launcher.cpp:273 gui/options.cpp:952
+#: gui/options.cpp:953
+msgid "Specifies where your savegames are put"
+msgstr "Legt fest, wo die Spielstände abgelegt werden."
+
+#: gui/launcher.cpp:289 gui/launcher.cpp:369 gui/launcher.cpp:418
+#: gui/options.cpp:230 gui/options.cpp:399 gui/options.cpp:497
+#: gui/options.cpp:555 gui/options.cpp:732 gui/options.cpp:956
+#: gui/options.cpp:959 gui/options.cpp:963 gui/options.cpp:1053
+#: gui/options.cpp:1059 gui/options.cpp:1065 gui/options.cpp:1073
+#: gui/options.cpp:1097 gui/options.cpp:1101 gui/options.cpp:1107
+#: gui/options.cpp:1114 gui/options.cpp:1213
+msgid "None"
+msgstr "-"
+
+#: gui/launcher.cpp:294 gui/launcher.cpp:373
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "Standard"
+
+#: gui/launcher.cpp:411 gui/options.cpp:1207
+msgid "Select SoundFont"
+msgstr "SoundFont auswählen"
+
+#: gui/launcher.cpp:430 gui/launcher.cpp:568
+msgid "Select directory with game data"
+msgstr "Verzeichnis mit Spieldateien auswählen"
+
+#: gui/launcher.cpp:448
+msgid "Select additional game directory"
+msgstr "Verzeichnis mit zusätzlichen Dateien auswählen"
+
+#: gui/launcher.cpp:460
+msgid "Select directory for saved games"
+msgstr "Verzeichnis für Spielstände auswählen"
+
+#: gui/launcher.cpp:479
+msgid "This game ID is already taken. Please choose another one."
+msgstr "Diese Spielkennung ist schon vergeben. Bitte eine andere wählen."
+
+#: gui/launcher.cpp:520 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "~B~eenden"
+
+#: gui/launcher.cpp:520
+msgid "Quit ScummVM"
+msgstr "ScummVM beenden"
+
+#: gui/launcher.cpp:521
+msgid "A~b~out..."
+msgstr "Übe~r~"
+
+#: gui/launcher.cpp:521
+msgid "About ScummVM"
+msgstr "Über ScummVM"
+
+#: gui/launcher.cpp:522
+msgid "~O~ptions..."
+msgstr "~O~ptionen"
+
+#: gui/launcher.cpp:522
+msgid "Change global ScummVM options"
+msgstr "Globale ScummVM-Einstellungen bearbeiten"
+
+#: gui/launcher.cpp:524
+msgid "~S~tart"
+msgstr "~S~tarten"
+
+#: gui/launcher.cpp:524
+msgid "Start selected game"
+msgstr "Ausgewähltes Spiel starten"
+
+#: gui/launcher.cpp:527
+msgid "~L~oad..."
+msgstr "~L~aden..."
+
+#: gui/launcher.cpp:527
+msgid "Load savegame for selected game"
+msgstr "Spielstand für ausgewähltes Spiel laden"
+
+#: gui/launcher.cpp:531
+msgid "~A~dd Game..."
+msgstr "Spiel ~h~inzufügen"
+
+#: gui/launcher.cpp:531
+msgid "Hold Shift for Mass Add"
+msgstr ""
+"Umschalttaste (Shift) gedrückt halten, um Verzeichnisse nach Spielen zu "
+"durchsuchen"
+
+#: gui/launcher.cpp:533
+msgid "~E~dit Game..."
+msgstr "Spielo~p~tionen"
+
+#: gui/launcher.cpp:533
+msgid "Change game options"
+msgstr "Spieloptionen ändern"
+
+#: gui/launcher.cpp:535
+msgid "~R~emove Game"
+msgstr "Spiel ~e~ntfernen"
+
+#: gui/launcher.cpp:535
+msgid "Remove game from the list. The game data files stay intact"
+msgstr "Spiel aus der Liste entfernen. Die Spieldateien bleiben erhalten."
+
+#: gui/launcher.cpp:542
+msgid "Search in game list"
+msgstr "In Spieleliste suchen"
+
+#: gui/launcher.cpp:546 gui/launcher.cpp:1057
+msgid "Search:"
+msgstr "Suchen:"
+
+#: gui/launcher.cpp:549 gui/options.cpp:733
+msgid "Clear value"
+msgstr "Wert löschen"
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "Spiel laden:"
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "Laden"
+
+#: gui/launcher.cpp:680
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+"Möchten Sie wirklich den PC nach Spielen durchsuchen? Möglicherweise wird "
+"dabei eine größere Menge an Spielen hinzugefügt."
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Yes"
+msgstr "Ja"
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "No"
+msgstr "Nein"
+
+#: gui/launcher.cpp:728
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM kann das gewählte Verzeichnis nicht öffnen!"
+
+#: gui/launcher.cpp:740
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr "ScummVM kann in dem gewählten Verzeichnis kein Spiel finden!"
+
+#: gui/launcher.cpp:754
+msgid "Pick the game:"
+msgstr "Spiel auswählen:"
+
+#: gui/launcher.cpp:830
+msgid "Do you really want to remove this game configuration?"
+msgstr "Möchten Sie wirklich diese Spielkonfiguration entfernen?"
+
+#: gui/launcher.cpp:893
+msgid "This game does not support loading games from the launcher."
+msgstr ""
+"Für dieses Spiel wird das Laden aus der Spieleliste heraus nicht unterstützt."
+
+#: gui/launcher.cpp:897
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr "ScummVM konnte keine Engine finden, um das Spiel zu starten!"
+
+#: gui/launcher.cpp:1009
+msgid "Mass Add..."
+msgstr "Durchsuchen"
+
+#: gui/launcher.cpp:1010
+msgid "Add Game..."
+msgstr "Spiel hinzufügen"
+
+#: gui/massadd.cpp:79 gui/massadd.cpp:82
+msgid "... progress ..."
+msgstr "... läuft..."
+
+#: gui/massadd.cpp:244
+msgid "Scan complete!"
+msgstr "Suchlauf abgeschlossen!"
+
+#: gui/massadd.cpp:247
+#, c-format
+msgid "Discovered %d new games."
+msgstr "%d neue Spiele gefunden."
+
+#: gui/massadd.cpp:251
+#, c-format
+msgid "Scanned %d directories ..."
+msgstr "%d Ordner durchsucht..."
+
+#: gui/massadd.cpp:254
+#, c-format
+msgid "Discovered %d new games ..."
+msgstr "%d neue Spiele gefunden..."
+
+#: gui/options.cpp:78
+msgid "Never"
+msgstr "Niemals"
+
+#: gui/options.cpp:78
+msgid "every 5 mins"
+msgstr "alle 5 Minuten"
+
+#: gui/options.cpp:78
+msgid "every 10 mins"
+msgstr "alle 10 Minuten"
+
+#: gui/options.cpp:78
+msgid "every 15 mins"
+msgstr "alle 15 Minuten"
+
+#: gui/options.cpp:78
+msgid "every 30 mins"
+msgstr "alle 30 Minuten"
+
+#: gui/options.cpp:80
+msgid "8 kHz"
+msgstr "8 kHz"
+
+#: gui/options.cpp:80
+msgid "11kHz"
+msgstr "11 kHz"
+
+#: gui/options.cpp:80
+msgid "22 kHz"
+msgstr "22 kHz"
+
+#: gui/options.cpp:80
+msgid "44 kHz"
+msgstr "44 kHz"
+
+#: gui/options.cpp:80
+msgid "48 kHz"
+msgstr "48 kHz"
+
+#: gui/options.cpp:632
+msgid "Graphics mode:"
+msgstr "Grafikmodus:"
+
+#: gui/options.cpp:643
+msgid "Render mode:"
+msgstr "Render-Modus:"
+
+#: gui/options.cpp:643 gui/options.cpp:644
+msgid "Special dithering modes supported by some games"
+msgstr ""
+"Spezielle Farbmischungsmethoden werden von manchen Spielen unterstützt."
+
+#: gui/options.cpp:653
+msgid "Fullscreen mode"
+msgstr "Vollbildmodus"
+
+#: gui/options.cpp:656
+msgid "Aspect ratio correction"
+msgstr "Seitenverhältnis korrigieren"
+
+#: gui/options.cpp:656
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "Seitenverhältnis für Spiele mit der Auflösung 320x200 korrigieren"
+
+#: gui/options.cpp:663
+msgid "Preferred Device:"
+msgstr "Standard-Gerät:"
+
+#: gui/options.cpp:663
+msgid "Music Device:"
+msgstr "Musikgerät:"
+
+#: gui/options.cpp:663
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr ""
+"Legt das bevorzugte Tonwiedergabe-Gerät oder den Soundkarten-Emulator fest."
+
+#: gui/options.cpp:663 gui/options.cpp:664
+msgid "Specifies output sound device or sound card emulator"
+msgstr "Legt das Musikwiedergabe-Gerät oder den Soundkarten-Emulator fest."
+
+#: gui/options.cpp:688
+msgid "AdLib emulator:"
+msgstr "AdLib-Emulator"
+
+#: gui/options.cpp:688 gui/options.cpp:689
+msgid "AdLib is used for music in many games"
+msgstr "AdLib wird für die Musik in vielen Spielen verwendet."
+
+#: gui/options.cpp:699
+msgid "Output rate:"
+msgstr "Ausgabefrequenz:"
+
+#: gui/options.cpp:699 gui/options.cpp:700
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+"Höhere Werte bewirken eine bessere Soundqualität, werden aber möglicherweise "
+"nicht von jeder Soundkarte unterstützt."
+
+#: gui/options.cpp:710
+msgid "GM Device:"
+msgstr "GM-Gerät:"
+
+#: gui/options.cpp:710
+msgid "Specifies default sound device for General MIDI output"
+msgstr ""
+"Legt das standardmäßige Musikwiedergabe-Gerät für General-MIDI-Ausgabe fest."
+
+#: gui/options.cpp:731
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:731 gui/options.cpp:732
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr ""
+"SoundFont wird von einigen Soundkarten, Fluidsynth und Timidity unterstützt."
+
+#: gui/options.cpp:736
+msgid "Mixed AdLib/MIDI mode"
+msgstr "AdLib-/MIDI-Modus"
+
+#: gui/options.cpp:736
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "Benutzt MIDI und AdLib zur Sounderzeugung."
+
+#: gui/options.cpp:739
+msgid "MIDI gain:"
+msgstr "MIDI-Lautstärke:"
+
+#: gui/options.cpp:749
+#, fuzzy
+msgid "MT-32 Device:"
+msgstr "MT32-Gerät:"
+
+#: gui/options.cpp:749
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr ""
+"Legt das standardmäßige Tonwiedergabe-Gerät für die Ausgabe von Roland MT-32/"
+"LAPC1/CM32l/CM64 fest."
+
+#: gui/options.cpp:753
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Echte Roland-MT-32-Emulation (GM-Emulation deaktiviert)"
+
+#: gui/options.cpp:753
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+"Wählen Sie dies aus, wenn Sie Ihre echte Hardware, die mit einer Roland-"
+"kompatiblen Soundkarte verbunden ist, verwenden möchten."
+
+#: gui/options.cpp:756
+msgid "Enable Roland GS Mode"
+msgstr "Roland-GS-Modus"
+
+#: gui/options.cpp:756
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr ""
+"Schaltet die General-MIDI-Zuweisung für Spiele mit Roland-MT-32-Audiospur "
+"aus."
+
+#: gui/options.cpp:780
+msgid "Text and Speech:"
+msgstr "Text und Sprache:"
+
+#: gui/options.cpp:785 gui/options.cpp:791
+msgid "Speech"
+msgstr "Sprache"
+
+#: gui/options.cpp:786 gui/options.cpp:792
+msgid "Subtitles"
+msgstr "Untertitel"
+
+#: gui/options.cpp:787 gui/options.cpp:793
+msgid "Both"
+msgstr "Beides"
+
+#: gui/options.cpp:791
+msgid "Spch"
+msgstr "Spr."
+
+#: gui/options.cpp:792
+msgid "Subs"
+msgstr "Untert."
+
+#: gui/options.cpp:793
+msgid "Show subtitles and play speech"
+msgstr "Untertitel anzeigen und Sprachausgabe aktivieren"
+
+#: gui/options.cpp:797
+msgid "Subtitle speed:"
+msgstr "Untertitel-Tempo:"
+
+#: gui/options.cpp:809
+msgid "Music volume:"
+msgstr "Musiklautstärke:"
+
+#: gui/options.cpp:816
+msgid "Mute All"
+msgstr "Alles aus"
+
+#: gui/options.cpp:819
+msgid "SFX volume:"
+msgstr "Effektlautstärke:"
+
+#: gui/options.cpp:819 gui/options.cpp:820
+msgid "Special sound effects volume"
+msgstr "Lautstärke spezieller Soundeffekte"
+
+#: gui/options.cpp:826
+msgid "Speech volume:"
+msgstr "Sprachlautstärke:"
+
+#: gui/options.cpp:952
+msgid "Save Path: "
+msgstr "Spielstände: "
+
+#: gui/options.cpp:955
+msgid "Theme Path:"
+msgstr "Themenpfad:"
+
+#: gui/options.cpp:958 gui/options.cpp:959
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr ""
+"Legt das Verzeichnis für zusätzliche Spieldateien für alle Spiele in ScummVM "
+"fest."
+
+#: gui/options.cpp:962
+msgid "Plugins Path:"
+msgstr "Plugin-Pfad:"
+
+#: gui/options.cpp:970
+msgid "Misc"
+msgstr "Sonstiges"
+
+#: gui/options.cpp:972
+msgid "Theme:"
+msgstr "Thema:"
+
+#: gui/options.cpp:976
+msgid "GUI Renderer:"
+msgstr "GUI-Renderer:"
+
+#: gui/options.cpp:982
+msgid "Autosave:"
+msgstr "Autom. Speichern:"
+
+#: gui/options.cpp:990
+msgid "Keys"
+msgstr "Tasten"
+
+#: gui/options.cpp:997
+msgid "GUI Language:"
+msgstr "GUI-Sprache:"
+
+#: gui/options.cpp:997
+msgid "Language of ScummVM GUI"
+msgstr "Sprache der ScummVM-Oberfläche"
+
+#: gui/options.cpp:1002
+msgid "English"
+msgstr "English"
+
+#: gui/options.cpp:1146
+msgid "You have to restart ScummVM to take the effect."
+msgstr "Sie müssen ScummVM neustarten, um die Einstellungen zu übernehmen."
+
+#: gui/options.cpp:1159
+msgid "Select directory for savegames"
+msgstr "Verzeichnis für Spielstände auswählen"
+
+#: gui/options.cpp:1166
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr ""
+"In das gewählte Verzeichnis kann nicht geschrieben werden. Bitte ein anderes "
+"auswählen."
+
+#: gui/options.cpp:1175
+msgid "Select directory for GUI themes"
+msgstr "Verzeichnis für Oberflächen-Themen"
+
+#: gui/options.cpp:1185
+msgid "Select directory for extra files"
+msgstr "Verzeichnis für zusätzliche Dateien auswählen"
+
+#: gui/options.cpp:1196
+msgid "Select directory for plugins"
+msgstr "Verzeichnis für Erweiterungen auswählen"
+
+#: gui/saveload.cpp:60 gui/saveload.cpp:241
+msgid "No date saved"
+msgstr "Kein Datum gespeichert"
+
+#: gui/saveload.cpp:61 gui/saveload.cpp:242
+msgid "No time saved"
+msgstr "Keine Zeit gespeichert"
+
+#: gui/saveload.cpp:62 gui/saveload.cpp:243
+msgid "No playtime saved"
+msgstr "Keine Spielzeit gespeichert"
+
+#: gui/saveload.cpp:69 gui/saveload.cpp:157
+msgid "Delete"
+msgstr "Löschen"
+
+#: gui/saveload.cpp:156
+msgid "Do you really want to delete this savegame?"
+msgstr "Diesen Spielstand wirklich löschen?"
+
+#: gui/saveload.cpp:265
+msgid "Date: "
+msgstr "Datum: "
+
+#: gui/saveload.cpp:268
+msgid "Time: "
+msgstr "Zeit: "
+
+#: gui/saveload.cpp:273
+msgid "Playtime: "
+msgstr "Spieldauer: "
+
+#: gui/saveload.cpp:286 gui/saveload.cpp:353
+msgid "Untitled savestate"
+msgstr "Unbenannt"
+
+#: gui/themebrowser.cpp:46
+msgid "Select a Theme"
+msgstr "Thema auswählen"
+
+#: gui/ThemeEngine.cpp:334
+msgid "Disabled GFX"
+msgstr "GFX ausgeschalten"
+
+#: gui/ThemeEngine.cpp:335
+msgid "Standard Renderer (16bpp)"
+msgstr "Standard-Renderer (16bpp)"
+
+#: gui/ThemeEngine.cpp:337
+msgid "Antialiased Renderer (16bpp)"
+msgstr "Kantenglättung (16bpp)"
+
+#: base/main.cpp:205
+#, c-format
+msgid "Engine does not support debug level '%s'"
+msgstr "Engine unterstützt den Debug-Level \"%s\" nicht"
+
+#: base/main.cpp:273
+msgid "Menu"
+msgstr "Menü"
+
+#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48
+#: backends/platform/wince/CEActionsPocket.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:45
+msgid "Skip"
+msgstr "Überspringen"
+
+#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53
+#: backends/platform/wince/CEActionsPocket.cpp:41
+msgid "Pause"
+msgstr "Pause"
+
+#: base/main.cpp:282
+msgid "Skip line"
+msgstr "Zeile überspringen"
+
+#: base/main.cpp:404
+msgid "Error running game:"
+msgstr "Fehler beim Ausführen des Spiels:"
+
+#: base/main.cpp:430 base/main.cpp:431
+msgid "Could not find any engine capable of running the selected game"
+msgstr "Kann keine Spiel-Engine finden, die dieses Spiel starten kann."
+
+#: common/error.cpp:43
+msgid "Invalid Path"
+msgstr "Ungültiges Verzeichnis"
+
+#: common/error.cpp:44
+msgid "Game Data not found"
+msgstr "Spieldaten nicht gefunden"
+
+#: common/error.cpp:45
+msgid "Game Id not supported"
+msgstr "Spielkennung nicht unterstützt"
+
+#: common/error.cpp:46
+msgid "Unsupported Color Mode"
+msgstr "Farbmodus nicht unterstützt"
+
+#: common/error.cpp:48
+msgid "Read permission denied"
+msgstr "Lese-Berechtigung nicht vorhanden"
+
+#: common/error.cpp:49
+msgid "Write permission denied"
+msgstr "Schreib-Berechtigung nicht vorhanden"
+
+#: common/error.cpp:52
+msgid "Path not exists"
+msgstr "Verzeichnis existiert nicht."
+
+#: common/error.cpp:53
+msgid "Path not a directory"
+msgstr "Ungültiges Verzeichnis"
+
+#: common/error.cpp:54
+msgid "Path not a file"
+msgstr "Pfad ist keine Datei."
+
+#: common/error.cpp:56
+msgid "Cannot create file"
+msgstr "Kann Datei nicht erstellen."
+
+#: common/error.cpp:57
+msgid "Reading failed"
+msgstr "Lesefehler aufgetreten"
+
+#: common/error.cpp:58
+msgid "Writing data failed"
+msgstr "Daten konnten nicht geschrieben werden."
+
+#: common/error.cpp:60 common/error.cpp:71
+msgid "Unknown Error"
+msgstr "Unbekannter Fehler"
+
+#: common/util.cpp:254
+msgid "Hercules Green"
+msgstr "Hercules-Grün"
+
+#: common/util.cpp:255
+msgid "Hercules Amber"
+msgstr "Hercules Bernsteingelb"
+
+#: engines/dialogs.cpp:89
+msgid "~R~esume"
+msgstr "~F~ortsetzen"
+
+#: engines/dialogs.cpp:91
+msgid "~L~oad"
+msgstr "~L~aden"
+
+#: engines/dialogs.cpp:95
+msgid "~S~ave"
+msgstr "~S~peichern"
+
+#: engines/dialogs.cpp:99
+msgid "~O~ptions"
+msgstr "~O~ptionen"
+
+#: engines/dialogs.cpp:104
+msgid "~H~elp"
+msgstr "~H~ilfe"
+
+#: engines/dialogs.cpp:107
+msgid "~A~bout"
+msgstr "Übe~r~"
+
+#: engines/dialogs.cpp:109
+msgid "~R~eturn to Launcher"
+msgstr "Zur Spiele~l~iste zurück"
+
+#: engines/dialogs.cpp:119
+msgid "Save game:"
+msgstr "Speichern:"
+
+#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47
+#: backends/platform/wince/CEActionsPocket.cpp:42
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Save"
+msgstr "Speichern"
+
+#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84
+#: engines/mohawk/dialogs.cpp:118
+msgid "~O~K"
+msgstr "~O~K"
+
+#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85
+#: engines/mohawk/dialogs.cpp:119
+msgid "~C~ancel"
+msgstr "~A~bbrechen"
+
+#: engines/dialogs.cpp:305
+msgid "~K~eys"
+msgstr "~T~asten"
+
+#: engines/scumm/dialogs.cpp:287
+msgid "~P~revious"
+msgstr "~Z~urück"
+
+#: engines/scumm/dialogs.cpp:288
+msgid "~N~ext"
+msgstr "~W~eiter"
+
+#: engines/scumm/dialogs.cpp:289
+#: backends/platform/ds/arm9/source/dsoptions.cpp:59
+msgid "~C~lose"
+msgstr "~S~chließen"
+
+#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115
+msgid "~Z~ip Mode Activated"
+msgstr "~Z~ip-Modus aktiviert"
+
+#: engines/mohawk/dialogs.cpp:82
+msgid "~T~ransitions Enabled"
+msgstr "Über~g~änge aktiviert"
+
+#: engines/mohawk/dialogs.cpp:116
+msgid "~W~ater Effect Enabled"
+msgstr "~W~assereffekt aktiviert"
+
+#: sound/fmopl.cpp:51
+msgid "MAME OPL emulator"
+msgstr "MAME-OPL-Emulator"
+
+#: sound/fmopl.cpp:53
+msgid "DOSBox OPL emulator"
+msgstr "DOSBox-OPL-Emulator"
+
+#: sound/null.h:45
+msgid "No music"
+msgstr "Keine Musik"
+
+#: sound/softsynth/adlib.cpp:1590
+msgid "AdLib Emulator"
+msgstr "AdLib-Emulator"
+
+#: sound/softsynth/mt32.cpp:327
+msgid "Initialising MT-32 Emulator"
+msgstr "MT-32-Emulator wird gestartet..."
+
+#: sound/softsynth/mt32.cpp:541
+msgid "MT-32 Emulator"
+msgstr "MT-32-Emulation"
+
+#: sound/softsynth/pcspk.cpp:142
+msgid "PC Speaker Emulator"
+msgstr "PC-Lautsprecher-Emulator"
+
+#: sound/softsynth/pcspk.cpp:161
+msgid "IBM PCjr Emulator"
+msgstr "IBM-PCjr-Emulator"
+
+#: sound/softsynth/ym2612.cpp:762
+msgid "FM Towns Emulator"
+msgstr "FM-Towns-Emulator"
+
+#: backends/keymapper/remap-dialog.cpp:49
+msgid "Keymap:"
+msgstr "Tasten-Layout:"
+
+#: backends/keymapper/remap-dialog.cpp:66
+msgid " (Active)"
+msgstr " (Aktiv)"
+
+#: backends/keymapper/remap-dialog.cpp:100
+msgid " (Global)"
+msgstr " (Global)"
+
+#: backends/keymapper/remap-dialog.cpp:110
+msgid " (Game)"
+msgstr " (Spiel)"
+
+#: backends/midi/windows.cpp:157
+msgid "Windows MIDI"
+msgstr "Windows MIDI"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:60
+msgid "ScummVM Main Menu"
+msgstr "ScummVM-Hauptmenü"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:66
+msgid "~L~eft handed mode"
+msgstr "~L~inke-Hand-Modus"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:67
+msgid "~I~ndy fight controls"
+msgstr "~K~ampfsteuerung für Indiana Jones"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:68
+msgid "Show mouse cursor"
+msgstr "Mauszeiger anzeigen"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:69
+msgid "Snap to edges"
+msgstr "An Ecken anheften"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:71
+msgid "Touch X Offset"
+msgstr "Zu X-Position gehen"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:78
+msgid "Touch Y Offset"
+msgstr "Zu Y-Position gehen"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:90
+msgid "Use laptop trackpad-style cursor control"
+msgstr "Den Trackpad-Style für Maussteuerung benutzen"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:91
+msgid "Tap for left click, double tap right click"
+msgstr "Tippen für Linksklick, Doppeltippen für Rechtsklick"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:93
+msgid "Sensitivity"
+msgstr "Empfindlichkeit"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:102
+msgid "Initial top screen scale:"
+msgstr "Vergößerung des oberen Bildschirms:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:108
+msgid "Main screen scaling:"
+msgstr "Hauptbildschirm-Skalierung:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:110
+msgid "Hardware scale (fast, but low quality)"
+msgstr "Hardware-Skalierung (schnell, aber schlechte Qualität)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:111
+msgid "Software scale (good quality, but slower)"
+msgstr "Software-Skalierung (gute Qualität, aber langsamer)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:112
+msgid "Unscaled (you must scroll left and right)"
+msgstr "Nicht skalieren (Sie müssen nach links und nach rechts scrollen)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:114
+msgid "Brightness:"
+msgstr "Helligkeit:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:124
+msgid "High quality audio (slower) (reboot)"
+msgstr "Hohe Audioqualität (lansamer) (erfordert Neustart)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:125
+msgid "Disable power off"
+msgstr "Stromsparmodus abschalten"
+
+#: backends/platform/iphone/osys_events.cpp:339
+msgid "Touchpad mode enabled."
+msgstr "Touchpad-Modus aktiviert."
+
+#: backends/platform/iphone/osys_events.cpp:341
+msgid "Touchpad mode disabled."
+msgstr "Touchpad-Modus ausgeschaltet."
+
+#: backends/platform/sdl/graphics.cpp:40
+#: backends/platform/wince/wince-sdl.cpp:111
+#: backends/platform/wince/wince-sdl.cpp:118
+msgid "Normal (no scaling)"
+msgstr "Normal (keine Skalierung)"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:41
+#: backends/platform/wince/CEActionsSmartphone.cpp:38
+msgid "Up"
+msgstr "Hoch"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:42
+#: backends/platform/wince/CEActionsSmartphone.cpp:39
+msgid "Down"
+msgstr "Runter"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:40
+msgid "Left"
+msgstr "Links"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:41
+msgid "Right"
+msgstr "Rechts"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:45
+#: backends/platform/wince/CEActionsPocket.cpp:59
+#: backends/platform/wince/CEActionsSmartphone.cpp:42
+msgid "Left Click"
+msgstr "Linksklick"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:46
+#: backends/platform/wince/CEActionsSmartphone.cpp:43
+msgid "Right Click"
+msgstr "Rechtsklick"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:49
+#: backends/platform/wince/CEActionsSmartphone.cpp:46
+msgid "Zone"
+msgstr "Zone"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:50
+#: backends/platform/wince/CEActionsPocket.cpp:53
+#: backends/platform/wince/CEActionsSmartphone.cpp:47
+msgid "Multi Function"
+msgstr "Multifunktion"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:51
+msgid "Swap character"
+msgstr "Figur wechseln"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:52
+msgid "Skip text"
+msgstr "Text überspringen"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:54
+msgid "Fast mode"
+msgstr "Schneller Modus"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:55
+#: backends/platform/wince/CEActionsPocket.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:51
+msgid "Quit"
+msgstr "Beenden"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:56
+msgid "Debugger"
+msgstr "Debugger"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:57
+msgid "Global menu"
+msgstr "Hauptmenü"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:58
+msgid "Virtual keyboard"
+msgstr "Virtuelle Tastatur"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:59
+msgid "Key mapper"
+msgstr "Tasten zuordnen"
+
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+msgid "Do you want to quit ?"
+msgstr "Möchten Sie beenden?"
+
+#: backends/platform/wii/options.cpp:51
+msgid "Video"
+msgstr "Video"
+
+#: backends/platform/wii/options.cpp:54
+msgid "Current video mode:"
+msgstr "Aktueller Videomodus:"
+
+#: backends/platform/wii/options.cpp:56
+msgid "Double-strike"
+msgstr "Doppelzeilen (kein Zeilensprungverfahren)"
+
+#: backends/platform/wii/options.cpp:60
+msgid "Horizontal underscan:"
+msgstr "Horizontale Bildverkleinerung:"
+
+#: backends/platform/wii/options.cpp:66
+msgid "Vertical underscan:"
+msgstr "Vertikale Bildverkleinerung:"
+
+#: backends/platform/wii/options.cpp:71
+msgid "Input"
+msgstr "Eingabe"
+
+#: backends/platform/wii/options.cpp:74
+msgid "GC Pad sensitivity:"
+msgstr "GC-Pad-Empfindlichkeit:"
+
+#: backends/platform/wii/options.cpp:80
+msgid "GC Pad acceleration:"
+msgstr "GC-Pad-Beschleunigung:"
+
+#: backends/platform/wii/options.cpp:86
+msgid "DVD"
+msgstr "DVD"
+
+#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101
+msgid "Status:"
+msgstr "Status:"
+
+#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102
+msgid "Unknown"
+msgstr "Unbekannt"
+
+#: backends/platform/wii/options.cpp:93
+msgid "Mount DVD"
+msgstr "DVD einbinden"
+
+#: backends/platform/wii/options.cpp:94
+msgid "Unmount DVD"
+msgstr "DVD aushängen"
+
+#: backends/platform/wii/options.cpp:98
+msgid "SMB"
+msgstr "SMB"
+
+#: backends/platform/wii/options.cpp:106
+msgid "Server:"
+msgstr "Server:"
+
+#: backends/platform/wii/options.cpp:110
+msgid "Share:"
+msgstr "Öffentliches Verzeichnis:"
+
+#: backends/platform/wii/options.cpp:114
+msgid "Username:"
+msgstr "Benutzername:"
+
+#: backends/platform/wii/options.cpp:118
+msgid "Password:"
+msgstr "Passwort:"
+
+#: backends/platform/wii/options.cpp:121
+msgid "Init network"
+msgstr "Netzwerk starten"
+
+#: backends/platform/wii/options.cpp:123
+msgid "Mount SMB"
+msgstr "SMB einbinden"
+
+#: backends/platform/wii/options.cpp:124
+msgid "Unmount SMB"
+msgstr "SMB aushängen"
+
+#: backends/platform/wii/options.cpp:145
+msgid "DVD Mounted successfully"
+msgstr "DVD erfolgreich eingebunden"
+
+#: backends/platform/wii/options.cpp:148
+msgid "Error while mounting the DVD"
+msgstr "Fehler beim Einbinden der DVD"
+
+#: backends/platform/wii/options.cpp:150
+msgid "DVD not mounted"
+msgstr "DVD nicht eingebunden"
+
+#: backends/platform/wii/options.cpp:163
+msgid "Network up, share mounted"
+msgstr "Netzwerk gestartet, öffentliches Verzeichnis eingebunden"
+
+#: backends/platform/wii/options.cpp:165
+msgid "Network up"
+msgstr "Netzwerk gestartet"
+
+#: backends/platform/wii/options.cpp:168
+msgid ", error while mounting the share"
+msgstr ", Fehler beim Einbinden des öffentlichen Verzeichnisses"
+
+#: backends/platform/wii/options.cpp:170
+msgid ", share not mounted"
+msgstr ", öffentliches Verzeichnis nicht eingebunden"
+
+#: backends/platform/wii/options.cpp:176
+msgid "Network down"
+msgstr "Netzwerk ist aus."
+
+#: backends/platform/wii/options.cpp:180
+msgid "Initialising network"
+msgstr "Netzwerk wird gestartet..."
+
+#: backends/platform/wii/options.cpp:184
+msgid "Timeout while initialising network"
+msgstr "Zeitüberschreitung beim Starten des Netzwerks"
+
+#: backends/platform/wii/options.cpp:188
+#, c-format
+msgid "Network not initialsed (%d)"
+msgstr "Netzwerk nicht gestartet (%d)"
+
+#: backends/platform/wince/CEActionsPocket.cpp:45
+msgid "Hide Toolbar"
+msgstr "Werkzeugleiste verbergen"
+
+#: backends/platform/wince/CEActionsPocket.cpp:46
+msgid "Show Keyboard"
+msgstr "Tastatur zeigen"
+
+#: backends/platform/wince/CEActionsPocket.cpp:47
+msgid "Sound on/off"
+msgstr "Ton ein/aus"
+
+#: backends/platform/wince/CEActionsPocket.cpp:48
+msgid "Right click"
+msgstr "Rechtsklick"
+
+#: backends/platform/wince/CEActionsPocket.cpp:49
+msgid "Show/Hide Cursor"
+msgstr "Cursor zeigen/verbergen"
+
+#: backends/platform/wince/CEActionsPocket.cpp:50
+msgid "Free look"
+msgstr "Freie Ansicht"
+
+#: backends/platform/wince/CEActionsPocket.cpp:51
+msgid "Zoom up"
+msgstr "Herauszoomen"
+
+#: backends/platform/wince/CEActionsPocket.cpp:52
+msgid "Zoom down"
+msgstr "Hineinzoomen"
+
+#: backends/platform/wince/CEActionsPocket.cpp:54
+#: backends/platform/wince/CEActionsSmartphone.cpp:48
+msgid "Bind Keys"
+msgstr "Tasten zuweisen"
+
+#: backends/platform/wince/CEActionsPocket.cpp:55
+msgid "Cursor Up"
+msgstr "Zeiger hoch"
+
+#: backends/platform/wince/CEActionsPocket.cpp:56
+msgid "Cursor Down"
+msgstr "Zeiger runter"
+
+#: backends/platform/wince/CEActionsPocket.cpp:57
+msgid "Cursor Left"
+msgstr "Zeiger nach links"
+
+#: backends/platform/wince/CEActionsPocket.cpp:58
+msgid "Cursor Right"
+msgstr "Zeiger nach rechts"
+
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Do you want to load or save the game?"
+msgstr "Möchten Sie ein Spiel laden oder speichern?"
+
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+msgid " Are you sure you want to quit ? "
+msgstr " Möchten Sie wirklich beenden? "
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:49
+msgid "Keyboard"
+msgstr "Tastatur"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:50
+msgid "Rotate"
+msgstr "Drehen"
+
+#: backends/platform/wince/CELauncherDialog.cpp:58
+msgid "Using SDL driver "
+msgstr "SDL-Treiber verwenden"
+
+#: backends/platform/wince/CELauncherDialog.cpp:62
+msgid "Display "
+msgstr "Anzeige"
+
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Do you want to perform an automatic scan ?"
+msgstr "Möchten Sie eine automatische Durchsuchung vornehmen?"
+
+#~ msgid "Failed to load any GUI theme, aborting"
+#~ msgstr "Fehler: Konnte kein Benutzeroberflächen-Thema laden. Abbruch..."
+
+#~ msgid "User picked target '%s' (gameid '%s')...\n"
+#~ msgstr "Gewähltes Ziel: \"%s\" (Spielkennung \"%s\")...\n"
+
+#~ msgid " Looking for a plugin supporting this gameid... "
+#~ msgstr ""
+#~ " Suche nach einer Erweiterung, die diese Spielkennung unterstützt..."
+
+#~ msgid "failed\n"
+#~ msgstr "fehlgeschlagen\n"
+
+#~ msgid ""
+#~ "%s is an invalid gameid. Use the --list-games option to list supported "
+#~ "gameid"
+#~ msgstr ""
+#~ "%s ist eine ungültige Spielkennung. Benutzen Sie die Option --list-games "
+#~ "zum Anzeigen der unterstützten Spielkennungen."
+
+#~ msgid " Starting '%s'\n"
+#~ msgstr " Starte \"%s\"\n"
+
+#~ msgid "%s failed to instantiate engine: %s (target '%s', path '%s')"
+#~ msgstr "%s konnte Engine nicht starten: %s (Ziel \"%s\", Pfad \"%s\")"
+
+#~ msgid "Ok"
+#~ msgstr "OK"
+
+#~ msgid "Music driver:"
+#~ msgstr "Musiktreiber:"
+
+#~ msgid "ALSA"
+#~ msgstr "ALSA"
+
+#~ msgid "Atari ST MIDI"
+#~ msgstr "Atari ST MIDI"
+
+#~ msgid "SEQ"
+#~ msgstr "SEQ"
+
+#~ msgid "DMedia"
+#~ msgstr "DMedia"
+
+#~ msgid "CAMD"
+#~ msgstr "CAMD"
+
+#~ msgid "CoreAudio"
+#~ msgstr "CoreAudio"
+
+#~ msgid "CoreMIDI"
+#~ msgstr "CoreMIDI"
+
+#~ msgid "Yamaha Pa1"
+#~ msgstr "Yamaha Pa1"
+
+#~ msgid "Tapwave Zodiac"
+#~ msgstr "Tapwave Zodiac"
+
+#~ msgid "FluidSynth"
+#~ msgstr "FluidSynth"
+
+#~ msgid "AdLib"
+#~ msgstr "AdLib"
+
+#~ msgid "IBM PCjr"
+#~ msgstr "IBM PCjr"
+
+#~ msgid "Creative Music System"
+#~ msgstr "Creative-Musik-System"
+
+#~ msgid "TiMidity"
+#~ msgstr "TiMidity"
diff --git a/po/es_ES.po b/po/es_ES.po
new file mode 100644
index 0000000000..de9374f844
--- /dev/null
+++ b/po/es_ES.po
@@ -0,0 +1,1428 @@
+# LANGUAGE translation for ScummVM.
+# Copyright (C) YEAR ScummVM Team
+# This file is distributed under the same license as the ScummVM package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ScummVM 1.2.0svn\n"
+"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
+"POT-Creation-Date: 2010-07-30 22:14+0100\n"
+"PO-Revision-Date: 2010-07-30 22:17+0100\n"
+"Last-Translator: Tomás Maidagan\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: Espanol\n"
+
+#: gui/about.cpp:96
+#, c-format
+msgid "(built on %s)"
+msgstr "(compilado el %s)"
+
+#: gui/about.cpp:103
+msgid "Features compiled in:"
+msgstr "Características compiladas:"
+
+#: gui/about.cpp:112
+msgid "Available engines:"
+msgstr "Motores disponibles:"
+
+#: gui/browser.cpp:69
+msgid "Go up"
+msgstr "Arriba"
+
+#: gui/browser.cpp:69
+msgid "Go to previous directory level"
+msgstr "Ir al directorio anterior"
+
+#: gui/browser.cpp:70
+#: gui/chooser.cpp:49
+#: gui/KeysDialog.cpp:46
+#: gui/launcher.cpp:280
+#: gui/massadd.cpp:95
+#: gui/options.cpp:1029
+#: gui/saveload.cpp:65
+#: gui/saveload.cpp:157
+#: gui/themebrowser.cpp:56
+#: backends/platform/wii/options.cpp:48
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: gui/browser.cpp:71
+#: gui/chooser.cpp:50
+#: gui/themebrowser.cpp:57
+msgid "Choose"
+msgstr "Elegir"
+
+#: gui/GuiManager.cpp:103
+#: backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "Cerrar"
+
+#: gui/GuiManager.cpp:106
+msgid "Mouse click"
+msgstr "Clic de ratón"
+
+#: gui/GuiManager.cpp:109
+#: base/main.cpp:285
+msgid "Display keyboard"
+msgstr "Mostrar el teclado"
+
+#: gui/GuiManager.cpp:112
+#: base/main.cpp:288
+msgid "Remap keys"
+msgstr "Asignar teclas"
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr "Asignar"
+
+#: gui/KeysDialog.cpp:45
+#: gui/launcher.cpp:281
+#: gui/launcher.cpp:893
+#: gui/launcher.cpp:897
+#: gui/massadd.cpp:92
+#: gui/options.cpp:1030
+#: backends/platform/wii/options.cpp:47
+#: backends/platform/wince/CELauncherDialog.cpp:56
+msgid "OK"
+msgstr "De acuerdo"
+
+#: gui/KeysDialog.cpp:52
+msgid "Select an action and click 'Map'"
+msgstr "Selecciona una acción y pulsa \"Asignar\""
+
+#: gui/KeysDialog.cpp:83
+#: gui/KeysDialog.cpp:105
+#: gui/KeysDialog.cpp:144
+#, c-format
+msgid "Associated key : %s"
+msgstr "Tecla asociada: %s"
+
+#: gui/KeysDialog.cpp:85
+#: gui/KeysDialog.cpp:107
+#: gui/KeysDialog.cpp:146
+#, c-format
+msgid "Associated key : none"
+msgstr "Tecla asociada: ninguna"
+
+#: gui/KeysDialog.cpp:93
+msgid "Please select an action"
+msgstr "Por favor, selecciona una acción"
+
+#: gui/KeysDialog.cpp:109
+msgid "Press the key to associate"
+msgstr "Pulsa la tecla a asignar"
+
+#: gui/KeysDialog.cpp:148
+msgid "Choose an action to map"
+msgstr "Elige la acción a asociar"
+
+#: gui/launcher.cpp:172
+msgid "Game"
+msgstr "Juego"
+
+#: gui/launcher.cpp:175
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:175
+#: gui/launcher.cpp:176
+msgid "Short game identifier used for referring to savegames and running the game from the command line"
+msgstr "Identificador usado para las partidas guardadas y para ejecutar el juego desde la línea de comando"
+
+#: gui/launcher.cpp:179
+msgid "Name:"
+msgstr "Nombre:"
+
+#: gui/launcher.cpp:179
+#: gui/launcher.cpp:180
+msgid "Full title of the game"
+msgstr "Título completo del juego"
+
+#: gui/launcher.cpp:183
+msgid "Language:"
+msgstr "Idioma:"
+
+#: gui/launcher.cpp:183
+#: gui/launcher.cpp:184
+msgid "Language of the game. This will not turn your Spanish game version into English"
+msgstr "Idioma del juego. No sirve para pasar al inglés la versión española de un juego"
+
+#: gui/launcher.cpp:185
+#: gui/launcher.cpp:196
+#: gui/options.cpp:80
+#: gui/options.cpp:635
+#: gui/options.cpp:645
+#: gui/options.cpp:1000
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<por defecto>"
+
+#: gui/launcher.cpp:194
+msgid "Platform:"
+msgstr "Plataforma:"
+
+#: gui/launcher.cpp:194
+#: gui/launcher.cpp:195
+msgid "Platform the game was originally designed for"
+msgstr "Plataforma para la que se diseñó el juego"
+
+#: gui/launcher.cpp:206
+#: gui/options.cpp:898
+#: gui/options.cpp:915
+msgid "Graphics"
+msgstr "Gráficos"
+
+#: gui/launcher.cpp:206
+#: gui/options.cpp:898
+#: gui/options.cpp:915
+msgid "GFX"
+msgstr "GFX"
+
+#: gui/launcher.cpp:208
+msgid "Override global graphic settings"
+msgstr "Ignorar opciones gráficas generales"
+
+#: gui/launcher.cpp:215
+#: gui/options.cpp:921
+msgid "Audio"
+msgstr "Sonido"
+
+#: gui/launcher.cpp:217
+msgid "Override global audio settings"
+msgstr "Ignorar opciones de sonido generales"
+
+#: gui/launcher.cpp:225
+#: gui/options.cpp:925
+msgid "Volume"
+msgstr "Volumen"
+
+#: gui/launcher.cpp:227
+msgid "Override global volume settings"
+msgstr "Ignorar opciones de volumen generales"
+
+#: gui/launcher.cpp:234
+#: gui/options.cpp:933
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:236
+msgid "Override global MIDI settings"
+msgstr "Ignorar opciones MIDI generales"
+
+#: gui/launcher.cpp:246
+#: gui/options.cpp:939
+msgid "MT-32"
+msgstr "MT-32"
+
+#: gui/launcher.cpp:248
+msgid "Override global MT-32 settings"
+msgstr "Ignorar opciones MT-32 generales"
+
+#: gui/launcher.cpp:258
+#: gui/options.cpp:945
+msgid "Paths"
+msgstr "Rutas"
+
+#: gui/launcher.cpp:264
+msgid "Game Path:"
+msgstr "Juego:"
+
+#: gui/launcher.cpp:268
+#: gui/options.cpp:958
+msgid "Extra Path:"
+msgstr "Adicional:"
+
+#: gui/launcher.cpp:268
+#: gui/launcher.cpp:269
+msgid "Specifies path to additional data used the game"
+msgstr "Especifica un directorio para datos adicionales del juego"
+
+#: gui/launcher.cpp:272
+msgid "Save Path:"
+msgstr "Partidas:"
+
+#: gui/launcher.cpp:272
+#: gui/launcher.cpp:273
+#: gui/options.cpp:952
+#: gui/options.cpp:953
+msgid "Specifies where your savegames are put"
+msgstr "Especifica dónde guardar tus partidas"
+
+#: gui/launcher.cpp:289
+#: gui/launcher.cpp:369
+#: gui/launcher.cpp:418
+#: gui/options.cpp:230
+#: gui/options.cpp:399
+#: gui/options.cpp:497
+#: gui/options.cpp:555
+#: gui/options.cpp:732
+#: gui/options.cpp:956
+#: gui/options.cpp:959
+#: gui/options.cpp:963
+#: gui/options.cpp:1053
+#: gui/options.cpp:1059
+#: gui/options.cpp:1065
+#: gui/options.cpp:1073
+#: gui/options.cpp:1097
+#: gui/options.cpp:1101
+#: gui/options.cpp:1107
+#: gui/options.cpp:1114
+#: gui/options.cpp:1213
+msgid "None"
+msgstr "Ninguno"
+
+#: gui/launcher.cpp:294
+#: gui/launcher.cpp:373
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "Por defecto"
+
+#: gui/launcher.cpp:411
+#: gui/options.cpp:1207
+msgid "Select SoundFont"
+msgstr "Seleccionar SoundFont"
+
+#: gui/launcher.cpp:430
+#: gui/launcher.cpp:568
+msgid "Select directory with game data"
+msgstr "Seleccionar directorio con los archivos del juego"
+
+#: gui/launcher.cpp:448
+msgid "Select additional game directory"
+msgstr "Seleccionar directorio de juego adicional"
+
+#: gui/launcher.cpp:460
+msgid "Select directory for saved games"
+msgstr "Seleccionar directorio para partidas guardadas"
+
+#: gui/launcher.cpp:479
+msgid "This game ID is already taken. Please choose another one."
+msgstr "Esta ID ya está siendo usada. Por favor, elige otra."
+
+#: gui/launcher.cpp:520
+#: engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "~S~alir"
+
+#: gui/launcher.cpp:520
+msgid "Quit ScummVM"
+msgstr "Cerrar ScummVM"
+
+#: gui/launcher.cpp:521
+msgid "A~b~out..."
+msgstr "Acerca ~d~e"
+
+#: gui/launcher.cpp:521
+msgid "About ScummVM"
+msgstr "Acerca de ScummVM"
+
+#: gui/launcher.cpp:522
+msgid "~O~ptions..."
+msgstr "~O~opciones..."
+
+#: gui/launcher.cpp:522
+msgid "Change global ScummVM options"
+msgstr "Cambiar opciones generales de ScummVM"
+
+#: gui/launcher.cpp:524
+msgid "~S~tart"
+msgstr "~J~ugar"
+
+#: gui/launcher.cpp:524
+msgid "Start selected game"
+msgstr "Jugar al juego seleccionado"
+
+#: gui/launcher.cpp:527
+msgid "~L~oad..."
+msgstr "~C~argar..."
+
+#: gui/launcher.cpp:527
+msgid "Load savegame for selected game"
+msgstr "Cargar partida del juego seleccionado"
+
+#: gui/launcher.cpp:531
+msgid "~A~dd Game..."
+msgstr "~A~ñadir juego..."
+
+#: gui/launcher.cpp:531
+msgid "Hold Shift for Mass Add"
+msgstr "Mantén pulsado Mayús para añadir varios"
+
+#: gui/launcher.cpp:533
+msgid "~E~dit Game..."
+msgstr "~E~ditar juego..."
+
+#: gui/launcher.cpp:533
+msgid "Change game options"
+msgstr "Cambiar opciones de juego"
+
+#: gui/launcher.cpp:535
+msgid "~R~emove Game"
+msgstr "E~l~iminar juego"
+
+#: gui/launcher.cpp:535
+msgid "Remove game from the list. The game data files stay intact"
+msgstr "Elimina el juego de la lista. Los archivos no se borran"
+
+#: gui/launcher.cpp:542
+msgid "Search in game list"
+msgstr "Buscar en la lista de juegos"
+
+#: gui/launcher.cpp:546
+#: gui/launcher.cpp:1057
+msgid "Search:"
+msgstr "Buscar:"
+
+#: gui/launcher.cpp:549
+#: gui/options.cpp:733
+msgid "Clear value"
+msgstr "Eliminar valor"
+
+#: gui/launcher.cpp:571
+#: engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "Cargar juego:"
+
+#: gui/launcher.cpp:571
+#: engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "Cargar"
+
+#: gui/launcher.cpp:680
+msgid "Do you really want to run the mass game detector? This could potentially add a huge number of games."
+msgstr "¿Seguro que quieres ejecutar la detección masiva? Puede que se añada un gran número de juegos."
+
+#: gui/launcher.cpp:681
+#: gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Yes"
+msgstr "Sí"
+
+#: gui/launcher.cpp:681
+#: gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "No"
+msgstr "No"
+
+#: gui/launcher.cpp:728
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "¡ScummVM no ha podido abrir el directorio!"
+
+#: gui/launcher.cpp:740
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr "¡ScummVM no ha encontrado ningún juego en el directorio!"
+
+#: gui/launcher.cpp:754
+msgid "Pick the game:"
+msgstr "Elige el juego:"
+
+#: gui/launcher.cpp:830
+msgid "Do you really want to remove this game configuration?"
+msgstr "¿Seguro que quieres eliminar la configuración de este juego?"
+
+#: gui/launcher.cpp:893
+msgid "This game does not support loading games from the launcher."
+msgstr "Este juego no permite cargar partidas desde el lanzador."
+
+#: gui/launcher.cpp:897
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr "¡ScummVM no ha podido encontrar ningún motor capaz de ejecutar el juego!"
+
+#: gui/launcher.cpp:1009
+msgid "Mass Add..."
+msgstr "Añadir varios..."
+
+#: gui/launcher.cpp:1010
+msgid "Add Game..."
+msgstr "Añadir juego..."
+
+#: gui/massadd.cpp:79
+#: gui/massadd.cpp:82
+msgid "... progress ..."
+msgstr "... progreso..."
+
+#: gui/massadd.cpp:244
+msgid "Scan complete!"
+msgstr "¡Búsqueda completada!"
+
+#: gui/massadd.cpp:247
+#, c-format
+msgid "Discovered %d new games."
+msgstr "Se han encontrado %d juegos nuevos."
+
+#: gui/massadd.cpp:251
+#, c-format
+msgid "Scanned %d directories ..."
+msgstr "Se ha buscado en %d directorios..."
+
+#: gui/massadd.cpp:254
+#, c-format
+msgid "Discovered %d new games ..."
+msgstr "Se han encontrado %d juegos nuevos..."
+
+#: gui/options.cpp:78
+msgid "Never"
+msgstr "Nunca"
+
+#: gui/options.cpp:78
+msgid "every 5 mins"
+msgstr "cada 5 minutos"
+
+#: gui/options.cpp:78
+msgid "every 10 mins"
+msgstr "cada 10 minutos"
+
+#: gui/options.cpp:78
+msgid "every 15 mins"
+msgstr "cada 15 minutos"
+
+#: gui/options.cpp:78
+msgid "every 30 mins"
+msgstr "cada 30 minutos"
+
+#: gui/options.cpp:80
+msgid "8 kHz"
+msgstr "8 kHz"
+
+#: gui/options.cpp:80
+msgid "11kHz"
+msgstr "11kHz"
+
+#: gui/options.cpp:80
+msgid "22 kHz"
+msgstr "22 kHz"
+
+#: gui/options.cpp:80
+msgid "44 kHz"
+msgstr "44 kHz"
+
+#: gui/options.cpp:80
+msgid "48 kHz"
+msgstr "48 kHz"
+
+#: gui/options.cpp:632
+msgid "Graphics mode:"
+msgstr "Modo gráfico:"
+
+#: gui/options.cpp:643
+msgid "Render mode:"
+msgstr "Modo de renderizado:"
+
+#: gui/options.cpp:643
+#: gui/options.cpp:644
+msgid "Special dithering modes supported by some games"
+msgstr "Modos especiales de expansión soportados por algunos juegos"
+
+#: gui/options.cpp:653
+msgid "Fullscreen mode"
+msgstr "Pantalla completa"
+
+#: gui/options.cpp:656
+msgid "Aspect ratio correction"
+msgstr "Corrección de aspecto"
+
+#: gui/options.cpp:656
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "Corregir relación de aspecto en juegos 320x200"
+
+#: gui/options.cpp:663
+msgid "Preferred Device:"
+msgstr "Dispositivo preferido:"
+
+#: gui/options.cpp:663
+msgid "Music Device:"
+msgstr "Dispositivo de música:"
+
+#: gui/options.cpp:663
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr "Especifica qué dispositivo de sonido o emulador de tarjeta de sonido prefieres"
+
+#: gui/options.cpp:663
+#: gui/options.cpp:664
+msgid "Specifies output sound device or sound card emulator"
+msgstr "Especifica el dispositivo de sonido o emulador de tarjeta de sonido de salida"
+
+#: gui/options.cpp:688
+msgid "AdLib emulator:"
+msgstr "Emulador de AdLib:"
+
+#: gui/options.cpp:688
+#: gui/options.cpp:689
+msgid "AdLib is used for music in many games"
+msgstr "AdLib se usa para la música en muchos juegos"
+
+#: gui/options.cpp:699
+msgid "Output rate:"
+msgstr "Frecuencia de salida:"
+
+#: gui/options.cpp:699
+#: gui/options.cpp:700
+msgid "Higher value specifies better sound quality but may be not supported by your soundcard"
+msgstr "Los valores más altos ofrecen mayor calidad, pero puede que tu tarjeta de sonido no sea compatible"
+
+#: gui/options.cpp:710
+msgid "GM Device:"
+msgstr "Dispositivo GM:"
+
+#: gui/options.cpp:710
+msgid "Specifies default sound device for General MIDI output"
+msgstr "Especifica el dispositivo de salida General MIDI por defecto"
+
+#: gui/options.cpp:731
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:731
+#: gui/options.cpp:732
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr "Algunas tarjetas de sonido, Fluidsynth y Timidity soportan SoundFont"
+
+#: gui/options.cpp:736
+msgid "Mixed AdLib/MIDI mode"
+msgstr "Modo AdLib/MIDI"
+
+#: gui/options.cpp:736
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "Usar tanto MIDI como AdLib en la generación de sonido"
+
+#: gui/options.cpp:739
+msgid "MIDI gain:"
+msgstr "Ganancia MIDI:"
+
+#: gui/options.cpp:749
+msgid "MT-32 Device:"
+msgstr "Dispositivo MT-32:"
+
+#: gui/options.cpp:749
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr "Especifica el dispositivo de sonido para la salida Roland MT-32/LAPC1/CM32l/CM64 por defecto"
+
+#: gui/options.cpp:753
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Roland MT-32 auténtica (desactivar emulación GM)"
+
+#: gui/options.cpp:753
+msgid "Check if you want to use your real hardware Roland-compatible sound device connected to your computer"
+msgstr "Marcar si se quiere usar un dispositivo de sonido real conectado al ordenador y compatible con Roland"
+
+#: gui/options.cpp:756
+msgid "Enable Roland GS Mode"
+msgstr "Activar modo Roland GS"
+
+#: gui/options.cpp:756
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr "Desactiva la conversión General MIDI en juegos con sonido Roland MT-32"
+
+#: gui/options.cpp:780
+msgid "Text and Speech:"
+msgstr "Texto y voces:"
+
+#: gui/options.cpp:785
+#: gui/options.cpp:791
+msgid "Speech"
+msgstr "Voces"
+
+#: gui/options.cpp:786
+#: gui/options.cpp:792
+msgid "Subtitles"
+msgstr "Subtítulos"
+
+#: gui/options.cpp:787
+#: gui/options.cpp:793
+msgid "Both"
+msgstr "Ambos"
+
+#: gui/options.cpp:791
+msgid "Spch"
+msgstr "Voces"
+
+#: gui/options.cpp:792
+msgid "Subs"
+msgstr "Subt."
+
+#: gui/options.cpp:793
+msgid "Show subtitles and play speech"
+msgstr "Reproducir voces y subtítulos"
+
+#: gui/options.cpp:797
+msgid "Subtitle speed:"
+msgstr "Velocidad de los subtítulos:"
+
+#: gui/options.cpp:809
+msgid "Music volume:"
+msgstr "Volumen de la música:"
+
+#: gui/options.cpp:816
+msgid "Mute All"
+msgstr "Silenciar"
+
+#: gui/options.cpp:819
+msgid "SFX volume:"
+msgstr "Volumen de los efectos"
+
+#: gui/options.cpp:819
+#: gui/options.cpp:820
+msgid "Special sound effects volume"
+msgstr "Volumen de los efectos de sonido"
+
+#: gui/options.cpp:826
+msgid "Speech volume:"
+msgstr "Volumen de las voces"
+
+#: gui/options.cpp:952
+msgid "Save Path: "
+msgstr "Partidas:"
+
+#: gui/options.cpp:955
+msgid "Theme Path:"
+msgstr "Temas:"
+
+#: gui/options.cpp:958
+#: gui/options.cpp:959
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr "Especifica el directorio adicional usado por los juegos y ScummVM"
+
+#: gui/options.cpp:962
+msgid "Plugins Path:"
+msgstr "Plugins:"
+
+#: gui/options.cpp:970
+msgid "Misc"
+msgstr "Otros"
+
+#: gui/options.cpp:972
+msgid "Theme:"
+msgstr "Tema:"
+
+#: gui/options.cpp:976
+msgid "GUI Renderer:"
+msgstr "Render de la interfaz"
+
+#: gui/options.cpp:982
+msgid "Autosave:"
+msgstr "Autoguardado:"
+
+#: gui/options.cpp:990
+msgid "Keys"
+msgstr "Teclas"
+
+#: gui/options.cpp:997
+msgid "GUI Language:"
+msgstr "Idioma de la interfaz:"
+
+#: gui/options.cpp:997
+msgid "Language of ScummVM GUI"
+msgstr "Idioma de la interfaz de ScummVM"
+
+#: gui/options.cpp:1002
+msgid "English"
+msgstr "Inglés"
+
+#: gui/options.cpp:1146
+msgid "You have to restart ScummVM to take the effect."
+msgstr "Tienes que reiniciar ScummVM para aplicar los cambios."
+
+#: gui/options.cpp:1159
+msgid "Select directory for savegames"
+msgstr "Selecciona el directorio para partidas guardadas."
+
+#: gui/options.cpp:1166
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr "No se puede escribir en el directorio elegido. Por favor, selecciona otro."
+
+#: gui/options.cpp:1175
+msgid "Select directory for GUI themes"
+msgstr "Selecciona el directorio para temas de interfaz"
+
+#: gui/options.cpp:1185
+msgid "Select directory for extra files"
+msgstr "Selecciona el directorio para archivos adicionales"
+
+#: gui/options.cpp:1196
+msgid "Select directory for plugins"
+msgstr "Selecciona el directorio para plugins"
+
+#: gui/saveload.cpp:60
+#: gui/saveload.cpp:241
+msgid "No date saved"
+msgstr "No hay fecha guardada"
+
+#: gui/saveload.cpp:61
+#: gui/saveload.cpp:242
+msgid "No time saved"
+msgstr "No hay hora guardada"
+
+#: gui/saveload.cpp:62
+#: gui/saveload.cpp:243
+msgid "No playtime saved"
+msgstr "No hay tiempo de juego guardado"
+
+#: gui/saveload.cpp:69
+#: gui/saveload.cpp:157
+msgid "Delete"
+msgstr "Borrar"
+
+#: gui/saveload.cpp:156
+msgid "Do you really want to delete this savegame?"
+msgstr "¿Seguro que quieres borrar esta partida?"
+
+#: gui/saveload.cpp:265
+msgid "Date: "
+msgstr "Fecha:"
+
+#: gui/saveload.cpp:268
+msgid "Time: "
+msgstr "Hora:"
+
+#: gui/saveload.cpp:273
+msgid "Playtime: "
+msgstr "Tiempo de juego:"
+
+#: gui/saveload.cpp:286
+#: gui/saveload.cpp:353
+msgid "Untitled savestate"
+msgstr "Partida sin nombre"
+
+#: gui/themebrowser.cpp:46
+msgid "Select a Theme"
+msgstr "Selecciona un tema"
+
+#: gui/ThemeEngine.cpp:334
+msgid "Disabled GFX"
+msgstr "GFX desactivados"
+
+#: gui/ThemeEngine.cpp:335
+msgid "Standard Renderer (16bpp)"
+msgstr "Estándar (16bpp)"
+
+#: gui/ThemeEngine.cpp:337
+msgid "Antialiased Renderer (16bpp)"
+msgstr "Antialiasing (16bpp)"
+
+#: base/main.cpp:205
+#, c-format
+msgid "Engine does not support debug level '%s'"
+msgstr "El motor no soporta el nivel de debug '%s'"
+
+#: base/main.cpp:273
+msgid "Menu"
+msgstr "Menú"
+
+#: base/main.cpp:276
+#: backends/platform/symbian/src/SymbianActions.cpp:48
+#: backends/platform/wince/CEActionsPocket.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:45
+msgid "Skip"
+msgstr "Saltar"
+
+#: base/main.cpp:279
+#: backends/platform/symbian/src/SymbianActions.cpp:53
+#: backends/platform/wince/CEActionsPocket.cpp:41
+msgid "Pause"
+msgstr "Pausar"
+
+#: base/main.cpp:282
+msgid "Skip line"
+msgstr "Saltar frase"
+
+#: base/main.cpp:404
+msgid "Error running game:"
+msgstr "Error al ejecutar el juego:"
+
+#: base/main.cpp:430
+#: base/main.cpp:431
+msgid "Could not find any engine capable of running the selected game"
+msgstr "No se ha podido encontrar ningún motor capaz de ejecutar el juego"
+
+#: common/error.cpp:43
+msgid "Invalid Path"
+msgstr "Ruta no válida"
+
+#: common/error.cpp:44
+msgid "Game Data not found"
+msgstr "No se han encontrado datos de juego"
+
+#: common/error.cpp:45
+msgid "Game Id not supported"
+msgstr "ID del juego no soportada"
+
+#: common/error.cpp:46
+msgid "Unsupported Color Mode"
+msgstr "Modo de color no soportado"
+
+#: common/error.cpp:48
+msgid "Read permission denied"
+msgstr "Permiso de lectura denegado"
+
+#: common/error.cpp:49
+msgid "Write permission denied"
+msgstr "Permiso de escritura denegado"
+
+#: common/error.cpp:52
+msgid "Path not exists"
+msgstr "La ruta no existe"
+
+#: common/error.cpp:53
+msgid "Path not a directory"
+msgstr "La ruta no es un directorio"
+
+#: common/error.cpp:54
+msgid "Path not a file"
+msgstr "La ruta no es un archivo"
+
+#: common/error.cpp:56
+msgid "Cannot create file"
+msgstr "Imposible crear el archivo"
+
+#: common/error.cpp:57
+msgid "Reading failed"
+msgstr "Lectura fallida"
+
+#: common/error.cpp:58
+msgid "Writing data failed"
+msgstr "Escritura de datos fallida"
+
+#: common/error.cpp:60
+#: common/error.cpp:71
+msgid "Unknown Error"
+msgstr "Error desconocido"
+
+#: common/util.cpp:254
+msgid "Hercules Green"
+msgstr "Hercules verde"
+
+#: common/util.cpp:255
+msgid "Hercules Amber"
+msgstr "Hercules ámbar"
+
+#: engines/dialogs.cpp:89
+msgid "~R~esume"
+msgstr "~R~eanudar"
+
+#: engines/dialogs.cpp:91
+msgid "~L~oad"
+msgstr "~C~argar"
+
+#: engines/dialogs.cpp:95
+msgid "~S~ave"
+msgstr "~G~uardar"
+
+#: engines/dialogs.cpp:99
+msgid "~O~ptions"
+msgstr "~O~opciones"
+
+#: engines/dialogs.cpp:104
+msgid "~H~elp"
+msgstr "~A~yuda"
+
+#: engines/dialogs.cpp:107
+msgid "~A~bout"
+msgstr "Acerca ~d~e"
+
+#: engines/dialogs.cpp:109
+msgid "~R~eturn to Launcher"
+msgstr "~V~olver al lanzador"
+
+#: engines/dialogs.cpp:119
+msgid "Save game:"
+msgstr "Guardar partida"
+
+#: engines/dialogs.cpp:119
+#: backends/platform/symbian/src/SymbianActions.cpp:47
+#: backends/platform/wince/CEActionsPocket.cpp:42
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Save"
+msgstr "Guardar"
+
+#: engines/dialogs.cpp:301
+#: engines/mohawk/dialogs.cpp:84
+#: engines/mohawk/dialogs.cpp:118
+msgid "~O~K"
+msgstr "~S~í"
+
+#: engines/dialogs.cpp:302
+#: engines/mohawk/dialogs.cpp:85
+#: engines/mohawk/dialogs.cpp:119
+msgid "~C~ancel"
+msgstr "~C~ancelar"
+
+#: engines/dialogs.cpp:305
+msgid "~K~eys"
+msgstr "~T~eclas"
+
+#: engines/scumm/dialogs.cpp:287
+msgid "~P~revious"
+msgstr "~A~nterior"
+
+#: engines/scumm/dialogs.cpp:288
+msgid "~N~ext"
+msgstr "Si~g~uiente"
+
+#: engines/scumm/dialogs.cpp:289
+#: backends/platform/ds/arm9/source/dsoptions.cpp:59
+msgid "~C~lose"
+msgstr "Cerra~r~"
+
+#: engines/mohawk/dialogs.cpp:81
+#: engines/mohawk/dialogs.cpp:115
+msgid "~Z~ip Mode Activated"
+msgstr "Modo ~Z~ip activado"
+
+#: engines/mohawk/dialogs.cpp:82
+msgid "~T~ransitions Enabled"
+msgstr "Tra~n~siciones activadas"
+
+#: engines/mohawk/dialogs.cpp:116
+msgid "~W~ater Effect Enabled"
+msgstr "Efecto ag~u~a activado"
+
+#: sound/fmopl.cpp:51
+msgid "MAME OPL emulator"
+msgstr "Emulador de MAME OPL"
+
+#: sound/fmopl.cpp:53
+msgid "DOSBox OPL emulator"
+msgstr "Emulador de DOSBox OPL"
+
+#: sound/null.h:45
+msgid "No music"
+msgstr "Sin música"
+
+#: sound/softsynth/adlib.cpp:1590
+msgid "AdLib Emulator"
+msgstr "Emulador de AdLib"
+
+#: sound/softsynth/mt32.cpp:327
+msgid "Initialising MT-32 Emulator"
+msgstr "Iniciando emulador de MT-32"
+
+#: sound/softsynth/mt32.cpp:541
+msgid "MT-32 Emulator"
+msgstr "Emulador de MT-32"
+
+#: sound/softsynth/pcspk.cpp:142
+msgid "PC Speaker Emulator"
+msgstr "Emulador del altavoz de PC"
+
+#: sound/softsynth/pcspk.cpp:161
+msgid "IBM PCjr Emulator"
+msgstr "Emulador de IBM PCjr"
+
+#: sound/softsynth/ym2612.cpp:762
+msgid "FM Towns Emulator"
+msgstr "Emulador de FM Towns"
+
+#: backends/keymapper/remap-dialog.cpp:49
+msgid "Keymap:"
+msgstr "Asignación de teclas:"
+
+#: backends/keymapper/remap-dialog.cpp:66
+msgid " (Active)"
+msgstr "(Activa)"
+
+#: backends/keymapper/remap-dialog.cpp:100
+msgid " (Global)"
+msgstr "(General)"
+
+#: backends/keymapper/remap-dialog.cpp:110
+msgid " (Game)"
+msgstr "(Juego)"
+
+#: backends/midi/windows.cpp:157
+msgid "Windows MIDI"
+msgstr "Windows MIDI"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:60
+msgid "ScummVM Main Menu"
+msgstr "Menú principal de ScummVM"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:66
+msgid "~L~eft handed mode"
+msgstr "Modo para ~z~urdos"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:67
+msgid "~I~ndy fight controls"
+msgstr "Controles para pelear de ~I~ndy"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:68
+msgid "Show mouse cursor"
+msgstr "Mostrar el cursor"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:69
+msgid "Snap to edges"
+msgstr "Pegar a los bordes"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:71
+msgid "Touch X Offset"
+msgstr "Compensación X del toque"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:78
+msgid "Touch Y Offset"
+msgstr "Compensación Y del toque"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:90
+msgid "Use laptop trackpad-style cursor control"
+msgstr "Activar el sistema de control tipo trackpad de los portátiles"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:91
+msgid "Tap for left click, double tap right click"
+msgstr "Un toque para clic izquierdo, dos para clic derecho"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:93
+msgid "Sensitivity"
+msgstr "Sensibilidad"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:102
+msgid "Initial top screen scale:"
+msgstr "Escalado de la pantalla inicial superior:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:108
+msgid "Main screen scaling:"
+msgstr "Escalado de la pantalla principal:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:110
+msgid "Hardware scale (fast, but low quality)"
+msgstr "Escalado por hardware (rápido, pero de baja calidad)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:111
+msgid "Software scale (good quality, but slower)"
+msgstr "Escalado por software (buena calidad, pero más lento)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:112
+msgid "Unscaled (you must scroll left and right)"
+msgstr "Sin escalado (debes desplazar la pantalla a los lados)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:114
+msgid "Brightness:"
+msgstr "Brillo:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:124
+msgid "High quality audio (slower) (reboot)"
+msgstr "Sonido de alta calidad (más lento) (reinicio)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:125
+msgid "Disable power off"
+msgstr "Desactivar apagado"
+
+#: backends/platform/iphone/osys_events.cpp:339
+msgid "Touchpad mode enabled."
+msgstr "Modo Touchpad activado."
+
+#: backends/platform/iphone/osys_events.cpp:341
+msgid "Touchpad mode disabled."
+msgstr "Modo Touchpad desactivado."
+
+#: backends/platform/sdl/graphics.cpp:40
+#: backends/platform/wince/wince-sdl.cpp:111
+#: backends/platform/wince/wince-sdl.cpp:118
+msgid "Normal (no scaling)"
+msgstr "Normal (sin escalado)"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:41
+#: backends/platform/wince/CEActionsSmartphone.cpp:38
+msgid "Up"
+msgstr "Arriba"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:42
+#: backends/platform/wince/CEActionsSmartphone.cpp:39
+msgid "Down"
+msgstr "Abajo"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:40
+msgid "Left"
+msgstr "Izquierda"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:41
+msgid "Right"
+msgstr "Derecha"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:45
+#: backends/platform/wince/CEActionsPocket.cpp:59
+#: backends/platform/wince/CEActionsSmartphone.cpp:42
+msgid "Left Click"
+msgstr "Clic izquierdo"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:46
+#: backends/platform/wince/CEActionsSmartphone.cpp:43
+msgid "Right Click"
+msgstr "Clic derecho"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:49
+#: backends/platform/wince/CEActionsSmartphone.cpp:46
+msgid "Zone"
+msgstr "Zona"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:50
+#: backends/platform/wince/CEActionsPocket.cpp:53
+#: backends/platform/wince/CEActionsSmartphone.cpp:47
+msgid "Multi Function"
+msgstr "Multifunción"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:51
+msgid "Swap character"
+msgstr "Cambiar personaje"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:52
+msgid "Skip text"
+msgstr "Saltar texto"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:54
+msgid "Fast mode"
+msgstr "Modo rápido"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:55
+#: backends/platform/wince/CEActionsPocket.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:51
+msgid "Quit"
+msgstr "Salir"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:56
+msgid "Debugger"
+msgstr "Debugger"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:57
+msgid "Global menu"
+msgstr "Menú general"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:58
+msgid "Virtual keyboard"
+msgstr "Teclado virtual"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:59
+msgid "Key mapper"
+msgstr "Asignación de teclas"
+
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+msgid "Do you want to quit ?"
+msgstr "¿Quieres salir?"
+
+#: backends/platform/wii/options.cpp:51
+msgid "Video"
+msgstr "Vídeo"
+
+#: backends/platform/wii/options.cpp:54
+msgid "Current video mode:"
+msgstr "Modo de vídeo actual:"
+
+#: backends/platform/wii/options.cpp:56
+msgid "Double-strike"
+msgstr "Doble golpe"
+
+#: backends/platform/wii/options.cpp:60
+msgid "Horizontal underscan:"
+msgstr "Underscan horizontal"
+
+#: backends/platform/wii/options.cpp:66
+msgid "Vertical underscan:"
+msgstr "Underscan vertical:"
+
+#: backends/platform/wii/options.cpp:71
+msgid "Input"
+msgstr "Entrada"
+
+#: backends/platform/wii/options.cpp:74
+msgid "GC Pad sensitivity:"
+msgstr "Sensibilidad del pad GC:"
+
+#: backends/platform/wii/options.cpp:80
+msgid "GC Pad acceleration:"
+msgstr "Aceleración del pad GC:"
+
+#: backends/platform/wii/options.cpp:86
+msgid "DVD"
+msgstr "DVD"
+
+#: backends/platform/wii/options.cpp:89
+#: backends/platform/wii/options.cpp:101
+msgid "Status:"
+msgstr "Estado:"
+
+#: backends/platform/wii/options.cpp:90
+#: backends/platform/wii/options.cpp:102
+msgid "Unknown"
+msgstr "Desconocido"
+
+#: backends/platform/wii/options.cpp:93
+msgid "Mount DVD"
+msgstr "Montar DVD"
+
+#: backends/platform/wii/options.cpp:94
+msgid "Unmount DVD"
+msgstr "Desmontar DVD"
+
+#: backends/platform/wii/options.cpp:98
+msgid "SMB"
+msgstr "SMB"
+
+#: backends/platform/wii/options.cpp:106
+msgid "Server:"
+msgstr "Servidor:"
+
+#: backends/platform/wii/options.cpp:110
+msgid "Share:"
+msgstr "Disco compartido:"
+
+#: backends/platform/wii/options.cpp:114
+msgid "Username:"
+msgstr "Usuario:"
+
+#: backends/platform/wii/options.cpp:118
+msgid "Password:"
+msgstr "Contraseña:"
+
+#: backends/platform/wii/options.cpp:121
+msgid "Init network"
+msgstr "Inicializar red"
+
+#: backends/platform/wii/options.cpp:123
+msgid "Mount SMB"
+msgstr "Montar SMB"
+
+#: backends/platform/wii/options.cpp:124
+msgid "Unmount SMB"
+msgstr "Desmontar SMB"
+
+#: backends/platform/wii/options.cpp:145
+msgid "DVD Mounted successfully"
+msgstr "DVD montado con éxito"
+
+#: backends/platform/wii/options.cpp:148
+msgid "Error while mounting the DVD"
+msgstr "Error al montar el DVD"
+
+#: backends/platform/wii/options.cpp:150
+msgid "DVD not mounted"
+msgstr "DVD no montado"
+
+#: backends/platform/wii/options.cpp:163
+msgid "Network up, share mounted"
+msgstr "Red conectada, disco compartido montado"
+
+#: backends/platform/wii/options.cpp:165
+msgid "Network up"
+msgstr "Red conectada"
+
+#: backends/platform/wii/options.cpp:168
+msgid ", error while mounting the share"
+msgstr ", error al montar el disco compartido"
+
+#: backends/platform/wii/options.cpp:170
+msgid ", share not mounted"
+msgstr ", disco compartido no montado"
+
+#: backends/platform/wii/options.cpp:176
+msgid "Network down"
+msgstr "Red desconectada"
+
+#: backends/platform/wii/options.cpp:180
+msgid "Initialising network"
+msgstr "Inicializando red"
+
+#: backends/platform/wii/options.cpp:184
+msgid "Timeout while initialising network"
+msgstr "Se ha excedido el tiempo de inicialización de red"
+
+#: backends/platform/wii/options.cpp:188
+#, c-format
+msgid "Network not initialsed (%d)"
+msgstr "Red no inicializada (%d)"
+
+#: backends/platform/wince/CEActionsPocket.cpp:45
+msgid "Hide Toolbar"
+msgstr "Ocultar barra de tareas"
+
+#: backends/platform/wince/CEActionsPocket.cpp:46
+msgid "Show Keyboard"
+msgstr "Mostrar teclado"
+
+#: backends/platform/wince/CEActionsPocket.cpp:47
+msgid "Sound on/off"
+msgstr "Sonido activado/desactivado"
+
+#: backends/platform/wince/CEActionsPocket.cpp:48
+msgid "Right click"
+msgstr "Clic derecho"
+
+#: backends/platform/wince/CEActionsPocket.cpp:49
+msgid "Show/Hide Cursor"
+msgstr "Mostrar/ocultar cursor"
+
+#: backends/platform/wince/CEActionsPocket.cpp:50
+msgid "Free look"
+msgstr "Vista libre"
+
+#: backends/platform/wince/CEActionsPocket.cpp:51
+msgid "Zoom up"
+msgstr "Aumentar zoom"
+
+#: backends/platform/wince/CEActionsPocket.cpp:52
+msgid "Zoom down"
+msgstr "Disminuir zoom"
+
+#: backends/platform/wince/CEActionsPocket.cpp:54
+#: backends/platform/wince/CEActionsSmartphone.cpp:48
+msgid "Bind Keys"
+msgstr "Asignar teclas"
+
+#: backends/platform/wince/CEActionsPocket.cpp:55
+msgid "Cursor Up"
+msgstr "Arriba"
+
+#: backends/platform/wince/CEActionsPocket.cpp:56
+msgid "Cursor Down"
+msgstr "Abajo"
+
+#: backends/platform/wince/CEActionsPocket.cpp:57
+msgid "Cursor Left"
+msgstr "Izquierda"
+
+#: backends/platform/wince/CEActionsPocket.cpp:58
+msgid "Cursor Right"
+msgstr "Derecha"
+
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Do you want to load or save the game?"
+msgstr "¿Quieres cargar o guardar el juego?"
+
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+msgid " Are you sure you want to quit ? "
+msgstr "¿Seguro que quieres salir?"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:49
+msgid "Keyboard"
+msgstr "Teclado"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:50
+msgid "Rotate"
+msgstr "Rotar"
+
+#: backends/platform/wince/CELauncherDialog.cpp:58
+msgid "Using SDL driver "
+msgstr "Usando driver SDL"
+
+#: backends/platform/wince/CELauncherDialog.cpp:62
+msgid "Display "
+msgstr "Pantalla"
+
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Do you want to perform an automatic scan ?"
+msgstr "¿Quieres realizar una búsqueda automática?"
+
diff --git a/po/fr_FR.po b/po/fr_FR.po
new file mode 100644
index 0000000000..51af254072
--- /dev/null
+++ b/po/fr_FR.po
@@ -0,0 +1,1549 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR ScummVM Team
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ScummVM 1.2.0svn\n"
+"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
+"POT-Creation-Date: 2010-07-30 22:14+0100\n"
+"PO-Revision-Date: 2010-07-30 22:18+0100\n"
+"Last-Translator: Thierry Crozat <criezy@scummvm.org>\n"
+"Language-Team: French <scummvm-devel@lists.sf.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: Francais\n"
+"Plural-Forms: nplurals=2; plural=n>1;\n"
+
+#: gui/about.cpp:96
+#, c-format
+msgid "(built on %s)"
+msgstr "(compilé sur %s)"
+
+#: gui/about.cpp:103
+msgid "Features compiled in:"
+msgstr "Options incluses:"
+
+#: gui/about.cpp:112
+msgid "Available engines:"
+msgstr "Moteurs disponibles:"
+
+#: gui/browser.cpp:69
+msgid "Go up"
+msgstr "Remonter"
+
+#: gui/browser.cpp:69
+msgid "Go to previous directory level"
+msgstr "Remonte d'un niveau dans la hiérarchie de répertoire"
+
+#: gui/browser.cpp:70
+#: gui/chooser.cpp:49
+#: gui/KeysDialog.cpp:46
+#: gui/launcher.cpp:280
+#: gui/massadd.cpp:95
+#: gui/options.cpp:1029
+#: gui/saveload.cpp:65
+#: gui/saveload.cpp:157
+#: gui/themebrowser.cpp:56
+#: backends/platform/wii/options.cpp:48
+msgid "Cancel"
+msgstr "Annuler"
+
+#: gui/browser.cpp:71
+#: gui/chooser.cpp:50
+#: gui/themebrowser.cpp:57
+msgid "Choose"
+msgstr "Choisir"
+
+#: gui/GuiManager.cpp:103
+#: backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "Fermer"
+
+#: gui/GuiManager.cpp:106
+msgid "Mouse click"
+msgstr "Clic de souris"
+
+#: gui/GuiManager.cpp:109
+#: base/main.cpp:285
+msgid "Display keyboard"
+msgstr "Afficher le clavier"
+
+#: gui/GuiManager.cpp:112
+#: base/main.cpp:288
+msgid "Remap keys"
+msgstr "Changer l'affectation des touches"
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr "Affecter"
+
+#: gui/KeysDialog.cpp:45
+#: gui/launcher.cpp:281
+#: gui/launcher.cpp:893
+#: gui/launcher.cpp:897
+#: gui/massadd.cpp:92
+#: gui/options.cpp:1030
+#: backends/platform/wii/options.cpp:47
+#: backends/platform/wince/CELauncherDialog.cpp:56
+msgid "OK"
+msgstr "OK"
+
+#: gui/KeysDialog.cpp:52
+msgid "Select an action and click 'Map'"
+msgstr "Selectionez une action et cliquez 'Affecter'"
+
+#: gui/KeysDialog.cpp:83
+#: gui/KeysDialog.cpp:105
+#: gui/KeysDialog.cpp:144
+#, c-format
+msgid "Associated key : %s"
+msgstr "Touche associée: %s"
+
+#: gui/KeysDialog.cpp:85
+#: gui/KeysDialog.cpp:107
+#: gui/KeysDialog.cpp:146
+#, c-format
+msgid "Associated key : none"
+msgstr "Touche associée: aucune"
+
+#: gui/KeysDialog.cpp:93
+msgid "Please select an action"
+msgstr "Selectionnez une action"
+
+#: gui/KeysDialog.cpp:109
+msgid "Press the key to associate"
+msgstr "Appuyez sur la touche à associer"
+
+#: gui/KeysDialog.cpp:148
+msgid "Choose an action to map"
+msgstr "Sélectionnez une action à affecter"
+
+#: gui/launcher.cpp:172
+msgid "Game"
+msgstr "Jeu"
+
+#: gui/launcher.cpp:175
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:175
+#: gui/launcher.cpp:176
+msgid "Short game identifier used for referring to savegames and running the game from the command line"
+msgstr "ID compact du jeu utilisé pour identifier les sauvegardes et démarrer le jeu depuis la ligne de commande"
+
+#: gui/launcher.cpp:179
+msgid "Name:"
+msgstr "Nom:"
+
+#: gui/launcher.cpp:179
+#: gui/launcher.cpp:180
+msgid "Full title of the game"
+msgstr "Nom complet du jeu"
+
+#: gui/launcher.cpp:183
+msgid "Language:"
+msgstr "Langue:"
+
+#: gui/launcher.cpp:183
+#: gui/launcher.cpp:184
+msgid "Language of the game. This will not turn your Spanish game version into English"
+msgstr "Langue du jeu. Cela ne traduira pas en anglais par magie votre version espagnole du jeu."
+
+#: gui/launcher.cpp:185
+#: gui/launcher.cpp:196
+#: gui/options.cpp:80
+#: gui/options.cpp:635
+#: gui/options.cpp:645
+#: gui/options.cpp:1000
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<defaut>"
+
+#: gui/launcher.cpp:194
+msgid "Platform:"
+msgstr "Plateforme:"
+
+#: gui/launcher.cpp:194
+#: gui/launcher.cpp:195
+msgid "Platform the game was originally designed for"
+msgstr "Plateforme pour laquelle votre jeu a été conçu"
+
+#: gui/launcher.cpp:206
+#: gui/options.cpp:898
+#: gui/options.cpp:915
+msgid "Graphics"
+msgstr "Graphique"
+
+#: gui/launcher.cpp:206
+#: gui/options.cpp:898
+#: gui/options.cpp:915
+msgid "GFX"
+msgstr "GFX"
+
+#: gui/launcher.cpp:208
+msgid "Override global graphic settings"
+msgstr "Utiliser des réglages graphiques spécifiques à ce jeux"
+
+#: gui/launcher.cpp:215
+#: gui/options.cpp:921
+msgid "Audio"
+msgstr "Audio"
+
+#: gui/launcher.cpp:217
+msgid "Override global audio settings"
+msgstr "Utiliser des réglages audio spécifiques à ce jeux"
+
+#: gui/launcher.cpp:225
+#: gui/options.cpp:925
+msgid "Volume"
+msgstr "Volume"
+
+#: gui/launcher.cpp:227
+msgid "Override global volume settings"
+msgstr "Utiliser des réglages de volume sonore spécifiques à ce jeux"
+
+#: gui/launcher.cpp:234
+#: gui/options.cpp:933
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:236
+msgid "Override global MIDI settings"
+msgstr "Utiliser des réglages MIDI spécifiques à ce jeux"
+
+#: gui/launcher.cpp:246
+#: gui/options.cpp:939
+msgid "MT-32"
+msgstr "MT-32"
+
+#: gui/launcher.cpp:248
+msgid "Override global MT-32 settings"
+msgstr "Utiliser des réglages MT-32 spécifiques à ce jeux"
+
+#: gui/launcher.cpp:258
+#: gui/options.cpp:945
+msgid "Paths"
+msgstr "Chemins"
+
+#: gui/launcher.cpp:264
+msgid "Game Path:"
+msgstr "Chemin du Jeu:"
+
+#: gui/launcher.cpp:268
+#: gui/options.cpp:958
+msgid "Extra Path:"
+msgstr "Extra:"
+
+#: gui/launcher.cpp:268
+#: gui/launcher.cpp:269
+msgid "Specifies path to additional data used the game"
+msgstr "Définie un chemin vers des données suplémentaires utilisées par le jeu"
+
+#: gui/launcher.cpp:272
+msgid "Save Path:"
+msgstr "Sauvegardes:"
+
+#: gui/launcher.cpp:272
+#: gui/launcher.cpp:273
+#: gui/options.cpp:952
+#: gui/options.cpp:953
+msgid "Specifies where your savegames are put"
+msgstr "Définie l'emplacement où les fichiers de sauvegarde sont créés"
+
+#: gui/launcher.cpp:289
+#: gui/launcher.cpp:369
+#: gui/launcher.cpp:418
+#: gui/options.cpp:230
+#: gui/options.cpp:399
+#: gui/options.cpp:497
+#: gui/options.cpp:555
+#: gui/options.cpp:732
+#: gui/options.cpp:956
+#: gui/options.cpp:959
+#: gui/options.cpp:963
+#: gui/options.cpp:1053
+#: gui/options.cpp:1059
+#: gui/options.cpp:1065
+#: gui/options.cpp:1073
+#: gui/options.cpp:1097
+#: gui/options.cpp:1101
+#: gui/options.cpp:1107
+#: gui/options.cpp:1114
+#: gui/options.cpp:1213
+msgid "None"
+msgstr "Aucun"
+
+#: gui/launcher.cpp:294
+#: gui/launcher.cpp:373
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "Défaut"
+
+#: gui/launcher.cpp:411
+#: gui/options.cpp:1207
+msgid "Select SoundFont"
+msgstr "Choisir une banque de sons"
+
+#: gui/launcher.cpp:430
+#: gui/launcher.cpp:568
+msgid "Select directory with game data"
+msgstr "Sélectionner le répertoire contenant les données du jeu"
+
+#: gui/launcher.cpp:448
+msgid "Select additional game directory"
+msgstr "Sélectionner un répertoire supplémentaire"
+
+#: gui/launcher.cpp:460
+msgid "Select directory for saved games"
+msgstr "Sélectionner le répertoire pour les sauvegardes"
+
+#: gui/launcher.cpp:479
+msgid "This game ID is already taken. Please choose another one."
+msgstr "Cet ID est déjà utilisé par un autre jeu. Choisissez en un autre svp."
+
+#: gui/launcher.cpp:520
+#: engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "~Q~uitter"
+
+#: gui/launcher.cpp:520
+msgid "Quit ScummVM"
+msgstr "Quitter ScummVM"
+
+#: gui/launcher.cpp:521
+msgid "A~b~out..."
+msgstr "À ~P~ropos..."
+
+#: gui/launcher.cpp:521
+msgid "About ScummVM"
+msgstr "À propos de ScummVM"
+
+#: gui/launcher.cpp:522
+msgid "~O~ptions..."
+msgstr "~O~ptions..."
+
+#: gui/launcher.cpp:522
+msgid "Change global ScummVM options"
+msgstr "Change les options globales de ScummVM"
+
+#: gui/launcher.cpp:524
+msgid "~S~tart"
+msgstr "~D~émarrer"
+
+#: gui/launcher.cpp:524
+msgid "Start selected game"
+msgstr "Démarre le jeu sélectionné"
+
+#: gui/launcher.cpp:527
+msgid "~L~oad..."
+msgstr "~C~harger"
+
+#: gui/launcher.cpp:527
+msgid "Load savegame for selected game"
+msgstr "Charge une sauvegarde pour le jeu sélectionné"
+
+#: gui/launcher.cpp:531
+msgid "~A~dd Game..."
+msgstr "~A~jouter..."
+
+#: gui/launcher.cpp:531
+msgid "Hold Shift for Mass Add"
+msgstr "Ajoute un jeu à la Liste. Maintenez Shift enfoncée pour un Ajout Massif"
+
+#: gui/launcher.cpp:533
+msgid "~E~dit Game..."
+msgstr "~E~diter..."
+
+#: gui/launcher.cpp:533
+msgid "Change game options"
+msgstr "Change les options du jeu"
+
+#: gui/launcher.cpp:535
+msgid "~R~emove Game"
+msgstr "~S~upprimer"
+
+#: gui/launcher.cpp:535
+msgid "Remove game from the list. The game data files stay intact"
+msgstr "Supprime le jeu de la liste. Les fichiers sont conservés"
+
+#: gui/launcher.cpp:542
+msgid "Search in game list"
+msgstr "Recherche dans la liste de jeux"
+
+#: gui/launcher.cpp:546
+#: gui/launcher.cpp:1057
+msgid "Search:"
+msgstr "Filtre:"
+
+#: gui/launcher.cpp:549
+#: gui/options.cpp:733
+msgid "Clear value"
+msgstr "Effacer la valeur"
+
+#: gui/launcher.cpp:571
+#: engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "Charger le jeu:"
+
+#: gui/launcher.cpp:571
+#: engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "Charger"
+
+#: gui/launcher.cpp:680
+msgid "Do you really want to run the mass game detector? This could potentially add a huge number of games."
+msgstr "Voulez-vous vraiment lancer la détection automatique des jeux? Cela peut potentiellement ajouter un grand nombre de jeux."
+
+#: gui/launcher.cpp:681
+#: gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Yes"
+msgstr "Oui"
+
+#: gui/launcher.cpp:681
+#: gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "No"
+msgstr "Non"
+
+#: gui/launcher.cpp:728
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM n'a pas pu ouvrir le répertoire sélectionné."
+
+#: gui/launcher.cpp:740
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr "ScummVM n'a pas trouvé de jeux dans le répertoire sélectionné."
+
+#: gui/launcher.cpp:754
+msgid "Pick the game:"
+msgstr "Choisissez le jeu:"
+
+#: gui/launcher.cpp:830
+msgid "Do you really want to remove this game configuration?"
+msgstr "Voulez-vous vraiment supprimer ce jeu?"
+
+#: gui/launcher.cpp:893
+msgid "This game does not support loading games from the launcher."
+msgstr "Le chargement de sauvegarde depuis le lanceur n'est pas supporté pour ce jeu."
+
+#: gui/launcher.cpp:897
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr "ScummVM n'a pas pu trouvé de moteur pour lancer le jeu sélectionné."
+
+#: gui/launcher.cpp:1009
+msgid "Mass Add..."
+msgstr "Ajout Massif..."
+
+#: gui/launcher.cpp:1010
+msgid "Add Game..."
+msgstr "Ajouter..."
+
+#: gui/massadd.cpp:79
+#: gui/massadd.cpp:82
+msgid "... progress ..."
+msgstr "... en cours ..."
+
+#: gui/massadd.cpp:244
+msgid "Scan complete!"
+msgstr "Examen terminé!"
+
+#: gui/massadd.cpp:247
+#, c-format
+msgid "Discovered %d new games."
+msgstr "%d nouveaux jeux trouvés."
+
+#: gui/massadd.cpp:251
+#, c-format
+msgid "Scanned %d directories ..."
+msgstr "%d répertoires examinés ..."
+
+#: gui/massadd.cpp:254
+#, c-format
+msgid "Discovered %d new games ..."
+msgstr "%d nouveaux jeux trouvés ..."
+
+#: gui/options.cpp:78
+msgid "Never"
+msgstr "Jamais"
+
+#: gui/options.cpp:78
+msgid "every 5 mins"
+msgstr "Toutes les 5 mins"
+
+#: gui/options.cpp:78
+msgid "every 10 mins"
+msgstr "Toutes les 10 mins"
+
+#: gui/options.cpp:78
+msgid "every 15 mins"
+msgstr "Toutes les 15 mins"
+
+#: gui/options.cpp:78
+msgid "every 30 mins"
+msgstr "Toutes les 30 mins"
+
+#: gui/options.cpp:80
+msgid "8 kHz"
+msgstr "8 kHz"
+
+#: gui/options.cpp:80
+msgid "11kHz"
+msgstr "11 kHz"
+
+#: gui/options.cpp:80
+msgid "22 kHz"
+msgstr "22 kHz"
+
+#: gui/options.cpp:80
+msgid "44 kHz"
+msgstr "44 kHz"
+
+#: gui/options.cpp:80
+msgid "48 kHz"
+msgstr "48 kHz"
+
+#: gui/options.cpp:632
+msgid "Graphics mode:"
+msgstr "Mode graphique:"
+
+#: gui/options.cpp:643
+msgid "Render mode:"
+msgstr "Mode de rendu:"
+
+#: gui/options.cpp:643
+#: gui/options.cpp:644
+msgid "Special dithering modes supported by some games"
+msgstr "Mode spécial de tramage supporté par certains jeux"
+
+#: gui/options.cpp:653
+msgid "Fullscreen mode"
+msgstr "Plein écran"
+
+#: gui/options.cpp:656
+msgid "Aspect ratio correction"
+msgstr "Correction du rapport d'aspect"
+
+#: gui/options.cpp:656
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "Corrige le rapport d'aspect pour les jeu 320x200"
+
+#: gui/options.cpp:663
+msgid "Preferred Device:"
+msgstr "Sortie Préféré:"
+
+#: gui/options.cpp:663
+msgid "Music Device:"
+msgstr "Sortie Audio:"
+
+#: gui/options.cpp:663
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr "Spécifie le périphérique de sortie audio ou l'émulateur de carte audio préféré"
+
+#: gui/options.cpp:663
+#: gui/options.cpp:664
+msgid "Specifies output sound device or sound card emulator"
+msgstr "Spécifie le périphérique de sortie audio ou l'émulateur de carte audio"
+
+#: gui/options.cpp:688
+msgid "AdLib emulator:"
+msgstr "Émulateur AdLib:"
+
+#: gui/options.cpp:688
+#: gui/options.cpp:689
+msgid "AdLib is used for music in many games"
+msgstr "AdLib est utilisé pour la musique dans de nombreux jeux"
+
+#: gui/options.cpp:699
+msgid "Output rate:"
+msgstr "Fréquence:"
+
+#: gui/options.cpp:699
+#: gui/options.cpp:700
+msgid "Higher value specifies better sound quality but may be not supported by your soundcard"
+msgstr "Une valeur plus élevée donne une meilleure qualité audio mais peut ne pas être supporté par votre carte son"
+
+#: gui/options.cpp:710
+msgid "GM Device:"
+msgstr "Sortie GM:"
+
+#: gui/options.cpp:710
+msgid "Specifies default sound device for General MIDI output"
+msgstr "Spécifie le périphérique audio par défaut pour la sortie General MIDI"
+
+#: gui/options.cpp:731
+msgid "SoundFont:"
+msgstr "Banque de sons:"
+
+#: gui/options.cpp:731
+#: gui/options.cpp:732
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr "La banque de sons est utilisée par certaines cartes audio, Fluidsynth et Timidity"
+
+#: gui/options.cpp:736
+msgid "Mixed AdLib/MIDI mode"
+msgstr "Mode mixe AdLib/MIDI"
+
+#: gui/options.cpp:736
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "Utiliser à la fois MIDI et AdLib"
+
+#: gui/options.cpp:739
+msgid "MIDI gain:"
+msgstr "Gain MIDI:"
+
+#: gui/options.cpp:749
+msgid "MT-32 Device:"
+msgstr "Sortie MT-32:"
+
+#: gui/options.cpp:749
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr "Spécifie le périphérique audio par défaut pour la sortie Roland MT-32/LAPC1/CM32l/CM64"
+
+#: gui/options.cpp:753
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Roland MT-32 exacte (désactive l'émulation GM)"
+
+#: gui/options.cpp:753
+msgid "Check if you want to use your real hardware Roland-compatible sound device connected to your computer"
+msgstr "Vérifie si vous voulez utiliser un périphérique audio compatible Roland connecté à l'ordinateur"
+
+#: gui/options.cpp:756
+msgid "Enable Roland GS Mode"
+msgstr "Activer le mode Roland GS"
+
+#: gui/options.cpp:756
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr "Désactiver la conversion des pistes MT-32 en General MIDI"
+
+#: gui/options.cpp:780
+msgid "Text and Speech:"
+msgstr "Dialogue:"
+
+#: gui/options.cpp:785
+#: gui/options.cpp:791
+msgid "Speech"
+msgstr "Audio"
+
+#: gui/options.cpp:786
+#: gui/options.cpp:792
+msgid "Subtitles"
+msgstr "Sous-titres"
+
+#: gui/options.cpp:787
+#: gui/options.cpp:793
+msgid "Both"
+msgstr "Les deux"
+
+#: gui/options.cpp:791
+msgid "Spch"
+msgstr "Audio"
+
+#: gui/options.cpp:792
+msgid "Subs"
+msgstr "Subs"
+
+#: gui/options.cpp:793
+msgid "Show subtitles and play speech"
+msgstr "Affiche les sous-titres et joue les dialogues audio"
+
+#: gui/options.cpp:797
+msgid "Subtitle speed:"
+msgstr "Vitesse des ST:"
+
+#: gui/options.cpp:809
+msgid "Music volume:"
+msgstr "Volume Musique:"
+
+#: gui/options.cpp:816
+msgid "Mute All"
+msgstr "Silence"
+
+#: gui/options.cpp:819
+msgid "SFX volume:"
+msgstr "Volume Bruitage:"
+
+#: gui/options.cpp:819
+#: gui/options.cpp:820
+msgid "Special sound effects volume"
+msgstr "Volume des effets spéciaux sonores"
+
+#: gui/options.cpp:826
+msgid "Speech volume:"
+msgstr "Volume Dialogues:"
+
+#: gui/options.cpp:952
+msgid "Save Path: "
+msgstr "Sauvegardes:"
+
+#: gui/options.cpp:955
+msgid "Theme Path:"
+msgstr "Thèmes:"
+
+#: gui/options.cpp:958
+#: gui/options.cpp:959
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr "Spécifie un chemin vers des données supplémentaires utilisées par tous les jeux ou ScummVM"
+
+#: gui/options.cpp:962
+msgid "Plugins Path:"
+msgstr "Plugins:"
+
+#: gui/options.cpp:970
+msgid "Misc"
+msgstr "Divers"
+
+#: gui/options.cpp:972
+msgid "Theme:"
+msgstr "Thème:"
+
+#: gui/options.cpp:976
+msgid "GUI Renderer:"
+msgstr "Interface:"
+
+#: gui/options.cpp:982
+msgid "Autosave:"
+msgstr "Sauvegarde auto:"
+
+#: gui/options.cpp:990
+msgid "Keys"
+msgstr "Touches"
+
+#: gui/options.cpp:997
+msgid "GUI Language:"
+msgstr "Langue:"
+
+#: gui/options.cpp:997
+msgid "Language of ScummVM GUI"
+msgstr "Langue de l'interface graphique de ScummVM"
+
+#: gui/options.cpp:1002
+msgid "English"
+msgstr "Anglais"
+
+#: gui/options.cpp:1146
+msgid "You have to restart ScummVM to take the effect."
+msgstr "Vous devez relancer ScummVM pour que le changement soit pris en compte."
+
+#: gui/options.cpp:1159
+msgid "Select directory for savegames"
+msgstr "Sélectionner le répertoire pour les sauvegardes"
+
+#: gui/options.cpp:1166
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr "Le répertoire sélectionné est vérouillé en écriture. Sélectionnez un autre répertoire."
+
+#: gui/options.cpp:1175
+msgid "Select directory for GUI themes"
+msgstr "Sélectionner le répertoire des thèmes d'interface"
+
+#: gui/options.cpp:1185
+msgid "Select directory for extra files"
+msgstr "Sélectionner le répertoire pour les fichiers suplémentaires"
+
+#: gui/options.cpp:1196
+msgid "Select directory for plugins"
+msgstr "Sélectionner le répertoire des plugins"
+
+#: gui/saveload.cpp:60
+#: gui/saveload.cpp:241
+msgid "No date saved"
+msgstr "Date non sauvée"
+
+#: gui/saveload.cpp:61
+#: gui/saveload.cpp:242
+msgid "No time saved"
+msgstr "Heure non sauvée"
+
+#: gui/saveload.cpp:62
+#: gui/saveload.cpp:243
+msgid "No playtime saved"
+msgstr "Durée de jeu non sauvée"
+
+#: gui/saveload.cpp:69
+#: gui/saveload.cpp:157
+msgid "Delete"
+msgstr "Supprimer"
+
+#: gui/saveload.cpp:156
+msgid "Do you really want to delete this savegame?"
+msgstr "Voulez-vous vraiment supprimer cette sauvegarde?"
+
+#: gui/saveload.cpp:265
+msgid "Date: "
+msgstr "Date:"
+
+#: gui/saveload.cpp:268
+msgid "Time: "
+msgstr "Heure:"
+
+#: gui/saveload.cpp:273
+msgid "Playtime: "
+msgstr "Durée de jeu:"
+
+#: gui/saveload.cpp:286
+#: gui/saveload.cpp:353
+msgid "Untitled savestate"
+msgstr "Sauvegarde sans nom"
+
+#: gui/themebrowser.cpp:46
+msgid "Select a Theme"
+msgstr "Sélectionnez un Thème"
+
+#: gui/ThemeEngine.cpp:334
+msgid "Disabled GFX"
+msgstr "GFX désactivé"
+
+#: gui/ThemeEngine.cpp:335
+msgid "Standard Renderer (16bpp)"
+msgstr "Standard (16bpp)"
+
+#: gui/ThemeEngine.cpp:337
+msgid "Antialiased Renderer (16bpp)"
+msgstr "Anti-crénelé (16 bpp)"
+
+#: base/main.cpp:205
+#, c-format
+msgid "Engine does not support debug level '%s'"
+msgstr "Le niveau de debug '%s' n'est pas supporté par ce moteur de jeu"
+
+#: base/main.cpp:273
+msgid "Menu"
+msgstr "Menu"
+
+#: base/main.cpp:276
+#: backends/platform/symbian/src/SymbianActions.cpp:48
+#: backends/platform/wince/CEActionsPocket.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:45
+msgid "Skip"
+msgstr "Passer"
+
+#: base/main.cpp:279
+#: backends/platform/symbian/src/SymbianActions.cpp:53
+#: backends/platform/wince/CEActionsPocket.cpp:41
+msgid "Pause"
+msgstr "Mettre en pause"
+
+#: base/main.cpp:282
+msgid "Skip line"
+msgstr "Passer la phrase"
+
+#: base/main.cpp:404
+msgid "Error running game:"
+msgstr "Erreur lors de l'éxécution du jeu:"
+
+#: base/main.cpp:430
+#: base/main.cpp:431
+msgid "Could not find any engine capable of running the selected game"
+msgstr "Impossible de trouver un moteur pour exécuter le jeu sélectionné"
+
+#: common/error.cpp:43
+msgid "Invalid Path"
+msgstr "Chemin Invalide"
+
+#: common/error.cpp:44
+msgid "Game Data not found"
+msgstr "Fichier de donées introuvable"
+
+#: common/error.cpp:45
+msgid "Game Id not supported"
+msgstr "ID de jeu non supporté"
+
+#: common/error.cpp:46
+msgid "Unsupported Color Mode"
+msgstr "Mode de couleurs non supporté"
+
+#: common/error.cpp:48
+msgid "Read permission denied"
+msgstr "Véroullié en lecture"
+
+#: common/error.cpp:49
+msgid "Write permission denied"
+msgstr "Verrouillé en écriture"
+
+#: common/error.cpp:52
+msgid "Path not exists"
+msgstr "Chemin inexistant"
+
+#: common/error.cpp:53
+msgid "Path not a directory"
+msgstr "Chemin n'est pas un répertoire"
+
+#: common/error.cpp:54
+msgid "Path not a file"
+msgstr "Chemin n'est pas un fichier"
+
+#: common/error.cpp:56
+msgid "Cannot create file"
+msgstr "Impossible de créer le fichier"
+
+#: common/error.cpp:57
+msgid "Reading failed"
+msgstr "Echec de la lecture"
+
+#: common/error.cpp:58
+msgid "Writing data failed"
+msgstr "Echec de l'écriture des données"
+
+#: common/error.cpp:60
+#: common/error.cpp:71
+msgid "Unknown Error"
+msgstr "Erreur inconnue"
+
+#: common/util.cpp:254
+msgid "Hercules Green"
+msgstr "Hercules Vert"
+
+#: common/util.cpp:255
+msgid "Hercules Amber"
+msgstr "Hercules Ambre"
+
+#: engines/dialogs.cpp:89
+msgid "~R~esume"
+msgstr "~R~eprendre"
+
+#: engines/dialogs.cpp:91
+msgid "~L~oad"
+msgstr "~C~harger"
+
+#: engines/dialogs.cpp:95
+msgid "~S~ave"
+msgstr "~S~auver"
+
+#: engines/dialogs.cpp:99
+msgid "~O~ptions"
+msgstr "~O~ptions"
+
+#: engines/dialogs.cpp:104
+msgid "~H~elp"
+msgstr "~A~ide"
+
+#: engines/dialogs.cpp:107
+msgid "~A~bout"
+msgstr "À ~P~ropos"
+
+#: engines/dialogs.cpp:109
+msgid "~R~eturn to Launcher"
+msgstr "Retour au ~L~anceur"
+
+#: engines/dialogs.cpp:119
+msgid "Save game:"
+msgstr "Sauvegarde:"
+
+#: engines/dialogs.cpp:119
+#: backends/platform/symbian/src/SymbianActions.cpp:47
+#: backends/platform/wince/CEActionsPocket.cpp:42
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Save"
+msgstr "Sauver"
+
+#: engines/dialogs.cpp:301
+#: engines/mohawk/dialogs.cpp:84
+#: engines/mohawk/dialogs.cpp:118
+msgid "~O~K"
+msgstr "~O~K"
+
+#: engines/dialogs.cpp:302
+#: engines/mohawk/dialogs.cpp:85
+#: engines/mohawk/dialogs.cpp:119
+msgid "~C~ancel"
+msgstr "~A~nnuler"
+
+#: engines/dialogs.cpp:305
+msgid "~K~eys"
+msgstr "~T~ouches"
+
+#: engines/scumm/dialogs.cpp:287
+msgid "~P~revious"
+msgstr "~P~récédent"
+
+#: engines/scumm/dialogs.cpp:288
+msgid "~N~ext"
+msgstr "~S~uivant"
+
+#: engines/scumm/dialogs.cpp:289
+#: backends/platform/ds/arm9/source/dsoptions.cpp:59
+msgid "~C~lose"
+msgstr "~F~ermer"
+
+#: engines/mohawk/dialogs.cpp:81
+#: engines/mohawk/dialogs.cpp:115
+msgid "~Z~ip Mode Activated"
+msgstr "Mode ~Z~ip Activé"
+
+#: engines/mohawk/dialogs.cpp:82
+msgid "~T~ransitions Enabled"
+msgstr "T~r~ansitions activé"
+
+#: engines/mohawk/dialogs.cpp:116
+msgid "~W~ater Effect Enabled"
+msgstr "~E~ffets de l'Eau Activés"
+
+#: sound/fmopl.cpp:51
+msgid "MAME OPL emulator"
+msgstr "Émulateur MAME OPL"
+
+#: sound/fmopl.cpp:53
+msgid "DOSBox OPL emulator"
+msgstr "Émulateur DOSBox OPL"
+
+#: sound/null.h:45
+msgid "No music"
+msgstr "Pas de musique"
+
+#: sound/softsynth/adlib.cpp:1590
+msgid "AdLib Emulator"
+msgstr "Émulateur AdLib"
+
+#: sound/softsynth/mt32.cpp:327
+msgid "Initialising MT-32 Emulator"
+msgstr "Initialisation de l'Émulateur MT-32"
+
+#: sound/softsynth/mt32.cpp:541
+msgid "MT-32 Emulator"
+msgstr "Émulateur MT-32"
+
+#: sound/softsynth/pcspk.cpp:142
+msgid "PC Speaker Emulator"
+msgstr "Émulateur Haut Parleur PC"
+
+#: sound/softsynth/pcspk.cpp:161
+msgid "IBM PCjr Emulator"
+msgstr "Émulateur IBM PCjr"
+
+#: sound/softsynth/ym2612.cpp:762
+msgid "FM Towns Emulator"
+msgstr "Émulateur FM Towns"
+
+#: backends/keymapper/remap-dialog.cpp:49
+msgid "Keymap:"
+msgstr "Affectation des touches:"
+
+#: backends/keymapper/remap-dialog.cpp:66
+msgid " (Active)"
+msgstr "(Actif)"
+
+#: backends/keymapper/remap-dialog.cpp:100
+msgid " (Global)"
+msgstr "(Global)"
+
+#: backends/keymapper/remap-dialog.cpp:110
+msgid " (Game)"
+msgstr "(Jeu)"
+
+#: backends/midi/windows.cpp:157
+msgid "Windows MIDI"
+msgstr "MIDI Windows"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:60
+msgid "ScummVM Main Menu"
+msgstr "Menu Principal ScummVM"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:66
+msgid "~L~eft handed mode"
+msgstr "Mode ~G~aucher"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:67
+msgid "~I~ndy fight controls"
+msgstr "Contrôle des combats d'~I~ndy"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:68
+msgid "Show mouse cursor"
+msgstr "Afficher le curseur de la souris"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:69
+msgid "Snap to edges"
+msgstr "Aligner sur les bords"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:71
+msgid "Touch X Offset"
+msgstr "Décalage X du toucher"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:78
+msgid "Touch Y Offset"
+msgstr "Décallage Y du toucher"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:90
+msgid "Use laptop trackpad-style cursor control"
+msgstr "Activer le contrôle du curseur de type trackpad"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:91
+msgid "Tap for left click, double tap right click"
+msgstr "Toucher pour un clic gauche, toucher deux fois pour un clic droit"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:93
+msgid "Sensitivity"
+msgstr "Sensibilité"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:102
+msgid "Initial top screen scale:"
+msgstr "Échelle initiale de l'écran du haut"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:108
+msgid "Main screen scaling:"
+msgstr "Échelle de l'écran principal"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:110
+msgid "Hardware scale (fast, but low quality)"
+msgstr "Mise à l'echelle matérielle (rapide mais qualité faible)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:111
+msgid "Software scale (good quality, but slower)"
+msgstr "Mise à l'échelle logicielle (bonne qualité mais plus lent)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:112
+msgid "Unscaled (you must scroll left and right)"
+msgstr "Sans changement d'échelle (vous devez faire défiler l'écran)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:114
+msgid "Brightness:"
+msgstr "Luminosité:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:124
+msgid "High quality audio (slower) (reboot)"
+msgstr "Audio haute qualité (plus lent) (redémarrer)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:125
+msgid "Disable power off"
+msgstr "Désactivé l'extinction"
+
+#: backends/platform/iphone/osys_events.cpp:339
+msgid "Touchpad mode enabled."
+msgstr "Mode touchpad activé"
+
+#: backends/platform/iphone/osys_events.cpp:341
+msgid "Touchpad mode disabled."
+msgstr "Mode touchpad désactivé"
+
+#: backends/platform/sdl/graphics.cpp:40
+#: backends/platform/wince/wince-sdl.cpp:111
+#: backends/platform/wince/wince-sdl.cpp:118
+msgid "Normal (no scaling)"
+msgstr "Normal (échelle d'origine)"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:41
+#: backends/platform/wince/CEActionsSmartphone.cpp:38
+msgid "Up"
+msgstr "Haut"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:42
+#: backends/platform/wince/CEActionsSmartphone.cpp:39
+msgid "Down"
+msgstr "Bas"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:40
+msgid "Left"
+msgstr "Gauche"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:41
+msgid "Right"
+msgstr "Droite"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:45
+#: backends/platform/wince/CEActionsPocket.cpp:59
+#: backends/platform/wince/CEActionsSmartphone.cpp:42
+msgid "Left Click"
+msgstr "Clic Gauche"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:46
+#: backends/platform/wince/CEActionsSmartphone.cpp:43
+msgid "Right Click"
+msgstr "Clic Droit"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:49
+#: backends/platform/wince/CEActionsSmartphone.cpp:46
+msgid "Zone"
+msgstr "Zone"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:50
+#: backends/platform/wince/CEActionsPocket.cpp:53
+#: backends/platform/wince/CEActionsSmartphone.cpp:47
+msgid "Multi Function"
+msgstr "Fonction Multiple"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:51
+msgid "Swap character"
+msgstr "Changement de personnage"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:52
+msgid "Skip text"
+msgstr "Sauter le texte"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:54
+msgid "Fast mode"
+msgstr "Mode rapide"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:55
+#: backends/platform/wince/CEActionsPocket.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:51
+msgid "Quit"
+msgstr "Quitter"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:56
+msgid "Debugger"
+msgstr "Debugger"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:57
+msgid "Global menu"
+msgstr "Menu global"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:58
+msgid "Virtual keyboard"
+msgstr "Clavier virtuel"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:59
+#, fuzzy
+msgid "Key mapper"
+msgstr "Affectation des touches"
+
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+msgid "Do you want to quit ?"
+msgstr "Voulez-vous quitter?"
+
+#: backends/platform/wii/options.cpp:51
+msgid "Video"
+msgstr "Vidéo"
+
+#: backends/platform/wii/options.cpp:54
+msgid "Current video mode:"
+msgstr "Mode vidéo actuel"
+
+#: backends/platform/wii/options.cpp:56
+#, fuzzy
+msgid "Double-strike"
+msgstr "Coup double"
+
+#: backends/platform/wii/options.cpp:60
+msgid "Horizontal underscan:"
+msgstr "Underscan horizontal:"
+
+#: backends/platform/wii/options.cpp:66
+msgid "Vertical underscan:"
+msgstr "Underscan vertical:"
+
+#: backends/platform/wii/options.cpp:71
+msgid "Input"
+msgstr "Entrée"
+
+#: backends/platform/wii/options.cpp:74
+msgid "GC Pad sensitivity:"
+msgstr "Sensibilité du pad GC:"
+
+#: backends/platform/wii/options.cpp:80
+msgid "GC Pad acceleration:"
+msgstr "Acceleration du pad GC:"
+
+#: backends/platform/wii/options.cpp:86
+msgid "DVD"
+msgstr "DVD"
+
+#: backends/platform/wii/options.cpp:89
+#: backends/platform/wii/options.cpp:101
+msgid "Status:"
+msgstr "Status:"
+
+#: backends/platform/wii/options.cpp:90
+#: backends/platform/wii/options.cpp:102
+msgid "Unknown"
+msgstr "Inconue"
+
+#: backends/platform/wii/options.cpp:93
+msgid "Mount DVD"
+msgstr "Monter le DVD"
+
+#: backends/platform/wii/options.cpp:94
+msgid "Unmount DVD"
+msgstr "Démonter le DVD"
+
+#: backends/platform/wii/options.cpp:98
+msgid "SMB"
+msgstr "SMB"
+
+#: backends/platform/wii/options.cpp:106
+msgid "Server:"
+msgstr "Serveur:"
+
+#: backends/platform/wii/options.cpp:110
+#, fuzzy
+msgid "Share:"
+msgstr "Disque partagé:"
+
+#: backends/platform/wii/options.cpp:114
+msgid "Username:"
+msgstr "Nom d'utilisateur:"
+
+#: backends/platform/wii/options.cpp:118
+msgid "Password:"
+msgstr "Mot de passe:"
+
+#: backends/platform/wii/options.cpp:121
+msgid "Init network"
+msgstr "Initialiser le réseau"
+
+#: backends/platform/wii/options.cpp:123
+msgid "Mount SMB"
+msgstr "Monter SMB"
+
+#: backends/platform/wii/options.cpp:124
+msgid "Unmount SMB"
+msgstr "Démonter SMB"
+
+#: backends/platform/wii/options.cpp:145
+msgid "DVD Mounted successfully"
+msgstr "DVD monté avec succès"
+
+#: backends/platform/wii/options.cpp:148
+msgid "Error while mounting the DVD"
+msgstr "Échec du montage du DVD"
+
+#: backends/platform/wii/options.cpp:150
+msgid "DVD not mounted"
+msgstr "DVD non monté"
+
+#: backends/platform/wii/options.cpp:163
+#, fuzzy
+msgid "Network up, share mounted"
+msgstr "Réseau connecté, disque partagé monté"
+
+#: backends/platform/wii/options.cpp:165
+#, fuzzy
+msgid "Network up"
+msgstr "Réseau connecté"
+
+#: backends/platform/wii/options.cpp:168
+#, fuzzy
+msgid ", error while mounting the share"
+msgstr ", échec du montage du disque partagé"
+
+#: backends/platform/wii/options.cpp:170
+#, fuzzy
+msgid ", share not mounted"
+msgstr ", disque partagé non monté"
+
+#: backends/platform/wii/options.cpp:176
+#, fuzzy
+msgid "Network down"
+msgstr "Réseau déconnecté"
+
+#: backends/platform/wii/options.cpp:180
+msgid "Initialising network"
+msgstr "Initialisation du réseau"
+
+#: backends/platform/wii/options.cpp:184
+msgid "Timeout while initialising network"
+msgstr "Dépassement du délai lors de l'initialisation du réseau"
+
+#: backends/platform/wii/options.cpp:188
+#, c-format
+msgid "Network not initialsed (%d)"
+msgstr "Réseau non initialisé (%d)"
+
+#: backends/platform/wince/CEActionsPocket.cpp:45
+msgid "Hide Toolbar"
+msgstr "Caché la barre d'outils"
+
+#: backends/platform/wince/CEActionsPocket.cpp:46
+msgid "Show Keyboard"
+msgstr "Afficher le clavier"
+
+#: backends/platform/wince/CEActionsPocket.cpp:47
+msgid "Sound on/off"
+msgstr "Audio marche/arrêt"
+
+#: backends/platform/wince/CEActionsPocket.cpp:48
+msgid "Right click"
+msgstr "Clic droit"
+
+#: backends/platform/wince/CEActionsPocket.cpp:49
+msgid "Show/Hide Cursor"
+msgstr "Afficher/Cacher le curseur"
+
+#: backends/platform/wince/CEActionsPocket.cpp:50
+#, fuzzy
+msgid "Free look"
+msgstr "Regarder autour"
+
+#: backends/platform/wince/CEActionsPocket.cpp:51
+#, fuzzy
+msgid "Zoom up"
+msgstr "Dézoomer"
+
+#: backends/platform/wince/CEActionsPocket.cpp:52
+#, fuzzy
+msgid "Zoom down"
+msgstr "Zoomer"
+
+#: backends/platform/wince/CEActionsPocket.cpp:54
+#: backends/platform/wince/CEActionsSmartphone.cpp:48
+#, fuzzy
+msgid "Bind Keys"
+msgstr "Affecter les touches"
+
+#: backends/platform/wince/CEActionsPocket.cpp:55
+#, fuzzy
+msgid "Cursor Up"
+msgstr "Haut"
+
+#: backends/platform/wince/CEActionsPocket.cpp:56
+#, fuzzy
+msgid "Cursor Down"
+msgstr "Bas"
+
+#: backends/platform/wince/CEActionsPocket.cpp:57
+#, fuzzy
+msgid "Cursor Left"
+msgstr "Gauche"
+
+#: backends/platform/wince/CEActionsPocket.cpp:58
+#, fuzzy
+msgid "Cursor Right"
+msgstr "Droit"
+
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Do you want to load or save the game?"
+msgstr "Voulez-vous charger ou sauver le jeu?"
+
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+msgid " Are you sure you want to quit ? "
+msgstr "Voulez-vous vraiment quitter?"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:49
+msgid "Keyboard"
+msgstr "Clavier"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:50
+msgid "Rotate"
+msgstr "Pivoter"
+
+#: backends/platform/wince/CELauncherDialog.cpp:58
+msgid "Using SDL driver "
+msgstr "Utilise le pilote SDL"
+
+#: backends/platform/wince/CELauncherDialog.cpp:62
+msgid "Display "
+msgstr "Affichage"
+
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Do you want to perform an automatic scan ?"
+msgstr "Voulez-vous exécuter une recherche automatique?"
+
+#~ msgid "Failed to load any GUI theme, aborting"
+#~ msgstr "Aucun thème GUI n'a pu être chargé; abandon"
+
+#~ msgid "User picked target '%s' (gameid '%s')...\n"
+#~ msgstr "L'utilisateur a choisi la cible '%s' (ID '%s')...\n"
+
+#~ msgid " Looking for a plugin supporting this gameid... "
+#~ msgstr "Recherche d'un plugin supportant cet ID..."
+
+#~ msgid "failed\n"
+#~ msgstr "Echec\n"
+
+#~ msgid ""
+#~ "%s is an invalid gameid. Use the --list-games option to list supported "
+#~ "gameid"
+#~ msgstr ""
+#~ "%s n'est pas un ID de jeu valide. Utilisez l'option --list-games pour "
+#~ "obtenir la liste des ID reconnus"
+
+#~ msgid " Starting '%s'\n"
+#~ msgstr "Démarrage de '%s'\n"
+
+#~ msgid "%s failed to instantiate engine: %s (target '%s', path '%s')"
+#~ msgstr ""
+#~ "Le plugin %s a échoué dans l'instanciation du moteur de jeu: %s (cible '%"
+#~ "s', chemin '%s')"
+
+#~ msgid "Ok"
+#~ msgstr "Ok"
+
+#~ msgid "Music driver:"
+#~ msgstr "Pilote audio:"
+
+#~ msgid "ALSA"
+#~ msgstr "ALSA"
+
+#~ msgid "Atari ST MIDI"
+#~ msgstr "MIDI Atari ST"
+
+#~ msgid "SEQ"
+#~ msgstr "SEQ"
+
+#~ msgid "DMedia"
+#~ msgstr "DMedia"
+
+#~ msgid "CAMD"
+#~ msgstr "CAMD"
+
+#~ msgid "CoreAudio"
+#~ msgstr "CoreAudio"
+
+#~ msgid "CoreMIDI"
+#~ msgstr "CoreMIDI"
+
+#~ msgid "Yamaha Pa1"
+#~ msgstr "Yamaha Pa1"
+
+#~ msgid "Tapwave Zodiac"
+#~ msgstr "Tapwave Zodiac"
+
+#~ msgid "FluidSynth"
+#~ msgstr "FluidSynth"
+
+#~ msgid "AdLib"
+#~ msgstr "AdLib"
+
+#~ msgid "IBM PCjr"
+#~ msgstr "IBM PCjr"
+
+#~ msgid "Creative Music System"
+#~ msgstr "Creative Music System"
+
+#~ msgid "TiMidity"
+#~ msgstr "TiMidity"
+
+#~ msgid "About..."
+#~ msgstr "A propos..."
+
+#~ msgid "Options..."
+#~ msgstr "Options..."
+
+#~ msgid "Start"
+#~ msgstr "Lancer"
+
+#~ msgid "Load..."
+#~ msgstr "Charger..."
+
+#~ msgid "Edit Game..."
+#~ msgstr "Préférence du Jeu..."
+
+#~ msgid "Remove Game"
+#~ msgstr "Supprimer le Jeu"
+
+#~ msgid "Speech Only"
+#~ msgstr "Audio Uniquement"
+
+#~ msgid "Speech and Subtitles"
+#~ msgstr "Audio et Sous-titres"
+
+#~ msgid "Subtitles Only"
+#~ msgstr "Sous-titres Uniquement"
+
+#~ msgid "Speech & Subs"
+#~ msgstr "Parole & Sous-titres"
diff --git a/po/hu_HU.po b/po/hu_HU.po
new file mode 100644
index 0000000000..8478f2ffaa
--- /dev/null
+++ b/po/hu_HU.po
@@ -0,0 +1,1393 @@
+# LANGUAGE translation for ScummVM.
+# Copyright (C) 2009 ScummVM
+# This file is distributed under the same license as the ScummVM package.
+# Alex Bevilacqua <alexbevi@gmail.com>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ScummVM VERSION\n"
+"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
+"POT-Creation-Date: 2010-07-30 22:14+0100\n"
+"PO-Revision-Date: 2009-11-25 07:42-0500\n"
+"Last-Translator: Alex Bevilacqua <alexbevi@gmail.com>\n"
+"Language-Team: Hungarian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=cp1250\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: gui/about.cpp:96
+#, c-format
+msgid "(built on %s)"
+msgstr ""
+
+#: gui/about.cpp:103
+msgid "Features compiled in:"
+msgstr ""
+
+#: gui/about.cpp:112
+msgid "Available engines:"
+msgstr ""
+
+#: gui/browser.cpp:69
+msgid "Go up"
+msgstr ""
+
+#: gui/browser.cpp:69
+msgid "Go to previous directory level"
+msgstr ""
+
+#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46
+#: gui/launcher.cpp:280 gui/massadd.cpp:95 gui/options.cpp:1029
+#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56
+#: backends/platform/wii/options.cpp:48
+msgid "Cancel"
+msgstr ""
+
+#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57
+msgid "Choose"
+msgstr ""
+
+#: gui/GuiManager.cpp:103 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr ""
+
+#: gui/GuiManager.cpp:106
+msgid "Mouse click"
+msgstr ""
+
+#: gui/GuiManager.cpp:109 base/main.cpp:285
+msgid "Display keyboard"
+msgstr ""
+
+#: gui/GuiManager.cpp:112 base/main.cpp:288
+msgid "Remap keys"
+msgstr ""
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr ""
+
+#: gui/KeysDialog.cpp:45 gui/launcher.cpp:281 gui/launcher.cpp:893
+#: gui/launcher.cpp:897 gui/massadd.cpp:92 gui/options.cpp:1030
+#: backends/platform/wii/options.cpp:47
+#: backends/platform/wince/CELauncherDialog.cpp:56
+msgid "OK"
+msgstr "Igen"
+
+#: gui/KeysDialog.cpp:52
+msgid "Select an action and click 'Map'"
+msgstr ""
+
+#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144
+#, c-format
+msgid "Associated key : %s"
+msgstr ""
+
+#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146
+#, c-format
+msgid "Associated key : none"
+msgstr ""
+
+#: gui/KeysDialog.cpp:93
+msgid "Please select an action"
+msgstr ""
+
+#: gui/KeysDialog.cpp:109
+msgid "Press the key to associate"
+msgstr ""
+
+#: gui/KeysDialog.cpp:148
+msgid "Choose an action to map"
+msgstr ""
+
+#: gui/launcher.cpp:172
+msgid "Game"
+msgstr ""
+
+#: gui/launcher.cpp:175
+msgid "ID:"
+msgstr ""
+
+#: gui/launcher.cpp:175 gui/launcher.cpp:176
+msgid ""
+"Short game identifier used for referring to savegames and running the game "
+"from the command line"
+msgstr ""
+
+#: gui/launcher.cpp:179
+msgid "Name:"
+msgstr ""
+
+#: gui/launcher.cpp:179 gui/launcher.cpp:180
+msgid "Full title of the game"
+msgstr ""
+
+#: gui/launcher.cpp:183
+msgid "Language:"
+msgstr ""
+
+#: gui/launcher.cpp:183 gui/launcher.cpp:184
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+
+#: gui/launcher.cpp:185 gui/launcher.cpp:196 gui/options.cpp:80
+#: gui/options.cpp:635 gui/options.cpp:645 gui/options.cpp:1000
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<alapértelmezett>"
+
+#: gui/launcher.cpp:194
+msgid "Platform:"
+msgstr ""
+
+#: gui/launcher.cpp:194 gui/launcher.cpp:195
+msgid "Platform the game was originally designed for"
+msgstr ""
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "Graphics"
+msgstr "Grafikával"
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "GFX"
+msgstr ""
+
+#: gui/launcher.cpp:208
+msgid "Override global graphic settings"
+msgstr ""
+
+#: gui/launcher.cpp:215 gui/options.cpp:921
+msgid "Audio"
+msgstr "Hang"
+
+#: gui/launcher.cpp:217
+msgid "Override global audio settings"
+msgstr ""
+
+#: gui/launcher.cpp:225 gui/options.cpp:925
+msgid "Volume"
+msgstr "Volumene"
+
+#: gui/launcher.cpp:227
+msgid "Override global volume settings"
+msgstr ""
+
+#: gui/launcher.cpp:234 gui/options.cpp:933
+msgid "MIDI"
+msgstr ""
+
+#: gui/launcher.cpp:236
+msgid "Override global MIDI settings"
+msgstr ""
+
+#: gui/launcher.cpp:246 gui/options.cpp:939
+msgid "MT-32"
+msgstr ""
+
+#: gui/launcher.cpp:248
+msgid "Override global MT-32 settings"
+msgstr ""
+
+#: gui/launcher.cpp:258 gui/options.cpp:945
+msgid "Paths"
+msgstr "Ösvények"
+
+#: gui/launcher.cpp:264
+#, fuzzy
+msgid "Game Path:"
+msgstr "Extra Útvonal:"
+
+#: gui/launcher.cpp:268 gui/options.cpp:958
+msgid "Extra Path:"
+msgstr "Extra Útvonal:"
+
+#: gui/launcher.cpp:268 gui/launcher.cpp:269
+msgid "Specifies path to additional data used the game"
+msgstr ""
+
+#: gui/launcher.cpp:272
+#, fuzzy
+msgid "Save Path:"
+msgstr "Extra Útvonal:"
+
+#: gui/launcher.cpp:272 gui/launcher.cpp:273 gui/options.cpp:952
+#: gui/options.cpp:953
+msgid "Specifies where your savegames are put"
+msgstr ""
+
+#: gui/launcher.cpp:289 gui/launcher.cpp:369 gui/launcher.cpp:418
+#: gui/options.cpp:230 gui/options.cpp:399 gui/options.cpp:497
+#: gui/options.cpp:555 gui/options.cpp:732 gui/options.cpp:956
+#: gui/options.cpp:959 gui/options.cpp:963 gui/options.cpp:1053
+#: gui/options.cpp:1059 gui/options.cpp:1065 gui/options.cpp:1073
+#: gui/options.cpp:1097 gui/options.cpp:1101 gui/options.cpp:1107
+#: gui/options.cpp:1114 gui/options.cpp:1213
+msgid "None"
+msgstr "Semmi"
+
+#: gui/launcher.cpp:294 gui/launcher.cpp:373
+#: backends/platform/wii/options.cpp:56
+#, fuzzy
+msgid "Default"
+msgstr "<alapértelmezett>"
+
+#: gui/launcher.cpp:411 gui/options.cpp:1207
+msgid "Select SoundFont"
+msgstr ""
+
+#: gui/launcher.cpp:430 gui/launcher.cpp:568
+msgid "Select directory with game data"
+msgstr ""
+
+#: gui/launcher.cpp:448
+msgid "Select additional game directory"
+msgstr ""
+
+#: gui/launcher.cpp:460
+msgid "Select directory for saved games"
+msgstr ""
+
+#: gui/launcher.cpp:479
+msgid "This game ID is already taken. Please choose another one."
+msgstr ""
+
+#: gui/launcher.cpp:520 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr ""
+
+#: gui/launcher.cpp:520
+msgid "Quit ScummVM"
+msgstr ""
+
+#: gui/launcher.cpp:521
+msgid "A~b~out..."
+msgstr ""
+
+#: gui/launcher.cpp:521
+msgid "About ScummVM"
+msgstr ""
+
+#: gui/launcher.cpp:522
+msgid "~O~ptions..."
+msgstr ""
+
+#: gui/launcher.cpp:522
+msgid "Change global ScummVM options"
+msgstr ""
+
+#: gui/launcher.cpp:524
+msgid "~S~tart"
+msgstr ""
+
+#: gui/launcher.cpp:524
+msgid "Start selected game"
+msgstr ""
+
+#: gui/launcher.cpp:527
+msgid "~L~oad..."
+msgstr ""
+
+#: gui/launcher.cpp:527
+msgid "Load savegame for selected game"
+msgstr ""
+
+#: gui/launcher.cpp:531
+msgid "~A~dd Game..."
+msgstr ""
+
+#: gui/launcher.cpp:531
+msgid "Hold Shift for Mass Add"
+msgstr ""
+
+#: gui/launcher.cpp:533
+msgid "~E~dit Game..."
+msgstr ""
+
+#: gui/launcher.cpp:533
+msgid "Change game options"
+msgstr ""
+
+#: gui/launcher.cpp:535
+msgid "~R~emove Game"
+msgstr ""
+
+#: gui/launcher.cpp:535
+msgid "Remove game from the list. The game data files stay intact"
+msgstr ""
+
+#: gui/launcher.cpp:542
+msgid "Search in game list"
+msgstr ""
+
+#: gui/launcher.cpp:546 gui/launcher.cpp:1057
+msgid "Search:"
+msgstr ""
+
+#: gui/launcher.cpp:549 gui/options.cpp:733
+msgid "Clear value"
+msgstr ""
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr ""
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr ""
+
+#: gui/launcher.cpp:680
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Yes"
+msgstr ""
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+#, fuzzy
+msgid "No"
+msgstr "Semmi"
+
+#: gui/launcher.cpp:728
+msgid "ScummVM couldn't open the specified directory!"
+msgstr ""
+
+#: gui/launcher.cpp:740
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr ""
+
+#: gui/launcher.cpp:754
+msgid "Pick the game:"
+msgstr ""
+
+#: gui/launcher.cpp:830
+msgid "Do you really want to remove this game configuration?"
+msgstr ""
+
+#: gui/launcher.cpp:893
+msgid "This game does not support loading games from the launcher."
+msgstr ""
+
+#: gui/launcher.cpp:897
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr ""
+
+#: gui/launcher.cpp:1009
+msgid "Mass Add..."
+msgstr ""
+
+#: gui/launcher.cpp:1010
+msgid "Add Game..."
+msgstr ""
+
+#: gui/massadd.cpp:79 gui/massadd.cpp:82
+msgid "... progress ..."
+msgstr ""
+
+#: gui/massadd.cpp:244
+msgid "Scan complete!"
+msgstr ""
+
+#: gui/massadd.cpp:247
+#, c-format
+msgid "Discovered %d new games."
+msgstr ""
+
+#: gui/massadd.cpp:251
+#, c-format
+msgid "Scanned %d directories ..."
+msgstr ""
+
+#: gui/massadd.cpp:254
+#, c-format
+msgid "Discovered %d new games ..."
+msgstr ""
+
+#: gui/options.cpp:78
+msgid "Never"
+msgstr "Soha"
+
+#: gui/options.cpp:78
+msgid "every 5 mins"
+msgstr "5 percenként"
+
+#: gui/options.cpp:78
+msgid "every 10 mins"
+msgstr "10 percenként"
+
+#: gui/options.cpp:78
+msgid "every 15 mins"
+msgstr "15 percenként"
+
+#: gui/options.cpp:78
+msgid "every 30 mins"
+msgstr "30 percenként"
+
+#: gui/options.cpp:80
+msgid "8 kHz"
+msgstr ""
+
+#: gui/options.cpp:80
+msgid "11kHz"
+msgstr ""
+
+#: gui/options.cpp:80
+msgid "22 kHz"
+msgstr ""
+
+#: gui/options.cpp:80
+msgid "44 kHz"
+msgstr ""
+
+#: gui/options.cpp:80
+msgid "48 kHz"
+msgstr ""
+
+#: gui/options.cpp:632
+msgid "Graphics mode:"
+msgstr "Grafikus mód:"
+
+#: gui/options.cpp:643
+msgid "Render mode:"
+msgstr "Renderelési mód:"
+
+#: gui/options.cpp:643 gui/options.cpp:644
+msgid "Special dithering modes supported by some games"
+msgstr ""
+
+#: gui/options.cpp:653
+msgid "Fullscreen mode"
+msgstr "Teljes képerny s mód:"
+
+#: gui/options.cpp:656
+msgid "Aspect ratio correction"
+msgstr "Aspect adag korrekció"
+
+#: gui/options.cpp:656
+msgid "Correct aspect ratio for 320x200 games"
+msgstr ""
+
+#: gui/options.cpp:663
+msgid "Preferred Device:"
+msgstr ""
+
+#: gui/options.cpp:663
+#, fuzzy
+msgid "Music Device:"
+msgstr "Zene mennyiség:"
+
+#: gui/options.cpp:663
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr ""
+
+#: gui/options.cpp:663 gui/options.cpp:664
+msgid "Specifies output sound device or sound card emulator"
+msgstr ""
+
+#: gui/options.cpp:688
+msgid "AdLib emulator:"
+msgstr "AdLib vezet :"
+
+#: gui/options.cpp:688 gui/options.cpp:689
+msgid "AdLib is used for music in many games"
+msgstr ""
+
+#: gui/options.cpp:699
+msgid "Output rate:"
+msgstr "Kimeneti teljesítmény:"
+
+#: gui/options.cpp:699 gui/options.cpp:700
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+
+#: gui/options.cpp:710
+msgid "GM Device:"
+msgstr ""
+
+#: gui/options.cpp:710
+msgid "Specifies default sound device for General MIDI output"
+msgstr ""
+
+#: gui/options.cpp:731
+msgid "SoundFont:"
+msgstr ""
+
+#: gui/options.cpp:731 gui/options.cpp:732
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr ""
+
+#: gui/options.cpp:736
+msgid "Mixed AdLib/MIDI mode"
+msgstr "Vegyes AdLib/MIDI mód"
+
+#: gui/options.cpp:736
+msgid "Use both MIDI and AdLib sound generation"
+msgstr ""
+
+#: gui/options.cpp:739
+msgid "MIDI gain:"
+msgstr "MIDI nyereség:"
+
+#: gui/options.cpp:749
+#, fuzzy
+msgid "MT-32 Device:"
+msgstr "Zene mennyiség:"
+
+#: gui/options.cpp:749
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr ""
+
+#: gui/options.cpp:753
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Igaz Roland MT-32 (megbénít GM emuláció)"
+
+#: gui/options.cpp:753
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+
+#: gui/options.cpp:756
+msgid "Enable Roland GS Mode"
+msgstr "Képessé Roland GS Mode"
+
+#: gui/options.cpp:756
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr ""
+
+#: gui/options.cpp:780
+msgid "Text and Speech:"
+msgstr "Szöveg és beszéd:"
+
+#: gui/options.cpp:785 gui/options.cpp:791
+#, fuzzy
+msgid "Speech"
+msgstr "Csak a beszéd"
+
+#: gui/options.cpp:786 gui/options.cpp:792
+#, fuzzy
+msgid "Subtitles"
+msgstr "Csak feliratok"
+
+#: gui/options.cpp:787 gui/options.cpp:793
+msgid "Both"
+msgstr ""
+
+#: gui/options.cpp:791
+msgid "Spch"
+msgstr ""
+
+#: gui/options.cpp:792
+msgid "Subs"
+msgstr ""
+
+#: gui/options.cpp:793
+msgid "Show subtitles and play speech"
+msgstr ""
+
+#: gui/options.cpp:797
+msgid "Subtitle speed:"
+msgstr "Felirat sebesség:"
+
+#: gui/options.cpp:809
+msgid "Music volume:"
+msgstr "Zene mennyiség:"
+
+#: gui/options.cpp:816
+msgid "Mute All"
+msgstr "Muta Összes"
+
+#: gui/options.cpp:819
+msgid "SFX volume:"
+msgstr "SFX mennyisége"
+
+#: gui/options.cpp:819 gui/options.cpp:820
+msgid "Special sound effects volume"
+msgstr ""
+
+#: gui/options.cpp:826
+msgid "Speech volume:"
+msgstr "Beszéd mennyiség:"
+
+#: gui/options.cpp:952
+msgid "Save Path: "
+msgstr ""
+
+#: gui/options.cpp:955
+msgid "Theme Path:"
+msgstr ""
+
+#: gui/options.cpp:958 gui/options.cpp:959
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr ""
+
+#: gui/options.cpp:962
+msgid "Plugins Path:"
+msgstr ""
+
+#: gui/options.cpp:970
+msgid "Misc"
+msgstr ""
+
+#: gui/options.cpp:972
+msgid "Theme:"
+msgstr "Téma:"
+
+#: gui/options.cpp:976
+msgid "GUI Renderer:"
+msgstr "Leképez eszköz GUI:"
+
+#: gui/options.cpp:982
+msgid "Autosave:"
+msgstr "Automatikus mentés:"
+
+#: gui/options.cpp:990
+msgid "Keys"
+msgstr "Kulcsok"
+
+#: gui/options.cpp:997
+msgid "GUI Language:"
+msgstr ""
+
+#: gui/options.cpp:997
+msgid "Language of ScummVM GUI"
+msgstr ""
+
+#: gui/options.cpp:1002
+msgid "English"
+msgstr ""
+
+#: gui/options.cpp:1146
+msgid "You have to restart ScummVM to take the effect."
+msgstr ""
+
+#: gui/options.cpp:1159
+msgid "Select directory for savegames"
+msgstr ""
+
+#: gui/options.cpp:1166
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr ""
+
+#: gui/options.cpp:1175
+msgid "Select directory for GUI themes"
+msgstr ""
+
+#: gui/options.cpp:1185
+msgid "Select directory for extra files"
+msgstr ""
+
+#: gui/options.cpp:1196
+msgid "Select directory for plugins"
+msgstr ""
+
+#: gui/saveload.cpp:60 gui/saveload.cpp:241
+msgid "No date saved"
+msgstr ""
+
+#: gui/saveload.cpp:61 gui/saveload.cpp:242
+msgid "No time saved"
+msgstr ""
+
+#: gui/saveload.cpp:62 gui/saveload.cpp:243
+msgid "No playtime saved"
+msgstr ""
+
+#: gui/saveload.cpp:69 gui/saveload.cpp:157
+msgid "Delete"
+msgstr ""
+
+#: gui/saveload.cpp:156
+msgid "Do you really want to delete this savegame?"
+msgstr ""
+
+#: gui/saveload.cpp:265
+msgid "Date: "
+msgstr ""
+
+#: gui/saveload.cpp:268
+#, fuzzy
+msgid "Time: "
+msgstr "Téma:"
+
+#: gui/saveload.cpp:273
+msgid "Playtime: "
+msgstr ""
+
+#: gui/saveload.cpp:286 gui/saveload.cpp:353
+msgid "Untitled savestate"
+msgstr ""
+
+#: gui/themebrowser.cpp:46
+msgid "Select a Theme"
+msgstr ""
+
+#: gui/ThemeEngine.cpp:334
+msgid "Disabled GFX"
+msgstr ""
+
+#: gui/ThemeEngine.cpp:335
+msgid "Standard Renderer (16bpp)"
+msgstr ""
+
+#: gui/ThemeEngine.cpp:337
+msgid "Antialiased Renderer (16bpp)"
+msgstr ""
+
+#: base/main.cpp:205
+#, c-format
+msgid "Engine does not support debug level '%s'"
+msgstr ""
+
+#: base/main.cpp:273
+msgid "Menu"
+msgstr ""
+
+#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48
+#: backends/platform/wince/CEActionsPocket.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:45
+msgid "Skip"
+msgstr ""
+
+#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53
+#: backends/platform/wince/CEActionsPocket.cpp:41
+#, fuzzy
+msgid "Pause"
+msgstr "Ösvények"
+
+#: base/main.cpp:282
+msgid "Skip line"
+msgstr ""
+
+#: base/main.cpp:404
+msgid "Error running game:"
+msgstr ""
+
+#: base/main.cpp:430 base/main.cpp:431
+msgid "Could not find any engine capable of running the selected game"
+msgstr ""
+
+#: common/error.cpp:43
+msgid "Invalid Path"
+msgstr ""
+
+#: common/error.cpp:44
+msgid "Game Data not found"
+msgstr ""
+
+#: common/error.cpp:45
+msgid "Game Id not supported"
+msgstr ""
+
+#: common/error.cpp:46
+msgid "Unsupported Color Mode"
+msgstr ""
+
+#: common/error.cpp:48
+msgid "Read permission denied"
+msgstr ""
+
+#: common/error.cpp:49
+msgid "Write permission denied"
+msgstr ""
+
+#: common/error.cpp:52
+msgid "Path not exists"
+msgstr ""
+
+#: common/error.cpp:53
+msgid "Path not a directory"
+msgstr ""
+
+#: common/error.cpp:54
+msgid "Path not a file"
+msgstr ""
+
+#: common/error.cpp:56
+msgid "Cannot create file"
+msgstr ""
+
+#: common/error.cpp:57
+msgid "Reading failed"
+msgstr ""
+
+#: common/error.cpp:58
+msgid "Writing data failed"
+msgstr ""
+
+#: common/error.cpp:60 common/error.cpp:71
+msgid "Unknown Error"
+msgstr ""
+
+#: common/util.cpp:254
+msgid "Hercules Green"
+msgstr ""
+
+#: common/util.cpp:255
+msgid "Hercules Amber"
+msgstr ""
+
+#: engines/dialogs.cpp:89
+msgid "~R~esume"
+msgstr ""
+
+#: engines/dialogs.cpp:91
+msgid "~L~oad"
+msgstr ""
+
+#: engines/dialogs.cpp:95
+msgid "~S~ave"
+msgstr ""
+
+#: engines/dialogs.cpp:99
+msgid "~O~ptions"
+msgstr ""
+
+#: engines/dialogs.cpp:104
+msgid "~H~elp"
+msgstr ""
+
+#: engines/dialogs.cpp:107
+msgid "~A~bout"
+msgstr ""
+
+#: engines/dialogs.cpp:109
+msgid "~R~eturn to Launcher"
+msgstr ""
+
+#: engines/dialogs.cpp:119
+msgid "Save game:"
+msgstr ""
+
+#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47
+#: backends/platform/wince/CEActionsPocket.cpp:42
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Save"
+msgstr ""
+
+#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84
+#: engines/mohawk/dialogs.cpp:118
+#, fuzzy
+msgid "~O~K"
+msgstr "Igen"
+
+#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85
+#: engines/mohawk/dialogs.cpp:119
+msgid "~C~ancel"
+msgstr ""
+
+#: engines/dialogs.cpp:305
+#, fuzzy
+msgid "~K~eys"
+msgstr "Kulcsok"
+
+#: engines/scumm/dialogs.cpp:287
+msgid "~P~revious"
+msgstr ""
+
+#: engines/scumm/dialogs.cpp:288
+msgid "~N~ext"
+msgstr ""
+
+#: engines/scumm/dialogs.cpp:289
+#: backends/platform/ds/arm9/source/dsoptions.cpp:59
+msgid "~C~lose"
+msgstr ""
+
+#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115
+msgid "~Z~ip Mode Activated"
+msgstr ""
+
+#: engines/mohawk/dialogs.cpp:82
+msgid "~T~ransitions Enabled"
+msgstr ""
+
+#: engines/mohawk/dialogs.cpp:116
+msgid "~W~ater Effect Enabled"
+msgstr ""
+
+#: sound/fmopl.cpp:51
+#, fuzzy
+msgid "MAME OPL emulator"
+msgstr "AdLib vezet :"
+
+#: sound/fmopl.cpp:53
+msgid "DOSBox OPL emulator"
+msgstr ""
+
+#: sound/null.h:45
+msgid "No music"
+msgstr ""
+
+#: sound/softsynth/adlib.cpp:1590
+#, fuzzy
+msgid "AdLib Emulator"
+msgstr "AdLib vezet :"
+
+#: sound/softsynth/mt32.cpp:327
+msgid "Initialising MT-32 Emulator"
+msgstr ""
+
+#: sound/softsynth/mt32.cpp:541
+msgid "MT-32 Emulator"
+msgstr ""
+
+#: sound/softsynth/pcspk.cpp:142
+msgid "PC Speaker Emulator"
+msgstr ""
+
+#: sound/softsynth/pcspk.cpp:161
+msgid "IBM PCjr Emulator"
+msgstr ""
+
+#: sound/softsynth/ym2612.cpp:762
+msgid "FM Towns Emulator"
+msgstr ""
+
+#: backends/keymapper/remap-dialog.cpp:49
+msgid "Keymap:"
+msgstr ""
+
+#: backends/keymapper/remap-dialog.cpp:66
+msgid " (Active)"
+msgstr ""
+
+#: backends/keymapper/remap-dialog.cpp:100
+msgid " (Global)"
+msgstr ""
+
+#: backends/keymapper/remap-dialog.cpp:110
+msgid " (Game)"
+msgstr ""
+
+#: backends/midi/windows.cpp:157
+msgid "Windows MIDI"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:60
+msgid "ScummVM Main Menu"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:66
+#, fuzzy
+msgid "~L~eft handed mode"
+msgstr "Renderelési mód:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:67
+msgid "~I~ndy fight controls"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:68
+msgid "Show mouse cursor"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:69
+msgid "Snap to edges"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:71
+msgid "Touch X Offset"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:78
+msgid "Touch Y Offset"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:90
+msgid "Use laptop trackpad-style cursor control"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:91
+msgid "Tap for left click, double tap right click"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:93
+msgid "Sensitivity"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:102
+msgid "Initial top screen scale:"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:108
+msgid "Main screen scaling:"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:110
+msgid "Hardware scale (fast, but low quality)"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:111
+msgid "Software scale (good quality, but slower)"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:112
+msgid "Unscaled (you must scroll left and right)"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:114
+msgid "Brightness:"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:124
+msgid "High quality audio (slower) (reboot)"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:125
+msgid "Disable power off"
+msgstr ""
+
+#: backends/platform/iphone/osys_events.cpp:339
+msgid "Touchpad mode enabled."
+msgstr ""
+
+#: backends/platform/iphone/osys_events.cpp:341
+msgid "Touchpad mode disabled."
+msgstr ""
+
+#: backends/platform/sdl/graphics.cpp:40
+#: backends/platform/wince/wince-sdl.cpp:111
+#: backends/platform/wince/wince-sdl.cpp:118
+msgid "Normal (no scaling)"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:41
+#: backends/platform/wince/CEActionsSmartphone.cpp:38
+msgid "Up"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:42
+#: backends/platform/wince/CEActionsSmartphone.cpp:39
+msgid "Down"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:40
+msgid "Left"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:41
+msgid "Right"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:45
+#: backends/platform/wince/CEActionsPocket.cpp:59
+#: backends/platform/wince/CEActionsSmartphone.cpp:42
+msgid "Left Click"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:46
+#: backends/platform/wince/CEActionsSmartphone.cpp:43
+msgid "Right Click"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:49
+#: backends/platform/wince/CEActionsSmartphone.cpp:46
+#, fuzzy
+msgid "Zone"
+msgstr "Semmi"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:50
+#: backends/platform/wince/CEActionsPocket.cpp:53
+#: backends/platform/wince/CEActionsSmartphone.cpp:47
+msgid "Multi Function"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:51
+msgid "Swap character"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:52
+msgid "Skip text"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:54
+#, fuzzy
+msgid "Fast mode"
+msgstr "Grafikus mód:"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:55
+#: backends/platform/wince/CEActionsPocket.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:51
+msgid "Quit"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:56
+msgid "Debugger"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:57
+msgid "Global menu"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:58
+msgid "Virtual keyboard"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:59
+msgid "Key mapper"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+msgid "Do you want to quit ?"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:51
+msgid "Video"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:54
+#, fuzzy
+msgid "Current video mode:"
+msgstr "Renderelési mód:"
+
+#: backends/platform/wii/options.cpp:56
+msgid "Double-strike"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:60
+msgid "Horizontal underscan:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:66
+msgid "Vertical underscan:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:71
+msgid "Input"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:74
+msgid "GC Pad sensitivity:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:80
+msgid "GC Pad acceleration:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:86
+msgid "DVD"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101
+msgid "Status:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102
+msgid "Unknown"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:93
+msgid "Mount DVD"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:94
+msgid "Unmount DVD"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:98
+msgid "SMB"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:106
+#, fuzzy
+msgid "Server:"
+msgstr "Soha"
+
+#: backends/platform/wii/options.cpp:110
+msgid "Share:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:114
+msgid "Username:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:118
+msgid "Password:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:121
+msgid "Init network"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:123
+msgid "Mount SMB"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:124
+msgid "Unmount SMB"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:145
+msgid "DVD Mounted successfully"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:148
+msgid "Error while mounting the DVD"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:150
+msgid "DVD not mounted"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:163
+msgid "Network up, share mounted"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:165
+msgid "Network up"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:168
+msgid ", error while mounting the share"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:170
+msgid ", share not mounted"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:176
+msgid "Network down"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:180
+msgid "Initialising network"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:184
+msgid "Timeout while initialising network"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:188
+#, c-format
+msgid "Network not initialsed (%d)"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:45
+msgid "Hide Toolbar"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:46
+msgid "Show Keyboard"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:47
+msgid "Sound on/off"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:48
+msgid "Right click"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:49
+msgid "Show/Hide Cursor"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:50
+msgid "Free look"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:51
+msgid "Zoom up"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:52
+msgid "Zoom down"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:54
+#: backends/platform/wince/CEActionsSmartphone.cpp:48
+#, fuzzy
+msgid "Bind Keys"
+msgstr "Kulcsok"
+
+#: backends/platform/wince/CEActionsPocket.cpp:55
+msgid "Cursor Up"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:56
+msgid "Cursor Down"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:57
+msgid "Cursor Left"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:58
+msgid "Cursor Right"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Do you want to load or save the game?"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+msgid " Are you sure you want to quit ? "
+msgstr ""
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:49
+msgid "Keyboard"
+msgstr ""
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:50
+msgid "Rotate"
+msgstr ""
+
+#: backends/platform/wince/CELauncherDialog.cpp:58
+#, fuzzy
+msgid "Using SDL driver "
+msgstr "Zenei vezet :"
+
+#: backends/platform/wince/CELauncherDialog.cpp:62
+msgid "Display "
+msgstr ""
+
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Do you want to perform an automatic scan ?"
+msgstr ""
+
+#~ msgid "Music driver:"
+#~ msgstr "Zenei vezet :"
+
+#, fuzzy
+#~ msgid "CoreAudio"
+#~ msgstr "Hang"
+
+#, fuzzy
+#~ msgid "AdLib"
+#~ msgstr "Hang"
+
+#~ msgid "Speech Only"
+#~ msgstr "Csak a beszéd"
+
+#~ msgid "Speech and Subtitles"
+#~ msgstr "Beszéd és a Feliratok"
+
+#~ msgid "Subtitles Only"
+#~ msgstr "Csak feliratok"
+
+#~ msgid "Speech & Subs"
+#~ msgstr "Beszéd s Feliratok"
diff --git a/po/it_IT.po b/po/it_IT.po
new file mode 100644
index 0000000000..efb92c9db9
--- /dev/null
+++ b/po/it_IT.po
@@ -0,0 +1,1371 @@
+# LANGUAGE translation for ScummVM.
+# Copyright (C) YEAR ScummVM Team
+# This file is distributed under the same license as the ScummVM package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ScummVM 1.2.0svn\n"
+"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
+"POT-Creation-Date: 2010-07-30 22:14+0100\n"
+"PO-Revision-Date: 2010-06-30 23:56+0100\n"
+"Last-Translator: Maff <matteo.maff at gmail dot com>\n"
+"Language-Team: Italian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: Italiano\n"
+
+#: gui/about.cpp:96
+#, c-format
+msgid "(built on %s)"
+msgstr "(build creata il %s)"
+
+#: gui/about.cpp:103
+msgid "Features compiled in:"
+msgstr "Funzionalità compilate in:"
+
+#: gui/about.cpp:112
+msgid "Available engines:"
+msgstr "Motori disponibili:"
+
+#: gui/browser.cpp:69
+msgid "Go up"
+msgstr "Cartella superiore"
+
+#: gui/browser.cpp:69
+msgid "Go to previous directory level"
+msgstr "Vai alla cartella superiore"
+
+#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46
+#: gui/launcher.cpp:280 gui/massadd.cpp:95 gui/options.cpp:1029
+#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56
+#: backends/platform/wii/options.cpp:48
+msgid "Cancel"
+msgstr "Annulla"
+
+#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57
+msgid "Choose"
+msgstr "Scegli"
+
+#: gui/GuiManager.cpp:103 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "Chiudi"
+
+#: gui/GuiManager.cpp:106
+msgid "Mouse click"
+msgstr "Clic del mouse"
+
+#: gui/GuiManager.cpp:109 base/main.cpp:285
+msgid "Display keyboard"
+msgstr "Mostra tastiera"
+
+#: gui/GuiManager.cpp:112 base/main.cpp:288
+msgid "Remap keys"
+msgstr "Riprogramma tasti"
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr "Mappa"
+
+#: gui/KeysDialog.cpp:45 gui/launcher.cpp:281 gui/launcher.cpp:893
+#: gui/launcher.cpp:897 gui/massadd.cpp:92 gui/options.cpp:1030
+#: backends/platform/wii/options.cpp:47
+#: backends/platform/wince/CELauncherDialog.cpp:56
+msgid "OK"
+msgstr "OK"
+
+#: gui/KeysDialog.cpp:52
+msgid "Select an action and click 'Map'"
+msgstr "Seleziona un'azione e clicca 'Mappa'"
+
+#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144
+#, c-format
+msgid "Associated key : %s"
+msgstr "Tasto associato: %s"
+
+#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146
+#, c-format
+msgid "Associated key : none"
+msgstr "Tasto associato: nessuno"
+
+#: gui/KeysDialog.cpp:93
+msgid "Please select an action"
+msgstr "Seleziona un'azione"
+
+#: gui/KeysDialog.cpp:109
+msgid "Press the key to associate"
+msgstr "Premi il tasto da associare"
+
+#: gui/KeysDialog.cpp:148
+msgid "Choose an action to map"
+msgstr "Scegli un'azione da mappare"
+
+#: gui/launcher.cpp:172
+msgid "Game"
+msgstr "Gioco"
+
+#: gui/launcher.cpp:175
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:175 gui/launcher.cpp:176
+msgid ""
+"Short game identifier used for referring to savegames and running the game "
+"from the command line"
+msgstr ""
+"Breve identificatore di gioco utilizzato per il riferimento a salvataggi e "
+"per l'esecuzione del gioco dalla riga di comando"
+
+#: gui/launcher.cpp:179
+msgid "Name:"
+msgstr "Nome:"
+
+#: gui/launcher.cpp:179 gui/launcher.cpp:180
+msgid "Full title of the game"
+msgstr "Titolo completo del gioco"
+
+#: gui/launcher.cpp:183
+msgid "Language:"
+msgstr "Lingua:"
+
+#: gui/launcher.cpp:183 gui/launcher.cpp:184
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+"Lingua del gioco. Un gioco inglese non potrà risultare tradotto in italiano"
+
+#: gui/launcher.cpp:185 gui/launcher.cpp:196 gui/options.cpp:80
+#: gui/options.cpp:635 gui/options.cpp:645 gui/options.cpp:1000
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<predefinito>"
+
+#: gui/launcher.cpp:194
+msgid "Platform:"
+msgstr "Piattaforma:"
+
+#: gui/launcher.cpp:194 gui/launcher.cpp:195
+msgid "Platform the game was originally designed for"
+msgstr "La piattaforma per la quale il gioco è stato concepito"
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "Graphics"
+msgstr "Grafica"
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "GFX"
+msgstr "Grafica"
+
+#: gui/launcher.cpp:208
+msgid "Override global graphic settings"
+msgstr "Ignora le impostazioni grafiche globali"
+
+#: gui/launcher.cpp:215 gui/options.cpp:921
+msgid "Audio"
+msgstr "Audio"
+
+#: gui/launcher.cpp:217
+msgid "Override global audio settings"
+msgstr "Ignora le impostazioni audio globali"
+
+#: gui/launcher.cpp:225 gui/options.cpp:925
+msgid "Volume"
+msgstr "Volume"
+
+#: gui/launcher.cpp:227
+msgid "Override global volume settings"
+msgstr "Ignora le impostazioni globali di volume"
+
+#: gui/launcher.cpp:234 gui/options.cpp:933
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:236
+msgid "Override global MIDI settings"
+msgstr "Ignora le impostazioni MIDI globali"
+
+#: gui/launcher.cpp:246 gui/options.cpp:939
+msgid "MT-32"
+msgstr ""
+
+#: gui/launcher.cpp:248
+#, fuzzy
+msgid "Override global MT-32 settings"
+msgstr "Ignora le impostazioni MIDI globali"
+
+#: gui/launcher.cpp:258 gui/options.cpp:945
+msgid "Paths"
+msgstr "Percorsi"
+
+#: gui/launcher.cpp:264
+msgid "Game Path:"
+msgstr "Percorso gioco:"
+
+#: gui/launcher.cpp:268 gui/options.cpp:958
+msgid "Extra Path:"
+msgstr "Percorso extra:"
+
+#: gui/launcher.cpp:268 gui/launcher.cpp:269
+msgid "Specifies path to additional data used the game"
+msgstr "Specifica il percorso di ulteriori dati usati dal gioco"
+
+#: gui/launcher.cpp:272
+msgid "Save Path:"
+msgstr "Salvataggi:"
+
+#: gui/launcher.cpp:272 gui/launcher.cpp:273 gui/options.cpp:952
+#: gui/options.cpp:953
+msgid "Specifies where your savegames are put"
+msgstr "Specifica dove archiviare i salvataggi"
+
+#: gui/launcher.cpp:289 gui/launcher.cpp:369 gui/launcher.cpp:418
+#: gui/options.cpp:230 gui/options.cpp:399 gui/options.cpp:497
+#: gui/options.cpp:555 gui/options.cpp:732 gui/options.cpp:956
+#: gui/options.cpp:959 gui/options.cpp:963 gui/options.cpp:1053
+#: gui/options.cpp:1059 gui/options.cpp:1065 gui/options.cpp:1073
+#: gui/options.cpp:1097 gui/options.cpp:1101 gui/options.cpp:1107
+#: gui/options.cpp:1114 gui/options.cpp:1213
+msgid "None"
+msgstr "Nessuno"
+
+#: gui/launcher.cpp:294 gui/launcher.cpp:373
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "Predefinito"
+
+#: gui/launcher.cpp:411 gui/options.cpp:1207
+msgid "Select SoundFont"
+msgstr "Seleziona SoundFont"
+
+#: gui/launcher.cpp:430 gui/launcher.cpp:568
+msgid "Select directory with game data"
+msgstr "Seleziona la cartella contenente i file di gioco"
+
+#: gui/launcher.cpp:448
+msgid "Select additional game directory"
+msgstr "Seleziona la cartella di gioco aggiuntiva"
+
+#: gui/launcher.cpp:460
+msgid "Select directory for saved games"
+msgstr "Seleziona la cartella dei salvataggi"
+
+#: gui/launcher.cpp:479
+msgid "This game ID is already taken. Please choose another one."
+msgstr "Questo ID di gioco è già in uso. Si prega di sceglierne un'altro."
+
+#: gui/launcher.cpp:520 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "C~h~iudi"
+
+#: gui/launcher.cpp:520
+msgid "Quit ScummVM"
+msgstr "Chiudi ScummVM"
+
+#: gui/launcher.cpp:521
+msgid "A~b~out..."
+msgstr "~I~nfo..."
+
+#: gui/launcher.cpp:521
+msgid "About ScummVM"
+msgstr "Informazioni su ScummVM"
+
+#: gui/launcher.cpp:522
+msgid "~O~ptions..."
+msgstr "~O~pzioni..."
+
+#: gui/launcher.cpp:522
+msgid "Change global ScummVM options"
+msgstr "Modifica le opzioni globali di ScummVM"
+
+#: gui/launcher.cpp:524
+msgid "~S~tart"
+msgstr "~G~ioca"
+
+#: gui/launcher.cpp:524
+msgid "Start selected game"
+msgstr "Esegue il gioco selezionato"
+
+#: gui/launcher.cpp:527
+msgid "~L~oad..."
+msgstr "~C~arica..."
+
+#: gui/launcher.cpp:527
+msgid "Load savegame for selected game"
+msgstr "Carica un salvataggio del gioco selezionato"
+
+#: gui/launcher.cpp:531
+msgid "~A~dd Game..."
+msgstr "~A~ggiungi gioco..."
+
+#: gui/launcher.cpp:531
+msgid "Hold Shift for Mass Add"
+msgstr "Tieni premuto Shift per l'aggiunta in massa"
+
+#: gui/launcher.cpp:533
+msgid "~E~dit Game..."
+msgstr "~M~odifica gioco..."
+
+#: gui/launcher.cpp:533
+msgid "Change game options"
+msgstr "Modifica le opzioni di gioco"
+
+#: gui/launcher.cpp:535
+msgid "~R~emove Game"
+msgstr "~R~imuovi gioco"
+
+#: gui/launcher.cpp:535
+msgid "Remove game from the list. The game data files stay intact"
+msgstr "Rimuove il gioco dalla lista. I file del gioco rimarranno intatti"
+
+#: gui/launcher.cpp:542
+msgid "Search in game list"
+msgstr "Cerca nella lista dei giochi"
+
+#: gui/launcher.cpp:546 gui/launcher.cpp:1057
+msgid "Search:"
+msgstr "Cerca:"
+
+#: gui/launcher.cpp:549 gui/options.cpp:733
+msgid "Clear value"
+msgstr "Cancella"
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "Carica gioco:"
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "Carica"
+
+#: gui/launcher.cpp:680
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+"Vuoi davvero eseguire il rilevatore di giochi in massa? Potrebbe aggiungere "
+"un numero enorme di giochi."
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Yes"
+msgstr "Sì"
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "No"
+msgstr "No"
+
+#: gui/launcher.cpp:728
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM non ha potuto aprire la cartella specificata!"
+
+#: gui/launcher.cpp:740
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr "ScummVM non ha potuto trovare nessun gioco nella cartella specificata!"
+
+#: gui/launcher.cpp:754
+msgid "Pick the game:"
+msgstr "Scegli il gioco:"
+
+#: gui/launcher.cpp:830
+msgid "Do you really want to remove this game configuration?"
+msgstr "Sei sicuro di voler rimuovere questa configurazione di gioco?"
+
+#: gui/launcher.cpp:893
+msgid "This game does not support loading games from the launcher."
+msgstr ""
+"Questo gioco non supporta il caricamento di salvataggi dalla schermata di "
+"avvio."
+
+#: gui/launcher.cpp:897
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr ""
+"ScummVM non ha potuto trovare un motore in grado di eseguire il gioco "
+"selezionato!"
+
+#: gui/launcher.cpp:1009
+msgid "Mass Add..."
+msgstr "Agg. in massa..."
+
+#: gui/launcher.cpp:1010
+msgid "Add Game..."
+msgstr "Aggiungi gioco..."
+
+#: gui/massadd.cpp:79 gui/massadd.cpp:82
+msgid "... progress ..."
+msgstr "... progresso ..."
+
+#: gui/massadd.cpp:244
+msgid "Scan complete!"
+msgstr "Scansione completa!"
+
+#: gui/massadd.cpp:247
+#, c-format
+msgid "Discovered %d new games."
+msgstr "Rilevati %d nuovi giochi."
+
+#: gui/massadd.cpp:251
+#, c-format
+msgid "Scanned %d directories ..."
+msgstr "%d cartelle analizzate..."
+
+#: gui/massadd.cpp:254
+#, c-format
+msgid "Discovered %d new games ..."
+msgstr "Rilevati %d nuovi giochi..."
+
+#: gui/options.cpp:78
+msgid "Never"
+msgstr "Mai"
+
+#: gui/options.cpp:78
+msgid "every 5 mins"
+msgstr "ogni 5 minuti"
+
+#: gui/options.cpp:78
+msgid "every 10 mins"
+msgstr "ogni 10 minuti"
+
+#: gui/options.cpp:78
+msgid "every 15 mins"
+msgstr "ogni 15 minuti"
+
+#: gui/options.cpp:78
+msgid "every 30 mins"
+msgstr "ogni 30 minuti"
+
+#: gui/options.cpp:80
+msgid "8 kHz"
+msgstr "8 kHz"
+
+#: gui/options.cpp:80
+msgid "11kHz"
+msgstr "11kHz"
+
+#: gui/options.cpp:80
+msgid "22 kHz"
+msgstr "22 kHz"
+
+#: gui/options.cpp:80
+msgid "44 kHz"
+msgstr "44 kHz"
+
+#: gui/options.cpp:80
+msgid "48 kHz"
+msgstr "48 kHz"
+
+#: gui/options.cpp:632
+msgid "Graphics mode:"
+msgstr "Modalità:"
+
+#: gui/options.cpp:643
+msgid "Render mode:"
+msgstr "Resa grafica:"
+
+#: gui/options.cpp:643 gui/options.cpp:644
+msgid "Special dithering modes supported by some games"
+msgstr "Modalità di resa grafica speciali supportate da alcuni giochi"
+
+#: gui/options.cpp:653
+msgid "Fullscreen mode"
+msgstr "Modalità a schermo intero"
+
+#: gui/options.cpp:656
+msgid "Aspect ratio correction"
+msgstr "Correzione proporzioni"
+
+#: gui/options.cpp:656
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "Corregge le proporzioni dei giochi 320x200"
+
+#: gui/options.cpp:663
+msgid "Preferred Device:"
+msgstr "Disp. preferito:"
+
+#: gui/options.cpp:663
+#, fuzzy
+msgid "Music Device:"
+msgstr "Dispositivo GM:"
+
+#: gui/options.cpp:663
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr ""
+"Specifica il dispositivo audio o l'emulatore della scheda audio preferiti"
+
+#: gui/options.cpp:663 gui/options.cpp:664
+msgid "Specifies output sound device or sound card emulator"
+msgstr ""
+"Specifica il dispositivo di output audio o l'emulatore della scheda audio"
+
+#: gui/options.cpp:688
+msgid "AdLib emulator:"
+msgstr "Emulatore AdLib:"
+
+#: gui/options.cpp:688 gui/options.cpp:689
+msgid "AdLib is used for music in many games"
+msgstr "AdLib è utilizzato per la musica in molti giochi"
+
+#: gui/options.cpp:699
+msgid "Output rate:"
+msgstr "Frequenza:"
+
+#: gui/options.cpp:699 gui/options.cpp:700
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+"Valori più alti restituiscono un suono di maggior qualità, ma potrebbero non "
+"essere supportati dalla tua scheda audio"
+
+#: gui/options.cpp:710
+msgid "GM Device:"
+msgstr "Dispositivo GM:"
+
+#: gui/options.cpp:710
+msgid "Specifies default sound device for General MIDI output"
+msgstr "Specifica il dispositivo audio predefinito per l'output General MIDI"
+
+#: gui/options.cpp:731
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:731 gui/options.cpp:732
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr "SoundFont è supportato da alcune schede audio, Fluidsynth e Timidity"
+
+#: gui/options.cpp:736
+msgid "Mixed AdLib/MIDI mode"
+msgstr "Modalità mista AdLib/MIDI"
+
+#: gui/options.cpp:736
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "Utilizza generazione di suono sia MIDI che AdLib"
+
+#: gui/options.cpp:739
+msgid "MIDI gain:"
+msgstr "Guadagno MIDI:"
+
+#: gui/options.cpp:749
+#, fuzzy
+msgid "MT-32 Device:"
+msgstr "Disposit. MT32:"
+
+#: gui/options.cpp:749
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr ""
+"Specifica il dispositivo audio predefinito per l'output Roland MT-32/LAPC1/"
+"CM32l/CM64"
+
+#: gui/options.cpp:753
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Roland MT-32 effettivo (disattiva emulazione GM)"
+
+#: gui/options.cpp:753
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+"Seleziona se vuoi usare il dispositivo hardware audio compatibile con Roland "
+"che è connesso al tuo computer"
+
+#: gui/options.cpp:756
+msgid "Enable Roland GS Mode"
+msgstr "Attiva la modalità Roland GS"
+
+#: gui/options.cpp:756
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr ""
+"Disattiva la mappatura General MIDI per i giochi con colonna sonora Roland "
+"MT-32"
+
+#: gui/options.cpp:780
+msgid "Text and Speech:"
+msgstr "Testo e voci:"
+
+#: gui/options.cpp:785 gui/options.cpp:791
+msgid "Speech"
+msgstr "Voci"
+
+#: gui/options.cpp:786 gui/options.cpp:792
+msgid "Subtitles"
+msgstr "Sottotitoli"
+
+#: gui/options.cpp:787 gui/options.cpp:793
+msgid "Both"
+msgstr "Entrambi"
+
+#: gui/options.cpp:791
+msgid "Spch"
+msgstr "Voci"
+
+#: gui/options.cpp:792
+msgid "Subs"
+msgstr "Sub"
+
+#: gui/options.cpp:793
+msgid "Show subtitles and play speech"
+msgstr "Mostra i sottotitoli e attiva le voci"
+
+#: gui/options.cpp:797
+msgid "Subtitle speed:"
+msgstr "Velocità testo:"
+
+#: gui/options.cpp:809
+msgid "Music volume:"
+msgstr "Volume musica:"
+
+#: gui/options.cpp:816
+msgid "Mute All"
+msgstr "Disattiva audio"
+
+#: gui/options.cpp:819
+msgid "SFX volume:"
+msgstr "Volume effetti:"
+
+#: gui/options.cpp:819 gui/options.cpp:820
+msgid "Special sound effects volume"
+msgstr "Volume degli effetti sonori"
+
+#: gui/options.cpp:826
+msgid "Speech volume:"
+msgstr "Volume voci:"
+
+#: gui/options.cpp:952
+msgid "Save Path: "
+msgstr "Salvataggi:"
+
+#: gui/options.cpp:955
+msgid "Theme Path:"
+msgstr "Percorso tema:"
+
+#: gui/options.cpp:958 gui/options.cpp:959
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr "Specifica il percorso di ulteriori dati usati dai giochi o da ScummVM"
+
+#: gui/options.cpp:962
+msgid "Plugins Path:"
+msgstr "Percorso plugin:"
+
+#: gui/options.cpp:970
+msgid "Misc"
+msgstr "Varie"
+
+#: gui/options.cpp:972
+msgid "Theme:"
+msgstr "Tema:"
+
+#: gui/options.cpp:976
+msgid "GUI Renderer:"
+msgstr "Renderer GUI:"
+
+#: gui/options.cpp:982
+msgid "Autosave:"
+msgstr "Autosalva:"
+
+#: gui/options.cpp:990
+msgid "Keys"
+msgstr "Tasti"
+
+#: gui/options.cpp:997
+msgid "GUI Language:"
+msgstr "Lingua GUI:"
+
+#: gui/options.cpp:997
+msgid "Language of ScummVM GUI"
+msgstr "Lingua dell'interfaccia grafica di ScummVM"
+
+#: gui/options.cpp:1002
+msgid "English"
+msgstr "Inglese"
+
+#: gui/options.cpp:1146
+msgid "You have to restart ScummVM to take the effect."
+msgstr "Devi riavviare ScummVM affinché le modifiche abbiano effetto."
+
+#: gui/options.cpp:1159
+msgid "Select directory for savegames"
+msgstr "Seleziona la cartella per i salvataggi"
+
+#: gui/options.cpp:1166
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr "La cartella scelta è in sola lettura. Si prega di sceglierne un'altra."
+
+#: gui/options.cpp:1175
+msgid "Select directory for GUI themes"
+msgstr "Seleziona la cartella dei temi dell'interfaccia"
+
+#: gui/options.cpp:1185
+msgid "Select directory for extra files"
+msgstr "Seleziona la cartella dei file aggiuntivi"
+
+#: gui/options.cpp:1196
+msgid "Select directory for plugins"
+msgstr "Seleziona la cartella dei plugin"
+
+#: gui/saveload.cpp:60 gui/saveload.cpp:241
+msgid "No date saved"
+msgstr "Nessuna data salvata"
+
+#: gui/saveload.cpp:61 gui/saveload.cpp:242
+msgid "No time saved"
+msgstr "Nessun orario salvato"
+
+#: gui/saveload.cpp:62 gui/saveload.cpp:243
+msgid "No playtime saved"
+msgstr "Nessun tempo salvato"
+
+#: gui/saveload.cpp:69 gui/saveload.cpp:157
+msgid "Delete"
+msgstr "Elimina"
+
+#: gui/saveload.cpp:156
+msgid "Do you really want to delete this savegame?"
+msgstr "Sei sicuro di voler eliminare questo salvataggio?"
+
+#: gui/saveload.cpp:265
+msgid "Date: "
+msgstr "Data: "
+
+#: gui/saveload.cpp:268
+msgid "Time: "
+msgstr "Ora: "
+
+#: gui/saveload.cpp:273
+msgid "Playtime: "
+msgstr "Tempo di gioco: "
+
+#: gui/saveload.cpp:286 gui/saveload.cpp:353
+msgid "Untitled savestate"
+msgstr "Salvataggio senza titolo"
+
+#: gui/themebrowser.cpp:46
+msgid "Select a Theme"
+msgstr "Seleziona un tema"
+
+#: gui/ThemeEngine.cpp:334
+msgid "Disabled GFX"
+msgstr "Grafica disattivata"
+
+#: gui/ThemeEngine.cpp:335
+msgid "Standard Renderer (16bpp)"
+msgstr "Renderer standard (16bpp)"
+
+#: gui/ThemeEngine.cpp:337
+msgid "Antialiased Renderer (16bpp)"
+msgstr "Renderer con antialiasing (16bpp)"
+
+#: base/main.cpp:205
+#, c-format
+msgid "Engine does not support debug level '%s'"
+msgstr "Il motore non supporta il livello di debug '%s'"
+
+#: base/main.cpp:273
+msgid "Menu"
+msgstr "Menu"
+
+#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48
+#: backends/platform/wince/CEActionsPocket.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:45
+msgid "Skip"
+msgstr "Salta"
+
+#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53
+#: backends/platform/wince/CEActionsPocket.cpp:41
+msgid "Pause"
+msgstr "Pausa"
+
+#: base/main.cpp:282
+msgid "Skip line"
+msgstr "Salta battuta"
+
+#: base/main.cpp:404
+msgid "Error running game:"
+msgstr "Errore nell'esecuzione del gioco:"
+
+#: base/main.cpp:430 base/main.cpp:431
+msgid "Could not find any engine capable of running the selected game"
+msgstr ""
+"Impossibile trovare un motore in grado di eseguire il gioco selezionato"
+
+#: common/error.cpp:43
+msgid "Invalid Path"
+msgstr "Percorso non valido"
+
+#: common/error.cpp:44
+msgid "Game Data not found"
+msgstr "Dati di gioco non trovati"
+
+#: common/error.cpp:45
+msgid "Game Id not supported"
+msgstr "ID di gioco non supportato"
+
+#: common/error.cpp:46
+msgid "Unsupported Color Mode"
+msgstr "Modalità colore non supportata"
+
+#: common/error.cpp:48
+msgid "Read permission denied"
+msgstr "Autorizzazione di lettura negata"
+
+#: common/error.cpp:49
+msgid "Write permission denied"
+msgstr "Autorizzazione di scrittura negata"
+
+#: common/error.cpp:52
+msgid "Path not exists"
+msgstr "Il percorso non esiste"
+
+#: common/error.cpp:53
+msgid "Path not a directory"
+msgstr "Il percorso non è una cartella"
+
+#: common/error.cpp:54
+msgid "Path not a file"
+msgstr "Il percorso non è un file"
+
+#: common/error.cpp:56
+msgid "Cannot create file"
+msgstr "Impossibile creare il file"
+
+#: common/error.cpp:57
+msgid "Reading failed"
+msgstr "Lettura fallita"
+
+#: common/error.cpp:58
+msgid "Writing data failed"
+msgstr "Scrittura dati fallita"
+
+#: common/error.cpp:60 common/error.cpp:71
+msgid "Unknown Error"
+msgstr "Errore sconosciuto"
+
+#: common/util.cpp:254
+msgid "Hercules Green"
+msgstr "Hercules verde"
+
+#: common/util.cpp:255
+msgid "Hercules Amber"
+msgstr "Hercules ambra"
+
+#: engines/dialogs.cpp:89
+msgid "~R~esume"
+msgstr "~R~ipristina"
+
+#: engines/dialogs.cpp:91
+msgid "~L~oad"
+msgstr "~C~arica"
+
+#: engines/dialogs.cpp:95
+msgid "~S~ave"
+msgstr "~S~alva"
+
+#: engines/dialogs.cpp:99
+msgid "~O~ptions"
+msgstr "~O~pzioni"
+
+#: engines/dialogs.cpp:104
+msgid "~H~elp"
+msgstr "~A~iuto"
+
+#: engines/dialogs.cpp:107
+msgid "~A~bout"
+msgstr "~I~nfo"
+
+#: engines/dialogs.cpp:109
+msgid "~R~eturn to Launcher"
+msgstr "~V~ai a schermata di avvio"
+
+#: engines/dialogs.cpp:119
+msgid "Save game:"
+msgstr "Salva gioco:"
+
+#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47
+#: backends/platform/wince/CEActionsPocket.cpp:42
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Save"
+msgstr "Salva"
+
+#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84
+#: engines/mohawk/dialogs.cpp:118
+msgid "~O~K"
+msgstr "~O~K"
+
+#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85
+#: engines/mohawk/dialogs.cpp:119
+msgid "~C~ancel"
+msgstr "~A~nnulla"
+
+#: engines/dialogs.cpp:305
+msgid "~K~eys"
+msgstr "~T~asti"
+
+#: engines/scumm/dialogs.cpp:287
+msgid "~P~revious"
+msgstr "~P~recedenti"
+
+#: engines/scumm/dialogs.cpp:288
+msgid "~N~ext"
+msgstr "~S~uccessivi"
+
+#: engines/scumm/dialogs.cpp:289
+#: backends/platform/ds/arm9/source/dsoptions.cpp:59
+msgid "~C~lose"
+msgstr "~C~hiudi"
+
+#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115
+msgid "~Z~ip Mode Activated"
+msgstr "Modalità ~Z~ip attivata"
+
+#: engines/mohawk/dialogs.cpp:82
+msgid "~T~ransitions Enabled"
+msgstr "~T~ransizioni attive"
+
+#: engines/mohawk/dialogs.cpp:116
+msgid "~W~ater Effect Enabled"
+msgstr "~E~ffetto acqua attivo"
+
+#: sound/fmopl.cpp:51
+msgid "MAME OPL emulator"
+msgstr "Emulatore OPL MAME"
+
+#: sound/fmopl.cpp:53
+msgid "DOSBox OPL emulator"
+msgstr "Emulatore OPL DOSBox"
+
+#: sound/null.h:45
+msgid "No music"
+msgstr "Nessuna musica"
+
+#: sound/softsynth/adlib.cpp:1590
+msgid "AdLib Emulator"
+msgstr "Emulatore AdLib"
+
+#: sound/softsynth/mt32.cpp:327
+msgid "Initialising MT-32 Emulator"
+msgstr "Avvio in corso dell'emulatore MT-32"
+
+#: sound/softsynth/mt32.cpp:541
+msgid "MT-32 Emulator"
+msgstr "Emulatore MT-32"
+
+#: sound/softsynth/pcspk.cpp:142
+msgid "PC Speaker Emulator"
+msgstr "Emulatore PC Speaker"
+
+#: sound/softsynth/pcspk.cpp:161
+msgid "IBM PCjr Emulator"
+msgstr "Emulatore IBM PCjr"
+
+#: sound/softsynth/ym2612.cpp:762
+msgid "FM Towns Emulator"
+msgstr "Emulatore FM Towns"
+
+#: backends/keymapper/remap-dialog.cpp:49
+msgid "Keymap:"
+msgstr "Mappa tasti:"
+
+#: backends/keymapper/remap-dialog.cpp:66
+msgid " (Active)"
+msgstr " (Attivo)"
+
+#: backends/keymapper/remap-dialog.cpp:100
+msgid " (Global)"
+msgstr " (Globale)"
+
+#: backends/keymapper/remap-dialog.cpp:110
+msgid " (Game)"
+msgstr " (Gioco)"
+
+#: backends/midi/windows.cpp:157
+msgid "Windows MIDI"
+msgstr "MIDI Windows"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:60
+msgid "ScummVM Main Menu"
+msgstr "Menu principale di ScummVM"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:66
+msgid "~L~eft handed mode"
+msgstr "~M~odalità mancini"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:67
+msgid "~I~ndy fight controls"
+msgstr "Controlli combattimento di ~I~ndy"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:68
+msgid "Show mouse cursor"
+msgstr "Mostra cursore del mouse"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:69
+msgid "Snap to edges"
+msgstr "Aggancia ai bordi"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:71
+msgid "Touch X Offset"
+msgstr "Compensa X del tocco"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:78
+msgid "Touch Y Offset"
+msgstr "Compensa Y del tocco"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:90
+msgid "Use laptop trackpad-style cursor control"
+msgstr "Utilizza il controllo del cursore stile trackpad del portatile"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:91
+msgid "Tap for left click, double tap right click"
+msgstr "Un tocco per il clic sinistro, doppio tocco per il clic destro"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:93
+msgid "Sensitivity"
+msgstr "Sensibilità"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:102
+msgid "Initial top screen scale:"
+msgstr "Schermo in primo piano:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:108
+msgid "Main screen scaling:"
+msgstr "Schermo principale:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:110
+msgid "Hardware scale (fast, but low quality)"
+msgstr "Ridimensionamento hardware (veloce, ma di bassa qualità)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:111
+msgid "Software scale (good quality, but slower)"
+msgstr "Ridimensionamento software (di buona qualità, ma più lento)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:112
+msgid "Unscaled (you must scroll left and right)"
+msgstr "Non ridimensionato (devi scorrere a sinistra e a destra)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:114
+msgid "Brightness:"
+msgstr "Luminosità:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:124
+msgid "High quality audio (slower) (reboot)"
+msgstr "Audio ad alta qualità (più lento) (riavviare)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:125
+msgid "Disable power off"
+msgstr "Disattiva spegnimento in chiusura"
+
+#: backends/platform/iphone/osys_events.cpp:339
+msgid "Touchpad mode enabled."
+msgstr "Modalità touchpad attivata."
+
+#: backends/platform/iphone/osys_events.cpp:341
+msgid "Touchpad mode disabled."
+msgstr "Modalità touchpad disattivata."
+
+#: backends/platform/sdl/graphics.cpp:40
+#: backends/platform/wince/wince-sdl.cpp:111
+#: backends/platform/wince/wince-sdl.cpp:118
+msgid "Normal (no scaling)"
+msgstr "Normale (nessun ridimensionamento)"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:41
+#: backends/platform/wince/CEActionsSmartphone.cpp:38
+msgid "Up"
+msgstr "Su"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:42
+#: backends/platform/wince/CEActionsSmartphone.cpp:39
+msgid "Down"
+msgstr "Giù"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:40
+msgid "Left"
+msgstr "Sinistra"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:41
+msgid "Right"
+msgstr "Destra"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:45
+#: backends/platform/wince/CEActionsPocket.cpp:59
+#: backends/platform/wince/CEActionsSmartphone.cpp:42
+msgid "Left Click"
+msgstr "Clic sinistro"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:46
+#: backends/platform/wince/CEActionsSmartphone.cpp:43
+msgid "Right Click"
+msgstr "Clic destro"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:49
+#: backends/platform/wince/CEActionsSmartphone.cpp:46
+msgid "Zone"
+msgstr "Zona"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:50
+#: backends/platform/wince/CEActionsPocket.cpp:53
+#: backends/platform/wince/CEActionsSmartphone.cpp:47
+msgid "Multi Function"
+msgstr "Multifunzione"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:51
+msgid "Swap character"
+msgstr "Cambia personaggio"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:52
+msgid "Skip text"
+msgstr "Salta testo"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:54
+msgid "Fast mode"
+msgstr "Modalità veloce"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:55
+#: backends/platform/wince/CEActionsPocket.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:51
+msgid "Quit"
+msgstr "Esci"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:56
+msgid "Debugger"
+msgstr "Debugger"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:57
+msgid "Global menu"
+msgstr "Menu globale"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:58
+msgid "Virtual keyboard"
+msgstr "Tastiera virtuale"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:59
+msgid "Key mapper"
+msgstr "Programmatore tasti"
+
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+msgid "Do you want to quit ?"
+msgstr "Sei sicuro di voler uscire?"
+
+#: backends/platform/wii/options.cpp:51
+msgid "Video"
+msgstr "Video"
+
+#: backends/platform/wii/options.cpp:54
+msgid "Current video mode:"
+msgstr "Modalità video attuale:"
+
+#: backends/platform/wii/options.cpp:56
+msgid "Double-strike"
+msgstr "Double-strike"
+
+#: backends/platform/wii/options.cpp:60
+msgid "Horizontal underscan:"
+msgstr "Underscan orizzontale:"
+
+#: backends/platform/wii/options.cpp:66
+msgid "Vertical underscan:"
+msgstr "Underscan verticale:"
+
+#: backends/platform/wii/options.cpp:71
+msgid "Input"
+msgstr "Input"
+
+#: backends/platform/wii/options.cpp:74
+msgid "GC Pad sensitivity:"
+msgstr "Sensibilità pad GC:"
+
+#: backends/platform/wii/options.cpp:80
+msgid "GC Pad acceleration:"
+msgstr "Accelerazione pad GC:"
+
+#: backends/platform/wii/options.cpp:86
+msgid "DVD"
+msgstr "DVD"
+
+#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101
+msgid "Status:"
+msgstr "Stato:"
+
+#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102
+msgid "Unknown"
+msgstr "Sconosciuto"
+
+#: backends/platform/wii/options.cpp:93
+msgid "Mount DVD"
+msgstr "Monta DVD"
+
+#: backends/platform/wii/options.cpp:94
+msgid "Unmount DVD"
+msgstr "Smonta DVD"
+
+#: backends/platform/wii/options.cpp:98
+msgid "SMB"
+msgstr "SMB"
+
+#: backends/platform/wii/options.cpp:106
+msgid "Server:"
+msgstr "Server:"
+
+#: backends/platform/wii/options.cpp:110
+msgid "Share:"
+msgstr "Condivisione:"
+
+#: backends/platform/wii/options.cpp:114
+msgid "Username:"
+msgstr "Nome utente:"
+
+#: backends/platform/wii/options.cpp:118
+msgid "Password:"
+msgstr "Password:"
+
+#: backends/platform/wii/options.cpp:121
+msgid "Init network"
+msgstr "Avvia rete"
+
+#: backends/platform/wii/options.cpp:123
+msgid "Mount SMB"
+msgstr "Monta SMB"
+
+#: backends/platform/wii/options.cpp:124
+msgid "Unmount SMB"
+msgstr "Smonta SMB"
+
+#: backends/platform/wii/options.cpp:145
+msgid "DVD Mounted successfully"
+msgstr "DVD montato con successo"
+
+#: backends/platform/wii/options.cpp:148
+msgid "Error while mounting the DVD"
+msgstr "Errore nel montare il DVD"
+
+#: backends/platform/wii/options.cpp:150
+msgid "DVD not mounted"
+msgstr "DVD non montato"
+
+#: backends/platform/wii/options.cpp:163
+msgid "Network up, share mounted"
+msgstr "Rete attiva, condivisione montata"
+
+#: backends/platform/wii/options.cpp:165
+msgid "Network up"
+msgstr "Rete attiva"
+
+#: backends/platform/wii/options.cpp:168
+msgid ", error while mounting the share"
+msgstr ", errore nel montare la condivisione"
+
+#: backends/platform/wii/options.cpp:170
+msgid ", share not mounted"
+msgstr ", condivisione non montata"
+
+#: backends/platform/wii/options.cpp:176
+msgid "Network down"
+msgstr "Rete disattivata"
+
+#: backends/platform/wii/options.cpp:180
+msgid "Initialising network"
+msgstr "Avvio rete in corso"
+
+#: backends/platform/wii/options.cpp:184
+msgid "Timeout while initialising network"
+msgstr "Attesa per l'avvio della rete"
+
+#: backends/platform/wii/options.cpp:188
+#, c-format
+msgid "Network not initialsed (%d)"
+msgstr "Rete non avviata (%d)"
+
+#: backends/platform/wince/CEActionsPocket.cpp:45
+msgid "Hide Toolbar"
+msgstr "Nascondi la barra degli strumenti"
+
+#: backends/platform/wince/CEActionsPocket.cpp:46
+msgid "Show Keyboard"
+msgstr "Mostra tastiera"
+
+#: backends/platform/wince/CEActionsPocket.cpp:47
+msgid "Sound on/off"
+msgstr "Suono on/off"
+
+#: backends/platform/wince/CEActionsPocket.cpp:48
+msgid "Right click"
+msgstr "Clic destro"
+
+#: backends/platform/wince/CEActionsPocket.cpp:49
+msgid "Show/Hide Cursor"
+msgstr "Mostra/nascondi cursore"
+
+#: backends/platform/wince/CEActionsPocket.cpp:50
+msgid "Free look"
+msgstr "Osservazione libera"
+
+#: backends/platform/wince/CEActionsPocket.cpp:51
+msgid "Zoom up"
+msgstr "Zoom avanti"
+
+#: backends/platform/wince/CEActionsPocket.cpp:52
+msgid "Zoom down"
+msgstr "Zoom indietro"
+
+#: backends/platform/wince/CEActionsPocket.cpp:54
+#: backends/platform/wince/CEActionsSmartphone.cpp:48
+msgid "Bind Keys"
+msgstr "Associa tasti"
+
+#: backends/platform/wince/CEActionsPocket.cpp:55
+msgid "Cursor Up"
+msgstr "Cursore su"
+
+#: backends/platform/wince/CEActionsPocket.cpp:56
+msgid "Cursor Down"
+msgstr "Cursore giù"
+
+#: backends/platform/wince/CEActionsPocket.cpp:57
+msgid "Cursor Left"
+msgstr "Cursore a sinistra"
+
+#: backends/platform/wince/CEActionsPocket.cpp:58
+msgid "Cursor Right"
+msgstr "Cursore a destra"
+
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Do you want to load or save the game?"
+msgstr "Vuoi caricare o salvare il gioco?"
+
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+msgid " Are you sure you want to quit ? "
+msgstr " Sei sicuro di voler uscire? "
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:49
+msgid "Keyboard"
+msgstr "Tastiera"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:50
+msgid "Rotate"
+msgstr "Rotazione"
+
+#: backends/platform/wince/CELauncherDialog.cpp:58
+msgid "Using SDL driver "
+msgstr "Utilizzo del driver SDL "
+
+#: backends/platform/wince/CELauncherDialog.cpp:62
+msgid "Display "
+msgstr "Visualizza "
+
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Do you want to perform an automatic scan ?"
+msgstr "Vuoi eseguire una scansione automatica?"
diff --git a/po/module.mk b/po/module.mk
new file mode 100644
index 0000000000..eb9a85e4e3
--- /dev/null
+++ b/po/module.mk
@@ -0,0 +1,43 @@
+POTFILE := $(srcdir)/po/scummvm.pot
+POFILES := $(wildcard $(srcdir)/po/*.po)
+
+updatepot:
+ xgettext -f $(srcdir)/po/POTFILES -D $(srcdir) -d scummvm --c++ -k_ -k_s -o $(POTFILE) \
+ "--copyright-holder=ScummVM Team" --package-name=ScummVM \
+ --package-version=$(VERSION) --msgid-bugs-address=scummvm-devel@lists.sf.net -o $(POTFILE)_
+
+ sed -e 's/SOME DESCRIPTIVE TITLE/LANGUAGE translation for ScummVM/' \
+ -e 's/UTF-8/CHARSET/' -e 's/PACKAGE/ScummVM/' $(POTFILE)_ > $(POTFILE).new
+
+ rm $(POTFILE)_
+ if test -f $(POTFILE); then \
+ sed -f $(srcdir)/po/remove-potcdate.sed < $(POTFILE) > $(POTFILE).1 && \
+ sed -f $(srcdir)/po/remove-potcdate.sed < $(POTFILE).new > $(POTFILE).2 && \
+ if cmp $(POTFILE).1 $(POTFILE).2 >/dev/null 2>&1; then \
+ rm -f $(POTFILE).new; \
+ else \
+ rm -f $(POTFILE) && \
+ mv -f $(POTFILE).new $(POTFILE); \
+ fi; \
+ rm -f $(POTFILE).1 $(POTFILE).2; \
+ else \
+ mv -f $(POTFILE).new $(POTFILE); \
+ fi;
+
+%.po: $(POTFILE)
+ msgmerge $@ $(POTFILE) -o $@.new
+ if cmp $@ $@.new >/dev/null 2>&1; then \
+ rm -f $@.new; \
+ else \
+ mv -f $@.new $@; \
+ fi;
+
+#$(srcdir)/common/messages.cpp: $(POFILES)
+# perl $(srcdir)/tools/po2c $^ > $(srcdir)/common/messages.cpp
+
+update-translations: updatepot $(POFILES)
+ @$(foreach file, $(POFILES), echo -n $(notdir $(basename $(file)))": ";msgfmt --statistic $(file);)
+ @rm -f messages.mo
+ perl $(srcdir)/tools/po2c $(POFILES) > $(srcdir)/common/messages.cpp
+
+.PHONY: updatepot update-translations
diff --git a/po/remove-potcdate.sed b/po/remove-potcdate.sed
new file mode 100644
index 0000000000..2436c49e78
--- /dev/null
+++ b/po/remove-potcdate.sed
@@ -0,0 +1,19 @@
+# Sed script that remove the POT-Creation-Date line in the header entry
+# from a POT file.
+#
+# The distinction between the first and the following occurrences of the
+# pattern is achieved by looking at the hold space.
+/^"POT-Creation-Date: .*"$/{
+x
+# Test if the hold space is empty.
+s/P/P/
+ta
+# Yes it was empty. First occurrence. Remove the line.
+g
+d
+bb
+:a
+# The hold space was nonempty. Following occurrences. Do nothing.
+x
+:b
+}
diff --git a/po/ru_RU.po b/po/ru_RU.po
new file mode 100644
index 0000000000..45bd5ceae2
--- /dev/null
+++ b/po/ru_RU.po
@@ -0,0 +1,1367 @@
+# Russian translation for ScummVM.
+# Copyright (C) 2010 ScummVM
+# This file is distributed under the same license as the ScummVM package.
+# Eugene Sandulenko <sev@scummvm.org>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ScummVM VERSION\n"
+"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
+"POT-Creation-Date: 2010-07-30 22:14+0100\n"
+"PO-Revision-Date: 2010-06-13 20:55+0300\n"
+"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
+"Language-Team: Russian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-5\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: Russian\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%"
+"10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+#: gui/about.cpp:96
+#, c-format
+msgid "(built on %s)"
+msgstr "(áÞÑàÐÝ %s)"
+
+#: gui/about.cpp:103
+msgid "Features compiled in:"
+msgstr "²ÚÛîçÕÝÝëÕ Ò ÑØÛÔ ÞßæØØ:"
+
+#: gui/about.cpp:112
+msgid "Available engines:"
+msgstr "´ÞáâãßÝëÕ ÔÒØÖÚØ:"
+
+#: gui/browser.cpp:69
+msgid "Go up"
+msgstr "²ÒÕàå"
+
+#: gui/browser.cpp:69
+msgid "Go to previous directory level"
+msgstr "¿ÕàÕÙâØ ÝÐ ÔØàÕÚâÞàØî ãàÞÒÝÕÜ ÒëèÕ"
+
+#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46
+#: gui/launcher.cpp:280 gui/massadd.cpp:95 gui/options.cpp:1029
+#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56
+#: backends/platform/wii/options.cpp:48
+msgid "Cancel"
+msgstr "¾âÜÕÝÐ"
+
+#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57
+msgid "Choose"
+msgstr "²ëÑàÐâì"
+
+#: gui/GuiManager.cpp:103 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "·ÐÚàëâì"
+
+#: gui/GuiManager.cpp:106
+msgid "Mouse click"
+msgstr "ºÛØÚ Üëèìî"
+
+#: gui/GuiManager.cpp:109 base/main.cpp:285
+msgid "Display keyboard"
+msgstr "¿ÞÚÐ×Ðâì ÚÛÐÒØÐâãàã"
+
+#: gui/GuiManager.cpp:112 base/main.cpp:288
+msgid "Remap keys"
+msgstr "¿ÕàÕÝÐ×ÝÐçØâì ÚÛÐÒØèØ"
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr "½Ð×ÝÐçØâì"
+
+#: gui/KeysDialog.cpp:45 gui/launcher.cpp:281 gui/launcher.cpp:893
+#: gui/launcher.cpp:897 gui/massadd.cpp:92 gui/options.cpp:1030
+#: backends/platform/wii/options.cpp:47
+#: backends/platform/wince/CELauncherDialog.cpp:56
+msgid "OK"
+msgstr "OK"
+
+#: gui/KeysDialog.cpp:52
+msgid "Select an action and click 'Map'"
+msgstr "²ëÑÕàØâÕ ÔÕÙáâÒØÕ Ø ÚÛØÚÝØâÕ '½Ð×ÝÐçØâì'"
+
+#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144
+#, c-format
+msgid "Associated key : %s"
+msgstr "½Ð×ÝÐçÕÝÝÐï ÚÛÐÒØèÐ : %s"
+
+#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146
+#, c-format
+msgid "Associated key : none"
+msgstr "½Ð×ÝÐçÕÝÝÐï ÚÛÐÒØèÐ : ÝÕâ"
+
+#: gui/KeysDialog.cpp:93
+msgid "Please select an action"
+msgstr "¿ÞÖÐÛãÙáâÐ, ÒëÑÕàØâÕ ÔÕÙáâÒØÕ"
+
+#: gui/KeysDialog.cpp:109
+msgid "Press the key to associate"
+msgstr "½ÐÖÜØâÕ ÚÛÐÒØèã ÔÛï ÝÐ×ÝÐçÕÝØï"
+
+#: gui/KeysDialog.cpp:148
+msgid "Choose an action to map"
+msgstr "²ëÑÕàØâÕ ÔÕÙáâÒØÕ ÔÛï ÝÐ×ÝÐçÕÝØï"
+
+#: gui/launcher.cpp:172
+msgid "Game"
+msgstr "¸ÓàÐ"
+
+#: gui/launcher.cpp:175
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:175 gui/launcher.cpp:176
+msgid ""
+"Short game identifier used for referring to savegames and running the game "
+"from the command line"
+msgstr ""
+"ºÞàÞâÚØÙ ØÔÕÝâØäØÚÐâÞà, ØáßÞÛì×ãÕÜëÙ ÔÛï ØÜÕÝ áÞåàÐÝÕÝØÙ ØÓà Ø ÔÛï ×ÐßãáÚÐ "
+"Ø× ÚÞÜÐÝÔÝÞÙ áâàÞÚØ"
+
+#: gui/launcher.cpp:179
+msgid "Name:"
+msgstr "½Ð×Ò:"
+
+#: gui/launcher.cpp:179 gui/launcher.cpp:180
+msgid "Full title of the game"
+msgstr "¿ÞÛÝÞÕ ÝÐ×ÒÐÝØÕ ØÓàë"
+
+#: gui/launcher.cpp:183
+msgid "Language:"
+msgstr "Ï×ëÚ:"
+
+#: gui/launcher.cpp:183 gui/launcher.cpp:184
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+"Ï×ëÚ ØÓàë. ¸×ÜÕÝÕÝØÕ íâÞÓÞ ßÐàÐÜÕâàÐ ÝÕ ßàÕÒàÐâØâ ØÓàã ÝÐ ÐÝÓÛØÙáÚÞÜ Ò "
+"àãááÚãî"
+
+#: gui/launcher.cpp:185 gui/launcher.cpp:196 gui/options.cpp:80
+#: gui/options.cpp:635 gui/options.cpp:645 gui/options.cpp:1000
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<ßÞ ãÜÞÛçÐÝØî>"
+
+#: gui/launcher.cpp:194
+msgid "Platform:"
+msgstr "¿ÛÐâäÞàÜÐ:"
+
+#: gui/launcher.cpp:194 gui/launcher.cpp:195
+msgid "Platform the game was originally designed for"
+msgstr "¿ÛÐâäÞàÜÐ, ÔÛï ÚÞâÞàÞÙ ØÓàÐ ÑëÛÐ Ø×ÝÐçÐÛìÝÞ àÐ×àÐÑÞâÐÝÐ"
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "Graphics"
+msgstr "³àÐäØÚÐ"
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "GFX"
+msgstr "³àä"
+
+#: gui/launcher.cpp:208
+msgid "Override global graphic settings"
+msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ ÓàÐäØÚØ"
+
+#: gui/launcher.cpp:215 gui/options.cpp:921
+msgid "Audio"
+msgstr "°ãÔØÞ"
+
+#: gui/launcher.cpp:217
+msgid "Override global audio settings"
+msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ ÐãÔØÞ"
+
+#: gui/launcher.cpp:225 gui/options.cpp:925
+msgid "Volume"
+msgstr "³àÞÜÚÞáâì"
+
+#: gui/launcher.cpp:227
+msgid "Override global volume settings"
+msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ ÓàÞÜÚÞáâØ"
+
+#: gui/launcher.cpp:234 gui/options.cpp:933
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:236
+msgid "Override global MIDI settings"
+msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ MIDI"
+
+#: gui/launcher.cpp:246 gui/options.cpp:939
+msgid "MT-32"
+msgstr "MT-32"
+
+#: gui/launcher.cpp:248
+msgid "Override global MT-32 settings"
+msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ MT-32"
+
+#: gui/launcher.cpp:258 gui/options.cpp:945
+msgid "Paths"
+msgstr "¿ãâØ"
+
+#: gui/launcher.cpp:264
+msgid "Game Path:"
+msgstr "³ÔÕ ØÓàÐ: "
+
+#: gui/launcher.cpp:268 gui/options.cpp:958
+msgid "Extra Path:"
+msgstr "´Þß. ßãâì:"
+
+#: gui/launcher.cpp:268 gui/launcher.cpp:269
+msgid "Specifies path to additional data used the game"
+msgstr "ÃÚÐ×ëÒÐÕâ ßãâì Ú ÔÞßÞÛÝØâÕÛìÝëÜ äÐÙÛÐÜ ÔÐÝÝëå ÔÛï ØÓàë"
+
+#: gui/launcher.cpp:272
+msgid "Save Path:"
+msgstr "¿ãâì áÞåà: "
+
+#: gui/launcher.cpp:272 gui/launcher.cpp:273 gui/options.cpp:952
+#: gui/options.cpp:953
+msgid "Specifies where your savegames are put"
+msgstr "ÃÚÐ×ëÒÐÕâ ßãâì Ú áÞåàÐÝÕÝØïÜ ØÓàë"
+
+#: gui/launcher.cpp:289 gui/launcher.cpp:369 gui/launcher.cpp:418
+#: gui/options.cpp:230 gui/options.cpp:399 gui/options.cpp:497
+#: gui/options.cpp:555 gui/options.cpp:732 gui/options.cpp:956
+#: gui/options.cpp:959 gui/options.cpp:963 gui/options.cpp:1053
+#: gui/options.cpp:1059 gui/options.cpp:1065 gui/options.cpp:1073
+#: gui/options.cpp:1097 gui/options.cpp:1101 gui/options.cpp:1107
+#: gui/options.cpp:1114 gui/options.cpp:1213
+msgid "None"
+msgstr "½Õ ×ÐÔÐÝ"
+
+#: gui/launcher.cpp:294 gui/launcher.cpp:373
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "¿Þ ãÜÞÛçÐÝØî"
+
+#: gui/launcher.cpp:411 gui/options.cpp:1207
+msgid "Select SoundFont"
+msgstr "²ëÑÕàØâÕ SoundFont"
+
+#: gui/launcher.cpp:430 gui/launcher.cpp:568
+msgid "Select directory with game data"
+msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî á äÐÙÛÐÜØ ØÓàë"
+
+#: gui/launcher.cpp:448
+msgid "Select additional game directory"
+msgstr "²ëÑÕàØâÕ ÔÞßÞÛÝØâÕÛìÝãî ÔØàÕÚâÞàØî ØÓàë"
+
+#: gui/launcher.cpp:460
+msgid "Select directory for saved games"
+msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî ÔÛï áÞåàÐÝÕÝØÙ"
+
+#: gui/launcher.cpp:479
+msgid "This game ID is already taken. Please choose another one."
+msgstr "ÍâÞâ ID ØÓàë ãÖÕ ØáßÞÛì×ãÕâáï. ¿ÞÖÐÛãÙáâÐ, ÒëÑÕàØâÕ ÔàãÓÞÙ."
+
+#: gui/launcher.cpp:520 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "~²~ëåÞÔ"
+
+#: gui/launcher.cpp:520
+msgid "Quit ScummVM"
+msgstr "²ëåÞÔ Ø× ScummVM"
+
+#: gui/launcher.cpp:521
+msgid "A~b~out..."
+msgstr "¾ ß~à~ÞÓàÐÜÜÕ..."
+
+#: gui/launcher.cpp:521
+msgid "About ScummVM"
+msgstr "¾ ßàÞÓàÐÜÜÕ ScummVM"
+
+#: gui/launcher.cpp:522
+msgid "~O~ptions..."
+msgstr "~¾~ßæØØ..."
+
+#: gui/launcher.cpp:522
+msgid "Change global ScummVM options"
+msgstr "¸×ÜÕÝØâì ÓÛÞÑÐÛìÝëÕ ÞßæØØ ScummVM"
+
+#: gui/launcher.cpp:524
+msgid "~S~tart"
+msgstr "¿~ã~áÚ"
+
+#: gui/launcher.cpp:524
+msgid "Start selected game"
+msgstr "·ÐßãáâØâì ÒëÑàÐÝÝãî ØÓàã"
+
+#: gui/launcher.cpp:527
+msgid "~L~oad..."
+msgstr "~·~ÐÓàã×Øâì..."
+
+#: gui/launcher.cpp:527
+msgid "Load savegame for selected game"
+msgstr "·ÐÓàã×Øâì áÞåàÝÕÝØÕ ÔÛï ÒëÑàÐÝÝÞÙ ØÓàë"
+
+#: gui/launcher.cpp:531
+msgid "~A~dd Game..."
+msgstr "~´~ÞÑ. ØÓàã..."
+
+#: gui/launcher.cpp:531
+msgid "Hold Shift for Mass Add"
+msgstr "ÃÔÕàÖØÒÐÙâÕ ÚÛÐÒØèã Shift ÔÛï âÞÓÞ, çâÞÑë ÔÞÑÐÒØâì ÝÕáÚÞÛìÚÞ ØÓà"
+
+#: gui/launcher.cpp:533
+msgid "~E~dit Game..."
+msgstr "¾~ß~æØØ ØÓàë..."
+
+#: gui/launcher.cpp:533
+msgid "Change game options"
+msgstr "¸×ÜÕÝØâì ÞßæØØ ØÓàë"
+
+#: gui/launcher.cpp:535
+msgid "~R~emove Game"
+msgstr "~Ã~ÔÐÛØâì ØÓàã"
+
+#: gui/launcher.cpp:535
+msgid "Remove game from the list. The game data files stay intact"
+msgstr "ÃÔÐÛØâì ØÓàã Ø× áßØáÚÐ. ½Õ ãÔÐÛïÕâ ØÓàã á ÖÕáâÚÞÓÞ ÔØáÚÐ"
+
+#: gui/launcher.cpp:542
+msgid "Search in game list"
+msgstr "¿ÞØáÚ Ò áßØáÚÕ ØÓà"
+
+#: gui/launcher.cpp:546 gui/launcher.cpp:1057
+msgid "Search:"
+msgstr "¿ÞØáÚ:"
+
+#: gui/launcher.cpp:549 gui/options.cpp:733
+msgid "Clear value"
+msgstr "¾çØáâØâì ×ÝÐçÕÝØÕ"
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "·ÐÓàã×Øâì ØÓàã:"
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "·ÐÓàã×Øâì"
+
+#: gui/launcher.cpp:680
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+"²ë ÔÕÙáâÒØâÕÛìÝÞ åÞâØâÕ ×ÐßãáâØâì ÔÕâÕÚâÞà ÒáÕå ØÓà? ÍâÞ ßÞâÕÝæØÐÛìÝÞ ÜÞÖÕâ "
+"ÔÞÑÐÒØâì ÑÞÛìèÞÕ ÚÞÛØçÕáâÒÞ ØÓà."
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Yes"
+msgstr "´Ð"
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "No"
+msgstr "½Õâ"
+
+#: gui/launcher.cpp:728
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM ÝÕ ÜÞÖÕâ ÞâÚàëâì ãÚÐ×ÐÝÝãî ÔØàÕÚâÞàØî!"
+
+#: gui/launcher.cpp:740
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr "ScummVM ÝÕ ÜÞÖÕâ ÝÐÙâØ ØÓàã Ò ãÚÐ×ÐÝÝÞÙ ÔØàÕÚâÞàØØ!"
+
+#: gui/launcher.cpp:754
+msgid "Pick the game:"
+msgstr "²ëÑÕàØâÕ ØÓàã:"
+
+#: gui/launcher.cpp:830
+msgid "Do you really want to remove this game configuration?"
+msgstr "²ë ÔÕÙáâÒØâÕÛìÝÞ åÞâØâÕ ãÔÐÛØâì ãáâÐÝÞÒÚØ ÔÛï íâÞÙ ØÓàë?"
+
+#: gui/launcher.cpp:893
+msgid "This game does not support loading games from the launcher."
+msgstr "ÍâÐ ØÓàÐ ÝÕ ßÞÔÔÕàÖØÒÐÕâ ×ÐÓàã×Úã áÞåàÐÝÕÝØÙ çÕàÕ× ÓÛÐÒÝÞÕ ÜÕÝî."
+
+#: gui/launcher.cpp:897
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr "ScummVM ÝÕ áÜÞÓ ÝÐÙâØ ÔÒØÖÞÚ ÔÛï ×ÐßãáÚÐ ÒëÑàÐÝÝÞÙ ØÓàë!"
+
+#: gui/launcher.cpp:1009
+msgid "Mass Add..."
+msgstr "¼ÝÞÓÞ ØÓà..."
+
+#: gui/launcher.cpp:1010
+msgid "Add Game..."
+msgstr "½ÞÒÐï ØÓàÐ..."
+
+#: gui/massadd.cpp:79 gui/massadd.cpp:82
+msgid "... progress ..."
+msgstr "... Øéã ..."
+
+#: gui/massadd.cpp:244
+msgid "Scan complete!"
+msgstr "¿ÞØáÚ ×ÐÚÞÝçÕÝ!"
+
+#: gui/massadd.cpp:247
+#, c-format
+msgid "Discovered %d new games."
+msgstr "½ÐÙÔÕÝÞ %d ÝÞÒëå ØÓà."
+
+#: gui/massadd.cpp:251
+#, c-format
+msgid "Scanned %d directories ..."
+msgstr "¿àÞáÜÞâàÕÝÞ %d ÔØàÕÚâÞàØÙ ..."
+
+#: gui/massadd.cpp:254
+#, c-format
+msgid "Discovered %d new games ..."
+msgstr "½ÐÙÔÕÝÞ %d ÝÞÒëå ØÓà ..."
+
+#: gui/options.cpp:78
+msgid "Never"
+msgstr "½ØÚÞÓÔÐ"
+
+#: gui/options.cpp:78
+msgid "every 5 mins"
+msgstr "ÚÐÖÔëÕ 5 ÜØÝãâ"
+
+#: gui/options.cpp:78
+msgid "every 10 mins"
+msgstr "ÚÐÖÔëÕ 10 ÜØÝãâ"
+
+#: gui/options.cpp:78
+msgid "every 15 mins"
+msgstr "ÚÐÖÔëÕ 15 ÜØÝãâ"
+
+#: gui/options.cpp:78
+msgid "every 30 mins"
+msgstr "ÚÐÖÔëÕ 30 ÜØÝãâ"
+
+#: gui/options.cpp:80
+msgid "8 kHz"
+msgstr "8 Ú³æ"
+
+#: gui/options.cpp:80
+msgid "11kHz"
+msgstr "11 Ú³æ"
+
+#: gui/options.cpp:80
+msgid "22 kHz"
+msgstr "22 Ú³æ"
+
+#: gui/options.cpp:80
+msgid "44 kHz"
+msgstr "44 Ú³æ"
+
+#: gui/options.cpp:80
+msgid "48 kHz"
+msgstr "48 Ú³æ"
+
+#: gui/options.cpp:632
+msgid "Graphics mode:"
+msgstr "³àÐä. àÕÖØÜ:"
+
+#: gui/options.cpp:643
+msgid "Render mode:"
+msgstr "ÀÕÖØÜ àÐáâàÐ:"
+
+#: gui/options.cpp:643 gui/options.cpp:644
+msgid "Special dithering modes supported by some games"
+msgstr "ÁßÕæØÐÛìÝëÕ àÕÖØÜë àÕÝÔÕàØÝÓÐ, ßÞÔÔÕàÖØÒÐÕÜëÕ ÝÕÚÞâÞàëÜØ ØÓàÐÜØ"
+
+#: gui/options.cpp:653
+msgid "Fullscreen mode"
+msgstr "¿ÞÛÝÞíÚàÐÝÝëÙ àÕÖØÜ"
+
+#: gui/options.cpp:656
+msgid "Aspect ratio correction"
+msgstr "ºÞààÕÚæØï áÞÞâÝÞèÕÝØï áâÞàÞÝ"
+
+#: gui/options.cpp:656
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "ºÞààÕÚâØàÞÒÐâì áÞÞâÝÞèÕÝØÕ áâÞàÞÝ ÔÛï ØÓà á àÐ×àÕèÕÝØÕÜ 320x200"
+
+#: gui/options.cpp:663
+msgid "Preferred Device:"
+msgstr "·ÒãÚÞÒÞÕ ãáâ-ÒÞ:"
+
+#: gui/options.cpp:663
+msgid "Music Device:"
+msgstr "·ÒãÚÞÒÞÕ ãáâ-ÒÞ:"
+
+#: gui/options.cpp:663
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr "ÃÚÐ×ëÒÐÕâ ÒëåÞÔÝÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ØÛØ íÜãÛïâÞà ×ÒãÚÞÒÞÙ ÚÐàâë"
+
+#: gui/options.cpp:663 gui/options.cpp:664
+msgid "Specifies output sound device or sound card emulator"
+msgstr "ÃÚÐ×ëÒÐÕâ ÒëåÞÔÝÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ØÛØ íÜãÛïâÞà ×ÒãÚÞÒÞÙ ÚÐàâë"
+
+#: gui/options.cpp:688
+msgid "AdLib emulator:"
+msgstr "ÍÜãÛïâÞà AdLib:"
+
+#: gui/options.cpp:688 gui/options.cpp:689
+msgid "AdLib is used for music in many games"
+msgstr "·ÒãÚÞÒÐï ÚÐàâÐ AdLib ØáßÞÛì×ãÕâáï ÜÝÞÓØÜØ ØÓàÐÜØ"
+
+#: gui/options.cpp:699
+msgid "Output rate:"
+msgstr "ÇÐáâÞâÐ ×ÒãÚÐ:"
+
+#: gui/options.cpp:699 gui/options.cpp:700
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+"±¾ÛìèØÕ ×ÝÐçÕÝØï ×ÐÔÐîâ ÛãçèÕÕ ÚÐçÕáâÒÞ ×ÒãÚÐ, ÞÔÝÐÚÞ ÞÝØ ÜÞÓãâ ÝÕ "
+"ßÞÔÔÕàÖØÒÐâìáï ÒÐèÕÙ ×ÒãÚÞÒÞÙ ÚÐàâÞÙ"
+
+#: gui/options.cpp:710
+msgid "GM Device:"
+msgstr "ÃáâàÞÙáâÒÞ GM:"
+
+#: gui/options.cpp:710
+msgid "Specifies default sound device for General MIDI output"
+msgstr "ÃÚÐ×ëÒÐÕâ ÒëåÞÔÝÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ÔÛï MIDI"
+
+#: gui/options.cpp:731
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:731 gui/options.cpp:732
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr ""
+"SoundFontë ßÞÔÔÕàÔÖØÒÐîâáï ÝÕÚÞâÞàëÜØ ×ÒãÚÞÒëÜØ ÚÐàâÐÜØ, Fluidsynth Ø "
+"Timidity"
+
+#: gui/options.cpp:736
+msgid "Mixed AdLib/MIDI mode"
+msgstr "ÁÜÕèÐÝÝëÙ àÕÖØÜ AdLib/MIDI"
+
+#: gui/options.cpp:736
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "¸áßÞÛì×ÞÒÐâì Ø MIDI Ø AdLib ÔÛï ÓÕÝÕàÐæØØ ×ÒãÚÐ"
+
+#: gui/options.cpp:739
+msgid "MIDI gain:"
+msgstr "ÃáØÛÕÝØÕ MIDI:"
+
+#: gui/options.cpp:749
+msgid "MT-32 Device:"
+msgstr "Ãáâà. MT-32:"
+
+#: gui/options.cpp:749
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr ""
+"ÃÚÐ×ëÒÐÕâ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ßÞ ãÜÞÛçÐÝØï ÔÛï ÒëÒÞÔÐ ÝÐ Roland MT-32/LAPC1/"
+"CM32l/CM64"
+
+#: gui/options.cpp:753
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "½ÐáâÞïéØÙ Roland MT-32 (×ÐßàÕâØâì íÜãÛïæØî GM)"
+
+#: gui/options.cpp:753
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+"¾âÜÕâìâÕ, ÕáÛØ ã ÒÐá ßÞÔÚÛîçÕÝÞ Roland-áÞÒÜÕáâØÜÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ Ø Òë "
+"åÞâØâÕ ÕÓÞ ØáßÞÛì×ÞÒÐâì"
+
+#: gui/options.cpp:756
+msgid "Enable Roland GS Mode"
+msgstr "²ÚÛîçØâì àÕÖØÜ Roland GS"
+
+#: gui/options.cpp:756
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr ""
+"²ëÚÛîçÐÕâ ÜÐßßØÝÓ General MIDI ÔÛï ØÓà á ×ÒãÚÞÒÞÙ ÔÞàÞÖÚÞÙ ÔÛï Roland MT-32"
+
+#: gui/options.cpp:780
+msgid "Text and Speech:"
+msgstr "ÂÕÚáâ Ø Þ×ÒãçÚÐ:"
+
+#: gui/options.cpp:785 gui/options.cpp:791
+msgid "Speech"
+msgstr "¾×ÒãçÚÐ"
+
+#: gui/options.cpp:786 gui/options.cpp:792
+msgid "Subtitles"
+msgstr "ÁãÑâØâàë"
+
+#: gui/options.cpp:787 gui/options.cpp:793
+msgid "Both"
+msgstr "²áñ"
+
+#: gui/options.cpp:791
+msgid "Spch"
+msgstr "¾×Ò"
+
+#: gui/options.cpp:792
+msgid "Subs"
+msgstr "狄"
+
+#: gui/options.cpp:793
+msgid "Show subtitles and play speech"
+msgstr "¿ÞÚÐ×ëÒÐâì áãÑâØâàë Ø ÒÞáßàÞØ×ÒÞÔØâì àÕçì"
+
+#: gui/options.cpp:797
+msgid "Subtitle speed:"
+msgstr "ÁÚÞàÞáâì âØâàÞÒ:"
+
+#: gui/options.cpp:809
+msgid "Music volume:"
+msgstr "³àÞÜÚ. Üã×ëÚØ:"
+
+#: gui/options.cpp:816
+msgid "Mute All"
+msgstr "²ëÚÛ. Òáñ"
+
+#: gui/options.cpp:819
+msgid "SFX volume:"
+msgstr "³àÞÜÚ. SFX:"
+
+#: gui/options.cpp:819 gui/options.cpp:820
+msgid "Special sound effects volume"
+msgstr "³àÞÜÚÞáâì áßÕæØÐÛìÝëå ×ÒãÚÞÒëå íääÕÚâÞÒ"
+
+#: gui/options.cpp:826
+msgid "Speech volume:"
+msgstr "³àÞÜÚ. Þ×ÒãçÚØ:"
+
+#: gui/options.cpp:952
+msgid "Save Path: "
+msgstr "ÁÞåàÐÝÕÝØï ØÓà:"
+
+#: gui/options.cpp:955
+msgid "Theme Path:"
+msgstr "³ÔÕ âÕÜë:"
+
+#: gui/options.cpp:958 gui/options.cpp:959
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr ""
+"ÃÚÐ×ëÒÐÕâ ßãâì Ú ÔÞßÞÛÝØâÕÛìÝëÜ äÐÙÛÐÜ ÔÐÝÝëå, ØáßÞÛì×ãÕÜëå ÒáÕÜØ ØÓàÐÜØ, "
+"ÛØÑÞ ScummVM"
+
+#: gui/options.cpp:962
+msgid "Plugins Path:"
+msgstr "¿ãâì Ú ßÛÐÓØÝÐÜ:"
+
+#: gui/options.cpp:970
+msgid "Misc"
+msgstr "ÀÐ×ÝÞÕ"
+
+#: gui/options.cpp:972
+msgid "Theme:"
+msgstr "ÂÕÜÐ:"
+
+#: gui/options.cpp:976
+msgid "GUI Renderer:"
+msgstr "ÀØáÞÒÐÛÚÐ GUI:"
+
+#: gui/options.cpp:982
+msgid "Autosave:"
+msgstr "°ÒâÞáÞåàÐÝÕÝØÕ:"
+
+#: gui/options.cpp:990
+msgid "Keys"
+msgstr "ºÛÐÒØèØ"
+
+#: gui/options.cpp:997
+msgid "GUI Language:"
+msgstr "Ï×ëÚ GUI:"
+
+#: gui/options.cpp:997
+msgid "Language of ScummVM GUI"
+msgstr "Ï×ëÚ ÓàÐäØçÕáÚÞÓÞ ØÝâÕàäÕÙáÐ ScummVM"
+
+#: gui/options.cpp:1002
+msgid "English"
+msgstr "English"
+
+#: gui/options.cpp:1146
+msgid "You have to restart ScummVM to take the effect."
+msgstr "²ë ÔÞÛÖÝë ßÕàÕ×ÐßãáâØâì ScummVM çâÞÑë ßàØÜÕÝØâì Ø×ÜÕÝÕÝØï."
+
+#: gui/options.cpp:1159
+msgid "Select directory for savegames"
+msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî ÔÛï áÞåàÐÝÕÝØÙ"
+
+#: gui/options.cpp:1166
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr "½Õ ÜÞÓã ßØáÐâì Ò ÒëÑàÐÝÝãî ÔØàÕÚâÞàØî. ¿ÞÖÐÛãÙáâÐ, ãÚÐÖØâÕ ÔàãÓãî."
+
+#: gui/options.cpp:1175
+msgid "Select directory for GUI themes"
+msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî ÔÛï âÕÜ GUI"
+
+#: gui/options.cpp:1185
+msgid "Select directory for extra files"
+msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî á ÔÞßÞÛÝØâÕÛìÝëÜØ äÐÙÛÐÜØ"
+
+#: gui/options.cpp:1196
+msgid "Select directory for plugins"
+msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî á ßÛÐÓØÝÐÜØ"
+
+#: gui/saveload.cpp:60 gui/saveload.cpp:241
+msgid "No date saved"
+msgstr "´ÐâÐ ÝÕ ×ÐßØáÐÝÐ"
+
+#: gui/saveload.cpp:61 gui/saveload.cpp:242
+msgid "No time saved"
+msgstr "²àÕÜï ÝÕ ×ÐßØáÐÝÞ"
+
+#: gui/saveload.cpp:62 gui/saveload.cpp:243
+msgid "No playtime saved"
+msgstr "²àÕÜï ØÓàë ÝÕ ×ÐßØáÐÝÞ"
+
+#: gui/saveload.cpp:69 gui/saveload.cpp:157
+msgid "Delete"
+msgstr "ÃÔÐÛØâì"
+
+#: gui/saveload.cpp:156
+msgid "Do you really want to delete this savegame?"
+msgstr "²ë ÔÕÙáâÒØâÕÛìÝÞ åÞâØâÕ ãÔÐÛØâì íâÞ áÞåàÐÝÕÝØÕ?"
+
+#: gui/saveload.cpp:265
+msgid "Date: "
+msgstr "´ÐâÐ: "
+
+#: gui/saveload.cpp:268
+msgid "Time: "
+msgstr "²àÕÜï: "
+
+#: gui/saveload.cpp:273
+msgid "Playtime: "
+msgstr "²àÕÜï ØÓàë: "
+
+#: gui/saveload.cpp:286 gui/saveload.cpp:353
+msgid "Untitled savestate"
+msgstr "ÁÞåàÐÝÕÝØÕ ÑÕ× ØÜÕÝØ"
+
+#: gui/themebrowser.cpp:46
+msgid "Select a Theme"
+msgstr "²ëÑÕàØâÕ âÕÜã"
+
+#: gui/ThemeEngine.cpp:334
+msgid "Disabled GFX"
+msgstr "±Õ× ÓàÐäØÚØ"
+
+#: gui/ThemeEngine.cpp:335
+msgid "Standard Renderer (16bpp)"
+msgstr "ÁâÐÝÔÐàâÝëÙ àÐáâÕàØ×ÐâÞà (16bpp)"
+
+#: gui/ThemeEngine.cpp:337
+msgid "Antialiased Renderer (16bpp)"
+msgstr "ÀÐáâÕàØ×ÐâÞà áÞ áÓÛÐÖØÒÐÝØÕÜ (16bpp)"
+
+#: base/main.cpp:205
+#, c-format
+msgid "Engine does not support debug level '%s'"
+msgstr "´ÒØÖÞÚ ÝÕ ßÞÔÔÕàÖØÒÐÕâ ãàÞÒÕÝì ÞâÛÐÔÚØ '%s'"
+
+#: base/main.cpp:273
+msgid "Menu"
+msgstr "¼ÕÝî"
+
+#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48
+#: backends/platform/wince/CEActionsPocket.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:45
+msgid "Skip"
+msgstr "¿àÞßãáâØâì"
+
+#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53
+#: backends/platform/wince/CEActionsPocket.cpp:41
+msgid "Pause"
+msgstr "¿Ðã×Ð"
+
+#: base/main.cpp:282
+msgid "Skip line"
+msgstr "¿àÞßãáâØâì áâàÞÚã"
+
+#: base/main.cpp:404
+msgid "Error running game:"
+msgstr "¾èØÑÚÐ ×ÐßãáÚÐ ØÓàë:"
+
+#: base/main.cpp:430 base/main.cpp:431
+msgid "Could not find any engine capable of running the selected game"
+msgstr "½Õ ÜÞÓã ÝÐÙâØ ÔÒØÖÞÚ ÔÛï ×ÐßãáÚÐ ÒëÑàÐÝÝÞÙ ØÓàë"
+
+#: common/error.cpp:43
+msgid "Invalid Path"
+msgstr "½ÕÒÕàÝëÙ ßãâì"
+
+#: common/error.cpp:44
+msgid "Game Data not found"
+msgstr "½Õâ äÐÙÛÞÒ ØÓàë"
+
+#: common/error.cpp:45
+msgid "Game Id not supported"
+msgstr "Game Id ÝÕ ßÞÔÔÕàÖØÒÐÕâáï"
+
+#: common/error.cpp:46
+msgid "Unsupported Color Mode"
+msgstr "½ÕßÞÔÔÕàÖØÒÐÕÜëÙ àÕÖØÜ æÒÕâÐ"
+
+#: common/error.cpp:48
+msgid "Read permission denied"
+msgstr "½ÕÔÞáâÐâÞçÝÞ ßàÐÒ ÔÛï çâÕÝØï"
+
+#: common/error.cpp:49
+msgid "Write permission denied"
+msgstr "½ÕÔÞáâÐâÞçÝÞ ßàÐÒ ÔÛï ×ÐßØáØ"
+
+#: common/error.cpp:52
+msgid "Path not exists"
+msgstr "¿ãâì ÝÕ ÝÐÙÔÕÝ"
+
+#: common/error.cpp:53
+msgid "Path not a directory"
+msgstr "¿ãâì ÝÕ ïÒÛïÕâáï ÔØàÕÚâÞàØÕÙ"
+
+#: common/error.cpp:54
+msgid "Path not a file"
+msgstr "¿ãâì ÝÕ ïÒÛïÕâáï äÐÙÛÞÜ"
+
+#: common/error.cpp:56
+msgid "Cannot create file"
+msgstr "½Õ ÜÞÓã áÞ×ÔÐâì äÐÙÛ"
+
+#: common/error.cpp:57
+msgid "Reading failed"
+msgstr "¾èØÑÚÐ çâÕÝØï"
+
+#: common/error.cpp:58
+msgid "Writing data failed"
+msgstr "¾èØÑÚÐ ×ÐßØáØ ÔÐÝÝëå"
+
+#: common/error.cpp:60 common/error.cpp:71
+msgid "Unknown Error"
+msgstr "½ÕØ×ÒÕáâÝÐï ÞèØÑÚÐ"
+
+#: common/util.cpp:254
+msgid "Hercules Green"
+msgstr "Hercules ·ÕÛÕÝëÙ"
+
+#: common/util.cpp:255
+msgid "Hercules Amber"
+msgstr "Hercules ÏÝâÐàÝëÙ"
+
+#: engines/dialogs.cpp:89
+msgid "~R~esume"
+msgstr "¿àÞÔÞÛ~Ö~Øâì"
+
+#: engines/dialogs.cpp:91
+msgid "~L~oad"
+msgstr "~·~ÐÓàã×Øâì"
+
+#: engines/dialogs.cpp:95
+msgid "~S~ave"
+msgstr "~·~ÐßØáÐâì"
+
+#: engines/dialogs.cpp:99
+msgid "~O~ptions"
+msgstr "~¾~ßæØØ"
+
+#: engines/dialogs.cpp:104
+msgid "~H~elp"
+msgstr "~¿~ÞÜÞéì"
+
+#: engines/dialogs.cpp:107
+msgid "~A~bout"
+msgstr "¾ ßàÞ~Ó~àÐÜÜÕ"
+
+#: engines/dialogs.cpp:109
+msgid "~R~eturn to Launcher"
+msgstr "~²~ëÙâØ Ò ÓÛÐÒÝÞÕ ÜÕÝî"
+
+#: engines/dialogs.cpp:119
+msgid "Save game:"
+msgstr "ÁÞåàÐÝØâì ØÓàã: "
+
+#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47
+#: backends/platform/wince/CEActionsPocket.cpp:42
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Save"
+msgstr "·ÐßØáÐâì"
+
+#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84
+#: engines/mohawk/dialogs.cpp:118
+msgid "~O~K"
+msgstr "~O~K"
+
+#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85
+#: engines/mohawk/dialogs.cpp:119
+msgid "~C~ancel"
+msgstr "¾~â~ÜÕÝÐ"
+
+#: engines/dialogs.cpp:305
+msgid "~K~eys"
+msgstr "~º~ÛÐÒØèØ"
+
+#: engines/scumm/dialogs.cpp:287
+msgid "~P~revious"
+msgstr "~¿~àÕÔ"
+
+#: engines/scumm/dialogs.cpp:288
+msgid "~N~ext"
+msgstr "~Á~ÛÕÔ"
+
+#: engines/scumm/dialogs.cpp:289
+#: backends/platform/ds/arm9/source/dsoptions.cpp:59
+msgid "~C~lose"
+msgstr "~·~ÐÚàëâì"
+
+#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115
+msgid "~Z~ip Mode Activated"
+msgstr "ÀÕÖØÜ ÑëáâàÞÓÞ ßÕàÕåÞÔÐ ÐÚâØÒØàÞÒÐÝ"
+
+#: engines/mohawk/dialogs.cpp:82
+msgid "~T~ransitions Enabled"
+msgstr "¿ÕàÕåÞÔë ÐÚâØÒØàÞÒÐÝë"
+
+#: engines/mohawk/dialogs.cpp:116
+msgid "~W~ater Effect Enabled"
+msgstr "ÍääÕÚâë ÒÞÔë ÒÚÛîçÕÝë"
+
+#: sound/fmopl.cpp:51
+msgid "MAME OPL emulator"
+msgstr "ÍÜãÛïâÞà MAME OPL"
+
+#: sound/fmopl.cpp:53
+msgid "DOSBox OPL emulator"
+msgstr "ÍÜãÛïâÞà DOSBox OPL"
+
+#: sound/null.h:45
+msgid "No music"
+msgstr "±Õ× Üã×ëÚØ"
+
+#: sound/softsynth/adlib.cpp:1590
+msgid "AdLib Emulator"
+msgstr "ÍÜãÛïâÞà AdLib"
+
+#: sound/softsynth/mt32.cpp:327
+msgid "Initialising MT-32 Emulator"
+msgstr "½ÐáâàÐØÒÐî íÜãÛïâÞà MT-32"
+
+#: sound/softsynth/mt32.cpp:541
+msgid "MT-32 Emulator"
+msgstr "ÍÜãÛïâÞà MT-32"
+
+#: sound/softsynth/pcspk.cpp:142
+msgid "PC Speaker Emulator"
+msgstr "ÍÜãÛïâÞà PC áßØÚÕàÐ"
+
+#: sound/softsynth/pcspk.cpp:161
+msgid "IBM PCjr Emulator"
+msgstr "ÍÜãÛïâÞà IBM PCjr"
+
+#: sound/softsynth/ym2612.cpp:762
+msgid "FM Towns Emulator"
+msgstr "ÍÜãÛïâÞà FM Towns"
+
+#: backends/keymapper/remap-dialog.cpp:49
+msgid "Keymap:"
+msgstr "ÂÐÑÛØæÐ ÚÛÐÒØè:"
+
+#: backends/keymapper/remap-dialog.cpp:66
+msgid " (Active)"
+msgstr " (°ÚâØÒÝÐï)"
+
+#: backends/keymapper/remap-dialog.cpp:100
+msgid " (Global)"
+msgstr " (³ÛÞÑÐÛìÝÐï)"
+
+#: backends/keymapper/remap-dialog.cpp:110
+msgid " (Game)"
+msgstr " (¸Óàë)"
+
+#: backends/midi/windows.cpp:157
+msgid "Windows MIDI"
+msgstr "Windows MIDI"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:60
+msgid "ScummVM Main Menu"
+msgstr "³ÛÐÒÝÞÕ ÜÕÝî ScummVM"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:66
+msgid "~L~eft handed mode"
+msgstr "»ÕÒÞàãÚØÙ àÕÖØÜ"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:67
+msgid "~I~ndy fight controls"
+msgstr "ÃßàÐÒÛÕÝØÕ ÑÞïÜØ Ò Indy"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:68
+msgid "Show mouse cursor"
+msgstr "¿ÞÚÐ×ëÒÐâì ÚãàáÞà ÜëèØ"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:69
+msgid "Snap to edges"
+msgstr "¿àØÚàÕßØâì Ú ÓàÐÝØæÐÜ"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:71
+msgid "Touch X Offset"
+msgstr "ÁÜÕéÕÝØÕ ÚÐáÐÝØÙ ßÞ ÞáØ X"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:78
+msgid "Touch Y Offset"
+msgstr "ÁÜÕéÕÝØÕ ÚÐáÐÝØÙ ßÞ ÞáØ Y"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:90
+msgid "Use laptop trackpad-style cursor control"
+msgstr "¸áßÞÛì×ÞÒÐâì ãßàÐÒÛÕÝØÕ ÚãàáÞàÞÜ ÚÐÚ ÝÐ âàÕÚßÐÔÕ ÛÕßâÞßÞÒ"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:91
+msgid "Tap for left click, double tap right click"
+msgstr "ÂÐß ÔÛï ÛÕÒÞÓÞ éÕÛçÚÐ, ÔÒÞÙÝÞÙ âÐß ÔÛï ßàÐÒÞÓÞ éÕÛçÚÐ"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:93
+msgid "Sensitivity"
+msgstr "ÇãÒáâÒØâÕÛìÝÞáâì"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:102
+msgid "Initial top screen scale:"
+msgstr "½ÐçÐÛìÝëÙ ÜÐáèâÐÑ ÒÕàåÝÕÓÞ íÚàÐÝÐ:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:108
+msgid "Main screen scaling:"
+msgstr "¼ÐáèâÐÑ ÓÛÐÒÝÞÓÞ íÚàÐÝÐ:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:110
+msgid "Hardware scale (fast, but low quality)"
+msgstr "ÅÐàÔÒÐàÝÞÕ ÜÐáèâÐÑØàÞÒÐÝØÕ (ÑëáâàÞ, ÝÞ ÝØ×ÚÞÓÞ ÚÐçÕáâÒÐ)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:111
+msgid "Software scale (good quality, but slower)"
+msgstr "¿àÞÓàÐÜÜÝÞÕ ÜÐáèâÐÑØàÞÒÐÝØÕ (åÞàÞèÕÕ ÚÐçÕáâÒÞ, ÝÞ ÜÕÔÛÕÝÝÕÕ)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:112
+msgid "Unscaled (you must scroll left and right)"
+msgstr "±Õ× ÜÐáèâÐÑØàÞÒÐÝØï (ÝãÖÝÞ ÑãÔÕâ ßàÞÚàãçØÒÐâì ÒÛÕÒÞ Ø ÒßàÐÒÞ)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:114
+msgid "Brightness:"
+msgstr "ÏàÚÞáâì:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:124
+msgid "High quality audio (slower) (reboot)"
+msgstr "²ëáÞÚÞÕ ÚÐçÕáâÒÞ ×ÒãÚÐ (ÜÕÔÛÕÝÝÕÕ) (àÕÑãâ)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:125
+msgid "Disable power off"
+msgstr "·ÐßàÕâØâì ÒëÚÛîçÕÝØÕ"
+
+#: backends/platform/iphone/osys_events.cpp:339
+msgid "Touchpad mode enabled."
+msgstr "ÀÕÖØÜ âÐçßÐÔÐ ÒÚÛîçÕÝ."
+
+#: backends/platform/iphone/osys_events.cpp:341
+msgid "Touchpad mode disabled."
+msgstr "ÀÕÖØÜ âÐçßÐÔÐ ÒëÚÛîçÕÝ."
+
+#: backends/platform/sdl/graphics.cpp:40
+#: backends/platform/wince/wince-sdl.cpp:111
+#: backends/platform/wince/wince-sdl.cpp:118
+msgid "Normal (no scaling)"
+msgstr "±Õ× ãÒÕÛØçÕÝØï"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:41
+#: backends/platform/wince/CEActionsSmartphone.cpp:38
+msgid "Up"
+msgstr "²ÒÕàå"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:42
+#: backends/platform/wince/CEActionsSmartphone.cpp:39
+msgid "Down"
+msgstr "²ÝØ×"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:40
+msgid "Left"
+msgstr "²ÛÕÒÞ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:41
+msgid "Right"
+msgstr "²ßàÐÒÞ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:45
+#: backends/platform/wince/CEActionsPocket.cpp:59
+#: backends/platform/wince/CEActionsSmartphone.cpp:42
+msgid "Left Click"
+msgstr "»ÕÒëÙ éÕÛçÞÚ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:46
+#: backends/platform/wince/CEActionsSmartphone.cpp:43
+msgid "Right Click"
+msgstr "¿àÐÒëÙ éÕÛçÞÚ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:49
+#: backends/platform/wince/CEActionsSmartphone.cpp:46
+msgid "Zone"
+msgstr "·ÞÝÐ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:50
+#: backends/platform/wince/CEActionsPocket.cpp:53
+#: backends/platform/wince/CEActionsSmartphone.cpp:47
+msgid "Multi Function"
+msgstr "¼ãÛìâØäãÝÚæØï"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:51
+msgid "Swap character"
+msgstr "ÁÜÕÝØâì ÓÕàÞï"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:52
+msgid "Skip text"
+msgstr "¿àÞßãáâØâì âÕÚáâ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:54
+msgid "Fast mode"
+msgstr "±ëáâàëÙ àÕÖØÜ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:55
+#: backends/platform/wince/CEActionsPocket.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:51
+msgid "Quit"
+msgstr "²ëåÞÔ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:56
+msgid "Debugger"
+msgstr "¾âÛÐÔçØÚ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:57
+msgid "Global menu"
+msgstr "³ÛÞÑÐÛìÝÞÕ ÜÕÝî"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:58
+msgid "Virtual keyboard"
+msgstr "²ØàâãÐÛìÝÐï ÚÛÐÒØÐâãàÐ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:59
+msgid "Key mapper"
+msgstr "½Ð×ÝÐçÕÝØÕ ÚÛÐÒØè"
+
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+msgid "Do you want to quit ?"
+msgstr "²ë åÞâØâÕ ÒëÙâØ?"
+
+#: backends/platform/wii/options.cpp:51
+msgid "Video"
+msgstr "²ØÔÕÞ"
+
+#: backends/platform/wii/options.cpp:54
+msgid "Current video mode:"
+msgstr "ÂÕÚãéØÙ ÒØÔÕÞàÕÖØÜ:"
+
+#: backends/platform/wii/options.cpp:56
+msgid "Double-strike"
+msgstr "´ÒÞÙÝÞÙ ãÔÐà"
+
+#: backends/platform/wii/options.cpp:60
+msgid "Horizontal underscan:"
+msgstr "³ÞàØ×ÞÝâÐÛìÝëÙ underscan:"
+
+#: backends/platform/wii/options.cpp:66
+msgid "Vertical underscan:"
+msgstr "²ÕàâØÚÐÛìÝëÙ underscan:"
+
+#: backends/platform/wii/options.cpp:71
+msgid "Input"
+msgstr "²ÒÞÔ"
+
+#: backends/platform/wii/options.cpp:74
+msgid "GC Pad sensitivity:"
+msgstr "ÇãÒáâÒØâÕÛìÝÞáâì GC ßÐÔÐ:"
+
+#: backends/platform/wii/options.cpp:80
+msgid "GC Pad acceleration:"
+msgstr "ÃáÚÞàÕÝØÕ GC ßÐÔÐ:"
+
+#: backends/platform/wii/options.cpp:86
+msgid "DVD"
+msgstr "DVD"
+
+#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101
+msgid "Status:"
+msgstr "ÁÞáâÞïÝØÕ:"
+
+#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102
+msgid "Unknown"
+msgstr "½ÕØ×ÒÕáâÝÞ"
+
+#: backends/platform/wii/options.cpp:93
+msgid "Mount DVD"
+msgstr "¿ÞÔÚÛîçØâì DVD"
+
+#: backends/platform/wii/options.cpp:94
+msgid "Unmount DVD"
+msgstr "¾âÚÛîçØâì DVD"
+
+#: backends/platform/wii/options.cpp:98
+msgid "SMB"
+msgstr "SMB"
+
+#: backends/platform/wii/options.cpp:106
+msgid "Server:"
+msgstr "ÁÕàÒÕà:"
+
+#: backends/platform/wii/options.cpp:110
+msgid "Share:"
+msgstr "ÁÕâÕÒÐï ßÐßÚÐ:"
+
+#: backends/platform/wii/options.cpp:114
+msgid "Username:"
+msgstr "¿ÞÛì×ÞÒÐâÕÛì:"
+
+#: backends/platform/wii/options.cpp:118
+msgid "Password:"
+msgstr "¿ÐàÞÛì:"
+
+#: backends/platform/wii/options.cpp:121
+msgid "Init network"
+msgstr "¸ÝØæØÐÛØ×ÐæØï áÕâØ"
+
+#: backends/platform/wii/options.cpp:123
+msgid "Mount SMB"
+msgstr "¿ÞÔÚÛîçØâì SMB"
+
+#: backends/platform/wii/options.cpp:124
+msgid "Unmount SMB"
+msgstr "¾âÚÛîçâì SMB"
+
+#: backends/platform/wii/options.cpp:145
+msgid "DVD Mounted successfully"
+msgstr "DVD ßÞÔÚÛîçÕÝ ãáßÕèÝÞ"
+
+#: backends/platform/wii/options.cpp:148
+msgid "Error while mounting the DVD"
+msgstr "¾èØÑÚÐ ÒÞ ÒàÕÜï ßÞÔÚÛîçÕÝØï DVD"
+
+#: backends/platform/wii/options.cpp:150
+msgid "DVD not mounted"
+msgstr "DVD ÝÕ ßÞÔÚÛîçÕÝ"
+
+#: backends/platform/wii/options.cpp:163
+msgid "Network up, share mounted"
+msgstr "ÁÕâì àÐÑÞâÐÕâ, ßÐßÚÐ ßÞÔÚÛîçÕÝÐ"
+
+#: backends/platform/wii/options.cpp:165
+msgid "Network up"
+msgstr "ÁÕâì àÐÑÞâÐÕâ"
+
+#: backends/platform/wii/options.cpp:168
+msgid ", error while mounting the share"
+msgstr ", ÞèØÑÚÐ ÒÞ ÒàÕÜï ßÞÔÚÛîçÕÝØï ßÐßÚØ"
+
+#: backends/platform/wii/options.cpp:170
+msgid ", share not mounted"
+msgstr ", ßÐßÚÐ ÝÕ ßÞÔÚÛîçÕÝÐ"
+
+#: backends/platform/wii/options.cpp:176
+msgid "Network down"
+msgstr "ÁÕâì ÒëÚÛîçÕÝÐ"
+
+#: backends/platform/wii/options.cpp:180
+msgid "Initialising network"
+msgstr "½ÐáâàÐØÒÐî áÕâì"
+
+#: backends/platform/wii/options.cpp:184
+msgid "Timeout while initialising network"
+msgstr "²àÕÜï ßÞÔÚÛîçÕÝØï Ú áÕâØ ØáâÕÚÛÞ"
+
+#: backends/platform/wii/options.cpp:188
+#, c-format
+msgid "Network not initialsed (%d)"
+msgstr "ÁÕâì ÝÕ ÝÐáâàÞÕÝÐ (%d)"
+
+#: backends/platform/wince/CEActionsPocket.cpp:45
+msgid "Hide Toolbar"
+msgstr "ÁßàïâÐâì ßÐÝÕÛì ØÝáâàãÜÕÝâÞÒ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:46
+msgid "Show Keyboard"
+msgstr "¿ÞÚÐ×Ðâì ÚÛÐÒØÐâãàã"
+
+#: backends/platform/wince/CEActionsPocket.cpp:47
+msgid "Sound on/off"
+msgstr "·ÒãÚ ÒÚÛ/ÒëÚÛ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:48
+msgid "Right click"
+msgstr "¿àÐÒëÙ éÕÛçÞÚ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:49
+msgid "Show/Hide Cursor"
+msgstr "¿ÞÚÐ×Ðâì/ÃÑàÐâì ÚãàáÞà"
+
+#: backends/platform/wince/CEActionsPocket.cpp:50
+msgid "Free look"
+msgstr "ÁÒÞÑÞÔÝëÙ ÞÑ×Þà"
+
+#: backends/platform/wince/CEActionsPocket.cpp:51
+msgid "Zoom up"
+msgstr "ÃÒÕÛ. ÜÐáèâÐÑ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:52
+msgid "Zoom down"
+msgstr "ÃÜÕÝìè. ÜÐáèâÐÑ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:54
+#: backends/platform/wince/CEActionsSmartphone.cpp:48
+msgid "Bind Keys"
+msgstr "½Ð×ÝÐçØâì ÚÛÐÒØèØ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:55
+msgid "Cursor Up"
+msgstr "ºãàáÞà ÒÒÕàå"
+
+#: backends/platform/wince/CEActionsPocket.cpp:56
+msgid "Cursor Down"
+msgstr "ºãàáÞà ÒÝØ×"
+
+#: backends/platform/wince/CEActionsPocket.cpp:57
+msgid "Cursor Left"
+msgstr "ºãàáÞà ÒÛÕÒÞ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:58
+msgid "Cursor Right"
+msgstr "ºãàáÞà ÒßàÐÒÞ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Do you want to load or save the game?"
+msgstr "²ë åÞâØâÕ ×ÐÓàã×Øâì ÛØÑÞ áÞåàÐÝØâì ØÓàã?"
+
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+msgid " Are you sure you want to quit ? "
+msgstr " ²ë ãÒÕàÕÝë, çâÞ åÞâØâÕ ÒëÙâØ? "
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:49
+msgid "Keyboard"
+msgstr "ºÛÐÒØÐâãàÐ"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:50
+msgid "Rotate"
+msgstr "¿ÞÒÕàÝãâì"
+
+#: backends/platform/wince/CELauncherDialog.cpp:58
+msgid "Using SDL driver "
+msgstr "¸áßÞÛì×ãî ÔàÐÙÒÕà SDL "
+
+#: backends/platform/wince/CELauncherDialog.cpp:62
+msgid "Display "
+msgstr "¿ÞÚÐ×Ðâì "
+
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Do you want to perform an automatic scan ?"
+msgstr "²ë åÞâØâÕ ßàÞØ×ÒÕáâØ ÐÒâÞÜÐâØçÕáÚØÙ ßÞØáÚ?"
diff --git a/po/scummvm.pot b/po/scummvm.pot
new file mode 100644
index 0000000000..38ce9b1a48
--- /dev/null
+++ b/po/scummvm.pot
@@ -0,0 +1,1348 @@
+# LANGUAGE translation for ScummVM.
+# Copyright (C) YEAR ScummVM Team
+# This file is distributed under the same license as the ScummVM package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: ScummVM 1.2.0svn\n"
+"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
+"POT-Creation-Date: 2010-07-30 22:14+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: gui/about.cpp:96
+#, c-format
+msgid "(built on %s)"
+msgstr ""
+
+#: gui/about.cpp:103
+msgid "Features compiled in:"
+msgstr ""
+
+#: gui/about.cpp:112
+msgid "Available engines:"
+msgstr ""
+
+#: gui/browser.cpp:69
+msgid "Go up"
+msgstr ""
+
+#: gui/browser.cpp:69
+msgid "Go to previous directory level"
+msgstr ""
+
+#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46
+#: gui/launcher.cpp:280 gui/massadd.cpp:95 gui/options.cpp:1029
+#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56
+#: backends/platform/wii/options.cpp:48
+msgid "Cancel"
+msgstr ""
+
+#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57
+msgid "Choose"
+msgstr ""
+
+#: gui/GuiManager.cpp:103 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr ""
+
+#: gui/GuiManager.cpp:106
+msgid "Mouse click"
+msgstr ""
+
+#: gui/GuiManager.cpp:109 base/main.cpp:285
+msgid "Display keyboard"
+msgstr ""
+
+#: gui/GuiManager.cpp:112 base/main.cpp:288
+msgid "Remap keys"
+msgstr ""
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr ""
+
+#: gui/KeysDialog.cpp:45 gui/launcher.cpp:281 gui/launcher.cpp:893
+#: gui/launcher.cpp:897 gui/massadd.cpp:92 gui/options.cpp:1030
+#: backends/platform/wii/options.cpp:47
+#: backends/platform/wince/CELauncherDialog.cpp:56
+msgid "OK"
+msgstr ""
+
+#: gui/KeysDialog.cpp:52
+msgid "Select an action and click 'Map'"
+msgstr ""
+
+#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144
+#, c-format
+msgid "Associated key : %s"
+msgstr ""
+
+#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146
+#, c-format
+msgid "Associated key : none"
+msgstr ""
+
+#: gui/KeysDialog.cpp:93
+msgid "Please select an action"
+msgstr ""
+
+#: gui/KeysDialog.cpp:109
+msgid "Press the key to associate"
+msgstr ""
+
+#: gui/KeysDialog.cpp:148
+msgid "Choose an action to map"
+msgstr ""
+
+#: gui/launcher.cpp:172
+msgid "Game"
+msgstr ""
+
+#: gui/launcher.cpp:175
+msgid "ID:"
+msgstr ""
+
+#: gui/launcher.cpp:175 gui/launcher.cpp:176
+msgid ""
+"Short game identifier used for referring to savegames and running the game "
+"from the command line"
+msgstr ""
+
+#: gui/launcher.cpp:179
+msgid "Name:"
+msgstr ""
+
+#: gui/launcher.cpp:179 gui/launcher.cpp:180
+msgid "Full title of the game"
+msgstr ""
+
+#: gui/launcher.cpp:183
+msgid "Language:"
+msgstr ""
+
+#: gui/launcher.cpp:183 gui/launcher.cpp:184
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+
+#: gui/launcher.cpp:185 gui/launcher.cpp:196 gui/options.cpp:80
+#: gui/options.cpp:635 gui/options.cpp:645 gui/options.cpp:1000
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr ""
+
+#: gui/launcher.cpp:194
+msgid "Platform:"
+msgstr ""
+
+#: gui/launcher.cpp:194 gui/launcher.cpp:195
+msgid "Platform the game was originally designed for"
+msgstr ""
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "Graphics"
+msgstr ""
+
+#: gui/launcher.cpp:206 gui/options.cpp:898 gui/options.cpp:915
+msgid "GFX"
+msgstr ""
+
+#: gui/launcher.cpp:208
+msgid "Override global graphic settings"
+msgstr ""
+
+#: gui/launcher.cpp:215 gui/options.cpp:921
+msgid "Audio"
+msgstr ""
+
+#: gui/launcher.cpp:217
+msgid "Override global audio settings"
+msgstr ""
+
+#: gui/launcher.cpp:225 gui/options.cpp:925
+msgid "Volume"
+msgstr ""
+
+#: gui/launcher.cpp:227
+msgid "Override global volume settings"
+msgstr ""
+
+#: gui/launcher.cpp:234 gui/options.cpp:933
+msgid "MIDI"
+msgstr ""
+
+#: gui/launcher.cpp:236
+msgid "Override global MIDI settings"
+msgstr ""
+
+#: gui/launcher.cpp:246 gui/options.cpp:939
+msgid "MT-32"
+msgstr ""
+
+#: gui/launcher.cpp:248
+msgid "Override global MT-32 settings"
+msgstr ""
+
+#: gui/launcher.cpp:258 gui/options.cpp:945
+msgid "Paths"
+msgstr ""
+
+#: gui/launcher.cpp:264
+msgid "Game Path:"
+msgstr ""
+
+#: gui/launcher.cpp:268 gui/options.cpp:958
+msgid "Extra Path:"
+msgstr ""
+
+#: gui/launcher.cpp:268 gui/launcher.cpp:269
+msgid "Specifies path to additional data used the game"
+msgstr ""
+
+#: gui/launcher.cpp:272
+msgid "Save Path:"
+msgstr ""
+
+#: gui/launcher.cpp:272 gui/launcher.cpp:273 gui/options.cpp:952
+#: gui/options.cpp:953
+msgid "Specifies where your savegames are put"
+msgstr ""
+
+#: gui/launcher.cpp:289 gui/launcher.cpp:369 gui/launcher.cpp:418
+#: gui/options.cpp:230 gui/options.cpp:399 gui/options.cpp:497
+#: gui/options.cpp:555 gui/options.cpp:732 gui/options.cpp:956
+#: gui/options.cpp:959 gui/options.cpp:963 gui/options.cpp:1053
+#: gui/options.cpp:1059 gui/options.cpp:1065 gui/options.cpp:1073
+#: gui/options.cpp:1097 gui/options.cpp:1101 gui/options.cpp:1107
+#: gui/options.cpp:1114 gui/options.cpp:1213
+msgid "None"
+msgstr ""
+
+#: gui/launcher.cpp:294 gui/launcher.cpp:373
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr ""
+
+#: gui/launcher.cpp:411 gui/options.cpp:1207
+msgid "Select SoundFont"
+msgstr ""
+
+#: gui/launcher.cpp:430 gui/launcher.cpp:568
+msgid "Select directory with game data"
+msgstr ""
+
+#: gui/launcher.cpp:448
+msgid "Select additional game directory"
+msgstr ""
+
+#: gui/launcher.cpp:460
+msgid "Select directory for saved games"
+msgstr ""
+
+#: gui/launcher.cpp:479
+msgid "This game ID is already taken. Please choose another one."
+msgstr ""
+
+#: gui/launcher.cpp:520 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr ""
+
+#: gui/launcher.cpp:520
+msgid "Quit ScummVM"
+msgstr ""
+
+#: gui/launcher.cpp:521
+msgid "A~b~out..."
+msgstr ""
+
+#: gui/launcher.cpp:521
+msgid "About ScummVM"
+msgstr ""
+
+#: gui/launcher.cpp:522
+msgid "~O~ptions..."
+msgstr ""
+
+#: gui/launcher.cpp:522
+msgid "Change global ScummVM options"
+msgstr ""
+
+#: gui/launcher.cpp:524
+msgid "~S~tart"
+msgstr ""
+
+#: gui/launcher.cpp:524
+msgid "Start selected game"
+msgstr ""
+
+#: gui/launcher.cpp:527
+msgid "~L~oad..."
+msgstr ""
+
+#: gui/launcher.cpp:527
+msgid "Load savegame for selected game"
+msgstr ""
+
+#: gui/launcher.cpp:531
+msgid "~A~dd Game..."
+msgstr ""
+
+#: gui/launcher.cpp:531
+msgid "Hold Shift for Mass Add"
+msgstr ""
+
+#: gui/launcher.cpp:533
+msgid "~E~dit Game..."
+msgstr ""
+
+#: gui/launcher.cpp:533
+msgid "Change game options"
+msgstr ""
+
+#: gui/launcher.cpp:535
+msgid "~R~emove Game"
+msgstr ""
+
+#: gui/launcher.cpp:535
+msgid "Remove game from the list. The game data files stay intact"
+msgstr ""
+
+#: gui/launcher.cpp:542
+msgid "Search in game list"
+msgstr ""
+
+#: gui/launcher.cpp:546 gui/launcher.cpp:1057
+msgid "Search:"
+msgstr ""
+
+#: gui/launcher.cpp:549 gui/options.cpp:733
+msgid "Clear value"
+msgstr ""
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr ""
+
+#: gui/launcher.cpp:571 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr ""
+
+#: gui/launcher.cpp:680
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Yes"
+msgstr ""
+
+#: gui/launcher.cpp:681 gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "No"
+msgstr ""
+
+#: gui/launcher.cpp:728
+msgid "ScummVM couldn't open the specified directory!"
+msgstr ""
+
+#: gui/launcher.cpp:740
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr ""
+
+#: gui/launcher.cpp:754
+msgid "Pick the game:"
+msgstr ""
+
+#: gui/launcher.cpp:830
+msgid "Do you really want to remove this game configuration?"
+msgstr ""
+
+#: gui/launcher.cpp:893
+msgid "This game does not support loading games from the launcher."
+msgstr ""
+
+#: gui/launcher.cpp:897
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr ""
+
+#: gui/launcher.cpp:1009
+msgid "Mass Add..."
+msgstr ""
+
+#: gui/launcher.cpp:1010
+msgid "Add Game..."
+msgstr ""
+
+#: gui/massadd.cpp:79 gui/massadd.cpp:82
+msgid "... progress ..."
+msgstr ""
+
+#: gui/massadd.cpp:244
+msgid "Scan complete!"
+msgstr ""
+
+#: gui/massadd.cpp:247
+#, c-format
+msgid "Discovered %d new games."
+msgstr ""
+
+#: gui/massadd.cpp:251
+#, c-format
+msgid "Scanned %d directories ..."
+msgstr ""
+
+#: gui/massadd.cpp:254
+#, c-format
+msgid "Discovered %d new games ..."
+msgstr ""
+
+#: gui/options.cpp:78
+msgid "Never"
+msgstr ""
+
+#: gui/options.cpp:78
+msgid "every 5 mins"
+msgstr ""
+
+#: gui/options.cpp:78
+msgid "every 10 mins"
+msgstr ""
+
+#: gui/options.cpp:78
+msgid "every 15 mins"
+msgstr ""
+
+#: gui/options.cpp:78
+msgid "every 30 mins"
+msgstr ""
+
+#: gui/options.cpp:80
+msgid "8 kHz"
+msgstr ""
+
+#: gui/options.cpp:80
+msgid "11kHz"
+msgstr ""
+
+#: gui/options.cpp:80
+msgid "22 kHz"
+msgstr ""
+
+#: gui/options.cpp:80
+msgid "44 kHz"
+msgstr ""
+
+#: gui/options.cpp:80
+msgid "48 kHz"
+msgstr ""
+
+#: gui/options.cpp:632
+msgid "Graphics mode:"
+msgstr ""
+
+#: gui/options.cpp:643
+msgid "Render mode:"
+msgstr ""
+
+#: gui/options.cpp:643 gui/options.cpp:644
+msgid "Special dithering modes supported by some games"
+msgstr ""
+
+#: gui/options.cpp:653
+msgid "Fullscreen mode"
+msgstr ""
+
+#: gui/options.cpp:656
+msgid "Aspect ratio correction"
+msgstr ""
+
+#: gui/options.cpp:656
+msgid "Correct aspect ratio for 320x200 games"
+msgstr ""
+
+#: gui/options.cpp:663
+msgid "Preferred Device:"
+msgstr ""
+
+#: gui/options.cpp:663
+msgid "Music Device:"
+msgstr ""
+
+#: gui/options.cpp:663
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr ""
+
+#: gui/options.cpp:663 gui/options.cpp:664
+msgid "Specifies output sound device or sound card emulator"
+msgstr ""
+
+#: gui/options.cpp:688
+msgid "AdLib emulator:"
+msgstr ""
+
+#: gui/options.cpp:688 gui/options.cpp:689
+msgid "AdLib is used for music in many games"
+msgstr ""
+
+#: gui/options.cpp:699
+msgid "Output rate:"
+msgstr ""
+
+#: gui/options.cpp:699 gui/options.cpp:700
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+
+#: gui/options.cpp:710
+msgid "GM Device:"
+msgstr ""
+
+#: gui/options.cpp:710
+msgid "Specifies default sound device for General MIDI output"
+msgstr ""
+
+#: gui/options.cpp:731
+msgid "SoundFont:"
+msgstr ""
+
+#: gui/options.cpp:731 gui/options.cpp:732
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr ""
+
+#: gui/options.cpp:736
+msgid "Mixed AdLib/MIDI mode"
+msgstr ""
+
+#: gui/options.cpp:736
+msgid "Use both MIDI and AdLib sound generation"
+msgstr ""
+
+#: gui/options.cpp:739
+msgid "MIDI gain:"
+msgstr ""
+
+#: gui/options.cpp:749
+msgid "MT-32 Device:"
+msgstr ""
+
+#: gui/options.cpp:749
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr ""
+
+#: gui/options.cpp:753
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr ""
+
+#: gui/options.cpp:753
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+
+#: gui/options.cpp:756
+msgid "Enable Roland GS Mode"
+msgstr ""
+
+#: gui/options.cpp:756
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr ""
+
+#: gui/options.cpp:780
+msgid "Text and Speech:"
+msgstr ""
+
+#: gui/options.cpp:785 gui/options.cpp:791
+msgid "Speech"
+msgstr ""
+
+#: gui/options.cpp:786 gui/options.cpp:792
+msgid "Subtitles"
+msgstr ""
+
+#: gui/options.cpp:787 gui/options.cpp:793
+msgid "Both"
+msgstr ""
+
+#: gui/options.cpp:791
+msgid "Spch"
+msgstr ""
+
+#: gui/options.cpp:792
+msgid "Subs"
+msgstr ""
+
+#: gui/options.cpp:793
+msgid "Show subtitles and play speech"
+msgstr ""
+
+#: gui/options.cpp:797
+msgid "Subtitle speed:"
+msgstr ""
+
+#: gui/options.cpp:809
+msgid "Music volume:"
+msgstr ""
+
+#: gui/options.cpp:816
+msgid "Mute All"
+msgstr ""
+
+#: gui/options.cpp:819
+msgid "SFX volume:"
+msgstr ""
+
+#: gui/options.cpp:819 gui/options.cpp:820
+msgid "Special sound effects volume"
+msgstr ""
+
+#: gui/options.cpp:826
+msgid "Speech volume:"
+msgstr ""
+
+#: gui/options.cpp:952
+msgid "Save Path: "
+msgstr ""
+
+#: gui/options.cpp:955
+msgid "Theme Path:"
+msgstr ""
+
+#: gui/options.cpp:958 gui/options.cpp:959
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr ""
+
+#: gui/options.cpp:962
+msgid "Plugins Path:"
+msgstr ""
+
+#: gui/options.cpp:970
+msgid "Misc"
+msgstr ""
+
+#: gui/options.cpp:972
+msgid "Theme:"
+msgstr ""
+
+#: gui/options.cpp:976
+msgid "GUI Renderer:"
+msgstr ""
+
+#: gui/options.cpp:982
+msgid "Autosave:"
+msgstr ""
+
+#: gui/options.cpp:990
+msgid "Keys"
+msgstr ""
+
+#: gui/options.cpp:997
+msgid "GUI Language:"
+msgstr ""
+
+#: gui/options.cpp:997
+msgid "Language of ScummVM GUI"
+msgstr ""
+
+#: gui/options.cpp:1002
+msgid "English"
+msgstr ""
+
+#: gui/options.cpp:1146
+msgid "You have to restart ScummVM to take the effect."
+msgstr ""
+
+#: gui/options.cpp:1159
+msgid "Select directory for savegames"
+msgstr ""
+
+#: gui/options.cpp:1166
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr ""
+
+#: gui/options.cpp:1175
+msgid "Select directory for GUI themes"
+msgstr ""
+
+#: gui/options.cpp:1185
+msgid "Select directory for extra files"
+msgstr ""
+
+#: gui/options.cpp:1196
+msgid "Select directory for plugins"
+msgstr ""
+
+#: gui/saveload.cpp:60 gui/saveload.cpp:241
+msgid "No date saved"
+msgstr ""
+
+#: gui/saveload.cpp:61 gui/saveload.cpp:242
+msgid "No time saved"
+msgstr ""
+
+#: gui/saveload.cpp:62 gui/saveload.cpp:243
+msgid "No playtime saved"
+msgstr ""
+
+#: gui/saveload.cpp:69 gui/saveload.cpp:157
+msgid "Delete"
+msgstr ""
+
+#: gui/saveload.cpp:156
+msgid "Do you really want to delete this savegame?"
+msgstr ""
+
+#: gui/saveload.cpp:265
+msgid "Date: "
+msgstr ""
+
+#: gui/saveload.cpp:268
+msgid "Time: "
+msgstr ""
+
+#: gui/saveload.cpp:273
+msgid "Playtime: "
+msgstr ""
+
+#: gui/saveload.cpp:286 gui/saveload.cpp:353
+msgid "Untitled savestate"
+msgstr ""
+
+#: gui/themebrowser.cpp:46
+msgid "Select a Theme"
+msgstr ""
+
+#: gui/ThemeEngine.cpp:334
+msgid "Disabled GFX"
+msgstr ""
+
+#: gui/ThemeEngine.cpp:335
+msgid "Standard Renderer (16bpp)"
+msgstr ""
+
+#: gui/ThemeEngine.cpp:337
+msgid "Antialiased Renderer (16bpp)"
+msgstr ""
+
+#: base/main.cpp:205
+#, c-format
+msgid "Engine does not support debug level '%s'"
+msgstr ""
+
+#: base/main.cpp:273
+msgid "Menu"
+msgstr ""
+
+#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48
+#: backends/platform/wince/CEActionsPocket.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:45
+msgid "Skip"
+msgstr ""
+
+#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53
+#: backends/platform/wince/CEActionsPocket.cpp:41
+msgid "Pause"
+msgstr ""
+
+#: base/main.cpp:282
+msgid "Skip line"
+msgstr ""
+
+#: base/main.cpp:404
+msgid "Error running game:"
+msgstr ""
+
+#: base/main.cpp:430 base/main.cpp:431
+msgid "Could not find any engine capable of running the selected game"
+msgstr ""
+
+#: common/error.cpp:43
+msgid "Invalid Path"
+msgstr ""
+
+#: common/error.cpp:44
+msgid "Game Data not found"
+msgstr ""
+
+#: common/error.cpp:45
+msgid "Game Id not supported"
+msgstr ""
+
+#: common/error.cpp:46
+msgid "Unsupported Color Mode"
+msgstr ""
+
+#: common/error.cpp:48
+msgid "Read permission denied"
+msgstr ""
+
+#: common/error.cpp:49
+msgid "Write permission denied"
+msgstr ""
+
+#: common/error.cpp:52
+msgid "Path not exists"
+msgstr ""
+
+#: common/error.cpp:53
+msgid "Path not a directory"
+msgstr ""
+
+#: common/error.cpp:54
+msgid "Path not a file"
+msgstr ""
+
+#: common/error.cpp:56
+msgid "Cannot create file"
+msgstr ""
+
+#: common/error.cpp:57
+msgid "Reading failed"
+msgstr ""
+
+#: common/error.cpp:58
+msgid "Writing data failed"
+msgstr ""
+
+#: common/error.cpp:60 common/error.cpp:71
+msgid "Unknown Error"
+msgstr ""
+
+#: common/util.cpp:254
+msgid "Hercules Green"
+msgstr ""
+
+#: common/util.cpp:255
+msgid "Hercules Amber"
+msgstr ""
+
+#: engines/dialogs.cpp:89
+msgid "~R~esume"
+msgstr ""
+
+#: engines/dialogs.cpp:91
+msgid "~L~oad"
+msgstr ""
+
+#: engines/dialogs.cpp:95
+msgid "~S~ave"
+msgstr ""
+
+#: engines/dialogs.cpp:99
+msgid "~O~ptions"
+msgstr ""
+
+#: engines/dialogs.cpp:104
+msgid "~H~elp"
+msgstr ""
+
+#: engines/dialogs.cpp:107
+msgid "~A~bout"
+msgstr ""
+
+#: engines/dialogs.cpp:109
+msgid "~R~eturn to Launcher"
+msgstr ""
+
+#: engines/dialogs.cpp:119
+msgid "Save game:"
+msgstr ""
+
+#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47
+#: backends/platform/wince/CEActionsPocket.cpp:42
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Save"
+msgstr ""
+
+#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84
+#: engines/mohawk/dialogs.cpp:118
+msgid "~O~K"
+msgstr ""
+
+#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85
+#: engines/mohawk/dialogs.cpp:119
+msgid "~C~ancel"
+msgstr ""
+
+#: engines/dialogs.cpp:305
+msgid "~K~eys"
+msgstr ""
+
+#: engines/scumm/dialogs.cpp:287
+msgid "~P~revious"
+msgstr ""
+
+#: engines/scumm/dialogs.cpp:288
+msgid "~N~ext"
+msgstr ""
+
+#: engines/scumm/dialogs.cpp:289
+#: backends/platform/ds/arm9/source/dsoptions.cpp:59
+msgid "~C~lose"
+msgstr ""
+
+#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115
+msgid "~Z~ip Mode Activated"
+msgstr ""
+
+#: engines/mohawk/dialogs.cpp:82
+msgid "~T~ransitions Enabled"
+msgstr ""
+
+#: engines/mohawk/dialogs.cpp:116
+msgid "~W~ater Effect Enabled"
+msgstr ""
+
+#: sound/fmopl.cpp:51
+msgid "MAME OPL emulator"
+msgstr ""
+
+#: sound/fmopl.cpp:53
+msgid "DOSBox OPL emulator"
+msgstr ""
+
+#: sound/null.h:45
+msgid "No music"
+msgstr ""
+
+#: sound/softsynth/adlib.cpp:1590
+msgid "AdLib Emulator"
+msgstr ""
+
+#: sound/softsynth/mt32.cpp:327
+msgid "Initialising MT-32 Emulator"
+msgstr ""
+
+#: sound/softsynth/mt32.cpp:541
+msgid "MT-32 Emulator"
+msgstr ""
+
+#: sound/softsynth/pcspk.cpp:142
+msgid "PC Speaker Emulator"
+msgstr ""
+
+#: sound/softsynth/pcspk.cpp:161
+msgid "IBM PCjr Emulator"
+msgstr ""
+
+#: sound/softsynth/ym2612.cpp:762
+msgid "FM Towns Emulator"
+msgstr ""
+
+#: backends/keymapper/remap-dialog.cpp:49
+msgid "Keymap:"
+msgstr ""
+
+#: backends/keymapper/remap-dialog.cpp:66
+msgid " (Active)"
+msgstr ""
+
+#: backends/keymapper/remap-dialog.cpp:100
+msgid " (Global)"
+msgstr ""
+
+#: backends/keymapper/remap-dialog.cpp:110
+msgid " (Game)"
+msgstr ""
+
+#: backends/midi/windows.cpp:157
+msgid "Windows MIDI"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:60
+msgid "ScummVM Main Menu"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:66
+msgid "~L~eft handed mode"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:67
+msgid "~I~ndy fight controls"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:68
+msgid "Show mouse cursor"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:69
+msgid "Snap to edges"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:71
+msgid "Touch X Offset"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:78
+msgid "Touch Y Offset"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:90
+msgid "Use laptop trackpad-style cursor control"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:91
+msgid "Tap for left click, double tap right click"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:93
+msgid "Sensitivity"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:102
+msgid "Initial top screen scale:"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:108
+msgid "Main screen scaling:"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:110
+msgid "Hardware scale (fast, but low quality)"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:111
+msgid "Software scale (good quality, but slower)"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:112
+msgid "Unscaled (you must scroll left and right)"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:114
+msgid "Brightness:"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:124
+msgid "High quality audio (slower) (reboot)"
+msgstr ""
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:125
+msgid "Disable power off"
+msgstr ""
+
+#: backends/platform/iphone/osys_events.cpp:339
+msgid "Touchpad mode enabled."
+msgstr ""
+
+#: backends/platform/iphone/osys_events.cpp:341
+msgid "Touchpad mode disabled."
+msgstr ""
+
+#: backends/platform/sdl/graphics.cpp:40
+#: backends/platform/wince/wince-sdl.cpp:111
+#: backends/platform/wince/wince-sdl.cpp:118
+msgid "Normal (no scaling)"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:41
+#: backends/platform/wince/CEActionsSmartphone.cpp:38
+msgid "Up"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:42
+#: backends/platform/wince/CEActionsSmartphone.cpp:39
+msgid "Down"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:40
+msgid "Left"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:41
+msgid "Right"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:45
+#: backends/platform/wince/CEActionsPocket.cpp:59
+#: backends/platform/wince/CEActionsSmartphone.cpp:42
+msgid "Left Click"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:46
+#: backends/platform/wince/CEActionsSmartphone.cpp:43
+msgid "Right Click"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:49
+#: backends/platform/wince/CEActionsSmartphone.cpp:46
+msgid "Zone"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:50
+#: backends/platform/wince/CEActionsPocket.cpp:53
+#: backends/platform/wince/CEActionsSmartphone.cpp:47
+msgid "Multi Function"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:51
+msgid "Swap character"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:52
+msgid "Skip text"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:54
+msgid "Fast mode"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:55
+#: backends/platform/wince/CEActionsPocket.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:51
+msgid "Quit"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:56
+msgid "Debugger"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:57
+msgid "Global menu"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:58
+msgid "Virtual keyboard"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianActions.cpp:59
+msgid "Key mapper"
+msgstr ""
+
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+msgid "Do you want to quit ?"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:51
+msgid "Video"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:54
+msgid "Current video mode:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:56
+msgid "Double-strike"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:60
+msgid "Horizontal underscan:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:66
+msgid "Vertical underscan:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:71
+msgid "Input"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:74
+msgid "GC Pad sensitivity:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:80
+msgid "GC Pad acceleration:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:86
+msgid "DVD"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101
+msgid "Status:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102
+msgid "Unknown"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:93
+msgid "Mount DVD"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:94
+msgid "Unmount DVD"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:98
+msgid "SMB"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:106
+msgid "Server:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:110
+msgid "Share:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:114
+msgid "Username:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:118
+msgid "Password:"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:121
+msgid "Init network"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:123
+msgid "Mount SMB"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:124
+msgid "Unmount SMB"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:145
+msgid "DVD Mounted successfully"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:148
+msgid "Error while mounting the DVD"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:150
+msgid "DVD not mounted"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:163
+msgid "Network up, share mounted"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:165
+msgid "Network up"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:168
+msgid ", error while mounting the share"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:170
+msgid ", share not mounted"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:176
+msgid "Network down"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:180
+msgid "Initialising network"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:184
+msgid "Timeout while initialising network"
+msgstr ""
+
+#: backends/platform/wii/options.cpp:188
+#, c-format
+msgid "Network not initialsed (%d)"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:45
+msgid "Hide Toolbar"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:46
+msgid "Show Keyboard"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:47
+msgid "Sound on/off"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:48
+msgid "Right click"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:49
+msgid "Show/Hide Cursor"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:50
+msgid "Free look"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:51
+msgid "Zoom up"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:52
+msgid "Zoom down"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:54
+#: backends/platform/wince/CEActionsSmartphone.cpp:48
+msgid "Bind Keys"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:55
+msgid "Cursor Up"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:56
+msgid "Cursor Down"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:57
+msgid "Cursor Left"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:58
+msgid "Cursor Right"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Do you want to load or save the game?"
+msgstr ""
+
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+msgid " Are you sure you want to quit ? "
+msgstr ""
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:49
+msgid "Keyboard"
+msgstr ""
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:50
+msgid "Rotate"
+msgstr ""
+
+#: backends/platform/wince/CELauncherDialog.cpp:58
+msgid "Using SDL driver "
+msgstr ""
+
+#: backends/platform/wince/CELauncherDialog.cpp:62
+msgid "Display "
+msgstr ""
+
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Do you want to perform an automatic scan ?"
+msgstr ""
diff --git a/po/uk_UA.po b/po/uk_UA.po
new file mode 100644
index 0000000000..fdbfcb89a4
--- /dev/null
+++ b/po/uk_UA.po
@@ -0,0 +1,1433 @@
+# Ukrainian translation for ScummVM.
+# Copyright (C) 2010 ScummVM
+# This file is distributed under the same license as the ScummVM package.
+# Lubomyr Lisen , 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ScummVM VERSION\n"
+"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
+"POT-Creation-Date: 2010-07-30 22:14+0100\n"
+"PO-Revision-Date: 2010-07-30 22:19+0100\n"
+"Last-Translator: Lubomyr Lisen\n"
+"Language-Team: Ukrainian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-5\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: Ukrainian\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+#: gui/about.cpp:96
+#, c-format
+msgid "(built on %s)"
+msgstr "(×öÑàÐÝØÙ %s)"
+
+#: gui/about.cpp:103
+msgid "Features compiled in:"
+msgstr "²ÚÛîçÕÝö Ò ÑöÛÔ Þßæö÷:"
+
+#: gui/about.cpp:112
+msgid "Available engines:"
+msgstr "´ÞáâãßÝö ÔÒØÖÚØ:"
+
+#: gui/browser.cpp:69
+msgid "Go up"
+msgstr "²ÒÕàå"
+
+#: gui/browser.cpp:69
+msgid "Go to previous directory level"
+msgstr "¿ÕàÕÙâØ ÝÐ ßÐßÚã àöÒÝÕÜ ÒØéÕ"
+
+#: gui/browser.cpp:70
+#: gui/chooser.cpp:49
+#: gui/KeysDialog.cpp:46
+#: gui/launcher.cpp:280
+#: gui/massadd.cpp:95
+#: gui/options.cpp:1029
+#: gui/saveload.cpp:65
+#: gui/saveload.cpp:157
+#: gui/themebrowser.cpp:56
+#: backends/platform/wii/options.cpp:48
+msgid "Cancel"
+msgstr "²öÔÜöÝÐ"
+
+#: gui/browser.cpp:71
+#: gui/chooser.cpp:50
+#: gui/themebrowser.cpp:57
+msgid "Choose"
+msgstr "²ØÑàÐâØ"
+
+#: gui/GuiManager.cpp:103
+#: backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "·ÐÚàØâØ"
+
+#: gui/GuiManager.cpp:106
+msgid "Mouse click"
+msgstr "ºÛöÚ ÜØèÚÞî"
+
+#: gui/GuiManager.cpp:109
+#: base/main.cpp:285
+msgid "Display keyboard"
+msgstr "¿ÞÚÐ×ÐâØ ÚÛÐÒöÐâãàã"
+
+#: gui/GuiManager.cpp:112
+#: base/main.cpp:288
+msgid "Remap keys"
+msgstr "¿ÕàÕßàØ×ÝÐçØâØ ÚÛÐÒöèö"
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr "¿àØ×ÝÐçØâØ"
+
+#: gui/KeysDialog.cpp:45
+#: gui/launcher.cpp:281
+#: gui/launcher.cpp:893
+#: gui/launcher.cpp:897
+#: gui/massadd.cpp:92
+#: gui/options.cpp:1030
+#: backends/platform/wii/options.cpp:47
+#: backends/platform/wince/CELauncherDialog.cpp:56
+msgid "OK"
+msgstr "OK"
+
+#: gui/KeysDialog.cpp:52
+msgid "Select an action and click 'Map'"
+msgstr "²ØÑÕàöâì Ôöî ö ÚÛöÚÝöâì '¿àØ×ÝÐçØâØ'"
+
+#: gui/KeysDialog.cpp:83
+#: gui/KeysDialog.cpp:105
+#: gui/KeysDialog.cpp:144
+#, c-format
+msgid "Associated key : %s"
+msgstr "¿àØ×ÝÐçÕÝÐ ÚÛÐÒöèÐ : %s"
+
+#: gui/KeysDialog.cpp:85
+#: gui/KeysDialog.cpp:107
+#: gui/KeysDialog.cpp:146
+#, c-format
+msgid "Associated key : none"
+msgstr "¿àØ×ÝÐçÕÝÐ ÚÛÐÒöèÐ : ÝÕÜÐô"
+
+#: gui/KeysDialog.cpp:93
+msgid "Please select an action"
+msgstr "±ãÔì ÛÐáÚÐ, ÒØÑÕàöâì Ôöî"
+
+#: gui/KeysDialog.cpp:109
+msgid "Press the key to associate"
+msgstr "½ÐâØáÝöâì ÚÛÐÒöèã ÔÛï ßàØ×ÝÐçÕÝÝï"
+
+#: gui/KeysDialog.cpp:148
+msgid "Choose an action to map"
+msgstr "²ØÑÕàöâì Ôöî ÔÛï ßàØ×ÝÐçÕÝÝï"
+
+#: gui/launcher.cpp:172
+msgid "Game"
+msgstr "³àÐ"
+
+#: gui/launcher.cpp:175
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:175
+#: gui/launcher.cpp:176
+msgid "Short game identifier used for referring to savegames and running the game from the command line"
+msgstr "ºÞàÞâÚØÙ öÔÕÝâØäöÚÐâÞà, ïÚØÙ ÒØÚÞàØáâÞÒãôâìáï ÔÛï ÝÐ×Ò ×ÑÕàÕÖÕÝØå öÓÞà ö ÔÛï ×ÐßãáÚã × ÚÞÜÐÝÔÝÞ÷ áâàöçÚØ"
+
+#: gui/launcher.cpp:179
+msgid "Name:"
+msgstr "½Ð×ÒÐ:"
+
+#: gui/launcher.cpp:179
+#: gui/launcher.cpp:180
+msgid "Full title of the game"
+msgstr "¿ÞÒÝÐ ÝÐ×ÒÐ ÓàØ"
+
+#: gui/launcher.cpp:183
+msgid "Language:"
+msgstr "¼ÞÒÐ:"
+
+#: gui/launcher.cpp:183
+#: gui/launcher.cpp:184
+msgid "Language of the game. This will not turn your Spanish game version into English"
+msgstr "¼ÞÒÐ ÓàØ. ·ÜöÝÐ æìÞÓÞ ßÐàÐÜÕâàã ÝÕ ßÕàÕâÒÞàØâì Óàã ÝÐ ÐÝÓÛöÙáìÚöÙ Ò ãÚàÐ÷ÝáìÚã"
+
+#: gui/launcher.cpp:185
+#: gui/launcher.cpp:196
+#: gui/options.cpp:80
+#: gui/options.cpp:635
+#: gui/options.cpp:645
+#: gui/options.cpp:1000
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<×Ð ãÜÞÒçÐÝÝïÜ>"
+
+#: gui/launcher.cpp:194
+msgid "Platform:"
+msgstr "¿ÛÐâäÞàÜÐ:"
+
+#: gui/launcher.cpp:194
+#: gui/launcher.cpp:195
+msgid "Platform the game was originally designed for"
+msgstr "¿ÛÐâäÞàÜÐ, ÔÛï ïÚÞ÷ ÓàÐ ÑãÛÐ áßÞçÐâÚã àÞ×àÞÑÛÕÝÐ"
+
+#: gui/launcher.cpp:206
+#: gui/options.cpp:898
+#: gui/options.cpp:915
+msgid "Graphics"
+msgstr "³àÐäöÚÐ"
+
+#: gui/launcher.cpp:206
+#: gui/options.cpp:898
+#: gui/options.cpp:915
+msgid "GFX"
+msgstr "³àä"
+
+#: gui/launcher.cpp:208
+msgid "Override global graphic settings"
+msgstr "¿ÕàÕÚàØâØ ÓÛÞÑÐÛìÝö ãáâÐÝÞÒÚØ ÓàÐäöÚØ"
+
+#: gui/launcher.cpp:215
+#: gui/options.cpp:921
+msgid "Audio"
+msgstr "°ãÔöÞ"
+
+#: gui/launcher.cpp:217
+msgid "Override global audio settings"
+msgstr "¿ÕàÕÚàØâØ ÓÛÞÑÐÛìÝö ãáâÐÝÞÒÚØ ÐãÔöÞ"
+
+#: gui/launcher.cpp:225
+#: gui/options.cpp:925
+msgid "Volume"
+msgstr "³ãçÝöáâì"
+
+#: gui/launcher.cpp:227
+msgid "Override global volume settings"
+msgstr "¿ÕàÕÚàØâØ ÓÛÞÑÐÛìÝö ãáâÐÝÞÒÚØ ÓãçÝÞáâö"
+
+#: gui/launcher.cpp:234
+#: gui/options.cpp:933
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:236
+msgid "Override global MIDI settings"
+msgstr "¿ÕàÕÚàØâØ ÓÛÞÑÐÛìÝö ãáâÐÝÞÒÚØ MIDI"
+
+#: gui/launcher.cpp:246
+#: gui/options.cpp:939
+#, fuzzy
+msgid "MT-32"
+msgstr "MT-32"
+
+#: gui/launcher.cpp:248
+#, fuzzy
+msgid "Override global MT-32 settings"
+msgstr "¿ÕàÕÚàØâØ ÓÛÞÑÐÛìÝö ãáâÐÝÞÒÚØ MT-32"
+
+#: gui/launcher.cpp:258
+#: gui/options.cpp:945
+msgid "Paths"
+msgstr "ÈÛïåØ"
+
+#: gui/launcher.cpp:264
+msgid "Game Path:"
+msgstr "ÈÛïå ÔÞ ÓàØ: "
+
+#: gui/launcher.cpp:268
+#: gui/options.cpp:958
+msgid "Extra Path:"
+msgstr "´ÞÔ. èÛïå:"
+
+#: gui/launcher.cpp:268
+#: gui/launcher.cpp:269
+msgid "Specifies path to additional data used the game"
+msgstr "²ÚÐ×ãô èÛïå ÔÞ ÔÞÔÐâÚÞÒØå äÐÙÛöÒ ÔÐÝØå ÔÛï ÓàØ"
+
+#: gui/launcher.cpp:272
+msgid "Save Path:"
+msgstr "ÈÛïå ×ÑÕà.: "
+
+#: gui/launcher.cpp:272
+#: gui/launcher.cpp:273
+#: gui/options.cpp:952
+#: gui/options.cpp:953
+msgid "Specifies where your savegames are put"
+msgstr "²ÚÐ×ãô èÛïå ÔÞ ×ÑÕàÕÖÕÝì ÓàØ"
+
+#: gui/launcher.cpp:289
+#: gui/launcher.cpp:369
+#: gui/launcher.cpp:418
+#: gui/options.cpp:230
+#: gui/options.cpp:399
+#: gui/options.cpp:497
+#: gui/options.cpp:555
+#: gui/options.cpp:732
+#: gui/options.cpp:956
+#: gui/options.cpp:959
+#: gui/options.cpp:963
+#: gui/options.cpp:1053
+#: gui/options.cpp:1059
+#: gui/options.cpp:1065
+#: gui/options.cpp:1073
+#: gui/options.cpp:1097
+#: gui/options.cpp:1101
+#: gui/options.cpp:1107
+#: gui/options.cpp:1114
+#: gui/options.cpp:1213
+msgid "None"
+msgstr "½Õ ×ÐÔÐÝØÙ"
+
+#: gui/launcher.cpp:294
+#: gui/launcher.cpp:373
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "·Ð ãÜÞÒçÐÝÝïÜ"
+
+#: gui/launcher.cpp:411
+#: gui/options.cpp:1207
+msgid "Select SoundFont"
+msgstr "²ØÑÕàöâì SoundFont"
+
+#: gui/launcher.cpp:430
+#: gui/launcher.cpp:568
+msgid "Select directory with game data"
+msgstr "²ØÑÕàöâì ßÐßÚã × äÐÙÛÐÜØ ÓàØ"
+
+#: gui/launcher.cpp:448
+msgid "Select additional game directory"
+msgstr "²ØÑÕàöâì ÔÞÔÐâÚÞÒã ßÐßÚã ÓàØ"
+
+#: gui/launcher.cpp:460
+msgid "Select directory for saved games"
+msgstr "²ØÑÕàöâì ßÐßÚã ÔÛï ×ÑÕàÕÖÕÝì"
+
+#: gui/launcher.cpp:479
+msgid "This game ID is already taken. Please choose another one."
+msgstr "ÆÕÙ ID ÓàØ ÒÖÕ ÒØÚÞàØáâÞÒãôâìáï. ±ãÔì ÛÐáÚÐ, ÒØÑÕàöâì öÝèØÙ."
+
+#: gui/launcher.cpp:520
+#: engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "~²~ØåöÔ"
+
+#: gui/launcher.cpp:520
+msgid "Quit ScummVM"
+msgstr "²ØåöÔ × ScummVM"
+
+#: gui/launcher.cpp:521
+msgid "A~b~out..."
+msgstr "¿àÞ ß~à~ÞÓàÐÜã..."
+
+#: gui/launcher.cpp:521
+msgid "About ScummVM"
+msgstr "¿àÞ ScummVM"
+
+#: gui/launcher.cpp:522
+msgid "~O~ptions..."
+msgstr "~¾~ßæö÷..."
+
+#: gui/launcher.cpp:522
+msgid "Change global ScummVM options"
+msgstr "·ÜöÝØâØ ÓÛÞÑÐÛìÝö Þßæö÷ ScummVM"
+
+#: gui/launcher.cpp:524
+msgid "~S~tart"
+msgstr "·~Ð~ßãáÚ"
+
+#: gui/launcher.cpp:524
+msgid "Start selected game"
+msgstr "·ÐßãáâØâØ ÒØÑàÐÝã Óàã"
+
+#: gui/launcher.cpp:527
+msgid "~L~oad..."
+msgstr "~·~ÐÒÐÝ..."
+
+#: gui/launcher.cpp:527
+msgid "Load savegame for selected game"
+msgstr "·ÐÒÐÝâÐÖØâØ ×ÑÕàÕÖÕÝÝï ÔÛï ÒØÑàÐÝÞ÷ ÓàØ"
+
+#: gui/launcher.cpp:531
+msgid "~A~dd Game..."
+msgstr "~´~ÞÔ. Óàã..."
+
+#: gui/launcher.cpp:531
+msgid "Hold Shift for Mass Add"
+msgstr "ÃâàØÜãÙâÕ ÚÛÐÒöèã Shift ÔÛï âÞÓÞ, éÞÑ ÔÞÔÐâØ ÔÕÚöÛìÚÐ öÓÞà"
+
+#: gui/launcher.cpp:533
+msgid "~E~dit Game..."
+msgstr "ÀÕÔÐ~Ó~. Óàã..."
+
+#: gui/launcher.cpp:533
+msgid "Change game options"
+msgstr "·ÜöÝØâØ Þßæö÷ ÓàØ"
+
+#: gui/launcher.cpp:535
+msgid "~R~emove Game"
+msgstr "~²~ØÔÐÛØâØ Óàã"
+
+#: gui/launcher.cpp:535
+msgid "Remove game from the list. The game data files stay intact"
+msgstr "²ØÔÐÛØâØ Óàã ×ö áßØáÚã. ½Õ ÒØÔÐÛïô Óàã × ÖÞàáâÚÞÓÞ ÔØáÚÐ"
+
+#: gui/launcher.cpp:542
+msgid "Search in game list"
+msgstr "¿ÞèãÚ Ò áßØáÚã öÓÞà"
+
+#: gui/launcher.cpp:546
+#: gui/launcher.cpp:1057
+msgid "Search:"
+msgstr "¿ÞèãÚ:"
+
+#: gui/launcher.cpp:549
+#: gui/options.cpp:733
+msgid "Clear value"
+msgstr "¾çØáâØâØ ×ÝÐçÕÝÝï"
+
+#: gui/launcher.cpp:571
+#: engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "·ÐÒÐÝâÐÖØâØ Óàã:"
+
+#: gui/launcher.cpp:571
+#: engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "·ÐÒÐÝâÐÖØâØ"
+
+#: gui/launcher.cpp:680
+msgid "Do you really want to run the mass game detector? This could potentially add a huge number of games."
+msgstr "²Ø ÔöÙáÝÞ åÞçÕâÕ ×ÐßãáâØâØ ÔÕâÕÚâÞà ãáöå öÓÞà? ÆÕ ßÞâÕÝæöÙÝÞ ÜÞÖÕ ÔÞÔÐâØ ÒÕÛØÚã ÚöÛìÚöáâì öÓÞà."
+
+#: gui/launcher.cpp:681
+#: gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Yes"
+msgstr "ÂÐÚ"
+
+#: gui/launcher.cpp:681
+#: gui/launcher.cpp:830
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "No"
+msgstr "½ö"
+
+#: gui/launcher.cpp:728
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM ÝÕ ÜÞÖÕ ÒöÔÚàØâØ ÒÚÐ×ÐÝã ßÐßÚã!"
+
+#: gui/launcher.cpp:740
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr "ScummVM ÝÕ ÜÞÖÕ ×ÝÐÙâØ Óàã ã ÒÚÐ×ÐÝöÙ ßÐßæö!"
+
+#: gui/launcher.cpp:754
+msgid "Pick the game:"
+msgstr "²ØÑÕàöâì Óàã:"
+
+#: gui/launcher.cpp:830
+msgid "Do you really want to remove this game configuration?"
+msgstr "²Ø ÔöÙáÝÞ åÞçÕâÕ ÒØÔÐÛØâØ ãáâÐÝÞÒÚØ ÔÛï æöô÷ ÓàØ?"
+
+#: gui/launcher.cpp:893
+msgid "This game does not support loading games from the launcher."
+msgstr "Æï ÓàÐ ÝÕ ßöÔâàØÜãô ×ÐÒÐÝâÐÖÕÝÝï ×ÑÕàÕÖÕÝì çÕàÕ× ÓÞÛÞÒÝÕ ÜÕÝî."
+
+#: gui/launcher.cpp:897
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr "ScummVM ÝÕ ×ÜöÓ ×ÝÐÙâØ ÔÒØÖÞÚ ÔÛï ×ÐßãáÚã ÒØÑàÐÝÞ÷ ÓàØ!"
+
+#: gui/launcher.cpp:1009
+msgid "Mass Add..."
+msgstr "´ÞÔ. ÑÐÓÐâÞ..."
+
+#: gui/launcher.cpp:1010
+msgid "Add Game..."
+msgstr "´ÞÔ. Óàã..."
+
+#: gui/massadd.cpp:79
+#: gui/massadd.cpp:82
+msgid "... progress ..."
+msgstr "... ßÞèãÚ ..."
+
+#: gui/massadd.cpp:244
+msgid "Scan complete!"
+msgstr "¿ÞèãÚ ×ÐÚöÝçÕÝØÙ!"
+
+#: gui/massadd.cpp:247
+#, c-format
+msgid "Discovered %d new games."
+msgstr "·ÝÐÙÔÕÝÞ %d ÝÞÒØå öÓÞà."
+
+#: gui/massadd.cpp:251
+#, c-format
+msgid "Scanned %d directories ..."
+msgstr "¿àÞÓÛïÝãâÞ %d ßÐßÞÚ ..."
+
+#: gui/massadd.cpp:254
+#, c-format
+msgid "Discovered %d new games ..."
+msgstr "·ÝÐÙÔÕÝÞ %d ÝÞÒØå öÓÞà ..."
+
+#: gui/options.cpp:78
+msgid "Never"
+msgstr "½öÚÞÛØ"
+
+#: gui/options.cpp:78
+msgid "every 5 mins"
+msgstr "ÚÞÖÝö 5 åÒ"
+
+#: gui/options.cpp:78
+msgid "every 10 mins"
+msgstr "ÚÞÖÝö 10 åÒ"
+
+#: gui/options.cpp:78
+msgid "every 15 mins"
+msgstr "ÚÞÖÝö 15 åÒ"
+
+#: gui/options.cpp:78
+msgid "every 30 mins"
+msgstr "ÚÞÖÝö 30 åÒ"
+
+#: gui/options.cpp:80
+msgid "8 kHz"
+msgstr "8 Ú³æ"
+
+#: gui/options.cpp:80
+msgid "11kHz"
+msgstr "11 Ú³æ"
+
+#: gui/options.cpp:80
+msgid "22 kHz"
+msgstr "22 Ú³æ"
+
+#: gui/options.cpp:80
+msgid "44 kHz"
+msgstr "44 Ú³æ"
+
+#: gui/options.cpp:80
+msgid "48 kHz"
+msgstr "48 Ú³æ"
+
+#: gui/options.cpp:632
+msgid "Graphics mode:"
+msgstr "³àÐäöçÝØÙ àÕÖØÜ:"
+
+#: gui/options.cpp:643
+msgid "Render mode:"
+msgstr "ÀÕÖØÜ àÐáâàãÒÐÝÝï:"
+
+#: gui/options.cpp:643
+#: gui/options.cpp:644
+msgid "Special dithering modes supported by some games"
+msgstr "ÁßÕæöÐÛìÝö àÕÖØÜØ àÕÝÔÕàØÝÓã, ïÚö ßöÔâàØÜãîâì ÔÕïÚö öÓàØ"
+
+#: gui/options.cpp:653
+msgid "Fullscreen mode"
+msgstr "¿ÞÒÝÞÕÚàÐÝÝØÙ àÕÖØÜ"
+
+#: gui/options.cpp:656
+msgid "Aspect ratio correction"
+msgstr "ºÞàÕÚæöï áßöÒÒöÔÝÞèÕÝÝï áâÞàöÝ"
+
+#: gui/options.cpp:656
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "ºÞàØÓãÒÐâØ áßöÒÒöÔÝÞèÕÝÝï áâÞàöÝ ÔÛï öÓÞà × ÓàÐäöÚÞî 320x200"
+
+#: gui/options.cpp:663
+msgid "Preferred Device:"
+msgstr "¿àØáâàöÙ ïÚÞÜã ÒöÔÔÐôâìáï ßÕàÕÒÐÓÐ:"
+
+#: gui/options.cpp:663
+#, fuzzy
+msgid "Music Device:"
+msgstr "¼ã×ØçÝØÙ ¿àØáâàöÙ:"
+
+#: gui/options.cpp:663
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr "²ÚÐ×ãô ÒØåöÔÝØÙ ×ÒãÚÞÒØÙ ßàØáâàöÙ ÐÑÞ ÕÜãÛïâÞà ×ÒãÚÞÒÞ÷ ÚÐàâØ"
+
+#: gui/options.cpp:663
+#: gui/options.cpp:664
+msgid "Specifies output sound device or sound card emulator"
+msgstr "²ÚÐ×ãô ÒØåöÔÝØÙ ×ÒãÚÞÒØÙ ßàØáâàöÙ ÐÑÞ ÕÜãÛïâÞà ×ÒãÚÞÒÞ÷ ÚÐàâØ"
+
+#: gui/options.cpp:688
+msgid "AdLib emulator:"
+msgstr "µÜãÛïâÞà AdLib:"
+
+#: gui/options.cpp:688
+#: gui/options.cpp:689
+msgid "AdLib is used for music in many games"
+msgstr "·ÒãÚÞÒÐ ÚÐàâÐ AdLib ÒØÚÞàØáâÞÒãôâìáï ÑÐÓÐâìÜÐ öÓàÐÜØ"
+
+#: gui/options.cpp:699
+msgid "Output rate:"
+msgstr "²ØåöÔÝÐ çÐáâÞâÐ:"
+
+#: gui/options.cpp:699
+#: gui/options.cpp:700
+msgid "Higher value specifies better sound quality but may be not supported by your soundcard"
+msgstr "²ÕÛØÚö ×ÝÐçÕÝÝï ×ÐÔÐîâì ÚàÐéã ïÚöáâì ×ÒãÚã, ßàÞâÕ ÒÞÝØ ÜÞÖãâì ÝÕ ßöÔâàØÜãÒÐâØáï ÒÐèÞî ×ÒãÚÞÒÞî ÚÐàâÞî"
+
+#: gui/options.cpp:710
+msgid "GM Device:"
+msgstr "¿àØáâàöÙ GM:"
+
+#: gui/options.cpp:710
+msgid "Specifies default sound device for General MIDI output"
+msgstr "²ÚÐ×ãô ÒØåöÔÝØÙ ×ÒãÚÞÒØÙ ßàØáâàöÙ ÔÛï MIDI"
+
+#: gui/options.cpp:731
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:731
+#: gui/options.cpp:732
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr "SoundFont ßöÔâàØÜãôâìáï ÔÕïÚØÜØ ×ÒãÚÞÒØÜØ ÚÐàâÐÜØ, Fluidsynth ö Timidity"
+
+#: gui/options.cpp:736
+msgid "Mixed AdLib/MIDI mode"
+msgstr "·ÜöèÐÝØÙ àÕÖØÜ AdLib/MIDI"
+
+#: gui/options.cpp:736
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "²ØÚÞàØáâÞÒãÒÐâØ ö MIDI ö AdLib ÔÛï ÓÕÝÕàÐæö÷ ×ÒãÚã"
+
+#: gui/options.cpp:739
+msgid "MIDI gain:"
+msgstr "¿ÞáØÛÕÝÝï MIDI:"
+
+#: gui/options.cpp:749
+#, fuzzy
+msgid "MT-32 Device:"
+msgstr "¿àØáâàöÙ MT-32:"
+
+#: gui/options.cpp:749
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr "²ÚÐ×ãô ×ÒãÚÞÒØÙ ßàØáâàöÙ ßÞ ãÜÞÒçÐÝÝî ÔÛï ÒØÒÞÔã ÝÐ Roland MT-32/LAPC1/CM32l/CM64"
+
+#: gui/options.cpp:753
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "ÁßàÐÒÖÝöÙ Roland MT-32 (ÒØÜÚÝãâØ ÕÜãÛïæØî GM)"
+
+#: gui/options.cpp:753
+msgid "Check if you want to use your real hardware Roland-compatible sound device connected to your computer"
+msgstr "²öÔÜöâìâÕ, ïÚéÞ ã ÒÐá ßöÔÚÛîçÕÝØÙ Roland-áãÜöáÝØÙ ×ÒãÚÞÒØÙ ßàØáâàöÙ ö ÒØ åÞçÕâÕ ÙÞÓÞ ÒØÚÞàØáâÐâØ"
+
+#: gui/options.cpp:756
+msgid "Enable Roland GS Mode"
+msgstr "ÃÒöÜÚÝãâØ àÕÖØÜ Roland GS"
+
+#: gui/options.cpp:756
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr "²ØÜØÚÐô ÜÐßßöÝÓ General MIDI ÔÛï öÓÞà ö× ×ÒãÚÞÒÞî ÔÞàöÖÚÞî ÔÛï Roland MT-32"
+
+#: gui/options.cpp:780
+msgid "Text and Speech:"
+msgstr "ÂÕÚáâ ö Þ×ÒãçÕÝÝï:"
+
+#: gui/options.cpp:785
+#: gui/options.cpp:791
+msgid "Speech"
+msgstr "¾×ÒãçÕÝÝï"
+
+#: gui/options.cpp:786
+#: gui/options.cpp:792
+msgid "Subtitles"
+msgstr "ÁãÑâØâàØ"
+
+#: gui/options.cpp:787
+#: gui/options.cpp:793
+msgid "Both"
+msgstr "²áÕ"
+
+#: gui/options.cpp:791
+msgid "Spch"
+msgstr "¾×Ò"
+
+#: gui/options.cpp:792
+msgid "Subs"
+msgstr "狄"
+
+#: gui/options.cpp:793
+msgid "Show subtitles and play speech"
+msgstr "¿ÞÚÐ×ãÒÐâØ áãÑâØâàØ ö ÒöÔâÒÞàîÒÐâØ ÜÞÒã"
+
+#: gui/options.cpp:797
+msgid "Subtitle speed:"
+msgstr "ÈÒØÔÚöáâì áãÑâØâàöÒ:"
+
+#: gui/options.cpp:809
+msgid "Music volume:"
+msgstr "³ãçÝöáâì Üã×ØÚØ:"
+
+#: gui/options.cpp:816
+msgid "Mute All"
+msgstr "²ØÜÚÝãâØ ãáÕ"
+
+#: gui/options.cpp:819
+msgid "SFX volume:"
+msgstr "³ãçÝöáâì ÕäÕÚâöÒ:"
+
+#: gui/options.cpp:819
+#: gui/options.cpp:820
+msgid "Special sound effects volume"
+msgstr "³ãçÝöáâì áßÕæöÐÛìÝØå ×ÒãÚÞÒØå ÕäÕÚâöÒ"
+
+#: gui/options.cpp:826
+msgid "Speech volume:"
+msgstr "³ãçÝöáâì Þ×ÒãçÕÝÝï:"
+
+#: gui/options.cpp:952
+msgid "Save Path: "
+msgstr "ÈÛïå ÔÛï ×ÑÕàÕÖÕÝì: "
+
+#: gui/options.cpp:955
+msgid "Theme Path:"
+msgstr "ÈÛïå ÔÞ âÕÜ:"
+
+#: gui/options.cpp:958
+#: gui/options.cpp:959
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr "²ÚÐ×ãô èÛïå ÔÞ ÔÞÔÐâÚÞÒØå äÐÙÛöÒ ÔÐÝØå, ÒØÚÞàØáâÞÒãÒÐÝØå ãáöÜÐ öÓàÐÜØ, ÐÑÞ ScummVM"
+
+#: gui/options.cpp:962
+msgid "Plugins Path:"
+msgstr "ÈÛïå ÔÞ ßÛÐÓöÝöÒ:"
+
+#: gui/options.cpp:970
+msgid "Misc"
+msgstr "Àö×ÝÕ"
+
+#: gui/options.cpp:972
+msgid "Theme:"
+msgstr "ÂÕÜÐ:"
+
+#: gui/options.cpp:976
+msgid "GUI Renderer:"
+msgstr "ÀÐáâÕàØ×ÐâÞà GUI:"
+
+#: gui/options.cpp:982
+msgid "Autosave:"
+msgstr "°ÒâÞ×ÑÕàÕÖÕÝÝï:"
+
+#: gui/options.cpp:990
+msgid "Keys"
+msgstr "ºÛÐÒöèö"
+
+#: gui/options.cpp:997
+msgid "GUI Language:"
+msgstr "¼ÞÒÐ öÝâÕàäÕÙáã:"
+
+#: gui/options.cpp:997
+msgid "Language of ScummVM GUI"
+msgstr "¼ÞÒÐ ÓàÐäöçÝÞÓÞ öÝâÕàäÕÙáã ScummVM"
+
+#: gui/options.cpp:1002
+msgid "English"
+msgstr "English"
+
+#: gui/options.cpp:1146
+msgid "You have to restart ScummVM to take the effect."
+msgstr "²Ø ßÞÒØÝÝö ßÕàÕ×ÐßãáâØâØ ScummVM éÞÑ ×ÐáâÞáãÒÐâØ ×ÜöÝØ."
+
+#: gui/options.cpp:1159
+msgid "Select directory for savegames"
+msgstr "²ØÑÕàöâì ßÐßÚã ÔÛï ×ÑÕàÕÖÕÝì"
+
+#: gui/options.cpp:1166
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr "½Õ ÜÞÖã ßØáÐâØ ã ÒØÑàÐÝã ßÐßÚã. ±ãÔì ÛÐáÚÐ, ÒÚÐÖöâì öÝèã."
+
+#: gui/options.cpp:1175
+msgid "Select directory for GUI themes"
+msgstr "²ØÑÕàöâì ßÐßÚã ÔÛï âÕÜ GUI"
+
+#: gui/options.cpp:1185
+msgid "Select directory for extra files"
+msgstr "²ØÑÕàöâì ßÐßÚã × ÔÞÔÐâÚÞÒØÜØ äÐÙÛÐÜØ"
+
+#: gui/options.cpp:1196
+msgid "Select directory for plugins"
+msgstr "²ØÑÕàöâì ßÐßÚã × ßÛÐÓØÝÐÜØ"
+
+#: gui/saveload.cpp:60
+#: gui/saveload.cpp:241
+msgid "No date saved"
+msgstr "´ÐâÐ ÝÕ ×ÐßØáÐÝÐ"
+
+#: gui/saveload.cpp:61
+#: gui/saveload.cpp:242
+msgid "No time saved"
+msgstr "ÇÐá ÝÕ ×ÐßØáÐÝØÙ"
+
+#: gui/saveload.cpp:62
+#: gui/saveload.cpp:243
+msgid "No playtime saved"
+msgstr "ÇÐá ÓàØ ÝÕ ×ÐßØáÐÝÞ"
+
+#: gui/saveload.cpp:69
+#: gui/saveload.cpp:157
+msgid "Delete"
+msgstr "²ØÔÐÛØâØ"
+
+#: gui/saveload.cpp:156
+msgid "Do you really want to delete this savegame?"
+msgstr "²Ø ÔöÙáÝÞ åÞçÕâÕ ÒØÔÐÛØâØ æÕ ×ÑÕàÕÖÕÝÝï?"
+
+#: gui/saveload.cpp:265
+msgid "Date: "
+msgstr "´ÐâÐ: "
+
+#: gui/saveload.cpp:268
+msgid "Time: "
+msgstr "ÇÐá: "
+
+#: gui/saveload.cpp:273
+msgid "Playtime: "
+msgstr "ÇÐá ÓàØ: "
+
+#: gui/saveload.cpp:286
+#: gui/saveload.cpp:353
+msgid "Untitled savestate"
+msgstr "·ÑÕàÕÖÕÝÝï ÑÕ× öÜÕÝö"
+
+#: gui/themebrowser.cpp:46
+msgid "Select a Theme"
+msgstr "²ØÑÕàöâì âÕÜã"
+
+#: gui/ThemeEngine.cpp:334
+msgid "Disabled GFX"
+msgstr "±Õ× ÓàÐäöÚØ"
+
+#: gui/ThemeEngine.cpp:335
+msgid "Standard Renderer (16bpp)"
+msgstr "ÁâÐÝÔÐàâÝØÙ àÐáâÕàØ×ÐâÞà (16bpp)"
+
+#: gui/ThemeEngine.cpp:337
+msgid "Antialiased Renderer (16bpp)"
+msgstr "ÀÐáâÕàØ×ÐâÞà ×ö ×ÓÛÐÔÖãÒÐÝÝïÜ (16bpp)"
+
+#: base/main.cpp:205
+#, c-format
+msgid "Engine does not support debug level '%s'"
+msgstr "´ÒØÖÞÚ ÝÕ ßöÔâàØÜãô àöÒÕÝì ÒöÔÛÐÔÚØ '%s'"
+
+#: base/main.cpp:273
+msgid "Menu"
+msgstr "¼ÕÝî"
+
+#: base/main.cpp:276
+#: backends/platform/symbian/src/SymbianActions.cpp:48
+#: backends/platform/wince/CEActionsPocket.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:45
+msgid "Skip"
+msgstr "¿àÞßãáâØâØ"
+
+#: base/main.cpp:279
+#: backends/platform/symbian/src/SymbianActions.cpp:53
+#: backends/platform/wince/CEActionsPocket.cpp:41
+msgid "Pause"
+msgstr "¿Ðã×Ð"
+
+#: base/main.cpp:282
+msgid "Skip line"
+msgstr "¿àÞßãáâØâØ àïÔÞÚ"
+
+#: base/main.cpp:404
+msgid "Error running game:"
+msgstr "¿ÞÜØÛÚÐ ×ÐßãáÚã ÓàØ:"
+
+#: base/main.cpp:430
+#: base/main.cpp:431
+msgid "Could not find any engine capable of running the selected game"
+msgstr "½Õ ÜÞÖã ×ÝÐÙâØ ÔÒØÖÞÚ ÔÛï ×ÐßãáÚã ÒØÑàÐÝÞ÷ ÓàØ"
+
+#: common/error.cpp:43
+msgid "Invalid Path"
+msgstr "½ÕßàÐÒØÛìÝØÙ èÛïå"
+
+#: common/error.cpp:44
+msgid "Game Data not found"
+msgstr "½ÕÜÐô äÐÙÛöÒ ÓàØ"
+
+#: common/error.cpp:45
+msgid "Game Id not supported"
+msgstr "Game Id ÝÕ ßöÔâàØÜãôâìáï"
+
+#: common/error.cpp:46
+msgid "Unsupported Color Mode"
+msgstr "ÀÕÖØÜ ºÞÛìÞàã ÝÕ ßöÔâàØÜãôâìáï"
+
+#: common/error.cpp:48
+msgid "Read permission denied"
+msgstr "½ÕÔÞáâÐâÝìÞ ßàÐÒ ÔÛï çØâÐÝÝï"
+
+#: common/error.cpp:49
+msgid "Write permission denied"
+msgstr "½ÕÔÞáâÐâÝìÞ ßàÐÒ ÔÛï ×ÐßØáã"
+
+#: common/error.cpp:52
+msgid "Path not exists"
+msgstr "ÈÛïå ÝÕ ×ÝÐÙÔÕÝØÙ"
+
+#: common/error.cpp:53
+msgid "Path not a directory"
+msgstr "ÈÛïå ÝÕ ô ßÐßÚÞî"
+
+#: common/error.cpp:54
+msgid "Path not a file"
+msgstr "ÈÛïå ÝÕ ô äÐÙÛÞÜ"
+
+#: common/error.cpp:56
+msgid "Cannot create file"
+msgstr "½Õ ÜÞÖã áâÒÞàØâØ äÐÙÛ"
+
+#: common/error.cpp:57
+msgid "Reading failed"
+msgstr "¿ÞÜØÛÚÐ çØâÐÝÝï"
+
+#: common/error.cpp:58
+msgid "Writing data failed"
+msgstr "¿ÞÜØÛÚÐ ×ÐßØáã ÔÐÝØå"
+
+#: common/error.cpp:60
+#: common/error.cpp:71
+msgid "Unknown Error"
+msgstr "½ÕÒöÔÞÜÐ ßÞÜØÛÚÐ"
+
+#: common/util.cpp:254
+msgid "Hercules Green"
+msgstr "Hercules ·ÕÛÕÝØÙ"
+
+#: common/util.cpp:255
+msgid "Hercules Amber"
+msgstr "Hercules ÏÝâÐàÝØÙ"
+
+#: engines/dialogs.cpp:89
+msgid "~R~esume"
+msgstr "¿àÞÔÞÒ~Ö~ØâØ"
+
+#: engines/dialogs.cpp:91
+msgid "~L~oad"
+msgstr "~·~ÐÒÐÝâÐÖØâØ"
+
+#: engines/dialogs.cpp:95
+msgid "~S~ave"
+msgstr "~·~ÐßØáÐâØ"
+
+#: engines/dialogs.cpp:99
+msgid "~O~ptions"
+msgstr "~¾~ßæö÷"
+
+#: engines/dialogs.cpp:104
+msgid "~H~elp"
+msgstr "~´~ÞßÞÜÞÓÐ"
+
+#: engines/dialogs.cpp:107
+msgid "~A~bout"
+msgstr "¿àÞ ßàÞ~Ó~àÐÜã"
+
+#: engines/dialogs.cpp:109
+msgid "~R~eturn to Launcher"
+msgstr "~¿~ÞÒÕàÝãâØáì Ò ÓÞÛÞÒÝÕ ÜÕÝî"
+
+#: engines/dialogs.cpp:119
+msgid "Save game:"
+msgstr "·ÑÕàÕÓâØ Óàã: "
+
+#: engines/dialogs.cpp:119
+#: backends/platform/symbian/src/SymbianActions.cpp:47
+#: backends/platform/wince/CEActionsPocket.cpp:42
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Save"
+msgstr "·ÐßØáÐâØ"
+
+#: engines/dialogs.cpp:301
+#: engines/mohawk/dialogs.cpp:84
+#: engines/mohawk/dialogs.cpp:118
+msgid "~O~K"
+msgstr "~O~K"
+
+#: engines/dialogs.cpp:302
+#: engines/mohawk/dialogs.cpp:85
+#: engines/mohawk/dialogs.cpp:119
+msgid "~C~ancel"
+msgstr "²ö~Ô~ÜöÝÐ"
+
+#: engines/dialogs.cpp:305
+msgid "~K~eys"
+msgstr "~º~ÛÐÒöèö"
+
+#: engines/scumm/dialogs.cpp:287
+msgid "~P~revious"
+msgstr "~¿~ÞßÕà"
+
+#: engines/scumm/dialogs.cpp:288
+msgid "~N~ext"
+msgstr "~½~Ðáâ"
+
+#: engines/scumm/dialogs.cpp:289
+#: backends/platform/ds/arm9/source/dsoptions.cpp:59
+msgid "~C~lose"
+msgstr "~·~ÐÚàØâØ"
+
+#: engines/mohawk/dialogs.cpp:81
+#: engines/mohawk/dialogs.cpp:115
+msgid "~Z~ip Mode Activated"
+msgstr "ÀÕÖØÜ èÒØÔÚÞÓÞ ßÕàÕåÞÔã ÐÚâØÒÞÒÐÝØÙ"
+
+#: engines/mohawk/dialogs.cpp:82
+msgid "~T~ransitions Enabled"
+msgstr "¿ÕàÕåÞÔØ ÐÚâØÒÞÒÐÝö"
+
+#: engines/mohawk/dialogs.cpp:116
+msgid "~W~ater Effect Enabled"
+msgstr "µäÕÚâØ ÒÞÔØ ÒÚÛîçÕÝö"
+
+#: sound/fmopl.cpp:51
+msgid "MAME OPL emulator"
+msgstr "µÜãÛïâÞà MAME OPL:"
+
+#: sound/fmopl.cpp:53
+msgid "DOSBox OPL emulator"
+msgstr "µÜãÛïâÞà DOSBox OPL"
+
+#: sound/null.h:45
+msgid "No music"
+msgstr "±Õ× Üã×ØÚØ"
+
+#: sound/softsynth/adlib.cpp:1590
+msgid "AdLib Emulator"
+msgstr "µÜãÛïâÞà AdLib"
+
+#: sound/softsynth/mt32.cpp:327
+msgid "Initialising MT-32 Emulator"
+msgstr "½ÐáâàÞîî ÕÜãÛïâÞà MT-32"
+
+#: sound/softsynth/mt32.cpp:541
+msgid "MT-32 Emulator"
+msgstr "µÜãÛïâÞà MT-32"
+
+#: sound/softsynth/pcspk.cpp:142
+msgid "PC Speaker Emulator"
+msgstr "µÜãÛïâÞà PC áßöÚÕàÐ"
+
+#: sound/softsynth/pcspk.cpp:161
+msgid "IBM PCjr Emulator"
+msgstr "µÜãÛïâÞà IBM PCjr"
+
+#: sound/softsynth/ym2612.cpp:762
+msgid "FM Towns Emulator"
+msgstr "µÜãÛïâÞà FM Towns"
+
+#: backends/keymapper/remap-dialog.cpp:49
+msgid "Keymap:"
+msgstr "ÂÐÑÛØæï ÚÛÐÒöè:"
+
+#: backends/keymapper/remap-dialog.cpp:66
+msgid " (Active)"
+msgstr " (°ÚâØÒÝÐ)"
+
+#: backends/keymapper/remap-dialog.cpp:100
+msgid " (Global)"
+msgstr " (³ÛÞÑÐÛìÝÐ)"
+
+#: backends/keymapper/remap-dialog.cpp:110
+msgid " (Game)"
+msgstr " (¦ÓàØ)"
+
+#: backends/midi/windows.cpp:157
+msgid "Windows MIDI"
+msgstr "Windows MIDI"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:60
+msgid "ScummVM Main Menu"
+msgstr "³ÞÛÞÒÝÕ ÜÕÝî ScummVM"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:66
+msgid "~L~eft handed mode"
+msgstr "»öÒÞàãÚØÙ àÕÖØÜ"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:67
+msgid "~I~ndy fight controls"
+msgstr "ºÕàãÒÐÝÝï ÑÞïÜØ Ò Indy"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:68
+msgid "Show mouse cursor"
+msgstr "¿ÞÚÐ×ãÒÐâØ ÚãàáÞà ÜØèö"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:69
+msgid "Snap to edges"
+msgstr "¿àØÚàößØâØ ÔÞ ÚàÐ÷Ò"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:71
+msgid "Touch X Offset"
+msgstr "·ÜöéÕÝÝï âÞàÚÐÝì ßÞ Þáö X"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:78
+msgid "Touch Y Offset"
+msgstr "·ÜöéÕÝÝï âÞàÚÐÝì ßÞ Þáö Y"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:90
+msgid "Use laptop trackpad-style cursor control"
+msgstr "²ØÚÞàØáâÞÒãÒÐâØ ãßàÐÒÛöÝÝï ÚãàáÞàÞÜ ïÚ ÝÐ âàÕÚßÐÔö ÛÐßâÞßöÒ"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:91
+msgid "Tap for left click, double tap right click"
+msgstr "ÂÐß ÔÛï ÛöÒÞÓÞ ÚÛÐæÐÝÝï, ßÞÔÒöÙÝØÙ âÐß ÔÛï ßàÐÒÞÓÞ ÚÛÐæÐÝÝï"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:93
+msgid "Sensitivity"
+msgstr "ÇãâÛØÒöáâì"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:102
+msgid "Initial top screen scale:"
+msgstr "¿ÞçÐâÚÞÒØÙ ÜÐáèâÐÑ ÒÕàåÝìÞÓÞ ÕÚàÐÝã:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:108
+msgid "Main screen scaling:"
+msgstr "¼ÐáèâÐÑ ÓÞÛÞÒÝÞÓÞ ÕÚàÐÝã:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:110
+msgid "Hardware scale (fast, but low quality)"
+msgstr "ÅÐàÔÒÐàÝÞÕ ÜÐáèâÐÑãÒÐÝÝï (èÒØÔÚÞ, ÐÛÕ ÝØ×ìÚÞ÷ ïÚÞáâö)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:111
+msgid "Software scale (good quality, but slower)"
+msgstr "¿àÞÓàÐÜÝÕ ÜÐáèâÐÑãÒÐÝÝï (åÞàÞèÐ ïÚöáâì, ÐÛÕ ßÞÒöÛìÝöèÕ)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:112
+msgid "Unscaled (you must scroll left and right)"
+msgstr "±Õ× ÜÐáèâÐÑãÒÐÝÝï (âàÕÑÐ ÑãÔÕ ßàÞÚàãçãÒÐâØ ÝÐÛöÒÞ ö ÝÐßàÐÒÞ)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:114
+msgid "Brightness:"
+msgstr "ÏáÚàÐÒöáâì:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:124
+msgid "High quality audio (slower) (reboot)"
+msgstr "²ØáÞÚÐ ïÚöáâì ×ÒãÚã (ßÞÒöÛìÝöèÕ) (àÕÑãâ)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:125
+msgid "Disable power off"
+msgstr "·ÐÑÞàÞÝØâØ ÒØÜÚÝÕÝÝï"
+
+#: backends/platform/iphone/osys_events.cpp:339
+msgid "Touchpad mode enabled."
+msgstr "ÀÕÖØÜ âÐçßÐÔã ãÒöÜÚÝÕÝØÙ."
+
+#: backends/platform/iphone/osys_events.cpp:341
+msgid "Touchpad mode disabled."
+msgstr "ÀÕÖØÜ âÐçßÐÔã ÒØÜÚÝÕÝØÙ."
+
+#: backends/platform/sdl/graphics.cpp:40
+#: backends/platform/wince/wince-sdl.cpp:111
+#: backends/platform/wince/wince-sdl.cpp:118
+msgid "Normal (no scaling)"
+msgstr "±Õ× ×ÑöÛìèÕÝÝï"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:41
+#: backends/platform/wince/CEActionsSmartphone.cpp:38
+msgid "Up"
+msgstr "²ÒÕàå"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:42
+#: backends/platform/wince/CEActionsSmartphone.cpp:39
+msgid "Down"
+msgstr "²ÝØ×"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:40
+msgid "Left"
+msgstr "²ÛöÒÞ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:41
+msgid "Right"
+msgstr "²ßàÐÒÞ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:45
+#: backends/platform/wince/CEActionsPocket.cpp:59
+#: backends/platform/wince/CEActionsSmartphone.cpp:42
+msgid "Left Click"
+msgstr "»öÒØÙ ÚÛöÚ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:46
+#: backends/platform/wince/CEActionsSmartphone.cpp:43
+msgid "Right Click"
+msgstr "¿àÐÒØÙ ÚÛöÚ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:49
+#: backends/platform/wince/CEActionsSmartphone.cpp:46
+msgid "Zone"
+msgstr "·ÞÝÐ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:50
+#: backends/platform/wince/CEActionsPocket.cpp:53
+#: backends/platform/wince/CEActionsSmartphone.cpp:47
+msgid "Multi Function"
+msgstr "¼ãÛìâöäãÝÚæöï"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:51
+msgid "Swap character"
+msgstr "·ÜöÝØâØ ÓÕàÞï"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:52
+msgid "Skip text"
+msgstr "¿àÞßãáâØâØ âÕÚáâ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:54
+msgid "Fast mode"
+msgstr "ÈÒØÔÚØÙ àÕÖØÜ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:55
+#: backends/platform/wince/CEActionsPocket.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:51
+msgid "Quit"
+msgstr "²ØåöÔ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:56
+msgid "Debugger"
+msgstr "²öÔÛÐÔçØÚ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:57
+msgid "Global menu"
+msgstr "³ÛÞÑÐÛìÝÕ ÜÕÝî"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:58
+msgid "Virtual keyboard"
+msgstr "²öàâãÐÛìÝÐ ÚÛÐÒöÐâãàÐ"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:59
+msgid "Key mapper"
+msgstr "¿àØ×ÝÐçÕÝÝï ÚÛÐÒöè"
+
+#: backends/platform/symbian/src/SymbianOS.cpp:446
+msgid "Do you want to quit ?"
+msgstr "²Ø åÞçØâÕ ÒØÙâØ?"
+
+#: backends/platform/wii/options.cpp:51
+msgid "Video"
+msgstr "²öÔÕÞ"
+
+#: backends/platform/wii/options.cpp:54
+msgid "Current video mode:"
+msgstr "ÂÕÚãçØÙ ÒöÔÕÞàÕÖØÜ:"
+
+#: backends/platform/wii/options.cpp:56
+msgid "Double-strike"
+msgstr "¿ÞÔÒöÙÝØÙ ãÔÐà"
+
+#: backends/platform/wii/options.cpp:60
+msgid "Horizontal underscan:"
+msgstr "³ÞàØ×ÞÝâÐÛìÝØÙ underscan:"
+
+#: backends/platform/wii/options.cpp:66
+msgid "Vertical underscan:"
+msgstr "²ÕàâØÚÐÛìÝØÙ underscan:"
+
+#: backends/platform/wii/options.cpp:71
+msgid "Input"
+msgstr "²ÒöÔ"
+
+#: backends/platform/wii/options.cpp:74
+msgid "GC Pad sensitivity:"
+msgstr "ÇãâÛØÒöáâì GC ßÐÔã:"
+
+#: backends/platform/wii/options.cpp:80
+msgid "GC Pad acceleration:"
+msgstr "¿àØáÚÞàÕÝÝï GC ßÐÔã:"
+
+#: backends/platform/wii/options.cpp:86
+msgid "DVD"
+msgstr "DVD"
+
+#: backends/platform/wii/options.cpp:89
+#: backends/platform/wii/options.cpp:101
+msgid "Status:"
+msgstr "ÁâÐÝ:"
+
+#: backends/platform/wii/options.cpp:90
+#: backends/platform/wii/options.cpp:102
+msgid "Unknown"
+msgstr "½ÕÒöÔÞÜÞ"
+
+#: backends/platform/wii/options.cpp:93
+msgid "Mount DVD"
+msgstr "¿öÔÚÛîçØâØ DVD"
+
+#: backends/platform/wii/options.cpp:94
+msgid "Unmount DVD"
+msgstr "²öÔÚÛîçØâØ DVD"
+
+#: backends/platform/wii/options.cpp:98
+msgid "SMB"
+msgstr "SMB"
+
+#: backends/platform/wii/options.cpp:106
+msgid "Server:"
+msgstr "ÁÕàÒÕà:"
+
+#: backends/platform/wii/options.cpp:110
+msgid "Share:"
+msgstr "¼ÕàÕÖÕÒÐ ßÐßÚÐ:"
+
+#: backends/platform/wii/options.cpp:114
+msgid "Username:"
+msgstr "ºÞàØáâãÒÐç:"
+
+#: backends/platform/wii/options.cpp:118
+msgid "Password:"
+msgstr "¿ÐàÞÛì:"
+
+#: backends/platform/wii/options.cpp:121
+msgid "Init network"
+msgstr "¦ÝöæöÐÛö×Ðæöï ÜÕàÕÖö"
+
+#: backends/platform/wii/options.cpp:123
+msgid "Mount SMB"
+msgstr "¿öÔÚÛîçØâØ SMB"
+
+#: backends/platform/wii/options.cpp:124
+msgid "Unmount SMB"
+msgstr "²öÔÚÛîçâØ SMB"
+
+#: backends/platform/wii/options.cpp:145
+msgid "DVD Mounted successfully"
+msgstr "DVD ßöÔÚÛîçÕÝØÙ ãáßöèÝÞ"
+
+#: backends/platform/wii/options.cpp:148
+msgid "Error while mounting the DVD"
+msgstr "¿ÞÜØÛÚÐ ßöÔ çÐá ßöÔÚÛîçÕÝÝï DVD"
+
+#: backends/platform/wii/options.cpp:150
+msgid "DVD not mounted"
+msgstr "DVD ÝÕ ßöÔÚÛîçÕÝØÙ"
+
+#: backends/platform/wii/options.cpp:163
+msgid "Network up, share mounted"
+msgstr "¼ÕàÕÖÐ ßàÐæîô, ßÐßÚÐ ßöÔÚÛîçÕÝÐ"
+
+#: backends/platform/wii/options.cpp:165
+msgid "Network up"
+msgstr "¼ÕàÕÖÐ ßàÐæîô"
+
+#: backends/platform/wii/options.cpp:168
+msgid ", error while mounting the share"
+msgstr ", ßÞÜØÛÚÐ ßöÔ çÐá ßöÔÚÛîçÕÝÝï ßÐßÚØ"
+
+#: backends/platform/wii/options.cpp:170
+msgid ", share not mounted"
+msgstr ", ßÐßÚÐ ÝÕ ßöÔÚÛîçÕÝÐ"
+
+#: backends/platform/wii/options.cpp:176
+msgid "Network down"
+msgstr "¼ÕàÕÖÐ ÒØÜÚÝÕÝÐ"
+
+#: backends/platform/wii/options.cpp:180
+msgid "Initialising network"
+msgstr "½ÐÛÐèâÞÒãî ÜÕàÕÖã"
+
+#: backends/platform/wii/options.cpp:184
+msgid "Timeout while initialising network"
+msgstr "ÇÐá ßöÔÚÛîçÕÝÝï ÔÞ ÜÕàÕÖö ÒØâöÚ"
+
+#: backends/platform/wii/options.cpp:188
+#, c-format
+msgid "Network not initialsed (%d)"
+msgstr "¼ÕàÕÖÐ ÝÕ ÝÐÛÐÓÞÔÖÕÝÐ (%d)"
+
+#: backends/platform/wince/CEActionsPocket.cpp:45
+msgid "Hide Toolbar"
+msgstr "·ÐåÞÒÐâØ ßÐÝÕÛì öÝáâàãÜÕÝâöÒ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:46
+msgid "Show Keyboard"
+msgstr "¿ÞÚÐ×ÐâØ ÚÛÐÒöÐâãàã"
+
+#: backends/platform/wince/CEActionsPocket.cpp:47
+msgid "Sound on/off"
+msgstr "·ÒãÚ ãÒöÜ/ÒØÜÚ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:48
+msgid "Right click"
+msgstr "¿àÐÒØÙ ÚÛöÚ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:49
+msgid "Show/Hide Cursor"
+msgstr "¿ÞÚÐ×ÐâØ/ÁåÞÒÐâØ ÚãàáÞà"
+
+#: backends/platform/wince/CEActionsPocket.cpp:50
+msgid "Free look"
+msgstr "²öÛìÝØÙ ÞÓÛïÔ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:51
+msgid "Zoom up"
+msgstr "·ÑöÛ. ÜÐèâÐÑ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:52
+msgid "Zoom down"
+msgstr "·ÜÝè. ÜÐèâÐÑ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:54
+#: backends/platform/wince/CEActionsSmartphone.cpp:48
+msgid "Bind Keys"
+msgstr "ßàØ×ÝÐçØâØ ÚÛÐÒöèö"
+
+#: backends/platform/wince/CEActionsPocket.cpp:55
+msgid "Cursor Up"
+msgstr "ºãàáÞà ÒÒÕàå"
+
+#: backends/platform/wince/CEActionsPocket.cpp:56
+msgid "Cursor Down"
+msgstr "ºãàáÞà ÒÝØ×"
+
+#: backends/platform/wince/CEActionsPocket.cpp:57
+msgid "Cursor Left"
+msgstr "ºãàáÞà ÒÛöÒÞ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:58
+msgid "Cursor Right"
+msgstr "ºãàáÞà ÒßàÐÒÞ"
+
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Do you want to load or save the game?"
+msgstr "²Ø åÞçÕâÕ ×ÐÒÐÝâÐÖØâØ ÐÑÞ ×ÑÕàÕÓâØ Óàã?"
+
+#: backends/platform/wince/CEActionsPocket.cpp:313
+#: backends/platform/wince/CEActionsSmartphone.cpp:272
+msgid " Are you sure you want to quit ? "
+msgstr " ²Ø ãßÕÒÝÕÝö, éÞ åÞçÕâÕ ÒØÙâØ? "
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:49
+msgid "Keyboard"
+msgstr "ºÛÐÒöÐâãàÐ"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:50
+msgid "Rotate"
+msgstr "¿ÞÒÕàÝãâØ"
+
+#: backends/platform/wince/CELauncherDialog.cpp:58
+msgid "Using SDL driver "
+msgstr "²ØÚÞàØáâÞÒãî ÔàÐÙÒÕà SDL "
+
+#: backends/platform/wince/CELauncherDialog.cpp:62
+msgid "Display "
+msgstr "¿ÞÚÐ×ÐâØ "
+
+#: backends/platform/wince/CELauncherDialog.cpp:104
+msgid "Do you want to perform an automatic scan ?"
+msgstr "²Ø åÞçÕâÕ ×ÔöÙáÝØâØ ÐÒâÞÜÐâØçÝØÙ ßÞèãÚ?"
+
diff --git a/ports.mk b/ports.mk
index 4d819f54f9..226052713e 100644
--- a/ports.mk
+++ b/ports.mk
@@ -61,8 +61,9 @@ iphonebundle: iphone
ldid -S scummvm
chmod 755 scummvm
cp scummvm $(bundle_name)/ScummVM
- cp $(srcdir)/dists/iphone/icon.png $(bundle_name)/icon.png
- cp $(srcdir)/dists/iphone/Default.png $(bundle_name)/Default.png
+ cp $(srcdir)/dists/iphone/icon.png $(bundle_name)/
+ cp $(srcdir)/dists/iphone/icon-72.png $(bundle_name)/
+ cp $(srcdir)/dists/iphone/Default.png $(bundle_name)/
# Location of static libs for the iPhone
ifneq ($(BACKEND), iphone)
@@ -97,6 +98,10 @@ ifdef USE_ZLIB
OSX_ZLIB ?= -lz
endif
+ifdef USE_TERMCONV
+OSX_ICONV ?= -liconv
+endif
+
# Special target to create a static linked binary for Mac OS X.
# We use -force_cpusubtype_ALL to ensure the binary runs on every
# PowerPC machine.
@@ -105,6 +110,7 @@ scummvm-static: $(OBJS)
-framework CoreMIDI \
$(OSX_STATIC_LIBS) \
$(OSX_ZLIB) \
+ $(OSX_ICONV) \
-lSystemStubs
# Special target to create a static linked binary for the iPhone
diff --git a/sound/audiocd.cpp b/sound/audiocd.cpp
index 7afbd12d03..625def58fe 100644
--- a/sound/audiocd.cpp
+++ b/sound/audiocd.cpp
@@ -42,6 +42,8 @@ AudioCDManager::AudioCDManager() {
_cd.start = 0;
_cd.duration = 0;
_cd.numLoops = 0;
+ _cd.volume = Mixer::kMaxChannelVolume;
+ _cd.balance = 0;
_mixer = g_system->getMixer();
_emulating = false;
assert(_mixer);
@@ -79,7 +81,8 @@ void AudioCDManager::play(int track, int numLoops, int startFrame, int duration,
*/
_emulating = true;
_mixer->playStream(Mixer::kMusicSoundType, &_handle,
- makeLoopingAudioStream(stream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops));
+ makeLoopingAudioStream(stream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops), -1, _cd.volume, _cd.balance);
+
} else {
_emulating = false;
if (!only_emulate)
@@ -109,6 +112,38 @@ bool AudioCDManager::isPlaying() const {
}
}
+void AudioCDManager::setVolume(byte volume) {
+ _cd.volume = volume;
+ if (_emulating) {
+ // Audio CD emulation
+ if (_mixer->isSoundHandleActive(_handle))
+ _mixer->setChannelVolume(_handle, _cd.volume);
+ } else {
+ // Real Audio CD
+
+ // Unfortunately I can't implement this atm
+ // since SDL doesn't seem to offer an interface method for this.
+
+ // g_system->setVolumeCD(_cd.volume);
+ }
+}
+
+void AudioCDManager::setBalance(int8 balance) {
+ _cd.balance = balance;
+ if (_emulating) {
+ // Audio CD emulation
+ if (isPlaying())
+ _mixer->setChannelBalance(_handle, _cd.balance);
+ } else {
+ // Real Audio CD
+
+ // Unfortunately I can't implement this atm
+ // since SDL doesn't seem to offer an interface method for this.
+
+ // g_system->setBalanceCD(_cd.balance);
+ }
+}
+
void AudioCDManager::updateCD() {
if (_emulating) {
// Check whether the audio track stopped playback
diff --git a/sound/audiocd.h b/sound/audiocd.h
index 3ef4a1ac09..abc45a1640 100644
--- a/sound/audiocd.h
+++ b/sound/audiocd.h
@@ -42,6 +42,8 @@ public:
int start;
int duration;
int numLoops;
+ int volume;
+ int balance;
};
/**
@@ -59,6 +61,9 @@ public:
void stop();
bool isPlaying() const;
+ void setVolume(byte volume);
+ void setBalance(int8 balance);
+
void updateCD();
Status getStatus() const;
diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp
index ce2c521e5e..b3efb2cefe 100644
--- a/sound/audiostream.cpp
+++ b/sound/audiostream.cpp
@@ -95,6 +95,12 @@ SeekableAudioStream *SeekableAudioStream::openStreamFile(const Common::String &b
LoopingAudioStream::LoopingAudioStream(RewindableAudioStream *stream, uint loops, DisposeAfterUse::Flag disposeAfterUse)
: _parent(stream), _disposeAfterUse(disposeAfterUse), _loops(loops), _completeIterations(0) {
+ assert(stream);
+
+ if (!stream->rewind()) {
+ // TODO: Properly indicate error
+ _loops = _completeIterations = 1;
+ }
}
LoopingAudioStream::~LoopingAudioStream() {
@@ -387,7 +393,7 @@ Timestamp convertTimeToStreamPos(const Timestamp &where, int rate, bool isStereo
//
// An example is when converting the timestamp 500ms to a 11025 Hz based
// stream. It would have an internal frame counter of 5512.5. Now when
- // doing calculations at frame precision, this might lead to unexpected
+ // doing calculations at frame precision, this might lead to unexpected
// results: The frame difference between a timestamp 1000ms and the above
// mentioned timestamp (both with 11025 as framerate) would be 5512,
// instead of 5513, which is what a frame-precision based code would expect.
diff --git a/sound/audiostream.h b/sound/audiostream.h
index 37a1953bb9..64ad128931 100644
--- a/sound/audiostream.h
+++ b/sound/audiostream.h
@@ -109,6 +109,9 @@ public:
/**
* Creates a looping audio stream object.
*
+ * Note that on creation of the LoopingAudioStream object
+ * the underlying stream will be rewound.
+ *
* @see makeLoopingAudioStream
*
* @param stream Stream to loop
@@ -126,6 +129,7 @@ public:
/**
* Returns number of loops the stream has played.
+ *
* @param numLoops number of loops to play, 0 - infinite
*/
uint getCompleteIterations() const { return _completeIterations; }
@@ -145,8 +149,8 @@ private:
* overhead down, when the code does not require any functionality only offered
* by LoopingAudioStream.
*
- * @param stream Stream to loop (will be automatically destroyed, when the looping is done)
- * @param loops How often to loop (0 = infinite)
+ * @param stream Stream to loop (will be automatically destroyed, when the looping is done)
+ * @param loops How often to loop (0 = infinite)
* @return A new AudioStream, which offers the desired functionality.
*/
AudioStream *makeLoopingAudioStream(RewindableAudioStream *stream, uint loops);
@@ -162,7 +166,8 @@ public:
* Tries to load a file by trying all available formats.
* In case of an error, the file handle will be closed, but deleting
* it is still the responsibility of the caller.
- * @param basename a filename without an extension
+ *
+ * @param basename a filename without an extension
* @return an SeekableAudioStream ready to use in case of success;
* NULL in case of an error (e.g. invalid/nonexisting file)
*/
@@ -208,9 +213,9 @@ public:
* by LoopingAudioStream.
*
* @param stream Stream to loop (will be automatically destroyed, when the looping is done)
- * @param start Starttime of the stream interval to be looped
- * @param end End of the stream interval to be looped (a zero time, means till end)
- * @param loops How often to loop (0 = infinite)
+ * @param start Starttime of the stream interval to be looped
+ * @param end End of the stream interval to be looped (a zero time, means till end)
+ * @param loops How often to loop (0 = infinite)
* @return A new AudioStream, which offers the desired functionality.
*/
AudioStream *makeLoopingAudioStream(SeekableAudioStream *stream, Timestamp start, Timestamp end, uint loops);
@@ -232,10 +237,13 @@ public:
/**
* Constructor for a SubLoopingAudioStream.
*
- * @param stream Stream to loop
- * @param loops How often the stream should be looped (0 means infinite)
- * @param loopStart Start of the loop (this must be smaller than loopEnd)
- * @param loopEnd End of the loop (thus must be greater than loopStart)
+ * Note that on creation of the SubLoopingAudioStream object
+ * the underlying stream will be rewound.
+ *
+ * @param stream Stream to loop
+ * @param loops How often the stream should be looped (0 means infinite)
+ * @param loopStart Start of the loop (this must be smaller than loopEnd)
+ * @param loopEnd End of the loop (thus must be greater than loopStart)
* @param disposeAfterUse Whether the stream should be disposed, when the
* SubLoopingAudioStream is destroyed.
*/
@@ -279,9 +287,9 @@ public:
/**
* Creates a new SubSeekableAudioStream.
*
- * @param parent parent stream object.
- * @param start Start time.
- * @param end End time.
+ * @param parent parent stream object.
+ * @param start Start time.
+ * @param end End time.
* @param disposeAfterUse Whether the parent stream object should be destroyed on destruction of the SubSeekableAudioStream.
*/
SubSeekableAudioStream(SeekableAudioStream *parent, const Timestamp start, const Timestamp end, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
@@ -317,7 +325,7 @@ public:
* contained in it has been played.
*/
virtual void queueAudioStream(Audio::AudioStream *audStream,
- DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) = 0;
+ DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) = 0;
/**
* Queue a block of raw audio data for playback. This stream plays all
@@ -327,10 +335,10 @@ public:
*
* @note Make sure to allocate the data block with malloc(), not with new[].
*
- * @param data pointer to the audio data block
- * @param size length of the audio data block
- * @param disposeAfterUse if equal to DisposeAfterUse::YES, the block is released using free() after use.
- * @param flags a bit-ORed combination of RawFlags describing the audio data format
+ * @param data pointer to the audio data block
+ * @param size length of the audio data block
+ * @param disposeAfterUse if equal to DisposeAfterUse::YES, the block is released using free() after use.
+ * @param flags a bit-ORed combination of RawFlags describing the audio data format
*/
void queueBuffer(byte *data, uint32 size, DisposeAfterUse::Flag disposeAfterUse, byte flags);
@@ -357,8 +365,8 @@ QueuingAudioStream *makeQueuingAudioStream(int rate, bool stereo);
* Converts a point in time to a precise sample offset
* with the given parameters.
*
- * @param where Point in time.
- * @param rate Rate of the stream.
+ * @param where Point in time.
+ * @param rate Rate of the stream.
* @param isStereo Is the stream a stereo stream?
*/
Timestamp convertTimeToStreamPos(const Timestamp &where, int rate, bool isStereo);
diff --git a/sound/decoders/adpcm.h b/sound/decoders/adpcm.h
index 7452478f35..04dbb1a521 100644
--- a/sound/decoders/adpcm.h
+++ b/sound/decoders/adpcm.h
@@ -71,7 +71,7 @@ enum typesADPCM {
* @param rate the sampling rate
* @param channels the number of channels
* @param blockAlign block alignment ???
- * @return a new RewindableAudioStream, or NULL, if an error occured
+ * @return a new RewindableAudioStream, or NULL, if an error occurred
*/
RewindableAudioStream *makeADPCMStream(
Common::SeekableReadStream *stream,
diff --git a/sound/decoders/aiff.cpp b/sound/decoders/aiff.cpp
index 2f12669072..ce8c6ad32c 100644
--- a/sound/decoders/aiff.cpp
+++ b/sound/decoders/aiff.cpp
@@ -161,16 +161,23 @@ bool loadAIFFFromStream(Common::SeekableReadStream &stream, int &size, int &rate
return true;
}
-SeekableAudioStream *makeAIFFStream(Common::SeekableReadStream &stream) {
+SeekableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream,
+ DisposeAfterUse::Flag disposeAfterUse) {
int size, rate;
byte *data, flags;
- if (!loadAIFFFromStream(stream, size, rate, flags))
+ if (!loadAIFFFromStream(*stream, size, rate, flags)) {
+ if (disposeAfterUse == DisposeAfterUse::YES)
+ delete stream;
return 0;
+ }
data = (byte *)malloc(size);
assert(data);
- stream.read(data, size);
+ stream->read(data, size);
+
+ if (disposeAfterUse == DisposeAfterUse::YES)
+ delete stream;
// Since we allocated our own buffer for the data, we must specify DisposeAfterUse::YES.
return makeRawStream(data, size, rate, flags);
diff --git a/sound/decoders/aiff.h b/sound/decoders/aiff.h
index e8a3b6f0b0..53f86c95fd 100644
--- a/sound/decoders/aiff.h
+++ b/sound/decoders/aiff.h
@@ -34,6 +34,7 @@
#define SOUND_AIFF_H
#include "common/scummsys.h"
+#include "common/types.h"
namespace Common { class SeekableReadStream; }
@@ -55,8 +56,14 @@ extern bool loadAIFFFromStream(Common::SeekableReadStream &stream, int &size, in
* from that data.
*
* This function uses loadAIFFFromStream() internally.
+ *
+ * @param stream the SeekableReadStream from which to read the AIFF data
+ * @param disposeAfterUse whether to delete the stream after use
+ * @return a new SeekableAudioStream, or NULL, if an error occurred
*/
-SeekableAudioStream *makeAIFFStream(Common::SeekableReadStream &stream);
+SeekableAudioStream *makeAIFFStream(
+ Common::SeekableReadStream *stream,
+ DisposeAfterUse::Flag disposeAfterUse);
} // End of namespace Audio
diff --git a/sound/decoders/flac.cpp b/sound/decoders/flac.cpp
index 91c48199e3..e588aa872f 100644
--- a/sound/decoders/flac.cpp
+++ b/sound/decoders/flac.cpp
@@ -230,7 +230,7 @@ FLACStream::FLACStream(Common::SeekableReadStream *inStream, bool dispose)
if (processUntilEndOfMetadata() && _streaminfo.channels > 0) {
_lastSample = _streaminfo.total_samples + 1;
_length = Timestamp(0, _lastSample - 1, getRate());
- return; // no error occured
+ return; // no error occurred
}
}
@@ -355,7 +355,7 @@ int FLACStream::readBuffer(int16 *buffer, const int numSamples) {
break;
default:
decoderOk = false;
- warning("FLACStream: An error occured while decoding. DecoderState is: %s",
+ warning("FLACStream: An error occurred while decoding. DecoderState is: %s",
FLAC__StreamDecoderStateString[getStreamDecoderState()]);
}
@@ -668,7 +668,7 @@ inline void FLACStream::callbackMetadata(const ::FLAC__StreamMetadata *metadata)
}
inline void FLACStream::callbackError(::FLAC__StreamDecoderErrorStatus status) {
// some of these are non-critical-Errors
- debug(1, "FLACStream: An error occured while decoding. DecoderState is: %s",
+ debug(1, "FLACStream: An error occurred while decoding. DecoderState is: %s",
FLAC__StreamDecoderErrorStatusString[status]);
}
diff --git a/sound/decoders/flac.h b/sound/decoders/flac.h
index 982450c045..3c00ec3d5d 100644
--- a/sound/decoders/flac.h
+++ b/sound/decoders/flac.h
@@ -41,8 +41,8 @@
#ifndef SOUND_FLAC_H
#define SOUND_FLAC_H
-#include "common/types.h"
#include "common/scummsys.h"
+#include "common/types.h"
#ifdef USE_FLAC
@@ -61,7 +61,7 @@ class SeekableAudioStream;
*
* @param stream the SeekableReadStream from which to read the FLAC data
* @param disposeAfterUse whether to delete the stream after use
- * @return a new SeekableAudioStream, or NULL, if an error occured
+ * @return a new SeekableAudioStream, or NULL, if an error occurred
*/
SeekableAudioStream *makeFLACStream(
Common::SeekableReadStream *stream,
diff --git a/sound/decoders/mac_snd.cpp b/sound/decoders/mac_snd.cpp
new file mode 100644
index 0000000000..d6894f1144
--- /dev/null
+++ b/sound/decoders/mac_snd.cpp
@@ -0,0 +1,116 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/*
+ * The code in this file is based on information found at
+ * http://developer.apple.com/legacy/mac/library/documentation/mac/Sound/Sound-60.html#HEADING60-15
+ *
+ * We implement both type 1 and type 2 snd resources, but only those that are sampled
+ */
+
+#include "common/util.h"
+#include "common/stream.h"
+
+#include "sound/decoders/mac_snd.h"
+#include "sound/audiostream.h"
+#include "sound/decoders/raw.h"
+
+namespace Audio {
+
+SeekableAudioStream *makeMacSndStream(Common::SeekableReadStream *stream,
+ DisposeAfterUse::Flag disposeAfterUse) {
+
+ uint16 sndType = stream->readUint16BE();
+
+ if (sndType == 1) {
+ // "normal" snd resources
+ if (stream->readUint16BE() != 1) {
+ warning("makeMacSndStream(): Unsupported data type count");
+ return 0;
+ }
+
+ if (stream->readUint16BE() != 5) {
+ // 5 == sampled
+ warning("makeMacSndStream(): Unsupported data type");
+ return 0;
+ }
+
+ stream->readUint32BE(); // initialization option
+ } else if (sndType == 2) {
+ // old HyperCard snd resources
+ stream->readUint16BE(); // reference count (unused)
+ } else {
+ warning("makeMacSndStream(): Unknown format type %d", sndType);
+ return 0;
+ }
+
+ // We really should never get this as long as we have sampled data only
+ if (stream->readUint16BE() != 1) {
+ warning("makeMacSndStream(): Unsupported command count");
+ return 0;
+ }
+
+ uint16 command = stream->readUint16BE();
+
+ // 0x8050 - soundCmd (with dataOffsetFlag set): install a sampled sound as a voice
+ // 0x8051 - bufferCmd (with dataOffsetFlag set): play a sample sound
+ if (command != 0x8050 && command != 0x8051) {
+ warning("makeMacSndStream(): Unsupported command %04x", command);
+ return 0;
+ }
+
+ stream->readUint16BE(); // 0
+ uint32 soundHeaderOffset = stream->readUint32BE();
+
+ stream->seek(soundHeaderOffset);
+
+ uint32 soundDataOffset = stream->readUint32BE();
+ uint32 size = stream->readUint32BE();
+ uint16 rate = stream->readUint32BE() >> 16; // Really fixed point, but we only support integer rates
+ stream->readUint32BE(); // loop start
+ stream->readUint32BE(); // loop end
+ byte encoding = stream->readByte();
+ stream->readByte(); // base frequency
+
+ if (encoding != 0) {
+ // 0 == PCM
+ warning("makeMacSndStream(): Unsupported compression %d", encoding);
+ return 0;
+ }
+
+ stream->skip(soundDataOffset);
+
+ byte *data = (byte *)malloc(size);
+ assert(data);
+ stream->read(data, size);
+
+ if (disposeAfterUse == DisposeAfterUse::YES)
+ delete stream;
+
+ // Since we allocated our own buffer for the data, we must specify DisposeAfterUse::YES.
+ return makeRawStream(data, size, rate, Audio::FLAG_UNSIGNED);
+}
+
+} // End of namespace Audio
diff --git a/sound/decoders/mac_snd.h b/sound/decoders/mac_snd.h
new file mode 100644
index 0000000000..198a61333e
--- /dev/null
+++ b/sound/decoders/mac_snd.h
@@ -0,0 +1,58 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/**
+ * @file
+ * Sound decoder used in engines:
+ * - sci
+ */
+
+#ifndef SOUND_MAC_SND_H
+#define SOUND_MAC_SND_H
+
+#include "common/scummsys.h"
+#include "common/types.h"
+
+namespace Common { class SeekableReadStream; }
+
+namespace Audio {
+
+class SeekableAudioStream;
+
+/**
+ * Try to load a Mac snd resource from the given seekable stream and create a SeekableAudioStream
+ * from that data.
+ *
+ * @param stream the SeekableReadStream from which to read the snd data
+ * @param disposeAfterUse whether to delete the stream after use
+ * @return a new SeekableAudioStream, or NULL, if an error occurred
+ */
+SeekableAudioStream *makeMacSndStream(
+ Common::SeekableReadStream *stream,
+ DisposeAfterUse::Flag disposeAfterUse);
+
+} // End of namespace Audio
+
+#endif
diff --git a/sound/decoders/mp3.cpp b/sound/decoders/mp3.cpp
index f66d6324ef..f22eae5102 100644
--- a/sound/decoders/mp3.cpp
+++ b/sound/decoders/mp3.cpp
@@ -36,7 +36,9 @@
#include <mad.h>
-
+#if defined(__PSP__)
+ #include "backends/platform/psp/mp3.h"
+#endif
namespace Audio {
@@ -347,7 +349,18 @@ int MP3Stream::readBuffer(int16 *buffer, const int numSamples) {
SeekableAudioStream *makeMP3Stream(
Common::SeekableReadStream *stream,
DisposeAfterUse::Flag disposeAfterUse) {
+
+#if defined(__PSP__)
+ SeekableAudioStream *s = 0;
+
+ if (Mp3PspStream::isOkToCreateStream())
+ s = new Mp3PspStream(stream, disposeAfterUse);
+
+ if (!s) // go to regular MAD mp3 stream if ME fails
+ s = new MP3Stream(stream, disposeAfterUse);
+#else
SeekableAudioStream *s = new MP3Stream(stream, disposeAfterUse);
+#endif
if (s && s->endOfData()) {
delete s;
return 0;
diff --git a/sound/decoders/mp3.h b/sound/decoders/mp3.h
index 3175df5e92..ed54c8b013 100644
--- a/sound/decoders/mp3.h
+++ b/sound/decoders/mp3.h
@@ -41,8 +41,8 @@
#ifndef SOUND_MP3_H
#define SOUND_MP3_H
-#include "common/types.h"
#include "common/scummsys.h"
+#include "common/types.h"
#ifdef USE_MAD
@@ -61,7 +61,7 @@ class SeekableAudioStream;
*
* @param stream the SeekableReadStream from which to read the MP3 data
* @param disposeAfterUse whether to delete the stream after use
- * @return a new SeekableAudioStream, or NULL, if an error occured
+ * @return a new SeekableAudioStream, or NULL, if an error occurred
*/
SeekableAudioStream *makeMP3Stream(
Common::SeekableReadStream *stream,
diff --git a/sound/decoders/vag.h b/sound/decoders/vag.h
index 7e0ed255be..cdf91a8ea1 100644
--- a/sound/decoders/vag.h
+++ b/sound/decoders/vag.h
@@ -49,7 +49,7 @@ class RewindableAudioStream;
*
* @param stream the SeekableReadStream from which to read the ADPCM data
* @param rate the sampling rate
- * @return a new RewindableAudioStream, or NULL, if an error occured
+ * @return a new RewindableAudioStream, or NULL, if an error occurred
*/
RewindableAudioStream *makeVagStream(
Common::SeekableReadStream *stream,
diff --git a/sound/decoders/voc.h b/sound/decoders/voc.h
index 79956ee62a..82cc261f2c 100644
--- a/sound/decoders/voc.h
+++ b/sound/decoders/voc.h
@@ -38,8 +38,8 @@
#ifndef SOUND_VOC_H
#define SOUND_VOC_H
-#include "common/types.h"
#include "common/scummsys.h"
+#include "common/types.h"
namespace Common { class ReadStream; }
namespace Common { class SeekableReadStream; }
diff --git a/sound/decoders/vorbis.cpp b/sound/decoders/vorbis.cpp
index 39068603de..7673c53010 100644
--- a/sound/decoders/vorbis.cpp
+++ b/sound/decoders/vorbis.cpp
@@ -35,7 +35,7 @@
#include "sound/audiocd.h"
#ifdef USE_TREMOR
-#ifdef __GP32__ // GP32 uses custom libtremor
+#if defined(__GP32__) // custom libtremor locations
#include <ivorbisfile.h>
#else
#include <tremor/ivorbisfile.h>
diff --git a/sound/decoders/vorbis.h b/sound/decoders/vorbis.h
index dd0a89bfdd..0a0cf43bc9 100644
--- a/sound/decoders/vorbis.h
+++ b/sound/decoders/vorbis.h
@@ -41,8 +41,8 @@
#ifndef SOUND_VORBIS_H
#define SOUND_VORBIS_H
-#include "common/types.h"
#include "common/scummsys.h"
+#include "common/types.h"
#ifdef USE_VORBIS
@@ -61,7 +61,7 @@ class SeekableAudioStream;
*
* @param stream the SeekableReadStream from which to read the Ogg Vorbis data
* @param disposeAfterUse whether to delete the stream after use
- * @return a new SeekableAudioStream, or NULL, if an error occured
+ * @return a new SeekableAudioStream, or NULL, if an error occurred
*/
SeekableAudioStream *makeVorbisStream(
Common::SeekableReadStream *stream,
diff --git a/sound/decoders/wave.h b/sound/decoders/wave.h
index f0e3bb249b..edd37e7ac9 100644
--- a/sound/decoders/wave.h
+++ b/sound/decoders/wave.h
@@ -38,8 +38,8 @@
#ifndef SOUND_WAVE_H
#define SOUND_WAVE_H
-#include "common/types.h"
#include "common/scummsys.h"
+#include "common/types.h"
namespace Common { class SeekableReadStream; }
@@ -71,7 +71,7 @@ extern bool loadWAVFromStream(
*
* @param stream the SeekableReadStream from which to read the WAVE data
* @param disposeAfterUse whether to delete the stream after use
- * @return a new RewindableAudioStream, or NULL, if an error occured
+ * @return a new RewindableAudioStream, or NULL, if an error occurred
*/
RewindableAudioStream *makeWAVStream(
Common::SeekableReadStream *stream,
diff --git a/sound/fmopl.cpp b/sound/fmopl.cpp
index 8fdddc20f8..16dc3986d6 100644
--- a/sound/fmopl.cpp
+++ b/sound/fmopl.cpp
@@ -28,6 +28,7 @@
#include "sound/softsynth/opl/mame.h"
#include "common/config-manager.h"
+#include "common/translation.h"
namespace OPL {
@@ -47,9 +48,9 @@ OPL::OPL() {
const Config::EmulatorDescription Config::_drivers[] = {
{ "auto", "<default>", kAuto, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 },
- { "mame", "MAME OPL emulator", kMame, kFlagOpl2 },
+ { "mame", _s("MAME OPL emulator"), kMame, kFlagOpl2 },
#ifndef DISABLE_DOSBOX_OPL
- { "db", "DOSBox OPL emulator", kDOSBox, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 },
+ { "db", _s("DOSBox OPL emulator"), kDOSBox, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 },
#endif
{ 0, 0, 0, 0 }
};
diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp
index a9a782184e..c7587992e0 100644
--- a/sound/mididrv.cpp
+++ b/sound/mididrv.cpp
@@ -29,72 +29,8 @@
#include "common/system.h"
#include "common/util.h"
#include "sound/mididrv.h"
-
-/** Internal list of all available 'midi' drivers. */
-static const MidiDriverDescription s_musicDrivers[] = {
-
- // The flags for the "auto" & "null" drivers indicate that they are anything
- // you want it to be.
- {"auto", "<default>", MD_AUTO, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS},
- {"null", "No music", MD_NULL, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS},
-
-#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
- {"windows", "Windows MIDI", MD_WINDOWS, MDT_MIDI},
-#endif
-
-#if defined(UNIX) && defined(USE_ALSA)
- {"alsa", "ALSA", MD_ALSA, MDT_MIDI},
-#endif
-
-#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
-
-#if defined(IRIX)
- {"dmedia", "DMedia", MD_DMEDIA, MDT_MIDI},
-#endif
-
-#if defined(__amigaos4__)
- {"camd", "CAMD", MD_CAMD, MDT_MIDI},
-#endif
-
-#if defined(MACOSX)
- {"core", "CoreAudio", MD_COREAUDIO, MDT_MIDI},
-// {"coreaudio", "CoreAudio", MD_COREAUDIO, MDT_MIDI},
- {"coremidi", "CoreMIDI", MD_COREMIDI, MDT_MIDI},
-#endif
-
-#if defined(PALMOS_MODE)
-# if defined(COMPILE_CLIE)
- {"ypa1", "Yamaha Pa1", MD_YPA1, MDT_MIDI},
-# elif defined(COMPILE_ZODIAC) && (!defined(ENABLE_SCUMM) || !defined(PALMOS_ARM))
- {"zodiac", "Tapwave Zodiac", MD_ZODIAC, MDT_MIDI},
-# endif
-#endif
-
-#ifdef USE_FLUIDSYNTH
- {"fluidsynth", "FluidSynth", MD_FLUIDSYNTH, MDT_MIDI},
-#endif
-#ifdef USE_MT32EMU
- {"mt32", "MT-32 Emulation", MD_MT32, MDT_MIDI},
-#endif
-
- // The flags for the "adlib" driver indicates that it can do AdLib and MIDI.
- {"adlib", "AdLib", MD_ADLIB, MDT_ADLIB},
- {"pcspk", "PC Speaker", MD_PCSPK, MDT_PCSPK},
- {"pcjr", "IBM PCjr", MD_PCJR, MDT_PCSPK},
- {"cms", "Creative Music System", MD_CMS, MDT_CMS},
- {"towns", "FM Towns", MD_TOWNS, MDT_TOWNS},
-#if defined(UNIX)
- {"timidity", "TiMidity", MD_TIMIDITY, MDT_MIDI},
-#endif
-
- {0, 0, MD_NULL, MDT_NONE}
-};
+#include "sound/musicplugin.h"
+#include "common/translation.h"
const byte MidiDriver::_mt32ToGm[128] = {
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
@@ -120,169 +56,224 @@ const byte MidiDriver::_gmToMt32[128] = {
101, 103, 100, 120, 117, 113, 99, 128, 128, 128, 128, 124, 123, 128, 128, 128, // 7x
};
-const MidiDriverDescription *MidiDriver::getAvailableMidiDrivers() {
- return s_musicDrivers;
-}
+static const uint32 GUIOMapping[] = {
+ MT_PCSPK, Common::GUIO_MIDIPCSPK,
+ /*MDT_CMS, Common::GUIO_MIDICMS,*/
+ MT_PCJR, Common::GUIO_MIDIPCJR,
+ MT_ADLIB, Common::GUIO_MIDIADLIB,
+ MT_TOWNS, Common::GUIO_MIDITOWNS,
+ MT_GM, Common::GUIO_MIDIGM,
+ MT_MT32, Common::GUIO_MIDIMT32,
+ 0, 0
+};
-const MidiDriverDescription *MidiDriver::findMusicDriver(const Common::String &str) {
- if (str.empty())
- return 0;
+uint32 MidiDriver::musicType2GUIO(uint32 musicType) {
+ uint32 res = 0;
- const char *s = str.c_str();
- int len = 0;
- const MidiDriverDescription *md = s_musicDrivers;
+ for (int i = 0; GUIOMapping[i] || GUIOMapping[i + 1]; i += 2) {
+ if (musicType == GUIOMapping[i] || musicType == (uint32)-1)
+ res |= GUIOMapping[i + 1];
+ }
+
+ return res;
+}
- // Scan for string end or a colon
- while (s[len] != 0 && s[len] != ':')
- len++;
+bool MidiDriver::_forceTypeMT32 = false;
- while (md->name) {
- // Compare the string passed to us with the current table entry.
- // We ignore any characters following an (optional) colon ':'
- // contained in str.
- if (!scumm_strnicmp(md->name, s, len)) {
- return md;
+MusicType MidiDriver::getMusicType(MidiDriver::DeviceHandle handle) {
+ if (_forceTypeMT32)
+ return MT_MT32;
+
+ if (handle) {
+ const MusicPlugin::List p = MusicMan.getPlugins();
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) {
+ MusicDevices i = (**m)->getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) {
+ if (handle == d->getHandle())
+ return d->getMusicType();
+ }
}
- md++;
}
- return 0;
+ return MT_INVALID;
}
-static MidiDriverType getDefaultMIDIDriver() {
-#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
- return MD_WINDOWS;
-#elif defined(MACOSX)
- return MD_COREAUDIO;
-#elif defined(PALMOS_MODE)
- #if defined(COMPILE_CLIE)
- return MD_YPA1;
- #elif defined(COMPILE_ZODIAC)
- return MD_ZODIAC;
- #else
- return MD_NULL;
- #endif
-#else
- return MD_NULL;
-#endif
-}
+Common::String MidiDriver::getDeviceString(DeviceHandle handle, DeviceStringType type) {
+ if (handle) {
+ const MusicPlugin::List p = MusicMan.getPlugins();
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) {
+ MusicDevices i = (**m)->getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) {
+ if (handle == d->getHandle()) {
+ if (type == kDriverName)
+ return d->getMusicDriverName();
+ else if (type == kDriverId)
+ return d->getMusicDriverId();
+ else if (type == kDeviceId)
+ return d->getCompleteId();
+ else
+ return Common::String("auto");
+ }
+ }
+ }
+ }
-MidiDriverType MidiDriver::parseMusicDriver(const Common::String &str) {
- const MidiDriverDescription *md = findMusicDriver(str);
- if (md)
- return md->id;
- return MD_AUTO;
+ return Common::String("auto");
}
-MidiDriverType MidiDriver::detectMusicDriver(int flags) {
- MidiDriverType musicDriver;
+MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
+ // Query the selected music device (defaults to MT_AUTO device).
+ DeviceHandle hdl = getDeviceHandle(ConfMan.get("music_driver"));
- // Query the selected music driver (defaults to MD_AUTO).
- const MidiDriverDescription *md = findMusicDriver(ConfMan.get("music_driver"));
+ _forceTypeMT32 = false;
// Check whether the selected music driver is compatible with the
// given flags.
- if (!md || !(md->flags & flags))
- musicDriver = MD_AUTO;
- else
- musicDriver = md->id;
-
- // If the selected driver is MD_AUTO, we try to determine
- // a suitable and "optimal" music driver.
- if (musicDriver == MD_AUTO) {
-
- if (flags & MDT_PREFER_MIDI) {
- // A MIDI music driver is preferred. Of course this implies
- // that MIDI is actually listed in flags, so we verify that.
- assert(flags & MDT_MIDI);
-
- // Query the default MIDI driver. It's possible that there
- // is none, in which case we revert to AUTO mode.
- musicDriver = getDefaultMIDIDriver();
- if (musicDriver == MD_NULL)
- musicDriver = MD_AUTO;
- }
+ switch (getMusicType(hdl)) {
+ case MT_PCSPK:
+ if (flags & MDT_PCSPK)
+ return hdl;
+ break;
+
+ case MT_PCJR:
+ if (flags & MDT_PCJR)
+ return hdl;
+ break;
+
+ case MT_CMS:
+ if (flags & MDT_CMS)
+ return hdl;
+ break;
+
+ case MT_ADLIB:
+ if (flags & MDT_ADLIB)
+ return hdl;
+ break;
+
+ case MT_TOWNS:
+ if (flags & MDT_TOWNS)
+ return hdl;
+ break;
+
+ case MT_PC98:
+ if (flags & MDT_PC98)
+ return hdl;
+ break;
+
+ case MT_GM:
+ case MT_GS:
+ case MT_MT32:
+ if (flags & MDT_MIDI)
+ return hdl;
+ break;
+
+ case MT_NULL:
+ return hdl;
- if (musicDriver == MD_AUTO) {
- // MIDI is not preferred, or no default MIDI device is available.
- // In this case we first try the alternate drivers before checking
- // for a 'real' MIDI driver.
-
- if (flags & MDT_TOWNS)
- musicDriver = MD_TOWNS;
- else if (flags & MDT_ADLIB)
- musicDriver = MD_ADLIB;
- else if (flags & MDT_PCSPK)
- musicDriver = MD_PCJR;
- else if (flags & MDT_MIDI)
- musicDriver = getDefaultMIDIDriver();
+ default:
+ break;
+ }
+
+ // If the selected driver did not match the flags setting,
+ // we try to determine a suitable and "optimal" music driver.
+ const MusicPlugin::List p = MusicMan.getPlugins();
+ // If only MDT_MIDI but not MDT_PREFER_MT32 or MDT_PREFER_GM is set we prefer the other devices (which will always be
+ // detected since they are hard coded and cannot be disabled.
+ for (int l = (flags & (MDT_PREFER_GM | MDT_PREFER_MT32)) ? 1 : 0; l < 2; ++l) {
+ if ((flags & MDT_MIDI) && (l == 1)) {
+ // If a preferred MT32 or GM device has been selected that device gets returned
+ if (flags & MDT_PREFER_MT32)
+ hdl = getDeviceHandle(ConfMan.get("mt32_device"));
+ else if (flags & MDT_PREFER_GM)
+ hdl = getDeviceHandle(ConfMan.get("gm_device"));
else
- musicDriver = MD_NULL;
+ hdl = getDeviceHandle("auto");
+
+ const MusicType type = getMusicType(hdl);
+ if (type != MT_AUTO && type != MT_INVALID) {
+ if (flags & MDT_PREFER_MT32)
+ // If we have a preferred MT32 device we disable the gm/mt32 mapping (more about this in mididrv.h)
+ _forceTypeMT32 = true;
+
+ return hdl;
+ }
+
+ // If we have no specific device selected (neither in the scummvm nor in the game domain)
+ // and no preferred MT32 or GM device selected we arrive here.
+ // If MT32 is preferred we try for the first available device with music type 'MT_MT32' (usually the mt32 emulator)
+ if (flags & MDT_PREFER_MT32) {
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) {
+ MusicDevices i = (**m)->getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
+ if (d->getMusicType() == MT_MT32)
+ return d->getHandle();
+ }
+ }
+ }
+
+ // Now we default to the first available device with music type 'MT_GM'
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) {
+ MusicDevices i = (**m)->getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
+ if (d->getMusicType() == MT_GM || d->getMusicType() == MT_GS)
+ return d->getHandle();
+ }
+ }
+ }
+
+ MusicType tp = MT_AUTO;
+ if (flags & MDT_TOWNS)
+ tp = MT_TOWNS;
+ else if (flags & MDT_ADLIB)
+ tp = MT_ADLIB;
+ else if (flags & MDT_PCSPK)
+ tp = MT_PCSPK;
+ else if (l == 0)
+ // if we haven't tried to find a MIDI device yet we do this now.
+ continue;
+ else
+ tp = MT_AUTO;
+
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) {
+ MusicDevices i = (**m)->getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
+ if (d->getMusicType() == tp)
+ return d->getHandle();
+ }
}
}
- return musicDriver;
+ return 0;
}
-MidiDriver *MidiDriver::createMidi(MidiDriverType midiDriver) {
- switch (midiDriver) {
- case MD_NULL: return MidiDriver_NULL_create();
-
- case MD_ADLIB: return MidiDriver_ADLIB_create();
-
- case MD_TOWNS: return MidiDriver_YM2612_create();
-
- // Right now PC Speaker and PCjr are handled
- // outside the MidiDriver architecture, so
- // don't create anything for now.
- case MD_PCSPK:
- case MD_CMS:
- case MD_PCJR: return NULL;
-
-#ifdef USE_FLUIDSYNTH
- case MD_FLUIDSYNTH: return MidiDriver_FluidSynth_create();
-#endif
-
-#ifdef USE_MT32EMU
- case MD_MT32: return MidiDriver_MT32_create();
-#endif
-
-#if defined(PALMOS_MODE)
-#if defined(COMPILE_CLIE)
- case MD_YPA1: return MidiDriver_YamahaPa1_create();
-#elif defined(COMPILE_ZODIAC) && (!defined(ENABLE_SCUMM) || !defined(PALMOS_ARM))
- case MD_ZODIAC: return MidiDriver_Zodiac_create();
-#endif
-#endif
-
-#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
- case MD_WINDOWS: return MidiDriver_WIN_create();
-#endif
-#if defined(__MINT__)
- case MD_STMIDI: return MidiDriver_STMIDI_create();
-#endif
-#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOSX) && !defined(__MAEMO__) && !defined(__MINT__)
- case MD_SEQ: return MidiDriver_SEQ_create();
-#endif
-#if defined(UNIX)
- case MD_TIMIDITY: return MidiDriver_TIMIDITY_create();
-#endif
-#if defined(IRIX)
- case MD_DMEDIA: return MidiDriver_DMEDIA_create();
-#endif
-#if defined(MACOSX)
- case MD_COREAUDIO: return MidiDriver_CORE_create();
- case MD_COREMIDI: return MidiDriver_CoreMIDI_create();
-#endif
-#if defined(UNIX) && defined(USE_ALSA)
- case MD_ALSA: return MidiDriver_ALSA_create();
-#endif
-#if defined(__amigaos4__)
- case MD_CAMD: return MidiDriver_CAMD_create();
-#endif
- default:
- error("Invalid midi driver selected");
+MidiDriver *MidiDriver::createMidi(MidiDriver::DeviceHandle handle) {
+ MidiDriver *driver = 0;
+ const MusicPlugin::List p = MusicMan.getPlugins();
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) {
+ if (getDeviceString(handle, MidiDriver::kDriverId).equals((**m)->getId()))
+ (**m)->createInstance(&driver, handle);
}
- return NULL;
+ return driver;
+}
+
+MidiDriver::DeviceHandle MidiDriver::getDeviceHandle(const Common::String &identifier) {
+ const MusicPlugin::List p = MusicMan.getPlugins();
+
+ if (p.begin() == p.end())
+ error("Music plugins must be loaded prior to calling this method");
+
+ for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) {
+ MusicDevices i = (**m)->getDevices();
+ for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) {
+ // The music driver id isn't unique, but it will match
+ // driver's first device. This is useful when selecting
+ // the driver from the command line.
+ if (identifier.equals(d->getMusicDriverId()) || identifier.equals(d->getCompleteId()) || identifier.equals(d->getCompleteName())) {
+ return d->getHandle();
+ }
+ }
+ }
+
+ return 0;
}
diff --git a/sound/mididrv.h b/sound/mididrv.h
index d7e89dd9ca..1184adee6c 100644
--- a/sound/mididrv.h
+++ b/sound/mididrv.h
@@ -30,6 +30,8 @@
#include "common/timer.h"
class MidiChannel;
+class MusicDevice;
+
namespace Audio {
class Mixer;
}
@@ -43,56 +45,32 @@ namespace Common { class String; }
*
* @todo Rename MidiDriverType to MusicDriverType
*/
-enum MidiDriverType {
- // Pseudo drivers
- MD_AUTO,
- MD_NULL,
-
- // Windows
- MD_WINDOWS,
-
- // Atari ST
- MD_STMIDI,
-
- // Linux
- MD_ALSA,
- MD_SEQ,
-
- // Mac OS X
- MD_QTMUSIC,
- MD_COREAUDIO,
- MD_COREMIDI,
-
- // PalmOS
- MD_YPA1,
- MD_ZODIAC,
-
- // IRIX
- MD_DMEDIA,
-
- // AMIGAOS4
- MD_CAMD,
-
- // MIDI softsynths
- MD_FLUIDSYNTH,
- MD_MT32,
-
- // "Fake" MIDI devices
- MD_ADLIB,
- MD_PCSPK,
- MD_CMS,
- MD_PCJR,
- MD_TOWNS,
- MD_TIMIDITY
+
+/**
+ * Music types that music drivers can implement and engines can rely on.
+ */
+enum MusicType {
+ MT_INVALID = -1, // Invalid output
+ MT_AUTO = 0, // Auto
+ MT_NULL, // Null
+ MT_PCSPK, // PC Speaker
+ MT_PCJR, // PCjr
+ MT_CMS, // CMS
+ MT_ADLIB, // AdLib
+ MT_TOWNS, // FM-TOWNS
+ MT_PC98, // PC98
+ MT_GM, // General MIDI
+ MT_MT32, // MT-32
+ MT_GS // Roland GS
};
/**
- * A set of flags to be passed to detectMusicDriver() which can be used to
+ * A set of flags to be passed to detectDevice() which can be used to
* specify what kind of music driver is preferred / accepted.
*
- * The flags (except for MDT_PREFER_MIDI) indicate whether a given driver
+ * The flags (except for MDT_PREFER_MT32 and MDT_PREFER_GM) indicate whether a given driver
* type is acceptable. E.g. the TOWNS music driver could be returned by
- * detectMusicDriver if and only if MDT_TOWNS is specified.
+ * detectDevice if and only if MDT_TOWNS is specified.
*
* @todo Rename MidiDriverFlags to MusicDriverFlags
*/
@@ -100,10 +78,13 @@ enum MidiDriverFlags {
MDT_NONE = 0,
MDT_PCSPK = 1 << 0, // PC Speaker: Maps to MD_PCSPK and MD_PCJR
MDT_CMS = 1 << 1, // Creative Music System / Gameblaster: Maps to MD_CMS
- MDT_ADLIB = 1 << 2, // AdLib: Maps to MD_ADLIB
- MDT_TOWNS = 1 << 3, // FM-TOWNS: Maps to MD_TOWNS
- MDT_MIDI = 1 << 4, // Real MIDI
- MDT_PREFER_MIDI = 1 << 5 // Real MIDI output is preferred
+ MDT_PCJR = 1 << 2, // Tandy/PC Junior driver
+ MDT_ADLIB = 1 << 3, // AdLib: Maps to MT_ADLIB
+ MDT_TOWNS = 1 << 4, // FM-TOWNS: Maps to MT_TOWNS
+ MDT_PC98 = 1 << 5, // FM-TOWNS: Maps to MT_PC98
+ MDT_MIDI = 1 << 6, // Real MIDI
+ MDT_PREFER_MT32 = 1 << 7, // MT-32 output is preferred
+ MDT_PREFER_GM = 1 << 8 // GM output is preferred
};
/**
@@ -113,12 +94,6 @@ enum MidiDriverFlags {
*
* @todo Rename MidiDriverType to MusicDriverType
*/
-struct MidiDriverDescription {
- const char *name;
- const char *description;
- MidiDriverType id; // A unique ID for each driver
- int flags; // Capabilities of this driver
-};
/**
* Abstract MIDI Driver Class
@@ -127,22 +102,45 @@ struct MidiDriverDescription {
*/
class MidiDriver {
public:
- /** Find the music driver matching the given driver name/description. */
- static const MidiDriverDescription *findMusicDriver(const Common::String &str);
-
- /** Get the id of the music driver matching the given driver name, or MD_AUTO if there is no match. */
- static MidiDriverType parseMusicDriver(const Common::String &str);
-
/**
- * Get a list of all available MidiDriver types.
- * @return list of all available midi drivers, terminated by a zero entry
+ * The device handle.
+ *
+ * The value 0 is reserved for an invalid device for now.
+ * TODO: Maybe we should use -1 (i.e. 0xFFFFFFFF) as
+ * invalid device?
*/
- static const MidiDriverDescription *getAvailableMidiDrivers();
+ typedef uint32 DeviceHandle;
+
+ enum DeviceStringType {
+ kDriverName,
+ kDriverId,
+ kDeviceId
+ };
+
+ static uint32 musicType2GUIO(uint32 musicType);
+
+ /** Create music driver matching the given device handle, or NULL if there is no match. */
+ static MidiDriver *createMidi(DeviceHandle handle);
+
+ /** Returns device handle based on the present devices and the flags parameter. */
+ static DeviceHandle detectDevice(int flags);
+
+ /** Find the music driver matching the given driver name/description. */
+ static DeviceHandle getDeviceHandle(const Common::String &identifier);
- static MidiDriver *createMidi(MidiDriverType midiDriver);
+ /** Get the music type matching the given device handle, or MT_AUTO if there is no match. */
+ static MusicType getMusicType(DeviceHandle handle);
- static MidiDriverType detectMusicDriver(int flags);
+ /** Get the device description string matching the given device handle and the given type. */
+ static Common::String getDeviceString(DeviceHandle handle, DeviceStringType type);
+private:
+ // If detectDevice() detects MT32 and we have a preferred MT32 device
+ // we use this to force getMusicType() to return MT_MT32 so that we don't
+ // have to rely on the 'True Roland MT-32' config manager setting (since nobody
+ // would possibly think about activating 'True Roland MT-32' when he has set
+ // 'Music Driver' to '<default>')
+ static bool _forceTypeMT32;
public:
virtual ~MidiDriver() { }
@@ -271,28 +269,4 @@ public:
virtual void sysEx_customInstrument(uint32 type, const byte *instr) = 0;
};
-
-// Factory functions, for faster compile
-extern MidiDriver *MidiDriver_NULL_create();
-extern MidiDriver *MidiDriver_ADLIB_create();
-extern MidiDriver *MidiDriver_WIN_create();
-extern MidiDriver *MidiDriver_STMIDI_create();
-extern MidiDriver *MidiDriver_SEQ_create();
-extern MidiDriver *MidiDriver_TIMIDITY_create();
-extern MidiDriver *MidiDriver_QT_create();
-extern MidiDriver *MidiDriver_CORE_create();
-extern MidiDriver *MidiDriver_CoreMIDI_create();
-extern MidiDriver *MidiDriver_ALSA_create();
-extern MidiDriver *MidiDriver_DMEDIA_create();
-extern MidiDriver *MidiDriver_CAMD_create();
-extern MidiDriver *MidiDriver_YM2612_create();
-#ifdef USE_FLUIDSYNTH
-extern MidiDriver *MidiDriver_FluidSynth_create();
-#endif
-#ifdef USE_MT32EMU
-extern MidiDriver *MidiDriver_MT32_create();
-#endif
-extern MidiDriver *MidiDriver_YamahaPa1_create();
-extern MidiDriver *MidiDriver_Zodiac_create();
-
#endif
diff --git a/sound/midiparser.cpp b/sound/midiparser.cpp
index 99319461e9..929b1d8b12 100644
--- a/sound/midiparser.cpp
+++ b/sound/midiparser.cpp
@@ -47,6 +47,10 @@ _num_tracks(0),
_active_track(255),
_abort_parse(0) {
memset(_active_notes, 0, sizeof(_active_notes));
+ _next_event.start = NULL;
+ _next_event.delta = 0;
+ _next_event.event = 0;
+ _next_event.length = 0;
}
void MidiParser::property(int prop, int value) {
@@ -63,6 +67,10 @@ void MidiParser::property(int prop, int value) {
}
}
+void MidiParser::sendToDriver(uint32 b) {
+ _driver->send(b);
+}
+
void MidiParser::setTempo(uint32 tempo) {
_tempo = tempo;
if (_ppqn)
@@ -123,7 +131,7 @@ void MidiParser::hangingNote(byte channel, byte note, uint32 time_left, bool rec
best = ptr;
if (ptr->time_left) {
if (recycle)
- _driver->send(0x80 | channel, note, 0);
+ sendToDriver(0x80 | channel, note, 0);
--_hanging_notes_count;
}
break;
@@ -168,7 +176,7 @@ void MidiParser::onTimer() {
for (i = ARRAYSIZE(_hanging_notes); i; --i, ++ptr) {
if (ptr->time_left) {
if (ptr->time_left <= _timer_rate) {
- _driver->send(0x80 | ptr->channel, ptr->note, 0);
+ sendToDriver(0x80 | ptr->channel, ptr->note, 0);
ptr->time_left = 0;
--_hanging_notes_count;
} else {
@@ -228,7 +236,7 @@ void MidiParser::onTimer() {
else
activeNote(info.channel(), info.basic.param1, true);
}
- _driver->send(info.event, info.basic.param1, info.basic.param2);
+ sendToDriver(info.event, info.basic.param1, info.basic.param2);
}
@@ -254,7 +262,7 @@ void MidiParser::allNotesOff() {
for (i = 0; i < 128; ++i) {
for (j = 0; j < 16; ++j) {
if (_active_notes[i] & (1 << j)) {
- _driver->send(0x80 | j, i, 0);
+ sendToDriver(0x80 | j, i, 0);
}
}
}
@@ -262,7 +270,7 @@ void MidiParser::allNotesOff() {
// Turn off all hanging notes
for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) {
if (_hanging_notes[i].time_left) {
- _driver->send(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0);
+ sendToDriver(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0);
_hanging_notes[i].time_left = 0;
}
}
@@ -272,7 +280,7 @@ void MidiParser::allNotesOff() {
// support this...).
for (i = 0; i < 16; ++i) {
- _driver->send(0xB0 | i, 0x7b, 0); // All notes off
+ sendToDriver(0xB0 | i, 0x7b, 0); // All notes off
}
memset(_active_notes, 0, sizeof(_active_notes));
@@ -325,7 +333,7 @@ void MidiParser::hangAllActiveNotes() {
uint32 advance_tick = _position._last_event_tick;
while (true) {
- int i, j;
+ int i;
for (i = 0; i < 128; ++i)
if (temp_active[i] != 0)
break;
@@ -341,10 +349,10 @@ void MidiParser::hangAllActiveNotes() {
} else if (_next_event.event == 0xFF && _next_event.ext.type == 0x2F) {
// warning("MidiParser::hangAllActiveNotes(): Hit End of Track with active notes left");
for (i = 0; i < 128; ++i) {
- for (j = 0; j < 16; ++j) {
+ for (int j = 0; j < 16; ++j) {
if (temp_active[i] & (1 << j)) {
activeNote(j, i, false);
- _driver->send(0x80 | j, i, 0);
+ sendToDriver(0x80 | j, i, 0);
}
}
}
@@ -395,7 +403,7 @@ bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes) {
else
_driver->sysEx(info.ext.data, (uint16)info.length);
} else
- _driver->send(info.event, info.basic.param1, info.basic.param2);
+ sendToDriver(info.event, info.basic.param1, info.basic.param2);
}
parseNextEvent(_next_event);
@@ -437,7 +445,7 @@ void MidiParser::unloadMusic() {
if (_driver) {
for (int i = 0; i < 16; ++i) {
- _driver->send(0xE0 | i, 0, 0x40);
+ sendToDriver(0xE0 | i, 0, 0x40);
}
}
}
diff --git a/sound/midiparser.h b/sound/midiparser.h
index 0ba12ce2b1..3ef99fcd6e 100644
--- a/sound/midiparser.h
+++ b/sound/midiparser.h
@@ -267,13 +267,12 @@ struct NoteTimer {
* memory block containing the music data.)
*/
class MidiParser {
-private:
+protected:
uint16 _active_notes[128]; ///< Each uint16 is a bit mask for channels that have that note on.
NoteTimer _hanging_notes[32]; ///< Maintains expiration info for up to 32 notes.
///< Used for "Smart Jump" and MIDI formats that do not include explicit Note Off events.
byte _hanging_notes_count; ///< Count of hanging notes, used to optimize expiration.
-protected:
MidiDriver *_driver; ///< The device to which all events will be transmitted.
uint32 _timer_rate; ///< The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
uint32 _ppqn; ///< Pulses Per Quarter Note. (We refer to "pulses" as "ticks".)
@@ -303,6 +302,11 @@ protected:
void hangingNote(byte channel, byte note, uint32 ticks_left, bool recycle = true);
void hangAllActiveNotes();
+ virtual void sendToDriver(uint32 b);
+ void sendToDriver(byte status, byte firstOp, byte secondOp) {
+ sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
+ }
+
/**
* Platform independent BE uint32 read-and-advance.
* This helper function reads Big Endian 32-bit numbers
diff --git a/sound/midiparser_smf.cpp b/sound/midiparser_smf.cpp
index 4261b1d770..a9c6f1eb3b 100644
--- a/sound/midiparser_smf.cpp
+++ b/sound/midiparser_smf.cpp
@@ -230,10 +230,8 @@ bool MidiParser_SMF::loadMusic(byte *data, uint32 size) {
// If this is a Type 1 MIDI, we need to now compress
// our tracks down into a single Type 0 track.
- if (_buffer) {
- free(_buffer);
- _buffer = 0;
- }
+ free(_buffer);
+ _buffer = 0;
if (midi_type == 1) {
// FIXME: Doubled the buffer size to prevent crashes with the
diff --git a/sound/mods/protracker.h b/sound/mods/protracker.h
index dfcb0e6c51..af722637c7 100644
--- a/sound/mods/protracker.h
+++ b/sound/mods/protracker.h
@@ -48,7 +48,7 @@ class AudioStream;
* @param stream the ReadStream from which to read the ProTracker data
* @param rate TODO
* @param stereo TODO
- * @return a new AudioStream, or NULL, if an error occured
+ * @return a new AudioStream, or NULL, if an error occurred
*/
AudioStream *makeProtrackerStream(Common::SeekableReadStream *stream, int offs = 0, int rate = 44100, bool stereo = true);
diff --git a/sound/module.mk b/sound/module.mk
index df593d8e1f..caf14be547 100644
--- a/sound/module.mk
+++ b/sound/module.mk
@@ -17,6 +17,7 @@ MODULE_OBJS := \
decoders/aiff.o \
decoders/flac.o \
decoders/iff_sound.o \
+ decoders/mac_snd.o \
decoders/mp3.o \
decoders/raw.o \
decoders/vag.o \
@@ -35,6 +36,10 @@ MODULE_OBJS := \
softsynth/opl/dbopl.o \
softsynth/opl/dosbox.o \
softsynth/opl/mame.o \
+ softsynth/fmtowns_pc98/towns_audio.o \
+ softsynth/fmtowns_pc98/towns_euphony.o \
+ softsynth/fmtowns_pc98/towns_pc98_driver.o \
+ softsynth/fmtowns_pc98/towns_pc98_fmsynth.o \
softsynth/ym2612.o \
softsynth/fluidsynth.o \
softsynth/mt32.o \
diff --git a/sound/musicplugin.cpp b/sound/musicplugin.cpp
index b4754230da..8078094616 100644
--- a/sound/musicplugin.cpp
+++ b/sound/musicplugin.cpp
@@ -24,10 +24,12 @@
*/
#include "sound/musicplugin.h"
+#include "common/hash-str.h"
+#include "common/translation.h"
MusicDevice::MusicDevice(MusicPluginObject const *musicPlugin, Common::String name, MusicType mt) :
- _musicDriverName(musicPlugin->getName()), _musicDriverId(musicPlugin->getId()),
- _name(name), _type(mt) {
+ _musicDriverName(_(musicPlugin->getName())), _musicDriverId(musicPlugin->getId()),
+ _name(_(name)), _type(mt) {
}
Common::String MusicDevice::getCompleteName() {
@@ -46,3 +48,17 @@ Common::String MusicDevice::getCompleteName() {
return name;
}
+
+Common::String MusicDevice::getCompleteId() {
+ Common::String id = _musicDriverId;
+ if (!_name.empty()) {
+ id += "_";
+ id += _name;
+ }
+
+ return id;
+}
+
+MidiDriver::DeviceHandle MusicDevice::getHandle() {
+ return (MidiDriver::DeviceHandle)Common::hashit(getCompleteId().c_str());
+}
diff --git a/sound/musicplugin.h b/sound/musicplugin.h
index df97494a90..bbb4ed778c 100644
--- a/sound/musicplugin.h
+++ b/sound/musicplugin.h
@@ -29,19 +29,6 @@
#include "sound/mididrv.h"
#include "common/list.h"
-/**
- * Music types that music drivers can implement and engines can rely on.
- */
-enum MusicType {
- MT_PCSPK = 1, // PC Speaker
- MT_PCJR = 2, // PCjr
- MT_ADLIB = 3, // AdLib
- MT_TOWNS = 4, // FM-TOWNS
- MT_GM = 5, // General MIDI
- MT_MT32 = 6, // MT-32
- MT_GS = 7 // Roland GS
-};
-
class MusicPluginObject;
/**
@@ -64,6 +51,14 @@ public:
*/
Common::String getCompleteName();
+ /**
+ * Returns a user readable string that contains the name of the current
+ * device name (if it isn't the default one) and the id of the driver.
+ */
+ Common::String getCompleteId();
+
+ MidiDriver::DeviceHandle getHandle();
+
private:
Common::String _name;
Common::String _musicDriverName;
@@ -94,15 +89,18 @@ public:
virtual MusicDevices getDevices() const = 0;
/**
- * Tries to instantiate a MIDI Driver instance based on the settings of
- * the currently active ConfMan target. That is, the MusicPluginObject
- * should query the ConfMan singleton for the device name, port, etc.
+ * Tries to instantiate a MIDI Driver instance based on the device
+ * previously detected via MidiDriver::detectDevice()
*
* @param mididriver Pointer to a pointer which the MusicPluginObject sets
* to the newly create MidiDriver, or 0 in case of an error
+ *
+ * @param dev Pointer to a device to be used then creating the driver instance.
+ * Default value of zero for driver types without devices.
+ *
* @return a Common::Error describing the error which occurred, or kNoError
*/
- virtual Common::Error createInstance(MidiDriver **mididriver) const = 0;
+ virtual Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const = 0;
};
diff --git a/sound/null.cpp b/sound/null.cpp
index 00a5f5e488..556b96c14c 100644
--- a/sound/null.cpp
+++ b/sound/null.cpp
@@ -22,63 +22,41 @@
* $Id$
*/
-#include "sound/musicplugin.h"
-#include "sound/mpu401.h"
+#include "sound/null.h"
-/* NULL driver */
-class MidiDriver_NULL : public MidiDriver_MPU401 {
-public:
- int open() { return 0; }
- void send(uint32 b) { }
-};
+Common::Error NullMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
+ *mididriver = new MidiDriver_NULL();
+ return Common::kNoError;
+}
-// Plugin interface
+MusicDevices NullMusicPlugin::getDevices() const {
+ MusicDevices devices;
+ devices.push_back(MusicDevice(this, "", MT_NULL));
+ return devices;
+}
-class NullMusicPlugin : public MusicPluginObject {
+class AutoMusicPlugin : public NullMusicPlugin {
public:
const char *getName() const {
- return "No music";
+ return _s("<default>");
}
const char *getId() const {
- return "null";
+ return "auto";
}
-
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
};
-Common::Error NullMusicPlugin::createInstance(MidiDriver **mididriver) const {
- *mididriver = new MidiDriver_NULL();
-
- return Common::kNoError;
-}
-
-MusicDevices NullMusicPlugin::getDevices() const {
+MusicDevices AutoMusicPlugin::getDevices() const {
MusicDevices devices;
- // TODO: return a different music type?
- devices.push_back(MusicDevice(this, "", MT_GM));
+ devices.push_back(MusicDevice(this, "", MT_AUTO));
return devices;
}
-MidiDriver *MidiDriver_NULL_create() {
- MidiDriver *mididriver;
-
- NullMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
-#ifdef DISABLE_ADLIB
-MidiDriver *MidiDriver_ADLIB_create() {
- return MidiDriver_NULL_create();
-}
-#endif
-
//#if PLUGIN_ENABLED_DYNAMIC(NULL)
//REGISTER_PLUGIN_DYNAMIC(NULL, PLUGIN_TYPE_MUSIC, NullMusicPlugin);
//#else
+ REGISTER_PLUGIN_STATIC(AUTO, PLUGIN_TYPE_MUSIC, AutoMusicPlugin);
REGISTER_PLUGIN_STATIC(NULL, PLUGIN_TYPE_MUSIC, NullMusicPlugin);
//#endif
diff --git a/sound/null.h b/sound/null.h
new file mode 100644
index 0000000000..d9343701fa
--- /dev/null
+++ b/sound/null.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef SOUND_NULL_H
+#define SOUND_NULL_H
+
+#include "sound/musicplugin.h"
+#include "sound/mpu401.h"
+#include "common/translation.h"
+
+/* NULL driver */
+class MidiDriver_NULL : public MidiDriver_MPU401 {
+public:
+ int open() { return 0; }
+ void send(uint32 b) { }
+};
+
+
+// Plugin interface
+
+class NullMusicPlugin : public MusicPluginObject {
+public:
+ virtual const char *getName() const {
+ return _s("No music");
+ }
+
+ virtual const char *getId() const {
+ return "null";
+ }
+
+ virtual MusicDevices getDevices() const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
+};
+
+#endif
diff --git a/sound/rate_arm_asm.s b/sound/rate_arm_asm.s
index a0e116f8f7..9431ae0649 100644
--- a/sound/rate_arm_asm.s
+++ b/sound/rate_arm_asm.s
@@ -212,9 +212,6 @@ SimpleRate_M_end:
SimpleRate_M_read:
LDR r0, [r13,#8] @ r0 = sr (8 = 4*2)
ADD r0, r0, #16 @ r0 = inPtr = inBuf
- .ifdef PALMOS_MODE
- LDR r10,[r13,#4*8] @ restore r10
- .endif
STMFD r13!,{r0,r2-r3,r12,r14}
MOV r1, r0 @ r1 = inBuf
@@ -229,9 +226,6 @@ SimpleRate_M_read:
SUBS r1, r0, #1 @ r1 = inLen-1
LDMFD r13!,{r0,r2-r3,r12,r14}
BLT SimpleRate_M_end
- .ifdef PALMOS_MODE
- MOV r10,#0
- .endif
SUBS r2, r2, #1 @ r2 = opos--
ADDGE r0, r0, #2 @ if (r2 >= 0) { sr.inPtr++
BGE SimpleRate_M_loop @ and loop }
@@ -297,9 +291,6 @@ SimpleRate_S_end:
SimpleRate_S_read:
LDR r0, [r13,#8] @ r0 = sr (8 = 4*2)
ADD r0, r0, #16 @ r0 = inPtr = inBuf
- .ifdef PALMOS_MODE
- LDR r10,[r13,#4*8] @ restore r10
- .endif
STMFD r13!,{r0,r2-r3,r12,r14}
MOV r1, r0 @ r1 = inBuf
LDR r0, [r13,#20] @ r0 = AudioStream & input (20 = 4*5)
@@ -313,9 +304,6 @@ SimpleRate_S_read:
SUBS r1, r0, #2 @ r1 = inLen-2
LDMFD r13!,{r0,r2-r3,r12,r14}
BLT SimpleRate_S_end
- .ifdef PALMOS_MODE
- MOV r10,#0
- .endif
SUBS r2, r2, #1 @ r2 = opos--
ADDGE r0, r0, #4 @ if (r2 >= 0) { sr.inPtr += 2
BGE SimpleRate_S_loop @ and loop }
@@ -382,9 +370,6 @@ SimpleRate_R_end:
SimpleRate_R_read:
LDR r0, [r13,#8] @ r0 = sr (8 = 4*2)
ADD r0, r0, #16 @ r0 = inPtr = inBuf
- .ifdef PALMOS_MODE
- LDR r10,[r13,#4*8] @ restore r10
- .endif
STMFD r13!,{r0,r2-r3,r12,r14}
MOV r1, r0 @ r1 = inBuf
@@ -399,9 +384,6 @@ SimpleRate_R_read:
SUBS r1, r0, #2 @ r1 = inLen-2
LDMFD r13!,{r0,r2-r3,r12,r14}
BLT SimpleRate_R_end
- .ifdef PALMOS_MODE
- MOV r10,#0
- .endif
SUBS r2, r2, #1 @ r2 = opos--
ADDGE r0, r0, #4 @ if (r2 >= 0) { sr.inPtr += 2
BGE SimpleRate_R_loop @ and loop }
@@ -484,9 +466,6 @@ LinearRate_M_end:
LDMFD r13!,{r4-r11,PC}
LinearRate_M_read:
ADD r0, r2, #28 @ r0 = inPtr = inBuf
- .ifdef PALMOS_MODE
- LDR r10,[r13,#4*8] @ restore r10
- .endif
STMFD r13!,{r0,r2-r3,r12,r14}
MOV r1, r0 @ r1 = inBuf
@@ -501,9 +480,6 @@ LinearRate_M_read:
SUBS r1, r0, #1 @ r1 = inLen-1
LDMFD r13!,{r0,r2-r3,r12,r14}
BLT LinearRate_M_end
- .ifdef PALMOS_MODE
- MOV r10,#0
- .endif
B LinearRate_M_read_return
_ARM_LinearRate_S:
@@ -592,9 +568,6 @@ LinearRate_S_end:
LDMFD r13!,{r4-r11,PC}
LinearRate_S_read:
ADD r0, r2, #28 @ r0 = inPtr = inBuf
- .ifdef PALMOS_MODE
- LDR r10,[r13,#4*8] @ restore r10
- .endif
STMFD r13!,{r0,r2-r3,r12,r14}
MOV r1, r0 @ r1 = inBuf
@@ -697,9 +670,6 @@ LinearRate_R_end:
LDMFD r13!,{r4-r11,PC}
LinearRate_R_read:
ADD r0, r2, #28 @ r0 = inPtr = inBuf
- .ifdef PALMOS_MODE
- LDR r10,[r13,#4*8] @ restore r10
- .endif
STMFD r13!,{r0,r2-r3,r12,r14}
MOV r1, r0 @ r1 = inBuf
diff --git a/sound/softsynth/adlib.cpp b/sound/softsynth/adlib.cpp
index 6697cef646..ffb359e816 100644
--- a/sound/softsynth/adlib.cpp
+++ b/sound/softsynth/adlib.cpp
@@ -27,6 +27,7 @@
#include "common/util.h"
#include "sound/fmopl.h"
#include "sound/musicplugin.h"
+#include "common/translation.h"
#ifdef DEBUG_ADLIB
static int tick;
@@ -1586,7 +1587,7 @@ void MidiDriver_ADLIB::adlib_note_on(int chan, byte note, int mod) {
class AdLibEmuMusicPlugin : public MusicPluginObject {
public:
const char *getName() const {
- return "AdLib Emulator";
+ return _s("AdLib Emulator");
}
const char *getId() const {
@@ -1594,7 +1595,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices AdLibEmuMusicPlugin::getDevices() const {
@@ -1603,21 +1604,12 @@ MusicDevices AdLibEmuMusicPlugin::getDevices() const {
return devices;
}
-Common::Error AdLibEmuMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error AdLibEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_ADLIB(g_system->getMixer());
return Common::kNoError;
}
-MidiDriver *MidiDriver_ADLIB_create() {
- MidiDriver *mididriver;
-
- AdLibEmuMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(ADLIB)
//REGISTER_PLUGIN_DYNAMIC(ADLIB, PLUGIN_TYPE_MUSIC, AdLibEmuMusicPlugin);
//#else
diff --git a/sound/softsynth/fluidsynth.cpp b/sound/softsynth/fluidsynth.cpp
index c3bd782cc1..fcb4591a20 100644
--- a/sound/softsynth/fluidsynth.cpp
+++ b/sound/softsynth/fluidsynth.cpp
@@ -230,7 +230,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices FluidSynthMusicPlugin::getDevices() const {
@@ -239,21 +239,12 @@ MusicDevices FluidSynthMusicPlugin::getDevices() const {
return devices;
}
-Common::Error FluidSynthMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error FluidSynthMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_FluidSynth(g_system->getMixer());
return Common::kNoError;
}
-MidiDriver *MidiDriver_FluidSynth_create() {
- MidiDriver *mididriver;
-
- FluidSynthMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(FLUIDSYNTH)
//REGISTER_PLUGIN_DYNAMIC(FLUIDSYNTH, PLUGIN_TYPE_MUSIC, FluidSynthMusicPlugin);
//#else
diff --git a/sound/softsynth/fmtowns_pc98/towns_audio.cpp b/sound/softsynth/fmtowns_pc98/towns_audio.cpp
new file mode 100644
index 0000000000..c9ba03ea27
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_audio.cpp
@@ -0,0 +1,1578 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "sound/softsynth/fmtowns_pc98/towns_audio.h"
+#include "sound/audiocd.h"
+#include "common/endian.h"
+
+
+class TownsAudio_PcmChannel {
+friend class TownsAudioInterface;
+public:
+ TownsAudio_PcmChannel();
+ ~TownsAudio_PcmChannel();
+
+private:
+ void loadExtData(uint8 *buffer, uint32 size);
+ void setupLoop(uint32 start, uint32 len);
+ void clear();
+
+ void envAttack();
+ void envDecay();
+ void envSustain();
+ void envRelease();
+
+ uint8 *curInstrument;
+ uint8 note;
+ uint8 velo;
+
+ int8 *data;
+ int8 *dataEnd;
+
+ int8 *loopEnd;
+ uint32 loopLen;
+
+ uint16 stepNote;
+ uint16 stepPitch;
+ uint16 step;
+
+ uint8 panLeft;
+ uint8 panRight;
+
+ uint32 pos;
+
+ uint8 envTotalLevel;
+ uint8 envAttackRate;
+ uint8 envDecayRate;
+ uint8 envSustainLevel;
+ uint8 envSustainRate;
+ uint8 envReleaseRate;
+
+ int16 envStep;
+ int16 envCurrentLevel;
+
+ EnvelopeState envState;
+
+ int8 *extData;
+};
+
+class TownsAudio_WaveTable {
+friend class TownsAudioInterface;
+public:
+ TownsAudio_WaveTable();
+ ~TownsAudio_WaveTable();
+
+private:
+ void readHeader(const uint8 *buffer);
+ void readData(const uint8 *buffer);
+ void clear();
+
+ char name[9];
+ int32 id;
+ uint32 size;
+ uint32 loopStart;
+ uint32 loopLen;
+ uint16 rate;
+ uint16 rateOffs;
+ uint16 baseNote;
+ int8 *data;
+};
+
+TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns),
+ _fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0),
+ _baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver),
+ _pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume),
+ _outputVolumeFlags(0), _outputMuteFlags(0), _ready(false) {
+
+#define INTCB(x) &TownsAudioInterface::intf_##x
+ static const TownsAudioIntfCallback intfCb[] = {
+ // 0
+ INTCB(reset),
+ INTCB(keyOn),
+ INTCB(keyOff),
+ INTCB(setPanPos),
+ // 4
+ INTCB(setInstrument),
+ INTCB(loadInstrument),
+ INTCB(notImpl),
+ INTCB(setPitch),
+ // 8
+ INTCB(setLevel),
+ INTCB(chanOff),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ // 12
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ // 16
+ INTCB(notImpl),
+ INTCB(writeReg),
+ INTCB(notImpl),
+ INTCB(writeRegBuffer),
+ // 20
+ INTCB(readRegBuffer),
+ INTCB(setTimerA),
+ INTCB(setTimerB),
+ INTCB(enableTimerA),
+ // 24
+ INTCB(enableTimerB),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ // 28
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ // 32
+ INTCB(loadSamples),
+ INTCB(reserveEffectChannels),
+ INTCB(loadWaveTable),
+ INTCB(unloadWaveTable),
+ // 36
+ INTCB(notImpl),
+ INTCB(pcmPlayEffect),
+ INTCB(notImpl),
+ INTCB(pcmChanOff),
+ // 40
+ INTCB(pcmEffectPlaying),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ // 44
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ // 48
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(fmKeyOn),
+ INTCB(fmKeyOff),
+ // 52
+ INTCB(fmSetPanPos),
+ INTCB(fmSetInstrument),
+ INTCB(fmLoadInstrument),
+ INTCB(notImpl),
+ // 56
+ INTCB(fmSetPitch),
+ INTCB(fmSetLevel),
+ INTCB(fmReset),
+ INTCB(notImpl),
+ // 60
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ // 64
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(setOutputVolume),
+ // 68
+ INTCB(resetOutputVolume),
+ INTCB(notImpl),
+ INTCB(updateOutputVolume),
+ INTCB(notImpl),
+ // 72
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ // 76
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ // 80
+ INTCB(pcmUpdateEnvelopeGenerator),
+ INTCB(notImpl)
+
+ };
+#undef INTCB
+
+ _intfOpcodes = intfCb;
+
+ memset(_fmSaveReg, 0, sizeof(_fmSaveReg));
+ memset(_outputLevel, 0, sizeof(_outputLevel));
+
+ _timerBase = (uint32)(_baserate * 1000000.0f);
+ _tickLength = 2 * _timerBase;
+}
+
+TownsAudioInterface::~TownsAudioInterface() {
+ delete[] _fmSaveReg[0];
+ delete[] _fmSaveReg[1];
+ delete[] _fmInstruments;
+ delete[] _pcmInstruments;
+ delete[] _waveTables;
+ delete[] _pcmChan;
+}
+
+bool TownsAudioInterface::init() {
+ if (_ready)
+ return true;
+
+ if (!_drv)
+ return false;
+
+ if (!TownsPC98_FmSynth::init())
+ return false;
+
+ _fmSaveReg[0] = new uint8[256];
+ _fmSaveReg[1] = new uint8[256];
+ _fmInstruments = new uint8[128 * 48];
+ _pcmInstruments = new uint8[32 * 128];
+ _waveTables = new TownsAudio_WaveTable[128];
+ _pcmChan = new TownsAudio_PcmChannel[8];
+
+ _timer = 0;
+
+ setVolumeChannelMasks(-1, 0);
+
+ callback(0);
+
+ _ready = true;
+ return true;
+}
+
+int TownsAudioInterface::callback(int command, ...) {
+ if (!_ready)
+ return 1;
+
+ va_list args;
+ va_start(args, command);
+
+ if (command > 81) {
+ va_end(args);
+ return 4;
+ }
+
+ int res = (this->*_intfOpcodes[command])(args);
+
+ va_end(args);
+ return res;
+}
+
+void TownsAudioInterface::setMusicVolume(int volume) {
+ _musicVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);
+ setVolumeIntern(_musicVolume, _sfxVolume);
+}
+
+void TownsAudioInterface::setSoundEffectVolume(int volume) {
+ _sfxVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);
+ setVolumeIntern(_musicVolume, _sfxVolume);
+}
+
+void TownsAudioInterface::setSoundEffectChanMask(int mask) {
+ _pcmSfxChanMask = mask >> 6;
+ mask &= 0x3f;
+ setVolumeChannelMasks(~mask, mask);
+}
+
+void TownsAudioInterface::nextTickEx(int32 *buffer, uint32 bufferSize) {
+ if (!_ready)
+ return;
+
+ for (uint32 i = 0; i < bufferSize; i++) {
+ _timer += _tickLength;
+ while (_timer > 0x514767) {
+ _timer -= 0x514767;
+
+ for (int ii = 0; ii < 8; ii++) {
+ if ((_pcmChanKeyPlaying & _chanFlags[ii]) || (_pcmChanEffectPlaying & _chanFlags[ii])) {
+ TownsAudio_PcmChannel *s = &_pcmChan[ii];
+ s->pos += s->step;
+
+ if (&s->data[s->pos >> 11] >= s->loopEnd) {
+ if (s->loopLen) {
+ s->pos -= s->loopLen;
+ } else {
+ s->pos = 0;
+ _pcmChanEffectPlaying &= ~_chanFlags[ii];
+ _pcmChanKeyPlaying &= ~_chanFlags[ii];
+ }
+ }
+ }
+ }
+ }
+
+ int32 finOutL = 0;
+ int32 finOutR = 0;
+
+ for (int ii = 0; ii < 8; ii++) {
+ if (_pcmChanOut & _chanFlags[ii]) {
+ int32 o = _pcmChan[ii].data[_pcmChan[ii].pos >> 11] * _pcmChan[ii].velo;
+ if ((1 << ii) & (~_pcmSfxChanMask))
+ o = (o * _musicVolume) / Audio::Mixer::kMaxMixerVolume;
+ if ((1 << ii) & _pcmSfxChanMask)
+ o = (o * _sfxVolume) / Audio::Mixer::kMaxMixerVolume;
+ if (_pcmChan[ii].panLeft)
+ finOutL += ((o * _pcmChan[ii].panLeft) >> 3);
+ if (_pcmChan[ii].panRight)
+ finOutR += ((o * _pcmChan[ii].panRight) >> 3);
+ if (!((_pcmChanKeyPlaying & _chanFlags[ii]) || (_pcmChanEffectPlaying & _chanFlags[ii])))
+ _pcmChanOut &= ~_chanFlags[ii];
+ }
+ }
+
+ buffer[i << 1] += finOutL;
+ buffer[(i << 1) + 1] += finOutR;
+ }
+}
+
+void TownsAudioInterface::timerCallbackA() {
+ Common::StackLock lock(_mutex);
+ if (_drv && _ready)
+ _drv->timerCallback(0);
+}
+
+void TownsAudioInterface::timerCallbackB() {
+ Common::StackLock lock(_mutex);
+ if (_drv && _ready) {
+ _drv->timerCallback(1);
+ callback(80);
+ }
+}
+
+int TownsAudioInterface::intf_reset(va_list &args) {
+ Common::StackLock lock(_mutex);
+ fmReset();
+ pcmReset();
+ callback(68);
+ return 0;
+}
+
+int TownsAudioInterface::intf_keyOn(va_list &args) {
+ int chan = va_arg(args, int);
+ int note = va_arg(args, int);
+ int velo = va_arg(args, int);
+ return (chan & 0x40) ? pcmKeyOn(chan, note, velo) : fmKeyOn(chan, note, velo);
+}
+
+int TownsAudioInterface::intf_keyOff(va_list &args) {
+ int chan = va_arg(args, int);
+ return (chan & 0x40) ? pcmKeyOff(chan) : fmKeyOff(chan);
+}
+
+int TownsAudioInterface::intf_setPanPos(va_list &args) {
+ int chan = va_arg(args, int);
+ int mode = va_arg(args, int);
+ return (chan & 0x40) ? pcmSetPanPos(chan, mode) : fmSetPanPos(chan, mode);
+}
+
+int TownsAudioInterface::intf_setInstrument(va_list &args) {
+ int chan = va_arg(args, int);
+ int instrId = va_arg(args, int);
+ return (chan & 0x40) ? pcmSetInstrument(chan, instrId) : fmSetInstrument(chan, instrId);
+}
+
+int TownsAudioInterface::intf_loadInstrument(va_list &args) {
+ int chanType = va_arg(args, int);
+ int instrId = va_arg(args, int);
+ uint8 *instrData = va_arg(args, uint8 *);
+ return (chanType & 0x40) ? pcmLoadInstrument(instrId, instrData) : fmLoadInstrument(instrId, instrData);
+}
+
+int TownsAudioInterface::intf_setPitch(va_list &args) {
+ int chan = va_arg(args, int);
+ int16 pitch = (int16)(va_arg(args, int) & 0xffff);
+ return (chan & 0x40) ? pcmSetPitch(chan, pitch) : fmSetPitch(chan, pitch);
+}
+
+int TownsAudioInterface::intf_setLevel(va_list &args) {
+ int chan = va_arg(args, int);
+ int lvl = va_arg(args, int);
+ return (chan & 0x40) ? pcmSetLevel(chan, lvl) : fmSetLevel(chan, lvl);
+}
+
+int TownsAudioInterface::intf_chanOff(va_list &args) {
+ int chan = va_arg(args, int);
+ return (chan & 0x40) ? pcmChanOff(chan) : fmChanOff(chan);
+}
+
+int TownsAudioInterface::intf_writeReg(va_list &args) {
+ int part = va_arg(args, int) ? 1 : 0;
+ int reg = va_arg(args, int);
+ int val = va_arg(args, int);
+ if ((!part && reg < 0x20) || (part && reg < 0x30) || (reg > 0xb6))
+ return 3;
+
+ bufferedWriteReg(part, reg, val);
+ return 0;
+}
+
+int TownsAudioInterface::intf_writeRegBuffer(va_list &args) {
+ int part = va_arg(args, int) ? 1 : 0;
+ int reg = va_arg(args, int);
+ int val = va_arg(args, int);
+
+ if ((!part && reg < 0x20) || (part && reg < 0x30) || (reg > 0xef))
+ return 3;
+
+ _fmSaveReg[part][reg] = val;
+ return 0;
+}
+
+int TownsAudioInterface::intf_readRegBuffer(va_list &args) {
+ int part = va_arg(args, int) ? 1 : 0;
+ int reg = va_arg(args, int);
+ uint8 *dst = va_arg(args, uint8 *);
+ *dst = 0;
+
+ if ((!part && reg < 0x20) || (part && reg < 0x30) || (reg > 0xef))
+ return 3;
+
+ *dst = _fmSaveReg[part][reg];
+ return 0;
+}
+
+int TownsAudioInterface::intf_setTimerA(va_list &args) {
+ int enable = va_arg(args, int);
+ int tempo = va_arg(args, int);
+
+ if (enable) {
+ bufferedWriteReg(0, 0x25, tempo & 3);
+ bufferedWriteReg(0, 0x24, (tempo >> 2) & 0xff);
+ bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x05);
+ } else {
+ bufferedWriteReg(0, 0x27, (_fmSaveReg[0][0x27] & 0xfa) | 0x10);
+ }
+
+ return 0;
+}
+
+int TownsAudioInterface::intf_setTimerB(va_list &args) {
+ int enable = va_arg(args, int);
+ int tempo = va_arg(args, int);
+
+ if (enable) {
+ bufferedWriteReg(0, 0x26, tempo & 0xff);
+ bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x0A);
+ } else {
+ bufferedWriteReg(0, 0x27, (_fmSaveReg[0][0x27] & 0xf5) | 0x20);
+ }
+
+ return 0;
+}
+
+int TownsAudioInterface::intf_enableTimerA(va_list &args) {
+ bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x15);
+ return 0;
+}
+
+int TownsAudioInterface::intf_enableTimerB(va_list &args) {
+ bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x2a);
+ return 0;
+}
+
+int TownsAudioInterface::intf_loadSamples(va_list &args) {
+ uint32 dest = va_arg(args, uint32);
+ int size = va_arg(args, int);
+ uint8 *src = va_arg(args, uint8*);
+
+ if (dest >= 65536 || size == 0 || size > 65536)
+ return 3;
+ if (size + dest > 65536)
+ return 5;
+
+ int dwIndex = _numWaveTables - 1;
+ for (uint32 t = _waveTablesTotalDataSize; dwIndex && (dest < t); dwIndex--)
+ t -= _waveTables[dwIndex].size;
+
+ TownsAudio_WaveTable *s = &_waveTables[dwIndex];
+ _waveTablesTotalDataSize -= s->size;
+ s->size = size;
+ s->readData(src);
+ _waveTablesTotalDataSize += s->size;
+
+ return 0;
+}
+
+int TownsAudioInterface::intf_reserveEffectChannels(va_list &args) {
+ int numChan = va_arg(args, int);
+ if (numChan > 8)
+ return 3;
+ if ((numChan << 13) + _waveTablesTotalDataSize > 65536)
+ return 5;
+
+ if (numChan == _numReservedChannels)
+ return 0;
+
+ if (numChan < _numReservedChannels) {
+ int c = 8 - _numReservedChannels;
+ for (int i = numChan; i; i--) {
+ uint8 f = ~_chanFlags[c--];
+ _pcmChanEffectPlaying &= f;
+ }
+ } else {
+ int c = 7 - _numReservedChannels;
+ for (int i = numChan - _numReservedChannels; i; i--) {
+ uint8 f = ~_chanFlags[c--];
+ _pcmChanKeyPressed &= f;
+ _pcmChanKeyPlaying &= f;
+ }
+ }
+
+ static const uint8 reserveChanFlags[] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF };
+ _numReservedChannels = numChan;
+ _pcmChanReserved = reserveChanFlags[_numReservedChannels];
+
+ return 0;
+}
+
+int TownsAudioInterface::intf_loadWaveTable(va_list &args) {
+ uint8 *data = va_arg(args, uint8 *);
+ if (_numWaveTables > 127)
+ return 3;
+
+ TownsAudio_WaveTable w;
+ w.readHeader(data);
+ if (!w.size)
+ return 6;
+
+ if (_waveTablesTotalDataSize + w.size > 65504)
+ return 5;
+
+ for (int i = 0; i < _numWaveTables; i++) {
+ if (_waveTables[i].id == w.id)
+ return 10;
+ }
+
+ TownsAudio_WaveTable *s = &_waveTables[_numWaveTables++];
+ s->readHeader(data);
+
+ _waveTablesTotalDataSize += s->size;
+ callback(32, _waveTablesTotalDataSize, s->size, data + 32);
+
+ return 0;
+}
+
+int TownsAudioInterface::intf_unloadWaveTable(va_list &args) {
+ int id = va_arg(args, int);
+
+ if (id == -1) {
+ for (int i = 0; i < 128; i++)
+ _waveTables[i].clear();
+ _numWaveTables = 0;
+ _waveTablesTotalDataSize = 0;
+ } else {
+ if (_waveTables) {
+ for (int i = 0; i < _numWaveTables; i++) {
+ if (_waveTables[i].id == id) {
+ _numWaveTables--;
+ _waveTablesTotalDataSize -= _waveTables[i].size;
+ _waveTables[i].clear();
+ for (; i < _numWaveTables; i++)
+ memcpy(&_waveTables[i], &_waveTables[i + 1], sizeof(TownsAudio_WaveTable));
+ return 0;
+ }
+ return 9;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int TownsAudioInterface::intf_pcmPlayEffect(va_list &args) {
+ int chan = va_arg(args, int);
+ int note = va_arg(args, int);
+ int velo = va_arg(args, int);
+ uint8 *data = va_arg(args, uint8 *);
+
+ if (chan < 0x40 || chan > 0x47)
+ return 1;
+
+ if (note & 0x80 || velo & 0x80)
+ return 3;
+
+ chan -= 0x40;
+
+ if (!(_pcmChanReserved & _chanFlags[chan]))
+ return 7;
+
+ if ((_pcmChanEffectPlaying & _chanFlags[chan]))
+ return 2;
+
+ TownsAudio_WaveTable w;
+ w.readHeader(data);
+
+ if (w.size < (w.loopStart + w.loopLen))
+ return 13;
+
+ if (!w.size)
+ return 6;
+
+ TownsAudio_PcmChannel *p = &_pcmChan[chan];
+
+ _pcmChanNote[chan] = note;
+ _pcmChanVelo[chan] = velo;
+
+ p->note = note;
+ p->velo = velo << 1;
+
+ p->loadExtData(data + 32, w.size);
+ p->setupLoop(w.loopStart, w.loopLen);
+
+ pcmCalcPhaseStep(p, &w);
+ if (p->step > 2048)
+ p->step = 2048;
+
+ _pcmChanEffectPlaying |= _chanFlags[chan];
+ _pcmChanOut |= _chanFlags[chan];
+
+ return 0;
+}
+
+int TownsAudioInterface::intf_pcmChanOff(va_list &args) {
+ int chan = va_arg(args, int);
+ pcmChanOff(chan);
+ return 0;
+}
+
+int TownsAudioInterface::intf_pcmEffectPlaying(va_list &args) {
+ int chan = va_arg(args, int);
+ if (chan < 0x40 || chan > 0x47)
+ return 1;
+ chan -= 0x40;
+ return (_pcmChanEffectPlaying & _chanFlags[chan]) ? true : false;
+}
+
+int TownsAudioInterface::intf_fmKeyOn(va_list &args) {
+ int chan = va_arg(args, int);
+ int note = va_arg(args, int);
+ int velo = va_arg(args, int);
+ return fmKeyOn(chan, note, velo);
+}
+
+int TownsAudioInterface::intf_fmKeyOff(va_list &args) {
+ int chan = va_arg(args, int);
+ return fmKeyOff(chan);
+}
+
+int TownsAudioInterface::intf_fmSetPanPos(va_list &args) {
+ int chan = va_arg(args, int);
+ int mode = va_arg(args, int);
+ return fmSetPanPos(chan, mode);
+}
+
+int TownsAudioInterface::intf_fmSetInstrument(va_list &args) {
+ int chan = va_arg(args, int);
+ int instrId = va_arg(args, int);
+ return fmSetInstrument(chan, instrId);
+}
+
+int TownsAudioInterface::intf_fmLoadInstrument(va_list &args) {
+ int instrId = va_arg(args, int);
+ uint8 *instrData = va_arg(args, uint8 *);
+ return fmLoadInstrument(instrId, instrData);
+}
+
+int TownsAudioInterface::intf_fmSetPitch(va_list &args) {
+ int chan = va_arg(args, int);
+ uint16 freq = va_arg(args, int) & 0xffff;
+ return fmSetPitch(chan, freq);
+}
+
+int TownsAudioInterface::intf_fmSetLevel(va_list &args) {
+ int chan = va_arg(args, int);
+ int lvl = va_arg(args, int);
+ return fmSetLevel(chan, lvl);
+}
+
+int TownsAudioInterface::intf_fmReset(va_list &args) {
+ fmReset();
+ return 0;
+}
+
+int TownsAudioInterface::intf_setOutputVolume(va_list &args) {
+ int chanType = va_arg(args, int);
+ int left = va_arg(args, int);
+ int right = va_arg(args, int);
+
+ if (left & 0xff80 || right & 0xff80)
+ return 3;
+
+ static const uint8 flags[] = { 0x0C, 0x30, 0x40, 0x80 };
+
+ uint8 chan = (chanType & 0x40) ? 8 : 12;
+
+ chanType &= 3;
+ left = (left & 0x7e) >> 1;
+ right = (right & 0x7e) >> 1;
+
+ if (chan)
+ _outputVolumeFlags |= flags[chanType];
+ else
+ _outputVolumeFlags &= ~flags[chanType];
+
+ if (chanType > 1) {
+ _outputLevel[chan + chanType] = left;
+ } else {
+ if (chanType == 0)
+ chan -= 8;
+ _outputLevel[chan] = left;
+ _outputLevel[chan + 1] = right;
+ }
+
+ updateOutputVolume();
+
+ return 0;
+}
+
+int TownsAudioInterface::intf_resetOutputVolume(va_list &args) {
+ memset(_outputLevel, 0, sizeof(_outputLevel));
+ _outputMuteFlags = 0;
+ _outputVolumeFlags = 0;
+ updateOutputVolume();
+ return 0;
+}
+
+int TownsAudioInterface::intf_updateOutputVolume(va_list &args) {
+ int flags = va_arg(args, int);
+ _outputMuteFlags = flags & 3;
+ updateOutputVolume();
+ return 0;
+}
+
+int TownsAudioInterface::intf_pcmUpdateEnvelopeGenerator(va_list &args) {
+ for (int i = 0; i < 8; i++)
+ pcmUpdateEnvelopeGenerator(i);
+ return 0;
+}
+
+int TownsAudioInterface::intf_notImpl(va_list &args) {
+ return 4;
+}
+
+void TownsAudioInterface::fmReset() {
+ TownsPC98_FmSynth::reset();
+
+ _fmChanPlaying = 0;
+ memset(_fmChanNote, 0, sizeof(_fmChanNote));
+ memset(_fmChanPitch, 0, sizeof(_fmChanPitch));
+
+ memset(_fmSaveReg[0], 0, 240);
+ memset(&_fmSaveReg[0][240], 0x7f, 16);
+ memset(_fmSaveReg[1], 0, 256);
+ memset(&_fmSaveReg[1][240], 0x7f, 16);
+ _fmSaveReg[0][243] = _fmSaveReg[0][247] = _fmSaveReg[0][251] = _fmSaveReg[0][255] =
+ _fmSaveReg[1][243] = _fmSaveReg[1][247] = _fmSaveReg[1][251] = _fmSaveReg[1][255] = 0xff;
+
+ for (int i = 0; i < 128; i++)
+ fmLoadInstrument(i, _fmDefaultInstrument);
+
+ bufferedWriteReg(0, 0x21, 0);
+ bufferedWriteReg(0, 0x2C, 0x80);
+ bufferedWriteReg(0, 0x2B, 0);
+ bufferedWriteReg(0, 0x27, 0x30);
+
+ for (int i = 0; i < 6; i++) {
+ fmKeyOff(i);
+ fmSetInstrument(i, 0);
+ fmSetLevel(i, 127);
+ }
+}
+
+int TownsAudioInterface::fmKeyOn(int chan, int note, int velo) {
+ if (chan > 5)
+ return 1;
+ if (note < 12 || note > 107 || (velo & 0x80))
+ return 3;
+ if (_fmChanPlaying & _chanFlags[chan])
+ return 2;
+
+ _fmChanPlaying |= _chanFlags[chan];
+ note -= 12;
+
+ _fmChanNote[chan] = note;
+ int16 pitch = _fmChanPitch[chan];
+
+ uint8 part = chan > 2 ? 1 : 0;
+ if (chan > 2)
+ chan -= 3;
+
+ int frq = 0;
+ uint8 bl = 0;
+
+ if (note) {
+ frq = _frequency[(note - 1) % 12];
+ bl = (note - 1) / 12;
+ } else {
+ frq = 616;
+ }
+
+ frq += pitch;
+
+ if (frq < 616) {
+ if (!bl) {
+ frq = 616;
+ } else {
+ frq += 616;
+ --bl;
+ }
+ } else if (frq > 1232) {
+ if (bl == 7) {
+ frq = 15500;
+ } else {
+ frq -= 616;
+ ++bl;
+ }
+ }
+
+ frq |= (bl << 11);
+
+ bufferedWriteReg(part, chan + 0xa4, (frq >> 8) & 0xff);
+ bufferedWriteReg(part, chan + 0xa0, frq & 0xff);
+
+ velo = (velo >> 2) + 96;
+ uint16 c = _carrier[_fmSaveReg[part][0xb0 + chan] & 7];
+ _fmSaveReg[part][0xe0 + chan] = velo;
+
+ for (uint8 reg = 0x40 + chan; reg < 0x50; reg += 4) {
+ c += c;
+ if (c & 0x100) {
+ c &= 0xff;
+ bufferedWriteReg(part, reg, (((((((_fmSaveReg[part][0x80 + reg] ^ 0x7f) * velo) >> 7) + 1) * _fmSaveReg[part][0xd0 + chan]) >> 7) + 1) ^ 0x7f);
+ }
+ }
+
+ uint8 v = chan;
+ if (part)
+ v |= 4;
+
+ for (uint8 reg = 0x80 + chan; reg < 0x90; reg += 4)
+ writeReg(part, reg, _fmSaveReg[part][reg] | 0x0f);
+
+ writeReg(0, 0x28, v);
+
+ for (uint8 reg = 0x80 + chan; reg < 0x90; reg += 4)
+ writeReg(part, reg, _fmSaveReg[part][reg]);
+
+ bufferedWriteReg(0, 0x28, v | 0xf0);
+
+ return 0;
+}
+
+int TownsAudioInterface::fmKeyOff(int chan) {
+ if (chan > 5)
+ return 1;
+ _fmChanPlaying &= ~_chanFlags[chan];
+ if (chan > 2)
+ chan++;
+ bufferedWriteReg(0, 0x28, chan);
+ return 0;
+}
+
+int TownsAudioInterface::fmChanOff(int chan) {
+ if (chan > 5)
+ return 1;
+ _fmChanPlaying &= ~_chanFlags[chan];
+
+ uint8 part = chan > 2 ? 1 : 0;
+ if (chan > 2)
+ chan -= 3;
+
+ for (uint8 reg = 0x80 + chan; reg < 0x90; reg += 4)
+ writeReg(part, reg, _fmSaveReg[part][reg] | 0x0f);
+
+ if (part)
+ chan += 4;
+ writeReg(0, 0x28, chan);
+ return 0;
+}
+
+int TownsAudioInterface::fmSetPanPos(int chan, int value) {
+ if (chan > 5)
+ return 1;
+
+ uint8 part = chan > 2 ? 1 : 0;
+ if (chan > 2)
+ chan -= 3;
+
+ if (value > 0x40)
+ value = 0x40;
+ else if (value < 0x40)
+ value = 0x80;
+ else
+ value = 0xC0;
+
+ bufferedWriteReg(part, 0xb4 + chan, (_fmSaveReg[part][0xb4 + chan] & 0x3f) | value);
+ return 0;
+}
+
+int TownsAudioInterface::fmSetInstrument(int chan, int instrId) {
+ if (chan > 5)
+ return 1;
+ if (instrId > 127)
+ return 3;
+
+ uint8 part = chan > 2 ? 1 : 0;
+ if (chan > 2)
+ chan -= 3;
+
+ uint8 *src = &_fmInstruments[instrId * 48 + 8];
+
+ uint16 c = _carrier[src[24] & 7];
+ uint8 reg = 0x30 + chan;
+
+ for (; reg < 0x40; reg += 4)
+ bufferedWriteReg(part, reg, *src++);
+
+ for (; reg < 0x50; reg += 4) {
+ uint8 v = *src++;
+ _fmSaveReg[part][0x80 + reg] = _fmSaveReg[part][reg] = v;
+ c += c;
+ if (c & 0x100) {
+ c &= 0xff;
+ v = 127;
+ }
+ writeReg(part, reg, v);
+ }
+
+ for (; reg < 0x90; reg += 4)
+ bufferedWriteReg(part, reg, *src++);
+
+ reg += 0x20;
+ bufferedWriteReg(part, reg, *src++);
+
+ uint8 v = *src++;
+ reg += 4;
+ if (v < 64)
+ v |= (_fmSaveReg[part][reg] & 0xc0);
+ bufferedWriteReg(part, reg, v);
+
+ return 0;
+}
+
+int TownsAudioInterface::fmLoadInstrument(int instrId, const uint8 *data) {
+ if (instrId > 127)
+ return 3;
+ assert(data);
+ memcpy(&_fmInstruments[instrId * 48], data, 48);
+ return 0;
+}
+
+int TownsAudioInterface::fmSetPitch(int chan, int pitch) {
+ if (chan > 5)
+ return 1;
+
+ uint8 bl = _fmChanNote[chan];
+ int frq = 0;
+
+ if (pitch < 0) {
+ if (bl) {
+ if (pitch < -8008)
+ pitch = -8008;
+ pitch *= -1;
+ pitch /= 13;
+ frq = _frequency[(bl - 1) % 12] - pitch;
+ bl = (bl - 1) / 12;
+ _fmChanPitch[chan] = -pitch;
+
+ if (frq < 616) {
+ if (bl) {
+ frq += 616;
+ bl--;
+ } else {
+ frq = 616;
+ bl = 0;
+ }
+ }
+ } else {
+ frq = 616;
+ bl = 0;
+ }
+
+ } else if (pitch > 0) {
+ if (bl < 96) {
+ if (pitch > 8008)
+ pitch = 8008;
+ pitch /= 13;
+
+ if (bl) {
+ frq = _frequency[(bl - 1) % 12] + pitch;
+ bl = (bl - 1) / 12;
+ } else {
+ frq = 616;
+ bl = 0;
+ }
+
+ _fmChanPitch[chan] = pitch;
+
+ if (frq > 1232) {
+ if (bl < 7) {
+ frq -= 616;
+ bl++;
+ } else {
+ frq = 1164;
+ bl = 7;
+ }
+ } else {
+ if (bl >= 7 && frq > 1164)
+ frq = 1164;
+ }
+
+ } else {
+ frq = 1164;
+ bl = 7;
+ }
+ } else {
+ _fmChanPitch[chan] = 0;
+ if (bl) {
+ frq = _frequency[(bl - 1) % 12];
+ bl = (bl - 1) / 12;
+ } else {
+ frq = 616;
+ bl = 0;
+ }
+ }
+
+ uint8 part = chan > 2 ? 1 : 0;
+ if (chan > 2)
+ chan -= 3;
+
+ frq |= (bl << 11);
+
+ bufferedWriteReg(part, chan + 0xa4, (frq >> 8));
+ bufferedWriteReg(part, chan + 0xa0, (frq & 0xff));
+
+ return 0;
+}
+
+int TownsAudioInterface::fmSetLevel(int chan, int lvl) {
+ if (chan > 5)
+ return 1;
+ if (lvl > 127)
+ return 3;
+
+ uint8 part = chan > 2 ? 1 : 0;
+ if (chan > 2)
+ chan -= 3;
+
+ uint16 c = _carrier[_fmSaveReg[part][0xb0 + chan] & 7];
+ _fmSaveReg[part][0xd0 + chan] = lvl;
+
+ for (uint8 reg = 0x40 + chan; reg < 0x50; reg += 4) {
+ c += c;
+ if (c & 0x100) {
+ c &= 0xff;
+ bufferedWriteReg(part, reg, (((((((_fmSaveReg[part][0x80 + reg] ^ 0x7f) * lvl) >> 7) + 1) * _fmSaveReg[part][0xe0 + chan]) >> 7) + 1) ^ 0x7f);
+ }
+ }
+ return 0;
+}
+
+void TownsAudioInterface::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) {
+ _fmSaveReg[part][regAddress] = value;
+ writeReg(part, regAddress, value);
+}
+
+void TownsAudioInterface::pcmReset() {
+ _pcmChanOut = 0;
+ _pcmChanReserved = _pcmChanKeyPressed = _pcmChanEffectPlaying = _pcmChanKeyPlaying = 0;
+ _numReservedChannels = 0;
+
+ memset(_pcmChanNote, 0, 8);
+ memset(_pcmChanVelo, 0, 8);
+ memset(_pcmChanLevel, 0, 8);
+
+ for (int i = 0; i < 8; i++)
+ _pcmChan[i].clear();
+
+ memset(_pcmInstruments, 0, 128 * 32);
+ static uint8 name[] = { 0x4E, 0x6F, 0x20, 0x44, 0x61, 0x74, 0x61, 0x21 };
+ for (int i = 0; i < 32; i++)
+ memcpy(_pcmInstruments + i * 128, name, 8);
+
+ for (int i = 0; i < 128; i++)
+ _waveTables[i].clear();
+ _numWaveTables = 0;
+ _waveTablesTotalDataSize = 0;
+
+ for (int i = 0x40; i < 0x48; i++) {
+ pcmSetInstrument(i, 0);
+ pcmSetLevel(i, 127);
+ }
+}
+
+int TownsAudioInterface::pcmKeyOn(int chan, int note, int velo) {
+ if (chan < 0x40 || chan > 0x47)
+ return 1;
+
+ if (note & 0x80 || velo & 0x80)
+ return 3;
+
+ chan -= 0x40;
+
+ if ((_pcmChanReserved & _chanFlags[chan]) || (_pcmChanKeyPressed & _chanFlags[chan]))
+ return 2;
+
+ _pcmChanNote[chan] = note;
+ _pcmChanVelo[chan] = velo;
+
+ TownsAudio_PcmChannel *p = &_pcmChan[chan];
+ p->note = note;
+
+ uint8 *instr = _pcmChan[chan].curInstrument;
+ int i = 0;
+ for (; i < 8; i++) {
+ if (note <= instr[16 + 2 * i])
+ break;
+ }
+
+ if (i == 8)
+ return 8;
+
+ int il = i << 3;
+ p->note += instr[il + 70];
+
+ p->envTotalLevel = instr[il + 64];
+ p->envAttackRate = instr[il + 65];
+ p->envDecayRate = instr[il + 66];
+ p->envSustainLevel = instr[il + 67];
+ p->envSustainRate = instr[il + 68];
+ p->envReleaseRate = instr[il + 69];
+ p->envStep = 0;
+
+ int32 id = (int32)READ_LE_UINT32(&instr[i * 4 + 32]);
+
+ for (i = 0; i < _numWaveTables; i++) {
+ if (id == _waveTables[i].id)
+ break;
+ }
+
+ if (i == _numWaveTables)
+ return 9;
+
+ TownsAudio_WaveTable *w = &_waveTables[i];
+
+ p->data = w->data;
+ p->dataEnd = w->data + w->size;
+ p->setupLoop(w->loopStart, w->loopLen);
+
+ pcmCalcPhaseStep(p, w);
+
+ uint32 lvl = _pcmChanLevel[chan] * _pcmChanVelo[chan];
+ p->envTotalLevel = ((p->envTotalLevel * lvl) >> 14) & 0xff;
+ p->envSustainLevel = ((p->envSustainLevel * lvl) >> 14) & 0xff;
+
+ p->envAttack();
+ p->velo = (p->envCurrentLevel >> 8) << 1;
+
+ _pcmChanKeyPressed |= _chanFlags[chan];
+ _pcmChanKeyPlaying |= _chanFlags[chan];
+ _pcmChanOut |= _chanFlags[chan];
+
+ return 0;
+}
+
+int TownsAudioInterface::pcmKeyOff(int chan) {
+ if (chan < 0x40 || chan > 0x47)
+ return 1;
+
+ chan -= 0x40;
+ _pcmChanKeyPressed &= ~_chanFlags[chan];
+ _pcmChan[chan].envRelease();
+ return 0;
+}
+
+int TownsAudioInterface::pcmChanOff(int chan) {
+ if (chan < 0x40 || chan > 0x47)
+ return 1;
+
+ chan -= 0x40;
+
+ _pcmChanKeyPressed &= ~_chanFlags[chan];
+ _pcmChanEffectPlaying &= ~_chanFlags[chan];
+ _pcmChanKeyPlaying &= ~_chanFlags[chan];
+ _pcmChanOut &= ~_chanFlags[chan];
+
+ return 0;
+}
+
+int TownsAudioInterface::pcmSetPanPos(int chan, int mode) {
+ if (chan > 0x47)
+ return 1;
+ if (mode & 0x80)
+ return 3;
+
+ chan -= 0x40;
+ uint8 blc = 0x77;
+
+ if (mode > 64) {
+ mode -= 64;
+ blc = ((blc ^ (mode >> 3)) + (mode << 4)) & 0xff;
+ } else if (mode < 64) {
+ mode = (mode >> 3) ^ 7;
+ blc = ((119 + mode) ^ (mode << 4)) & 0xff;
+ }
+
+ _pcmChan[chan].panLeft = blc & 0x0f;
+ _pcmChan[chan].panRight = blc >> 4;
+
+ return 0;
+}
+
+int TownsAudioInterface::pcmSetInstrument(int chan, int instrId) {
+ if (chan > 0x47)
+ return 1;
+ if (instrId > 31)
+ return 3;
+ chan -= 0x40;
+ _pcmChan[chan].curInstrument = &_pcmInstruments[instrId * 128];
+ return 0;
+}
+
+int TownsAudioInterface::pcmLoadInstrument(int instrId, const uint8 *data) {
+ if (instrId > 31)
+ return 3;
+ assert(data);
+ memcpy(&_pcmInstruments[instrId * 128], data, 128);
+ return 0;
+}
+
+int TownsAudioInterface::pcmSetPitch(int chan, int pitch) {
+ if (chan > 0x47)
+ return 1;
+
+ if (pitch < -8192 || pitch > 8191)
+ return 3;
+
+ chan -= 0x40;
+ TownsAudio_PcmChannel *p = &_pcmChan[chan];
+
+ uint32 pts = 0x4000;
+
+ if (pitch < 0)
+ pts = (0x20000000 / (-pitch + 0x2001)) >> 2;
+ else if (pitch > 0)
+ pts = (((pitch + 0x2001) << 16) / 0x2000) >> 2;
+
+ p->stepPitch = pts & 0xffff;
+ p->step = (p->stepNote * p->stepPitch) >> 14;
+
+// if (_pcmChanUnkFlag & _chanFlags[chan])
+// unk[chan] = (((p->step * 1000) << 11) / 98) / 20833;
+
+ /*else*/
+ if ((_pcmChanEffectPlaying & _chanFlags[chan]) && (p->step > 2048))
+ p->step = 2048;
+
+ return 0;
+}
+
+int TownsAudioInterface::pcmSetLevel(int chan, int lvl) {
+ if (chan > 0x47)
+ return 1;
+
+ if (lvl & 0x80)
+ return 3;
+
+ chan -= 0x40;
+ TownsAudio_PcmChannel *p = &_pcmChan[chan];
+
+ if (_pcmChanReserved & _chanFlags[chan]) {
+ _pcmChanVelo[chan] = lvl;
+ p->velo = lvl << 1;
+ } else {
+ int32 t = p->envStep * lvl;
+ if (_pcmChanLevel[chan])
+ t /= _pcmChanLevel[chan];
+ p->envStep = t;
+ t = p->envCurrentLevel * lvl;
+ if (_pcmChanLevel[chan])
+ t /= _pcmChanLevel[chan];
+ p->envCurrentLevel = t;
+ _pcmChanLevel[chan] = lvl;
+ p->velo = p->envCurrentLevel >> 8;
+ }
+
+ return 0;
+}
+
+void TownsAudioInterface::pcmUpdateEnvelopeGenerator(int chan) {
+ TownsAudio_PcmChannel *p = &_pcmChan[chan];
+ if (!p->envCurrentLevel) {
+ _pcmChanKeyPlaying &= ~_chanFlags[chan];
+ p->envState = kEnvReady;
+ }
+
+ if (!(_pcmChanKeyPlaying & _chanFlags[chan]))
+ return;
+
+ switch (p->envState) {
+ case kEnvAttacking:
+ if (((p->envCurrentLevel + p->envStep) >> 8) > p->envTotalLevel) {
+ p->envDecay();
+ return;
+ } else {
+ p->envCurrentLevel += p->envStep;
+ }
+ break;
+
+ case kEnvDecaying:
+ if (((p->envCurrentLevel - p->envStep) >> 8) < p->envSustainLevel) {
+ p->envSustain();
+ return;
+ } else {
+ p->envCurrentLevel -= p->envStep;
+ }
+ break;
+
+ case kEnvSustaining:
+ case kEnvReleasing:
+ p->envCurrentLevel -= p->envStep;
+ if (p->envCurrentLevel <= 0)
+ p->envCurrentLevel = 0;
+ break;
+
+ default:
+ break;
+ }
+ p->velo = (p->envCurrentLevel >> 8) << 1;
+}
+
+void TownsAudioInterface::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) {
+ int8 diff = p->note - w->baseNote;
+ uint16 r = w->rate + w->rateOffs;
+ uint16 bl = 0;
+ uint32 s = 0;
+
+ if (diff < 0) {
+ diff *= -1;
+ bl = diff % 12;
+ diff /= 12;
+ s = (r >> diff);
+ if (bl)
+ s = (s * _pcmPhase2[bl]) >> 16;
+
+ } else if (diff > 0) {
+ bl = diff % 12;
+ diff /= 12;
+ s = (r << diff);
+ if (bl)
+ s += ((s * _pcmPhase1[bl]) >> 16);
+
+ } else {
+ s = r;
+ }
+
+ p->stepNote = s & 0xffff;
+ p->step = (s * p->stepPitch) >> 14;
+}
+
+void TownsAudioInterface::updateOutputVolume() {
+ // FM Towns seems to support volumes of 0 - 63 for each channel.
+ // We recalculate sane values for our 0 to 255 volume range and
+ // balance values for our -128 to 127 volume range
+
+ // CD-AUDIO
+ int vl = (int)(((float)_outputLevel[12] * 127.0f) / 63.0f);
+ int vr = (int)(((float)_outputLevel[13] * 127.0f) / 63.0f);
+ int8 balance = vr - vl;
+ vl = (int)(((float)_outputLevel[12] * 255.0f) / 63.0f);
+ vr = (int)(((float)_outputLevel[13] * 255.0f) / 63.0f);
+ AudioCD.setVolume((vl + vr) >> 1);
+ AudioCD.setBalance(balance);
+}
+
+const uint8 TownsAudioInterface::_chanFlags[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
+};
+
+const uint16 TownsAudioInterface::_frequency[] = {
+ 0x028C, 0x02B4, 0x02DC, 0x030A, 0x0338, 0x0368, 0x039C, 0x03D4, 0x040E, 0x044A, 0x048C, 0x04D0
+};
+
+const uint8 TownsAudioInterface::_carrier[] = {
+ 0x10, 0x10, 0x10, 0x10, 0x30, 0x70, 0x70, 0xF0
+};
+
+const uint8 TownsAudioInterface::_fmDefaultInstrument[] = {
+ 0x45, 0x4C, 0x45, 0x50, 0x49, 0x41, 0x4E, 0x4F, 0x01, 0x0A, 0x02, 0x01,
+ 0x1E, 0x32, 0x05, 0x00, 0x9C, 0xDC, 0x9C, 0xDC, 0x07, 0x03, 0x14, 0x08,
+ 0x00, 0x03, 0x05, 0x05, 0x55, 0x45, 0x27, 0xA7, 0x04, 0xC0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+const uint16 TownsAudioInterface::_pcmPhase1[] = {
+ 0x879B, 0x0F37, 0x1F58, 0x306E, 0x4288, 0x55B6, 0x6A08, 0x7F8F, 0x965E, 0xAE88, 0xC882, 0xE341
+};
+
+const uint16 TownsAudioInterface::_pcmPhase2[] = {
+ 0xFEFE, 0xF1A0, 0xE411, 0xD744, 0xCB2F, 0xBFC7, 0xB504, 0xAAE2, 0xA144, 0x9827, 0x8FAC
+};
+
+TownsAudio_PcmChannel::TownsAudio_PcmChannel() {
+ extData = 0;
+ clear();
+}
+
+TownsAudio_PcmChannel::~TownsAudio_PcmChannel() {
+ clear();
+}
+
+void TownsAudio_PcmChannel::loadExtData(uint8 *buffer, uint32 size) {
+ delete[] extData;
+ extData = new int8[size];
+ int8 *src = (int8 *)buffer;
+ int8 *dst = extData;
+ for (uint32 i = 0; i < size; i++)
+ *dst++ = *src & 0x80 ? (*src++ & 0x7f) : -*src++;
+
+ data = extData;
+ dataEnd = extData + size;
+ pos = 0;
+}
+
+void TownsAudio_PcmChannel::setupLoop(uint32 start, uint32 len) {
+ loopLen = len << 11;
+ loopEnd = loopLen ? &data[(start + loopLen) >> 11] : dataEnd;
+ pos = start;
+}
+
+void TownsAudio_PcmChannel::clear() {
+ curInstrument = 0;
+ note = 0;
+ velo = 0;
+
+ data = 0;
+ dataEnd = 0;
+ loopLen = 0;
+
+ pos = 0;
+ loopEnd = 0;
+
+ step = 0;
+ stepNote = 0x4000;
+ stepPitch = 0x4000;
+
+ panLeft = panRight = 7;
+
+ envTotalLevel = envAttackRate = envDecayRate = envSustainLevel = envSustainRate = envReleaseRate = 0;
+ envStep = envCurrentLevel = 0;
+
+ envState = kEnvReady;
+
+ delete[] extData;
+ extData = 0;
+}
+
+void TownsAudio_PcmChannel::envAttack() {
+ envState = kEnvAttacking;
+ int16 t = envTotalLevel << 8;
+ if (envAttackRate == 127) {
+ envStep = 0;
+ } else if (envAttackRate) {
+ envStep = t / envAttackRate;
+ envCurrentLevel = 1;
+ } else {
+ envCurrentLevel = t;
+ envDecay();
+ }
+}
+
+void TownsAudio_PcmChannel::envDecay() {
+ envState = kEnvDecaying;
+ int16 t = envTotalLevel - envSustainLevel;
+ if (t < 0 || envDecayRate == 127) {
+ envStep = 0;
+ } else if (envDecayRate) {
+ envStep = (t << 8) / envDecayRate;
+ } else {
+ envCurrentLevel = envSustainLevel << 8;
+ envSustain();
+ }
+}
+
+void TownsAudio_PcmChannel::envSustain() {
+ envState = kEnvSustaining;
+ if (envSustainLevel && envSustainRate)
+ envStep = (envSustainRate == 127) ? 0 : (envCurrentLevel / envSustainRate) >> 1;
+ else
+ envStep = envCurrentLevel = 1;
+}
+
+void TownsAudio_PcmChannel::envRelease() {
+ envState = kEnvReleasing;
+ if (envReleaseRate == 127)
+ envStep = 0;
+ else if (envReleaseRate)
+ envStep = envCurrentLevel / envReleaseRate;
+ else
+ envStep = envCurrentLevel = 1;
+}
+
+TownsAudio_WaveTable::TownsAudio_WaveTable() {
+ data = 0;
+ clear();
+}
+
+TownsAudio_WaveTable::~TownsAudio_WaveTable() {
+ clear();
+}
+
+void TownsAudio_WaveTable::readHeader(const uint8 *buffer) {
+ memcpy(name, buffer, 8);
+ name[8] = 0;
+ id = READ_LE_UINT32(&buffer[8]);
+ size = READ_LE_UINT32(&buffer[12]);
+ loopStart = READ_LE_UINT32(&buffer[16]);
+ loopLen = READ_LE_UINT32(&buffer[20]);
+ rate = READ_LE_UINT16(&buffer[24]);
+ rateOffs = READ_LE_UINT16(&buffer[26]);
+ baseNote = READ_LE_UINT32(&buffer[28]);
+}
+
+void TownsAudio_WaveTable::readData(const uint8 *buffer) {
+ if (!size)
+ return;
+
+ delete[] data;
+ data = new int8[size];
+
+ const int8 *src = (const int8 *)buffer;
+ int8 *dst = data;
+ for (uint32 i = 0; i < size; i++)
+ *dst++ = *src & 0x80 ? (*src++ & 0x7f) : -*src++;
+}
+
+void TownsAudio_WaveTable::clear() {
+ name[0] = name[8] = 0;
+ id = -1;
+ size = 0;
+ loopStart = 0;
+ loopLen = 0;
+ rate = 0;
+ rateOffs = 0;
+ baseNote = 0;
+ delete[] data;
+ data = 0;
+}
+
diff --git a/sound/softsynth/fmtowns_pc98/towns_audio.h b/sound/softsynth/fmtowns_pc98/towns_audio.h
new file mode 100644
index 0000000000..950c016b4e
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_audio.h
@@ -0,0 +1,178 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 TOWNS_AUDIO_H
+#define TOWNS_AUDIO_H
+
+#include "sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
+
+class TownsAudioInterfacePluginDriver {
+public:
+ virtual ~TownsAudioInterfacePluginDriver() {}
+ virtual void timerCallback(int timerId) = 0;
+};
+
+class TownsAudio_PcmChannel;
+class TownsAudio_WaveTable;
+
+class TownsAudioInterface : public TownsPC98_FmSynth {
+public:
+ TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);
+ ~TownsAudioInterface();
+
+ bool init();
+
+ int callback(int command, ...);
+
+ void setMusicVolume(int volume);
+ void setSoundEffectVolume(int volume);
+ // Defines the channels used as sound effect channels for the purpose of ScummVM GUI volume control.
+ // The first 6 bits are the 6 fm channels. The next 8 bits are pcm channels.
+ void setSoundEffectChanMask(int mask);
+
+private:
+ void nextTickEx(int32 *buffer, uint32 bufferSize);
+
+ void timerCallbackA();
+ void timerCallbackB();
+
+ typedef int (TownsAudioInterface::*TownsAudioIntfCallback)(va_list &);
+ const TownsAudioIntfCallback *_intfOpcodes;
+
+ int intf_reset(va_list &args);
+ int intf_keyOn(va_list &args);
+ int intf_keyOff(va_list &args);
+ int intf_setPanPos(va_list &args);
+ int intf_setInstrument(va_list &args);
+ int intf_loadInstrument(va_list &args);
+ int intf_setPitch(va_list &args);
+ int intf_setLevel(va_list &args);
+ int intf_chanOff(va_list &args);
+ int intf_writeReg(va_list &args);
+ int intf_writeRegBuffer(va_list &args);
+ int intf_readRegBuffer(va_list &args);
+ int intf_setTimerA(va_list &args);
+ int intf_setTimerB(va_list &args);
+ int intf_enableTimerA(va_list &args);
+ int intf_enableTimerB(va_list &args);
+ int intf_loadSamples(va_list &args);
+ int intf_reserveEffectChannels(va_list &args);
+ int intf_loadWaveTable(va_list &args);
+ int intf_unloadWaveTable(va_list &args);
+ int intf_pcmPlayEffect(va_list &args);
+ int intf_pcmChanOff(va_list &args);
+ int intf_pcmEffectPlaying(va_list &args);
+ int intf_fmKeyOn(va_list &args);
+ int intf_fmKeyOff(va_list &args);
+ int intf_fmSetPanPos(va_list &args);
+ int intf_fmSetInstrument(va_list &args);
+ int intf_fmLoadInstrument(va_list &args);
+ int intf_fmSetPitch(va_list &args);
+ int intf_fmSetLevel(va_list &args);
+ int intf_fmReset(va_list &args);
+ int intf_setOutputVolume(va_list &args);
+ int intf_resetOutputVolume(va_list &args);
+ int intf_updateOutputVolume(va_list &args);
+ int intf_pcmUpdateEnvelopeGenerator(va_list &args);
+
+ int intf_notImpl(va_list &args);
+
+ void fmReset();
+ int fmKeyOn(int chan, int note, int velo);
+ int fmKeyOff(int chan);
+ int fmChanOff(int chan);
+ int fmSetPanPos(int chan, int mode);
+ int fmSetInstrument(int chan, int instrId);
+ int fmLoadInstrument(int instrId, const uint8 *data);
+ int fmSetPitch(int chan, int pitch);
+ int fmSetLevel(int chan, int lvl);
+
+ void bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value);
+
+ uint8 _fmChanPlaying;
+ uint8 _fmChanNote[6];
+ int16 _fmChanPitch[6];
+
+ uint8 *_fmSaveReg[2];
+ uint8 *_fmInstruments;
+
+ void pcmReset();
+ int pcmKeyOn(int chan, int note, int velo);
+ int pcmKeyOff(int chan);
+ int pcmChanOff(int chan);
+ int pcmSetPanPos(int chan, int mode);
+ int pcmSetInstrument(int chan, int instrId);
+ int pcmLoadInstrument(int instrId, const uint8 *data);
+ int pcmSetPitch(int chan, int pitch);
+ int pcmSetLevel(int chan, int lvl);
+ void pcmUpdateEnvelopeGenerator(int chan);
+
+ TownsAudio_PcmChannel *_pcmChan;
+ uint8 _pcmChanOut;
+ uint8 _pcmChanReserved;
+ uint8 _pcmChanKeyPressed;
+ uint8 _pcmChanEffectPlaying;
+ uint8 _pcmChanKeyPlaying;
+
+ uint8 _pcmChanNote[8];
+ uint8 _pcmChanVelo[8];
+ uint8 _pcmChanLevel[8];
+
+ uint8 _numReservedChannels;
+ uint8 *_pcmInstruments;
+
+ TownsAudio_WaveTable *_waveTables;
+ uint8 _numWaveTables;
+ uint32 _waveTablesTotalDataSize;
+
+ void pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w);
+
+ void updateOutputVolume();
+ uint8 _outputVolumeFlags;
+ uint8 _outputLevel[16];
+ uint8 _outputMuteFlags;
+
+ const float _baserate;
+ uint32 _timerBase;
+ uint32 _tickLength;
+ uint32 _timer;
+
+ uint16 _musicVolume;
+ uint16 _sfxVolume;
+ int _pcmSfxChanMask;
+
+ TownsAudioInterfacePluginDriver *_drv;
+ bool _ready;
+
+ static const uint8 _chanFlags[];
+ static const uint16 _frequency[];
+ static const uint8 _carrier[];
+ static const uint8 _fmDefaultInstrument[];
+ static const uint16 _pcmPhase1[];
+ static const uint16 _pcmPhase2[];
+};
+
+#endif
+
diff --git a/sound/softsynth/fmtowns_pc98/towns_euphony.cpp b/sound/softsynth/fmtowns_pc98/towns_euphony.cpp
new file mode 100644
index 0000000000..0c0c203cc9
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_euphony.cpp
@@ -0,0 +1,907 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "sound/softsynth/fmtowns_pc98/towns_euphony.h"
+#include "common/endian.h"
+
+TownsEuphonyDriver::TownsEuphonyDriver(Audio::Mixer *mixer) : _activeChannels(0), _sustainChannels(0),
+ _assignedChannels(0), _paraCount(0), _command(0), _tEnable(0), _tMode(0), _tOrdr(0), _tLevel(0),
+ _tTranspose(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0),
+ _tempoControlMode(0) {
+ _para[0] = _para[1] = 0;
+ _intf = new TownsAudioInterface(mixer, this);
+ resetTempo();
+}
+
+TownsEuphonyDriver::~TownsEuphonyDriver() {
+ delete[] _activeChannels;
+ delete[] _sustainChannels;
+ delete[] _assignedChannels;
+
+ delete[] _tEnable;
+ delete[] _tMode;
+ delete[] _tOrdr;
+ delete[] _tLevel;
+ delete[] _tTranspose;
+
+ delete _intf;
+}
+
+bool TownsEuphonyDriver::init() {
+ if (!_intf->init())
+ return false;
+
+ _activeChannels = new int8[16];
+ _sustainChannels = new int8[16];
+ _assignedChannels = new ActiveChannel[128];
+ _eventBuffer = new DlEvent[64];
+
+ _tEnable = new uint8[32];
+ _tMode = new uint8[32];
+ _tOrdr = new uint8[32];
+ _tLevel = new int8[32];
+ _tTranspose = new int8[32];
+
+ reset();
+
+ return true;
+}
+
+void TownsEuphonyDriver::reset() {
+ _intf->callback(0);
+
+ _intf->callback(74);
+ _intf->callback(70);
+ _intf->callback(75, 3);
+
+ setTimerA(true, 1);
+ setTimerA(false, 1);
+ setTimerB(true, 221);
+
+ _paraCount = _command = _para[0] = _para[1] = 0;
+ memset(_sustainChannels, 0, 16);
+ memset(_activeChannels, -1, 16);
+ for (int i = 0; i < 128; i++) {
+ _assignedChannels[i].chan = _assignedChannels[i].next = -1;
+ _assignedChannels[i].note = _assignedChannels[i].sub = 0;
+ }
+
+ int e = 0;
+ for (int i = 0; i < 6; i++)
+ assignChannel(i, e++);
+ for (int i = 0x40; i < 0x48; i++)
+ assignChannel(i, e++);
+
+ resetTables();
+
+ memset(_eventBuffer, 0, 64 * sizeof(DlEvent));
+ _bufferedEventsCount = 0;
+
+ _playing = _endOfTrack = _suspendParsing = _loop = false;
+ _elapsedEvents = 0;
+ _tempoDiff = 0;
+
+ resetTempo();
+
+ if (_tempoControlMode == 1) {
+ //if (///)
+ // return;
+ setTempoIntern(_defaultTempo);
+ } else {
+ setTempoIntern(_defaultTempo);
+ }
+
+ resetControl();
+}
+
+void TownsEuphonyDriver::loadInstrument(int chanType, int id, const uint8 *data) {
+ _intf->callback(5, chanType, id, data);
+}
+
+void TownsEuphonyDriver::loadWaveTable(const uint8 *data) {
+ _intf->callback(34, data);
+}
+
+void TownsEuphonyDriver::unloadWaveTable(int id) {
+ _intf->callback(35, id);
+}
+
+void TownsEuphonyDriver::reserveSoundEffectChannels(int num) {
+ _intf->callback(33, num);
+ uint32 volMask = 0;
+
+ if (num > 8)
+ return;
+
+ for (uint32 v = 1 << 13; num; num--) {
+ volMask |= v;
+ v >>= 1;
+ }
+
+ _intf->setSoundEffectChanMask(volMask);
+}
+
+int TownsEuphonyDriver::setMusicTempo(int tempo) {
+ if (tempo > 250)
+ return 3;
+ _defaultTempo = tempo;
+ _trackTempo = tempo;
+ setTempoIntern(tempo);
+ return 0;
+}
+
+int TownsEuphonyDriver::startMusicTrack(const uint8 *data, int trackSize, int startTick) {
+ if (_playing)
+ return 2;
+
+ _musicPos = _musicStart = data;
+ _defaultBaseTickLen = _baseTickLen = startTick;
+ _musicTrackSize = trackSize;
+ _timeStampBase = _timeStampDest = 0;
+ _tickCounter = 0;
+ _playing = true;
+
+ return 0;
+}
+
+void TownsEuphonyDriver::setMusicLoop(bool loop) {
+ _loop = loop;
+}
+
+void TownsEuphonyDriver::stopParser() {
+ if (_playing) {
+ _playing = false;
+ _pulseCount = 0;
+ _endOfTrack = false;
+ flushEventBuffer();
+ resetControl();
+ }
+}
+
+void TownsEuphonyDriver::continueParsing() {
+ _suspendParsing = false;
+}
+
+void TownsEuphonyDriver::playSoundEffect(int chan, int note, int velo, const uint8 *data) {
+ _intf->callback(37, chan, note, velo, data);
+}
+
+void TownsEuphonyDriver::stopSoundEffect(int chan) {
+ _intf->callback(39, chan);
+}
+
+bool TownsEuphonyDriver::soundEffectIsPlaying(int chan) {
+ return _intf->callback(40, chan) ? true : false;
+}
+
+void TownsEuphonyDriver::chanPanPos(int chan, int mode) {
+ _intf->callback(3, chan, mode);
+}
+
+void TownsEuphonyDriver::chanPitch(int chan, int pitch) {
+ _intf->callback(7, chan, pitch);
+}
+
+void TownsEuphonyDriver::chanVolume(int chan, int vol) {
+ _intf->callback(8, chan, vol);
+}
+
+void TownsEuphonyDriver::setOutputVolume(int mode, int volLeft, int volRight) {
+ _intf->callback(67, mode, volLeft, volRight);
+}
+
+int TownsEuphonyDriver::chanEnable(int tableEntry, int val) {
+ if (tableEntry > 31)
+ return 3;
+ _tEnable[tableEntry] = val;
+ return 0;
+}
+
+int TownsEuphonyDriver::chanMode(int tableEntry, int val) {
+ if (tableEntry > 31)
+ return 3;
+ _tMode[tableEntry] = val;
+ return 0;
+}
+
+int TownsEuphonyDriver::chanOrdr(int tableEntry, int val) {
+ if (tableEntry > 31)
+ return 3;
+ if (val < 16)
+ _tOrdr[tableEntry] = val;
+ return 0;
+}
+
+int TownsEuphonyDriver::chanVolumeShift(int tableEntry, int val) {
+ if (tableEntry > 31)
+ return 3;
+ if (val <= 40)
+ _tLevel[tableEntry] = (int8)(val & 0xff);
+ return 0;
+}
+
+int TownsEuphonyDriver::chanNoteShift(int tableEntry, int val) {
+ if (tableEntry > 31)
+ return 3;
+ if (val <= 40)
+ _tTranspose[tableEntry] = (int8)(val & 0xff);
+ return 0;
+}
+
+int TownsEuphonyDriver::assignChannel(int chan, int tableEntry) {
+ if (tableEntry > 15 || chan > 127 || chan < 0)
+ return 3;
+
+ ActiveChannel *a = &_assignedChannels[chan];
+ if (a->chan == tableEntry)
+ return 0;
+
+ if (a->chan != -1) {
+ int8 *b = &_activeChannels[a->chan];
+ while (*b != chan) {
+ b = &_assignedChannels[*b].next;
+ if (*b == -1 && *b != chan)
+ return 3;
+ }
+
+ *b = a->next;
+
+ if (a->note)
+ _intf->callback(2, chan);
+
+ a->chan = a->next = -1;
+ a->note = 0;
+ }
+
+ a->next = _activeChannels[tableEntry];
+ _activeChannels[tableEntry] = chan;
+ a->chan = tableEntry;
+ a->note = a->sub = 0;
+
+ return 0;
+}
+
+void TownsEuphonyDriver::timerCallback(int timerId) {
+ switch (timerId) {
+ case 0:
+ updatePulseCount();
+ while (_pulseCount > 0) {
+ --_pulseCount;
+ updateTimeStampBase();
+ if (!_playing)
+ continue;
+ updateEventBuffer();
+ updateParser();
+ updateCheckEot();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void TownsEuphonyDriver::setMusicVolume(int volume) {
+ _intf->setMusicVolume(volume);
+}
+
+void TownsEuphonyDriver::setSoundEffectVolume(int volume) {
+ _intf->setSoundEffectVolume(volume);
+}
+
+void TownsEuphonyDriver::resetTables() {
+ memset(_tEnable, 0xff, 32);
+ memset(_tMode, 0xff, 16);
+ memset(_tMode + 16, 0, 16);
+ for (int i = 0; i < 32; i++)
+ _tOrdr[i] = i & 0x0f;
+ memset(_tLevel, 0, 32);
+ memset(_tTranspose, 0, 32);
+}
+
+void TownsEuphonyDriver::resetTempo() {
+ _defaultBaseTickLen = _baseTickLen = 0x33;
+ _pulseCount = 0;
+ _extraTimingControlRemainder = 0;
+ _extraTimingControl = 16;
+ _tempoModifier = 0;
+ _timeStampDest = 0;
+ _deltaTicks = 0;
+ _tickCounter = 0;
+ _defaultTempo = 90;
+ _trackTempo = 90;
+}
+
+void TownsEuphonyDriver::setTempoIntern(int tempo) {
+ tempo = CLIP(tempo + _tempoModifier, 0, 500);
+ if (_tempoControlMode == 0) {
+ _timerSetting = 34750 / (tempo + 30);
+ _extraTimingControl = 16;
+
+ while (_timerSetting < 126) {
+ _timerSetting <<= 1;
+ _extraTimingControl <<= 1;
+ }
+
+ while (_timerSetting > 383) {
+ _timerSetting >>= 1;
+ _extraTimingControl >>= 1;
+ }
+
+ setTimerA(true, -(_timerSetting - 2));
+
+ } else if (_tempoControlMode == 1) {
+ _timerSetting = 312500 / (tempo + 30);
+ _extraTimingControl = 16;
+ while (_timerSetting < 1105) {
+ _timerSetting <<= 1;
+ _extraTimingControl <<= 1;
+ }
+
+ } else if (_tempoControlMode == 2) {
+ _timerSetting = 625000 / (tempo + 30);
+ _extraTimingControlRemainder = 0;
+ }
+}
+
+void TownsEuphonyDriver::setTimerA(bool enable, int tempo) {
+ _intf->callback(21, enable ? 255 : 0, tempo);
+}
+
+void TownsEuphonyDriver::setTimerB(bool enable, int tempo) {
+ _intf->callback(22, enable ? 255 : 0, tempo);
+}
+
+void TownsEuphonyDriver::updatePulseCount() {
+ int tc = _extraTimingControl + _extraTimingControlRemainder;
+ _extraTimingControlRemainder = tc & 0x0f;
+ tc >>= 4;
+ _tempoDiff -= tc;
+
+ while (_tempoDiff < 0) {
+ _elapsedEvents++;
+ _tempoDiff += 4;
+ }
+
+ if (_playing && !_suspendParsing)
+ _pulseCount += tc;
+}
+
+void TownsEuphonyDriver::updateTimeStampBase() {
+ static const uint16 table[] = { 0x180, 0xC0, 0x80, 0x60, 0x40, 0x30, 0x20, 0x18 };
+ if ((uint32)(table[_baseTickLen >> 4] * ((_baseTickLen & 0x0f) + 1)) > ++_tickCounter)
+ return;
+ ++_timeStampDest;
+ _tickCounter = 0;
+ _deltaTicks = 0;
+}
+
+void TownsEuphonyDriver::updateParser() {
+ for (bool loop = true; loop;) {
+ uint8 cmd = _musicPos[0];
+
+ if (cmd == 0xff || cmd == 0xf7) {
+ jumpNextLoop();
+
+ } else if (cmd < 0x90) {
+ _endOfTrack = true;
+ flushEventBuffer();
+ loop = false;
+
+ } else if (_timeStampBase > _timeStampDest) {
+ loop = false;
+
+ } else {
+ if (_timeStampBase == _timeStampDest) {
+ uint16 timeStamp = READ_LE_UINT16(&_musicPos[2]);
+ uint8 l = (timeStamp & 0xff) + (timeStamp & 0xff);
+ timeStamp = ((timeStamp & 0xff00) | l) >> 1;
+ if (timeStamp > _tickCounter)
+ loop = false;
+ }
+
+ if (loop) {
+ if (parseNext())
+ loop = false;
+ }
+ }
+ }
+}
+
+void TownsEuphonyDriver::updateCheckEot() {
+ if (!_endOfTrack || _bufferedEventsCount)
+ return;
+ stopParser();
+}
+
+bool TownsEuphonyDriver::parseNext() {
+#define OPC(x) &TownsEuphonyDriver::evt##x
+ static const EuphonyOpcode opcodes[] = {
+ OPC(NotImpl),
+ OPC(SetupNote),
+ OPC(PolyphonicAftertouch),
+ OPC(ControlPitch),
+ OPC(InstrumentChanAftertouch),
+ OPC(InstrumentChanAftertouch),
+ OPC(ControlPitch)
+ };
+#undef OPC
+
+ uint cmd = _musicPos[0];
+ if (cmd != 0xfe && cmd != 0xfd) {
+ if (cmd >= 0xf0) {
+ cmd &= 0x0f;
+ if (cmd == 0)
+ evtLoadInstrument();
+ else if (cmd == 2)
+ evtAdvanceTimestampOffset();
+ else if (cmd == 8)
+ evtTempo();
+ else if (cmd == 12)
+ evtModeOrdrChange();
+ jumpNextLoop();
+ return false;
+
+ } else if (!(this->*opcodes[(cmd - 0x80) >> 4])()) {
+ jumpNextLoop();
+ return false;
+ }
+ }
+
+ if (cmd == 0xfd) {
+ _suspendParsing = true;
+ return true;
+ }
+
+ if (!_loop) {
+ _endOfTrack = true;
+ return true;
+ }
+
+ _endOfTrack = false;
+ _musicPos = _musicStart;
+ _timeStampBase = _timeStampDest = _tickCounter = 0;
+ _baseTickLen = _defaultBaseTickLen;
+
+ return false;
+}
+
+void TownsEuphonyDriver::jumpNextLoop() {
+ _musicPos += 6;
+ if (_musicPos >= _musicStart + _musicTrackSize)
+ _musicPos = _musicStart;
+}
+
+void TownsEuphonyDriver::updateEventBuffer() {
+ DlEvent *e = _eventBuffer;
+ for (int i = _bufferedEventsCount; i; e++) {
+ if (e->evt == 0)
+ continue;
+ if (--e->len) {
+ --i;
+ continue;
+ }
+ processBufferNote(e->mode, e->evt, e->note, e->velo);
+ e->evt = 0;
+ --i;
+ --_bufferedEventsCount;
+ }
+}
+
+void TownsEuphonyDriver::flushEventBuffer() {
+ DlEvent *e = _eventBuffer;
+ for (int i = _bufferedEventsCount; i; e++) {
+ if (e->evt == 0)
+ continue;
+ processBufferNote(e->mode, e->evt, e->note, e->velo);
+ e->evt = 0;
+ --i;
+ --_bufferedEventsCount;
+ }
+}
+
+void TownsEuphonyDriver::processBufferNote(int mode, int evt, int note, int velo) {
+ if (!velo)
+ evt &= 0x8f;
+ sendEvent(mode, evt);
+ sendEvent(mode, note);
+ sendEvent(mode, velo);
+}
+
+void TownsEuphonyDriver::resetControl() {
+ for (int i = 0; i < 32; i++) {
+ if (_tOrdr[i] > 15) {
+ for (int ii = 0; ii < 16; ii++)
+ resetControlIntern(_tMode[i], ii);
+ } else {
+ resetControlIntern(_tMode[i], _tOrdr[i]);
+ }
+ }
+}
+
+void TownsEuphonyDriver::resetControlIntern(int mode, int chan) {
+ sendEvent(mode, 0xb0 | chan);
+ sendEvent(mode, 0x40);
+ sendEvent(mode, 0);
+ sendEvent(mode, 0xb0 | chan);
+ sendEvent(mode, 0x7b);
+ sendEvent(mode, 0);
+ sendEvent(mode, 0xb0 | chan);
+ sendEvent(mode, 0x79);
+ sendEvent(mode, 0x40);
+}
+
+uint8 TownsEuphonyDriver::appendEvent(uint8 evt, uint8 chan) {
+ if (evt >= 0x80 && evt < 0xf0 && _tOrdr[chan] < 16)
+ return (evt & 0xf0) | _tOrdr[chan];
+ return evt;
+}
+
+void TownsEuphonyDriver::sendEvent(uint8 mode, uint8 command) {
+ if (mode == 0) {
+ warning("TownsEuphonyDriver: Mode 0 not implemented.");
+
+ } else if (mode == 0x10) {
+ warning("TownsEuphonyDriver: Mode 0x10 not implemented.");
+
+ } else if (mode == 0xff) {
+ if (command >= 0xf0) {
+ _paraCount = 1;
+ _command = 0;
+ } else if (command >= 0x80) {
+ _paraCount = 1;
+ _command = command;
+ } else if (_command >= 0x80) {
+ switch ((_command - 0x80) >> 4) {
+ case 0:
+ if (_paraCount < 2) {
+ _paraCount++;
+ _para[0] = command;
+ } else {
+ _paraCount = 1;
+ _para[1] = command;
+ sendNoteOff();
+ }
+ break;
+
+ case 1:
+ if (_paraCount < 2) {
+ _paraCount++;
+ _para[0] = command;
+ } else {
+ _paraCount = 1;
+ _para[1] = command;
+ if (command)
+ sendNoteOn();
+ else
+ sendNoteOff();
+ }
+ break;
+
+ case 2:
+ if (_paraCount < 2) {
+ _paraCount++;
+ _para[0] = command;
+ } else {
+ _paraCount = 1;
+ }
+ break;
+
+ case 3:
+ if (_paraCount < 2) {
+ _paraCount++;
+ _para[0] = command;
+ } else {
+ _paraCount = 1;
+ _para[1] = command;
+
+ if (_para[0] == 7)
+ sendChanVolume();
+ else if (_para[0] == 10)
+ sendPanPosition();
+ else if (_para[0] == 64)
+ sendAllNotesOff();
+ }
+ break;
+
+ case 4:
+ _paraCount = 1;
+ _para[0] = command;
+ sendSetInstrument();
+ break;
+
+ case 5:
+ _paraCount = 1;
+ _para[0] = command;
+ break;
+
+ case 6:
+ if (_paraCount < 2) {
+ _paraCount++;
+ _para[0] = command;
+ } else {
+ _paraCount = 1;
+ _para[1] = command;
+ sendPitch();
+ }
+ break;
+ }
+ }
+ }
+}
+
+bool TownsEuphonyDriver::evtSetupNote() {
+ if (_musicPos[1] > 31)
+ return false;
+ if (!_tEnable[_musicPos[1]]) {
+ jumpNextLoop();
+ return (_musicPos[0] == 0xfe || _musicPos[0] == 0xfd) ? true : false;
+ }
+ uint8 evt = appendEvent(_musicPos[0], _musicPos[1]);
+ uint8 mode = _tMode[_musicPos[1]];
+ uint8 note = _musicPos[4];
+ uint8 velo = _musicPos[5];
+
+ sendEvent(mode, evt);
+ sendEvent(mode, applyNoteShift(note));
+ sendEvent(mode, applyVolumeShift(velo));
+
+ jumpNextLoop();
+ if (_musicPos[0] == 0xfe || _musicPos[0] == 0xfd)
+ return true;
+
+ velo = _musicPos[5];
+ uint16 len = ((((_musicPos[1] << 4) | (_musicPos[2] << 8)) >> 4) & 0xff) | ((((_musicPos[3] << 4) | (_musicPos[4] << 8)) >> 4) << 8);
+
+ int i = 0;
+ for (; i < 64; i++) {
+ if (_eventBuffer[i].evt == 0)
+ break;
+ }
+
+ if (i == 64) {
+ processBufferNote(mode, evt, note, velo);
+ } else {
+ _eventBuffer[i].evt = evt;
+ _eventBuffer[i].mode = mode;
+ _eventBuffer[i].note = note;
+ _eventBuffer[i].velo = velo;
+ _eventBuffer[i].len = len ? len : 1;
+ _bufferedEventsCount++;
+ }
+
+ return false;
+}
+
+bool TownsEuphonyDriver::evtPolyphonicAftertouch() {
+ if (_musicPos[1] > 31)
+ return false;
+ if (!_tEnable[_musicPos[1]])
+ return false;
+
+ uint8 evt = appendEvent(_musicPos[0], _musicPos[1]);
+ uint8 mode = _tMode[_musicPos[1]];
+
+ sendEvent(mode, evt);
+ sendEvent(mode, applyNoteShift(_musicPos[4]));
+ sendEvent(mode, _musicPos[5]);
+
+ return false;
+}
+
+bool TownsEuphonyDriver::evtControlPitch() {
+ if (_musicPos[1] > 31)
+ return false;
+ if (!_tEnable[_musicPos[1]])
+ return false;
+
+ uint8 evt = appendEvent(_musicPos[0], _musicPos[1]);
+ uint8 mode = _tMode[_musicPos[1]];
+
+ sendEvent(mode, evt);
+ sendEvent(mode, _musicPos[4]);
+ sendEvent(mode, _musicPos[5]);
+
+ return false;
+}
+
+bool TownsEuphonyDriver::evtInstrumentChanAftertouch() {
+ if (_musicPos[1] > 31)
+ return false;
+ if (!_tEnable[_musicPos[1]])
+ return false;
+
+ uint8 evt = appendEvent(_musicPos[0], _musicPos[1]);
+ uint8 mode = _tMode[_musicPos[1]];
+
+ sendEvent(mode, evt);
+ sendEvent(mode, _musicPos[4]);
+
+ return false;
+}
+
+bool TownsEuphonyDriver::evtLoadInstrument() {
+ return false;
+}
+
+bool TownsEuphonyDriver::evtAdvanceTimestampOffset() {
+ ++_timeStampBase;
+ _baseTickLen = _musicPos[1];
+ return false;
+}
+
+bool TownsEuphonyDriver::evtTempo() {
+ uint8 l = _musicPos[4] << 1;
+ _trackTempo = (l | (_musicPos[5] << 8)) >> 1;
+ setTempoIntern(_trackTempo);
+ return false;
+}
+
+bool TownsEuphonyDriver::evtModeOrdrChange() {
+ if (_musicPos[1] > 31)
+ return false;
+ if (!_tEnable[_musicPos[1]])
+ return false;
+
+ if (_musicPos[4] == 1)
+ _tMode[_musicPos[1]] = _musicPos[5];
+ else if (_musicPos[4] == 2)
+ _tOrdr[_musicPos[1]] = _musicPos[5];
+
+ return false;
+}
+
+uint8 TownsEuphonyDriver::applyNoteShift(uint8 in) {
+ int out = _tTranspose[_musicPos[1]];
+ if (!out)
+ return in;
+ out += (in & 0x7f);
+
+ if (out > 127)
+ out -= 12;
+
+ if (out < 0)
+ out += 12;
+
+ return out & 0xff;
+}
+
+uint8 TownsEuphonyDriver::applyVolumeShift(uint8 in) {
+ int out = _tLevel[_musicPos[1]];
+ out += (in & 0x7f);
+ out = CLIP(out, 1, 127);
+
+ return out & 0xff;
+}
+
+void TownsEuphonyDriver::sendNoteOff() {
+ int8 *chan = &_activeChannels[_command & 0x0f];
+ if (*chan == -1)
+ return;
+
+ while (_assignedChannels[*chan].note != _para[0]) {
+ chan = &_assignedChannels[*chan].next;
+ if (*chan == -1)
+ return;
+ }
+
+ if (_sustainChannels[_command & 0x0f]) {
+ _assignedChannels[*chan].note |= 0x80;
+ } else {
+ _assignedChannels[*chan].note = 0;
+ _intf->callback(2, *chan);
+ }
+}
+
+void TownsEuphonyDriver::sendNoteOn() {
+ if (!_para[0])
+ return;
+ int8 *chan = &_activeChannels[_command & 0x0f];
+ if (*chan == -1)
+ return;
+
+ do {
+ _assignedChannels[*chan].sub++;
+ chan = &_assignedChannels[*chan].next;
+ } while (*chan != -1);
+
+ chan = &_activeChannels[_command & 0x0f];
+
+ int d = 0;
+ int c = 0;
+ bool found = false;
+
+ do {
+ if (!_assignedChannels[*chan].note) {
+ found = true;
+ break;
+ }
+ if (d <= _assignedChannels[*chan].sub) {
+ c = *chan;
+ d = _assignedChannels[*chan].sub;
+ }
+ chan = &_assignedChannels[*chan].next;
+ } while (*chan != -1);
+
+ if (found)
+ c = *chan;
+ else
+ _intf->callback(2, c);
+
+ _assignedChannels[c].note = _para[0];
+ _assignedChannels[c].sub = 0;
+ _intf->callback(1, c, _para[0], _para[1]);
+}
+
+void TownsEuphonyDriver::sendChanVolume() {
+ int8 *chan = &_activeChannels[_command & 0x0f];
+ while (*chan != -1) {
+ _intf->callback(8, *chan, _para[1] & 0x7f);
+ chan = &_assignedChannels[*chan].next;
+ };
+}
+
+void TownsEuphonyDriver::sendPanPosition() {
+ int8 *chan = &_activeChannels[_command & 0x0f];
+ while (*chan != -1) {
+ _intf->callback(3, *chan, _para[1] & 0x7f);
+ chan = &_assignedChannels[*chan].next;
+ };
+}
+
+void TownsEuphonyDriver::sendAllNotesOff() {
+ if (_para[1] > 63) {
+ _sustainChannels[_command & 0x0f] = -1;
+ return;
+ }
+
+ _sustainChannels[_command & 0x0f] = 0;
+ int8 *chan = &_activeChannels[_command & 0x0f];
+ while (*chan != -1) {
+ if (_assignedChannels[*chan].note & 0x80) {
+ _assignedChannels[*chan].note = 0;
+ _intf->callback(2, *chan);
+ }
+ chan = &_assignedChannels[*chan].next;
+ };
+}
+
+void TownsEuphonyDriver::sendSetInstrument() {
+ int8 *chan = &_activeChannels[_command & 0x0f];
+ while (*chan != -1) {
+ _intf->callback(4, *chan, _para[0]);
+ _intf->callback(7, *chan, 0);
+ chan = &_assignedChannels[*chan].next;
+ };
+}
+
+void TownsEuphonyDriver::sendPitch() {
+ int8 *chan = &_activeChannels[_command & 0x0f];
+ while (*chan != -1) {
+ _para[0] += _para[0];
+ int16 pitch = (((READ_LE_UINT16(_para)) >> 1) & 0x3fff) - 0x2000;
+ _intf->callback(7, *chan, pitch);
+ chan = &_assignedChannels[*chan].next;
+ };
+}
diff --git a/sound/softsynth/fmtowns_pc98/towns_euphony.h b/sound/softsynth/fmtowns_pc98/towns_euphony.h
new file mode 100644
index 0000000000..fa1f8ba496
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_euphony.h
@@ -0,0 +1,187 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 TOWNS_EUP_H
+#define TOWNS_EUP_H
+
+#include "sound/softsynth/fmtowns_pc98/towns_audio.h"
+
+class TownsEuphonyDriver : public TownsAudioInterfacePluginDriver {
+public:
+ TownsEuphonyDriver(Audio::Mixer *mixer);
+ virtual ~TownsEuphonyDriver();
+
+ bool init();
+ void reset();
+
+ void loadInstrument(int chanType, int id, const uint8 *data);
+ void loadWaveTable(const uint8 *data);
+ void unloadWaveTable(int id);
+ void reserveSoundEffectChannels(int num);
+
+ int setMusicTempo(int tempo);
+ int startMusicTrack(const uint8 *data, int trackSize, int startTick);
+ void setMusicLoop(bool loop);
+ void stopParser();
+ bool parserIsPlaying() {return _playing; }
+ void continueParsing();
+
+ void playSoundEffect(int chan, int note, int velo, const uint8 *data);
+ void stopSoundEffect(int chan);
+ bool soundEffectIsPlaying(int chan);
+
+ void chanPanPos(int chan, int mode);
+ void chanPitch(int chan, int pitch);
+ void chanVolume(int chan, int vol);
+
+ void setOutputVolume(int chanType, int volLeft, int volRight);
+
+ int chanEnable(int tableEntry, int val);
+ int chanMode(int tableEntry, int val);
+ int chanOrdr(int tableEntry, int val);
+ int chanVolumeShift(int tableEntry, int val);
+ int chanNoteShift(int tableEntry, int val);
+
+ int assignChannel(int chan, int tableEntry);
+
+ void timerCallback(int timerId);
+
+ void setMusicVolume(int volume);
+ void setSoundEffectVolume(int volume);
+
+ TownsAudioInterface *intf() {
+ return _intf;
+ }
+
+private:
+ void resetTables();
+
+ void resetTempo();
+ void setTempoIntern(int tempo);
+ void setTimerA(bool enable, int tempo);
+ void setTimerB(bool enable, int tempo);
+
+ void updatePulseCount();
+ void updateTimeStampBase();
+ void updateParser();
+ void updateCheckEot();
+
+ bool parseNext();
+ void jumpNextLoop();
+
+ void updateEventBuffer();
+ void flushEventBuffer();
+ void processBufferNote(int mode, int evt, int note, int velo);
+
+ void resetControl();
+ void resetControlIntern(int mode, int chan);
+ uint8 appendEvent(uint8 evt, uint8 chan);
+
+ void sendEvent(uint8 mode, uint8 command);
+
+ typedef bool(TownsEuphonyDriver::*EuphonyOpcode)();
+ bool evtSetupNote();
+ bool evtPolyphonicAftertouch();
+ bool evtControlPitch();
+ bool evtInstrumentChanAftertouch();
+ bool evtLoadInstrument();
+ bool evtAdvanceTimestampOffset();
+ bool evtTempo();
+ bool evtModeOrdrChange();
+ bool evtNotImpl() {
+ return false;
+ }
+
+ uint8 applyNoteShift(uint8 in);
+ uint8 applyVolumeShift(uint8 in);
+
+ void sendNoteOff();
+ void sendNoteOn();
+ void sendChanVolume();
+ void sendPanPosition();
+ void sendAllNotesOff();
+ void sendSetInstrument();
+ void sendPitch();
+
+ int8 *_activeChannels;
+ int8 *_sustainChannels;
+
+ struct ActiveChannel {
+ int8 chan;
+ int8 next;
+ uint8 note;
+ uint8 sub;
+ } *_assignedChannels;
+
+ uint8 *_tEnable;
+ uint8 *_tMode;
+ uint8 *_tOrdr;
+ int8 *_tLevel;
+ int8 *_tTranspose;
+
+ struct DlEvent {
+ uint8 evt;
+ uint8 mode;
+ uint8 note;
+ uint8 velo;
+ uint16 len;
+ } *_eventBuffer;
+ int _bufferedEventsCount;
+
+ uint8 _para[2];
+ uint8 _paraCount;
+ uint8 _command;
+
+ uint8 _defaultBaseTickLen;
+ uint8 _baseTickLen;
+ uint32 _pulseCount;
+ int _tempoControlMode;
+ int _extraTimingControlRemainder;
+ int _extraTimingControl;
+ int _timerSetting;
+ int8 _tempoDiff;
+ int _tempoModifier;
+ uint32 _timeStampDest;
+ uint32 _timeStampBase;
+ int8 _elapsedEvents;
+ uint8 _deltaTicks;
+ uint32 _tickCounter;
+ uint8 _defaultTempo;
+ int _trackTempo;
+
+ bool _loop;
+ bool _playing;
+ bool _endOfTrack;
+ bool _suspendParsing;
+
+ const uint8 *_musicStart;
+ const uint8 *_musicPos;
+ uint32 _musicTrackSize;
+
+ TownsAudioInterface *_intf;
+};
+
+#endif
+
diff --git a/sound/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/sound/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
new file mode 100644
index 0000000000..82d0bd0438
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
@@ -0,0 +1,1403 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "sound/softsynth/fmtowns_pc98/towns_pc98_driver.h"
+#include "common/endian.h"
+
+class TownsPC98_MusicChannel {
+public:
+ TownsPC98_MusicChannel(TownsPC98_AudioDriver *driver, uint8 regOffs, uint8 flgs, uint8 num,
+ uint8 key, uint8 prt, uint8 id);
+ virtual ~TownsPC98_MusicChannel();
+ virtual void init();
+
+ typedef enum channelState {
+ CHS_RECALCFREQ = 0x01,
+ CHS_KEYOFF = 0x02,
+ 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();
+ virtual bool processControlEvent(uint8 cmd);
+
+ virtual void keyOn();
+ void keyOff();
+
+ void setOutputLevel();
+ virtual void fadeStep();
+ virtual void reset();
+
+ 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);
+ bool control_f2_setKeyOffTime(uint8 para);
+ bool control_f3_setFreqLSB(uint8 para);
+ bool control_f4_setOutputLevel(uint8 para);
+ bool control_f5_setTempo(uint8 para);
+ bool control_f6_repeatSection(uint8 para);
+ bool control_f7_setupVibrato(uint8 para);
+ bool control_f8_toggleVibrato(uint8 para);
+ bool control_fa_writeReg(uint8 para);
+ virtual bool control_fb_incOutLevel(uint8 para);
+ virtual bool control_fc_decOutLevel(uint8 para);
+ bool control_fd_jump(uint8 para);
+ virtual bool control_ff_endOfTrack(uint8 para);
+
+ uint8 _ticksLeft;
+ uint8 _algorithm;
+ uint8 _instr;
+ uint8 _totalLevel;
+ uint8 _frqBlockMSB;
+ int8 _frqLSB;
+ uint8 _keyOffTime;
+ bool _hold;
+ uint8 *_dataPtr;
+ uint8 _vbrInitDelayHi;
+ uint8 _vbrInitDelayLo;
+ int16 _vbrModInitVal;
+ uint8 _vbrDuration;
+ uint8 _vbrCurDelay;
+ int16 _vbrModCurVal;
+ uint8 _vbrDurLeft;
+ uint16 _frequency;
+ uint8 _block;
+ uint8 _regOffset;
+ uint8 _flags;
+ uint8 _ssgTl;
+ uint8 _ssgStep;
+ uint8 _ssgTicksLeft;
+ uint8 _ssgTargetLvl;
+ uint8 _ssgStartLvl;
+
+ const uint8 _chanNum;
+ const uint8 _keyNum;
+ const uint8 _part;
+
+ TownsPC98_AudioDriver *_drv;
+
+ typedef bool (TownsPC98_MusicChannel::*ControlEventFunc)(uint8 para);
+ const ControlEventFunc *controlEvents;
+};
+
+class TownsPC98_MusicChannelSSG : public TownsPC98_MusicChannel {
+public:
+ TownsPC98_MusicChannelSSG(TownsPC98_AudioDriver *driver, uint8 regOffs,
+ uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id);
+ virtual ~TownsPC98_MusicChannelSSG() {}
+ void init();
+
+ virtual void loadData(uint8 *data);
+ void processEvents();
+ void processFrequency();
+ bool processControlEvent(uint8 cmd);
+
+ void keyOn();
+ void nextShape();
+
+ void protect();
+ void restore();
+ virtual void reset();
+
+ void fadeStep();
+
+protected:
+ void setOutputLevel(uint8 lvl);
+
+ bool control_f0_setPatch(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_MusicChannelSSG::*ControlEventFunc)(uint8 para);
+ const ControlEventFunc *controlEvents;
+};
+
+class TownsPC98_SfxChannel : public TownsPC98_MusicChannelSSG {
+public:
+ TownsPC98_SfxChannel(TownsPC98_AudioDriver *driver, uint8 regOffs,
+ uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
+ TownsPC98_MusicChannelSSG(driver, regOffs, flgs, num, key, prt, id) {}
+ ~TownsPC98_SfxChannel() {}
+
+ void loadData(uint8 *data);
+ void reset();
+};
+
+class TownsPC98_MusicChannelPCM : public TownsPC98_MusicChannel {
+public:
+ TownsPC98_MusicChannelPCM(TownsPC98_AudioDriver *driver, uint8 regOffs,
+ uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id);
+ ~TownsPC98_MusicChannelPCM() {}
+ void init();
+
+ void loadData(uint8 *data);
+ void processEvents();
+ bool processControlEvent(uint8 cmd);
+
+private:
+ bool control_f1_prcStart(uint8 para);
+ bool control_ff_endOfTrack(uint8 para);
+
+ typedef bool (TownsPC98_MusicChannelPCM::*ControlEventFunc)(uint8 para);
+ const ControlEventFunc *controlEvents;
+};
+
+TownsPC98_MusicChannel::TownsPC98_MusicChannel(TownsPC98_AudioDriver *driver, uint8 regOffs, uint8 flgs, uint8 num,
+ uint8 key, uint8 prt, uint8 id) : _drv(driver), _regOffset(regOffs), _flags(flgs), _chanNum(num), _keyNum(key),
+ _part(prt), _idFlag(id), controlEvents(0) {
+
+ _ticksLeft = _algorithm = _instr = _totalLevel = _frqBlockMSB = _keyOffTime = 0;
+ _ssgStartLvl = _ssgTl = _ssgStep = _ssgTicksLeft = _ssgTargetLvl = _block = 0;
+ _vbrInitDelayHi = _vbrInitDelayLo = _vbrDuration = _vbrCurDelay = _vbrDurLeft = 0;
+ _frqLSB = 0;
+ _hold = false;
+ _dataPtr = 0;
+ _vbrModInitVal = _vbrModCurVal = 0;
+ _frequency = 0;
+}
+
+TownsPC98_MusicChannel::~TownsPC98_MusicChannel() {
+}
+
+void TownsPC98_MusicChannel::init() {
+#define Control(x) &TownsPC98_MusicChannel::control_##x
+ static const ControlEventFunc ctrlEvents[] = {
+ Control(f0_setPatch),
+ Control(f1_presetOutputLevel),
+ Control(f2_setKeyOffTime),
+ Control(f3_setFreqLSB),
+ Control(f4_setOutputLevel),
+ Control(f5_setTempo),
+ Control(f6_repeatSection),
+ Control(f7_setupVibrato),
+ Control(f8_toggleVibrato),
+ Control(dummy),
+ Control(fa_writeReg),
+ Control(fb_incOutLevel),
+ Control(fc_decOutLevel),
+ Control(fd_jump),
+ Control(dummy),
+ Control(ff_endOfTrack)
+ };
+#undef Control
+
+ controlEvents = ctrlEvents;
+}
+
+void TownsPC98_MusicChannel::keyOff() {
+ // all operators off
+ uint8 value = _keyNum & 0x0f;
+ if (_part)
+ value |= 4;
+ uint8 regAddress = 0x28;
+ _drv->writeReg(0, regAddress, value);
+ _flags |= CHS_KEYOFF;
+}
+
+void TownsPC98_MusicChannel::keyOn() {
+ // all operators on
+ uint8 value = _keyNum | 0xf0;
+ if (_part)
+ value |= 4;
+ uint8 regAddress = 0x28;
+ _drv->writeReg(0, regAddress, value);
+}
+
+void TownsPC98_MusicChannel::loadData(uint8 *data) {
+ _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
+ _ticksLeft = 1;
+ _dataPtr = data;
+ _totalLevel = 0x7F;
+
+ uint8 *tmp = _dataPtr;
+ for (bool loop = true; loop;) {
+ uint8 cmd = *tmp++;
+ if (cmd < 0xf0) {
+ tmp++;
+ } else if (cmd == 0xff) {
+ if (READ_LE_UINT16(tmp)) {
+ _drv->_looping |= _idFlag;
+ tmp += _drv->_opnFxCmdLen[cmd - 240];
+ } else
+ loop = false;
+ } else if (cmd == 0xf6) {
+ // reset repeat section countdown
+ tmp[0] = tmp[1];
+ tmp += 4;
+ } else {
+ tmp += _drv->_opnFxCmdLen[cmd - 240];
+ }
+ }
+}
+
+void TownsPC98_MusicChannel::processEvents() {
+ if (_flags & CHS_EOT)
+ return;
+
+ if (!_hold && _ticksLeft == _keyOffTime)
+ keyOff();
+
+ if (--_ticksLeft)
+ return;
+
+ if (!_hold)
+ keyOff();
+
+ 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) {
+ keyOff();
+ _hold = false;
+ } else {
+ keyOn();
+
+ if (_hold == false || cmd != _frqBlockMSB)
+ _flags |= CHS_RECALCFREQ;
+
+ _hold = (para & 0x80) ? true : false;
+ _frqBlockMSB = cmd;
+ }
+
+ _ticksLeft = para & 0x7f;
+}
+
+void TownsPC98_MusicChannel::processFrequency() {
+ if (_flags & CHS_RECALCFREQ) {
+
+ _frequency = (((const uint16 *)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f] + _frqLSB) | (((_frqBlockMSB & 0x70) >> 1) << 8);
+
+ _drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8));
+ _drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff));
+
+ setupVibrato();
+ }
+
+ if (!(_flags & CHS_VBROFF)) {
+ if (!processVibrato())
+ return;
+
+ _drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8));
+ _drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff));
+ }
+}
+
+void TownsPC98_MusicChannel::setupVibrato() {
+ _vbrCurDelay = _vbrInitDelayHi;
+ if (_flags & CHS_KEYOFF) {
+ _vbrModCurVal = _vbrModInitVal;
+ _vbrCurDelay += _vbrInitDelayLo;
+ }
+ _vbrDurLeft = (_vbrDuration >> 1);
+ _flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ);
+}
+
+bool TownsPC98_MusicChannel::processVibrato() {
+ if (--_vbrCurDelay)
+ return false;
+
+ _vbrCurDelay = _vbrInitDelayHi;
+ _frequency += _vbrModCurVal;
+
+ if (!--_vbrDurLeft) {
+ _vbrDurLeft = _vbrDuration;
+ _vbrModCurVal = -_vbrModCurVal;
+ }
+
+ return true;
+}
+
+bool TownsPC98_MusicChannel::processControlEvent(uint8 cmd) {
+ uint8 para = *_dataPtr++;
+ return (this->*controlEvents[cmd & 0x0f])(para);
+}
+
+void TownsPC98_MusicChannel::setOutputLevel() {
+ uint8 outopr = _drv->_opnCarrier[_algorithm];
+ uint8 reg = 0x40 + _regOffset;
+
+ for (int i = 0; i < 4; i++) {
+ if (outopr & 1)
+ _drv->writeReg(_part, reg, _totalLevel);
+ outopr >>= 1;
+ reg += 4;
+ }
+}
+
+void TownsPC98_MusicChannel::fadeStep() {
+ _totalLevel += 3;
+ if (_totalLevel > 0x7f)
+ _totalLevel = 0x7f;
+ setOutputLevel();
+}
+
+void TownsPC98_MusicChannel::reset() {
+ _hold = false;
+ _keyOffTime = 0;
+ _ticksLeft = 1;
+
+ _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
+
+ _totalLevel = 0;
+ _algorithm = 0;
+ _flags = CHS_EOT;
+ _algorithm = 0;
+
+ _block = 0;
+ _frequency = 0;
+ _frqBlockMSB = 0;
+ _frqLSB = 0;
+
+ _ssgTl = 0;
+ _ssgStartLvl = 0;
+ _ssgTargetLvl = 0;
+ _ssgStep = 0;
+ _ssgTicksLeft = 0;
+
+ _vbrInitDelayHi = 0;
+ _vbrInitDelayLo = 0;
+ _vbrModInitVal = 0;
+ _vbrDuration = 0;
+ _vbrCurDelay = 0;
+ _vbrModCurVal = 0;
+ _vbrDurLeft = 0;
+}
+
+bool TownsPC98_MusicChannel::control_f0_setPatch(uint8 para) {
+ _instr = para;
+ uint8 reg = _regOffset + 0x80;
+
+ for (int i = 0; i < 4; i++) {
+ // set release rate for each operator
+ _drv->writeReg(_part, reg, 0x0f);
+ reg += 4;
+ }
+
+ const uint8 *tptr = _drv->_patches + ((uint32)_instr << 5);
+ reg = _regOffset + 0x30;
+
+ // write registers 0x30 to 0x8f
+ for (int i = 0; i < 6; i++) {
+ _drv->writeReg(_part, reg, tptr[0]);
+ reg += 4;
+ _drv->writeReg(_part, reg, tptr[2]);
+ reg += 4;
+ _drv->writeReg(_part, reg, tptr[1]);
+ reg += 4;
+ _drv->writeReg(_part, reg, tptr[3]);
+ reg += 4;
+ tptr += 4;
+ }
+
+ reg = _regOffset + 0xB0;
+ _algorithm = tptr[0] & 7;
+ // set feedback and algorithm
+ _drv->writeReg(_part, reg, tptr[0]);
+
+ setOutputLevel();
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_f1_presetOutputLevel(uint8 para) {
+ if (_drv->_fading)
+ return true;
+
+ _totalLevel = _drv->_opnLvlPresets[para];
+ setOutputLevel();
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_f2_setKeyOffTime(uint8 para) {
+ _keyOffTime = para;
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_f3_setFreqLSB(uint8 para) {
+ _frqLSB = (int8) para;
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_f4_setOutputLevel(uint8 para) {
+ if (_drv->_fading)
+ return true;
+
+ _totalLevel = para;
+ setOutputLevel();
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_f5_setTempo(uint8 para) {
+ _drv->setMusicTempo(para);
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_f6_repeatSection(uint8 para) {
+ _dataPtr--;
+ _dataPtr[0]--;
+
+ if (*_dataPtr) {
+ // repeat section until counter has reached zero
+ _dataPtr = _drv->_trackPtr + READ_LE_UINT16(_dataPtr + 2);
+ } else {
+ // reset counter, advance to next section
+ _dataPtr[0] = _dataPtr[1];
+ _dataPtr += 4;
+ }
+ return true;
+}
+
+bool TownsPC98_MusicChannel::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_VBROFF) | CHS_KEYOFF | CHS_RECALCFREQ;
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_f8_toggleVibrato(uint8 para) {
+ if (para == 0x10) {
+ if (*_dataPtr++) {
+ _flags = (_flags & ~CHS_VBROFF) | CHS_KEYOFF;
+ } else {
+ _flags |= CHS_VBROFF;
+ }
+ } else {
+ /* NOT IMPLEMENTED
+ uint8 skipChannels = para / 36;
+ uint8 entry = para % 36;
+ TownsPC98_AudioDriver::TownsPC98_MusicChannel *t = &chan[skipChannels];
+
+ t->unnamedEntries[entry] = *_dataPtr++;*/
+ }
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_fa_writeReg(uint8 para) {
+ _drv->writeReg(_part, para, *_dataPtr++);
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_fb_incOutLevel(uint8 para) {
+ _dataPtr--;
+ if (_drv->_fading)
+ return true;
+
+ uint8 val = (_totalLevel + 3);
+ if (val > 0x7f)
+ val = 0x7f;
+
+ _totalLevel = val;
+ setOutputLevel();
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_fc_decOutLevel(uint8 para) {
+ _dataPtr--;
+ if (_drv->_fading)
+ return true;
+
+ int8 val = (int8)(_totalLevel - 3);
+ if (val < 0)
+ val = 0;
+
+ _totalLevel = (uint8) val;
+ setOutputLevel();
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_fd_jump(uint8 para) {
+ uint8 *tmp = _drv->_trackPtr + READ_LE_UINT16(_dataPtr - 1);
+ _dataPtr = (tmp[1] == 1) ? tmp : (_dataPtr + 1);
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_dummy(uint8 para) {
+ _dataPtr--;
+ return true;
+}
+
+bool TownsPC98_MusicChannel::control_ff_endOfTrack(uint8 para) {
+ uint16 val = READ_LE_UINT16(--_dataPtr);
+ if (val) {
+ // loop
+ _dataPtr = _drv->_trackPtr + val;
+ return true;
+ } else {
+ // quit parsing for active channel
+ --_dataPtr;
+ _flags |= CHS_EOT;
+ _drv->_finishedChannelsFlag |= _idFlag;
+ keyOff();
+ return false;
+ }
+}
+
+TownsPC98_MusicChannelSSG::TownsPC98_MusicChannelSSG(TownsPC98_AudioDriver *driver, uint8 regOffs,
+ uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
+ TownsPC98_MusicChannel(driver, regOffs, flgs, num, key, prt, id), controlEvents(0) {
+}
+
+void TownsPC98_MusicChannelSSG::init() {
+ _algorithm = 0x80;
+
+#define Control(x) &TownsPC98_MusicChannelSSG::control_##x
+ static const ControlEventFunc ctrlEventsSSG[] = {
+ Control(f0_setPatch),
+ 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_MusicChannelSSG::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_MusicChannelSSG::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_MusicChannelSSG::processControlEvent(uint8 cmd) {
+ uint8 para = *_dataPtr++;
+ return (this->*controlEvents[cmd & 0x0f])(para);
+}
+
+void TownsPC98_MusicChannelSSG::nextShape() {
+ _instr = (_instr & 0xf0) + 0x0c;
+ _ssgStep = _drv->_ssgPatches[_instr];
+ _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
+ _ssgTargetLvl = _drv->_ssgPatches[_instr + 2];
+}
+
+void TownsPC98_MusicChannelSSG::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_MusicChannelSSG::protect() {
+ _flags |= CHS_PROTECT;
+}
+
+void TownsPC98_MusicChannelSSG::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_MusicChannelSSG::loadData(uint8 *data) {
+ _drv->toggleRegProtection(_flags & CHS_PROTECT ? true : false);
+ TownsPC98_MusicChannel::loadData(data);
+ setOutputLevel(0);
+ _algorithm = 0x80;
+}
+
+void TownsPC98_MusicChannelSSG::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_MusicChannelSSG::reset() {
+ TownsPC98_MusicChannel::reset();
+
+ // Unlike the original we restore the default patch data. This fixes a bug
+ // where certain sound effects would bring each other out of tune (e.g. the
+ // dragon's fire in Darm's house in Kyra 1 would sound different each time
+ // you triggered another sfx by dropping an item etc.)
+ uint8 i = (10 + _regOffset) << 4;
+ const uint8 *src = &_drv->_drvTables[156];
+ _drv->_ssgPatches[i] = src[i];
+ _drv->_ssgPatches[i + 3] = src[i + 3];
+ _drv->_ssgPatches[i + 4] = src[i + 4];
+ _drv->_ssgPatches[i + 6] = src[i + 6];
+ _drv->_ssgPatches[i + 8] = src[i + 8];
+ _drv->_ssgPatches[i + 12] = src[i + 12];
+}
+
+void TownsPC98_MusicChannelSSG::fadeStep() {
+ _totalLevel--;
+ if ((int8)_totalLevel < 0)
+ _totalLevel = 0;
+ setOutputLevel(_ssgStartLvl);
+}
+
+bool TownsPC98_MusicChannelSSG::control_f0_setPatch(uint8 para) {
+ _instr = para << 4;
+ para = (para >> 3) & 0x1e;
+ if (para)
+ return control_f4_setAlgorithm(para | 0x40);
+ return true;
+}
+
+bool TownsPC98_MusicChannelSSG::control_f1_setTotalLevel(uint8 para) {
+ if (!_drv->_fading)
+ _totalLevel = para;
+ return true;
+}
+
+bool TownsPC98_MusicChannelSSG::control_f4_setAlgorithm(uint8 para) {
+ _algorithm = para;
+ return true;
+}
+
+bool TownsPC98_MusicChannelSSG::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_MusicChannelSSG::control_fb_incOutLevel(uint8 para) {
+ _dataPtr--;
+ if (_drv->_fading)
+ return true;
+
+ _totalLevel--;
+ if ((int8)_totalLevel < 0)
+ _totalLevel = 0;
+
+ return true;
+}
+
+bool TownsPC98_MusicChannelSSG::control_fc_decOutLevel(uint8 para) {
+ _dataPtr--;
+ if (_drv->_fading)
+ return true;
+
+ if (_totalLevel + 1 < 0x10)
+ _totalLevel++;
+
+ return true;
+}
+
+bool TownsPC98_MusicChannelSSG::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 {
+ // end of sfx track - restore ssg music channel
+ _flags |= CHS_EOT;
+ _drv->_finishedSfxFlag |= _idFlag;
+ _drv->_ssgChannels[_chanNum]->restore();
+ }
+
+ return false;
+}
+
+void TownsPC98_SfxChannel::loadData(uint8 *data) {
+ _flags = CHS_ALLOFF;
+ _ticksLeft = 1;
+ _dataPtr = data;
+ _ssgTl = 0xff;
+ _algorithm = 0x80;
+
+ uint8 *tmp = _dataPtr;
+ for (bool loop = true; loop;) {
+ uint8 cmd = *tmp++;
+ if (cmd < 0xf0) {
+ tmp++;
+ } else if (cmd == 0xff) {
+ loop = false;
+ } else if (cmd == 0xf6) {
+ // reset repeat section countdown
+ tmp[0] = tmp[1];
+ tmp += 4;
+ } else {
+ tmp += _drv->_opnFxCmdLen[cmd - 240];
+ }
+ }
+}
+
+void TownsPC98_SfxChannel::reset() {
+ TownsPC98_MusicChannel::reset();
+
+ // Unlike the original we restore the default patch data. This fixes a bug
+ // where certain sound effects would bring each other out of tune (e.g. the
+ // dragon's fire in Darm's house in Kyra 1 would sound different each time
+ // you triggered another sfx by dropping an item etc.)
+ uint8 i = (13 + _regOffset) << 4;
+ const uint8 *src = &_drv->_drvTables[156];
+ _drv->_ssgPatches[i] = src[i];
+ _drv->_ssgPatches[i + 3] = src[i + 3];
+ _drv->_ssgPatches[i + 4] = src[i + 4];
+ _drv->_ssgPatches[i + 6] = src[i + 6];
+ _drv->_ssgPatches[i + 8] = src[i + 8];
+ _drv->_ssgPatches[i + 12] = src[i + 12];
+}
+
+TownsPC98_MusicChannelPCM::TownsPC98_MusicChannelPCM(TownsPC98_AudioDriver *driver, uint8 regOffs,
+ uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
+ TownsPC98_MusicChannel(driver, regOffs, flgs, num, key, prt, id), controlEvents(0) {
+}
+
+void TownsPC98_MusicChannelPCM::init() {
+ _algorithm = 0x80;
+
+#define Control(x) &TownsPC98_MusicChannelPCM::control_##x
+ static const ControlEventFunc ctrlEventsPCM[] = {
+ Control(dummy),
+ Control(f1_prcStart),
+ Control(dummy),
+ Control(dummy),
+ Control(dummy),
+ Control(dummy),
+ Control(f6_repeatSection),
+ Control(dummy),
+ Control(dummy),
+ Control(dummy),
+ Control(fa_writeReg),
+ Control(dummy),
+ Control(dummy),
+ Control(dummy),
+ Control(dummy),
+ Control(ff_endOfTrack)
+ };
+#undef Control
+
+ controlEvents = ctrlEventsPCM;
+}
+
+void TownsPC98_MusicChannelPCM::loadData(uint8 *data) {
+ _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
+ _ticksLeft = 1;
+ _dataPtr = data;
+ _totalLevel = 0x7F;
+}
+
+void TownsPC98_MusicChannelPCM::processEvents() {
+ if (_flags & CHS_EOT)
+ return;
+
+ if (--_ticksLeft)
+ return;
+
+ uint8 cmd = 0;
+ bool loop = true;
+
+ while (loop) {
+ cmd = *_dataPtr++;
+ if (cmd == 0x80) {
+ loop = false;
+ } else if (cmd < 0xf0) {
+ _drv->writeReg(_part, 0x10, cmd);
+ } else if (!processControlEvent(cmd)) {
+ return;
+ }
+ }
+
+ _ticksLeft = *_dataPtr++;
+}
+
+bool TownsPC98_MusicChannelPCM::processControlEvent(uint8 cmd) {
+ uint8 para = *_dataPtr++;
+ return (this->*controlEvents[cmd & 0x0f])(para);
+}
+
+bool TownsPC98_MusicChannelPCM::control_f1_prcStart(uint8 para) {
+ _totalLevel = para;
+ _drv->writeReg(_part, 0x11, para);
+ return true;
+}
+
+bool TownsPC98_MusicChannelPCM::control_ff_endOfTrack(uint8 para) {
+ uint16 val = READ_LE_UINT16(--_dataPtr);
+ if (val) {
+ // loop
+ _dataPtr = _drv->_trackPtr + val;
+ return true;
+ } else {
+ // quit parsing for active channel
+ --_dataPtr;
+ _flags |= CHS_EOT;
+ _drv->_finishedRhythmFlag |= _idFlag;
+ return false;
+ }
+}
+
+TownsPC98_AudioDriver::TownsPC98_AudioDriver(Audio::Mixer *mixer, EmuType type) : TownsPC98_FmSynth(mixer, type),
+ _channels(0), _ssgChannels(0), _sfxChannels(0), _rhythmChannel(0),
+ _trackPtr(0), _sfxData(0), _sfxOffs(0), _ssgPatches(0),
+ _patches(0), _sfxBuffer(0), _musicBuffer(0),
+
+ _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 108), _opnFreqTableSSG(_drvTables + 132),
+ _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == kTypeTowns ? 52 : 84)),
+
+ _updateChannelsFlag(type == kType26 ? 0x07 : 0x3F), _finishedChannelsFlag(0),
+ _updateSSGFlag(type == kTypeTowns ? 0x00 : 0x07), _finishedSSGFlag(0),
+ _updateRhythmFlag(type == kType86 ? 0x01 : 0x00), _finishedRhythmFlag(0),
+ _updateSfxFlag(0), _finishedSfxFlag(0),
+
+ _musicTickCounter(0),
+
+ _musicVolume(255), _sfxVolume(255),
+
+ _musicPlaying(false), _sfxPlaying(false), _fading(false), _looping(0), _ready(false) {
+
+ _sfxOffsets[0] = _sfxOffsets[1] = 0;
+}
+
+TownsPC98_AudioDriver::~TownsPC98_AudioDriver() {
+ reset();
+
+ 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;
+ }
+
+ delete _rhythmChannel;
+
+ delete[] _ssgPatches;
+}
+
+bool TownsPC98_AudioDriver::init() {
+ if (_ready) {
+ reset();
+ return true;
+ }
+
+ TownsPC98_FmSynth::init();
+
+ setVolumeChannelMasks(-1, 0);
+
+ _channels = new TownsPC98_MusicChannel *[_numChan];
+ for (int i = 0; i < _numChan; i++) {
+ int ii = i * 6;
+ _channels[i] = new TownsPC98_MusicChannel(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_MusicChannelSSG *[_numSSG];
+ for (int i = 0; i < _numSSG; i++) {
+ int ii = i * 6;
+ _ssgChannels[i] = new TownsPC98_MusicChannelSSG(this, _drvTables[ii], _drvTables[ii + 1],
+ _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
+ _ssgChannels[i]->init();
+ }
+
+ _sfxChannels = new TownsPC98_SfxChannel *[2];
+ for (int i = 0; i < 2; i++) {
+ int ii = (i + 1) * 6;
+ _sfxChannels[i] = new TownsPC98_SfxChannel(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_MusicChannelPCM(this, 0, 0, 0, 0, 0, 1);
+ _rhythmChannel->init();
+ }
+
+ setMusicTempo(84);
+ setSfxTempo(654);
+
+ _ready = true;
+
+ return true;
+}
+
+void TownsPC98_AudioDriver::loadMusicData(uint8 *data, bool loadPaused) {
+ if (!_ready) {
+ warning("TownsPC98_AudioDriver: Driver must be initialized before loading data");
+ return;
+ }
+
+ if (!data) {
+ warning("TownsPC98_AudioDriver: Invalid music file data");
+ return;
+ }
+
+ reset();
+
+ Common::StackLock lock(_mutex);
+ 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);
+}
+
+void TownsPC98_AudioDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) {
+ if (!_ready) {
+ warning("TownsPC98_AudioDriver: Driver must be initialized before loading data");
+ return;
+ }
+
+ if (!_sfxChannels) {
+ warning("TownsPC98_AudioDriver: Sound effects not supported by this configuration");
+ return;
+ }
+
+ if (!data) {
+ warning("TownsPC98_AudioDriver: Invalid sound effects file data");
+ return;
+ }
+
+ Common::StackLock lock(_mutex);
+ _sfxData = _sfxBuffer = data;
+ _sfxOffsets[0] = READ_LE_UINT16(&_sfxData[(trackNum << 2)]);
+ _sfxOffsets[1] = READ_LE_UINT16(&_sfxData[(trackNum << 2) + 2]);
+ _sfxPlaying = true;
+ _finishedSfxFlag = 0;
+}
+
+void TownsPC98_AudioDriver::reset() {
+ Common::StackLock lock(_mutex);
+
+ _musicPlaying = false;
+ _sfxPlaying = false;
+ _fading = false;
+ _looping = 0;
+ _musicTickCounter = 0;
+ _sfxData = 0;
+
+ TownsPC98_FmSynth::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();
+}
+
+void TownsPC98_AudioDriver::fadeStep() {
+ if (!_musicPlaying)
+ return;
+
+ Common::StackLock lock(_mutex);
+ 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();
+ }
+}
+
+void TownsPC98_AudioDriver::timerCallbackB() {
+ _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;
+}
+
+void TownsPC98_AudioDriver::timerCallbackA() {
+ 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 (_updateSfxFlag && _finishedSfxFlag == _updateSfxFlag) {
+ _sfxPlaying = false;
+ _updateSfxFlag = 0;
+ setVolumeChannelMasks(-1, 0);
+ }
+}
+
+void TownsPC98_AudioDriver::setMusicTempo(uint8 tempo) {
+ writeReg(0, 0x26, tempo);
+ writeReg(0, 0x27, 0x33);
+}
+
+void TownsPC98_AudioDriver::setSfxTempo(uint16 tempo) {
+ writeReg(0, 0x24, tempo & 0xff);
+ writeReg(0, 0x25, tempo >> 8);
+ writeReg(0, 0x27, 0x33);
+}
+
+void TownsPC98_AudioDriver::startSoundEffect() {
+ int volFlags = 0;
+
+ for (int i = 0; i < 2; i++) {
+ if (_sfxOffsets[i]) {
+ _ssgChannels[i + 1]->protect();
+ _sfxChannels[i]->reset();
+ _sfxChannels[i]->loadData(_sfxData + _sfxOffsets[i]);
+ _updateSfxFlag |= _sfxChannels[i]->_idFlag;
+ volFlags |= (_sfxChannels[i]->_idFlag << _numChan);
+ } else {
+ _ssgChannels[i + 1]->restore();
+ _updateSfxFlag &= ~_sfxChannels[i]->_idFlag;
+ }
+ }
+
+ setVolumeChannelMasks(~volFlags, volFlags);
+ _sfxData = 0;
+}
+
+const uint8 TownsPC98_AudioDriver::_drvTables[] = {
+ // channel presets
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x80, 0x01, 0x01, 0x00, 0x02,
+ 0x02, 0x80, 0x02, 0x02, 0x00, 0x04,
+ 0x00, 0x80, 0x03, 0x04, 0x01, 0x08,
+ 0x01, 0x80, 0x04, 0x05, 0x01, 0x10,
+ 0x02, 0x80, 0x05, 0x06, 0x01, 0x20,
+
+ // control event size
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05,
+ 0x02, 0x06, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02,
+
+ // 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,
+
+ // 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,
+
+ // 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
+};
+
+#undef EUPHONY_FADEOUT_TICKS
+
diff --git a/sound/softsynth/fmtowns_pc98/towns_pc98_driver.h b/sound/softsynth/fmtowns_pc98/towns_pc98_driver.h
new file mode 100644
index 0000000000..18daee1e72
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_pc98_driver.h
@@ -0,0 +1,129 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TOWNS_PC98_AUDIODRIVER_H
+#define TOWNS_PC98_AUDIODRIVER_H
+
+#include "sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
+
+class TownsPC98_MusicChannel;
+class TownsPC98_MusicChannelSSG;
+class TownsPC98_SfxChannel;
+class TownsPC98_MusicChannelPCM;
+
+class TownsPC98_AudioDriver : public TownsPC98_FmSynth {
+friend class TownsPC98_MusicChannel;
+friend class TownsPC98_MusicChannelSSG;
+friend class TownsPC98_SfxChannel;
+friend class TownsPC98_MusicChannelPCM;
+public:
+ TownsPC98_AudioDriver(Audio::Mixer *mixer, EmuType type);
+ ~TownsPC98_AudioDriver();
+
+ 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;
+ }
+
+ void setMusicVolume(int volume) {
+ _musicVolume = volume;
+ setVolumeIntern(_musicVolume, _sfxVolume);
+ }
+ void setSoundEffectVolume(int volume) {
+ _sfxVolume = volume;
+ setVolumeIntern(_musicVolume, _sfxVolume);
+ }
+
+protected:
+ void startSoundEffect();
+
+ void setMusicTempo(uint8 tempo);
+ void setSfxTempo(uint16 tempo);
+
+ TownsPC98_MusicChannel **_channels;
+ TownsPC98_MusicChannelSSG **_ssgChannels;
+ TownsPC98_SfxChannel **_sfxChannels;
+ TownsPC98_MusicChannelPCM *_rhythmChannel;
+
+ 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 _updateChannelsFlag;
+ uint8 _updateSSGFlag;
+ uint8 _updateRhythmFlag;
+ uint8 _updateSfxFlag;
+ uint8 _finishedChannelsFlag;
+ uint8 _finishedSSGFlag;
+ uint8 _finishedRhythmFlag;
+ uint8 _finishedSfxFlag;
+
+ bool _musicPlaying;
+ bool _sfxPlaying;
+ uint8 _fading;
+ uint8 _looping;
+ uint32 _musicTickCounter;
+
+ int _sfxOffs;
+ uint8 *_sfxData;
+ uint16 _sfxOffsets[2];
+
+ uint16 _musicVolume;
+ uint16 _sfxVolume;
+
+ static const uint8 _drvTables[];
+
+ bool _ready;
+};
+
+#endif
+
diff --git a/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
new file mode 100644
index 0000000000..241b9bde50
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -0,0 +1,1513 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
+#include "common/endian.h"
+
+class TownsPC98_FmSynthOperator {
+public:
+ TownsPC98_FmSynthOperator(const uint32 timerbase, const uint32 rtt, const uint8 *rateTable,
+ const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable,
+ const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable);
+ ~TownsPC98_FmSynthOperator() {}
+
+ void keyOn();
+ void keyOff();
+ void frequency(int freq);
+ void updatePhaseIncrement();
+ void recalculateRates();
+ 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];
+ }
+ void multiple(uint32 value) {
+ _multiple = value ? (value << 1) : 1;
+ }
+ void attackRate(uint32 value) {
+ _specifiedAttackRate = value;
+ }
+ bool scaleRate(uint8 value);
+ void decayRate(uint32 value) {
+ _specifiedDecayRate = value;
+ recalculateRates();
+ }
+ void sustainRate(uint32 value) {
+ _specifiedSustainRate = value;
+ recalculateRates();
+ }
+ void sustainLevel(uint32 value) {
+ _sustainLevel = (value == 0x0f) ? 0x3e0 : value << 5;
+ }
+ void releaseRate(uint32 value) {
+ _specifiedReleaseRate = value;
+ recalculateRates();
+ }
+ void totalLevel(uint32 value) {
+ _totalLevel = value << 3;
+ }
+ void ampModulation(bool enable) {
+ _ampMod = enable;
+ }
+ void reset();
+
+protected:
+ EnvelopeState _state;
+ bool _playing;
+ uint32 _feedbackLevel;
+ uint32 _multiple;
+ uint32 _totalLevel;
+ uint8 _keyScale1;
+ uint8 _keyScale2;
+ uint32 _specifiedAttackRate;
+ uint32 _specifiedDecayRate;
+ uint32 _specifiedSustainRate;
+ uint32 _specifiedReleaseRate;
+ uint32 _tickCount;
+ uint32 _sustainLevel;
+
+ bool _ampMod;
+ uint32 _frequency;
+ uint8 _kcode;
+ uint32 _phase;
+ uint32 _phaseIncrement;
+ const int32 *_detn;
+
+ const uint8 *_rateTbl;
+ const uint8 *_rshiftTbl;
+ const uint8 *_adTbl;
+ const uint32 *_fTbl;
+ const uint32 *_sinTbl;
+ const int32 *_tLvlTbl;
+ const int32 *_detnTbl;
+
+ const uint32 _tickLength;
+ uint32 _timer;
+ const uint32 _rtt;
+ int32 _currentLevel;
+
+ struct EvpState {
+ uint8 rate;
+ uint8 shift;
+ } fs_a, fs_d, fs_s, fs_r;
+};
+
+TownsPC98_FmSynthOperator::TownsPC98_FmSynthOperator(const uint32 timerbase, const uint32 rtt,
+ const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable,
+ const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable) :
+ _rtt(rtt), _rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable),
+ _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(timerbase * 2),
+ _specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0),
+ _phase(0), _state(kEnvReady), _playing(false), _timer(0), _keyScale1(0),
+ _keyScale2(0), _currentLevel(1023), _ampMod(false), _tickCount(0) {
+
+ fs_a.rate = fs_a.shift = fs_d.rate = fs_d.shift = fs_s.rate = fs_s.shift = fs_r.rate = fs_r.shift = 0;
+
+ reset();
+}
+
+void TownsPC98_FmSynthOperator::keyOn() {
+ if (_playing)
+ return;
+
+ _playing = true;
+ _state = kEnvAttacking;
+ _phase = 0;
+}
+
+void TownsPC98_FmSynthOperator::keyOff() {
+ if (!_playing)
+ return;
+
+ _playing = false;
+ if (_state != kEnvReady)
+ _state = kEnvReleasing;
+}
+
+void TownsPC98_FmSynthOperator::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);
+}
+
+void TownsPC98_FmSynthOperator::updatePhaseIncrement() {
+ _phaseIncrement = ((_frequency + _detn[_kcode]) * _multiple) >> 1;
+ uint8 keyscale = _kcode >> _keyScale1;
+ if (_keyScale2 != keyscale) {
+ _keyScale2 = keyscale;
+ recalculateRates();
+ }
+}
+
+void TownsPC98_FmSynthOperator::recalculateRates() {
+ int k = _keyScale2;
+ int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0;
+ fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136;
+ fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0;
+
+ r = _specifiedDecayRate ? (_specifiedDecayRate << 1) + 0x20 : 0;
+ fs_d.rate = _rateTbl[r + k];
+ fs_d.shift = _rshiftTbl[r + k];
+
+ r = _specifiedSustainRate ? (_specifiedSustainRate << 1) + 0x20 : 0;
+ fs_s.rate = _rateTbl[r + k];
+ fs_s.shift = _rshiftTbl[r + k];
+
+ r = (_specifiedReleaseRate << 2) + 0x22;
+ fs_r.rate = _rateTbl[r + k];
+ fs_r.shift = _rshiftTbl[r + k];
+}
+
+void TownsPC98_FmSynthOperator::generateOutput(int32 phasebuf, int32 *feed, int32 &out) {
+ if (_state == kEnvReady)
+ return;
+
+ _timer += _tickLength;
+ while (_timer > _rtt) {
+ _timer -= _rtt;
+ ++_tickCount;
+
+ int32 levelIncrement = 0;
+ uint32 targetTime = 0;
+ int32 targetLevel = 0;
+ EnvelopeState nextState = kEnvReady;
+
+ switch (_state) {
+ case kEnvReady:
+ return;
+ case kEnvAttacking:
+ targetLevel = 0;
+ nextState = kEnvDecaying;
+ if ((_specifiedAttackRate << 1) + _keyScale2 < 64) {
+ targetTime = (1 << fs_a.shift) - 1;
+ levelIncrement = (~_currentLevel * _adTbl[fs_a.rate + ((_tickCount >> fs_a.shift) & 7)]) >> 4;
+ break;
+ } else {
+ _currentLevel = targetLevel;
+ _state = nextState;
+ }
+ // Fall through
+ case kEnvDecaying:
+ targetTime = (1 << fs_d.shift) - 1;
+ nextState = kEnvSustaining;
+ targetLevel = _sustainLevel;
+ levelIncrement = _adTbl[fs_d.rate + ((_tickCount >> fs_d.shift) & 7)];
+ break;
+ case kEnvSustaining:
+ targetTime = (1 << fs_s.shift) - 1;
+ nextState = kEnvSustaining;
+ targetLevel = 1023;
+ levelIncrement = _adTbl[fs_s.rate + ((_tickCount >> fs_s.shift) & 7)];
+ break;
+ case kEnvReleasing:
+ targetTime = (1 << fs_r.shift) - 1;
+ nextState = kEnvReady;
+ targetLevel = 1023;
+ levelIncrement = _adTbl[fs_r.rate + ((_tickCount >> fs_r.shift) & 7)];
+ break;
+ }
+
+ if (!(_tickCount & targetTime)) {
+ _currentLevel += levelIncrement;
+ if ((_state == kEnvAttacking && _currentLevel <= targetLevel) || (_state != kEnvAttacking && _currentLevel >= targetLevel)) {
+ if (_state != kEnvDecaying)
+ _currentLevel = targetLevel;
+ _state = nextState;
+ }
+ }
+ }
+
+ uint32 lvlout = _totalLevel + (uint32) _currentLevel;
+
+
+ int32 outp = 0;
+ int32 *i = &outp, *o = &outp;
+ int phaseShift = 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)
+ + phaseShift)) >> 16) & 0x3ff];
+ *i = ((index < 6656) ? _tLvlTbl[index] : 0);
+ } else {
+ *i = 0;
+ }
+
+ _phase += _phaseIncrement;
+ out += *o;
+}
+
+void TownsPC98_FmSynthOperator::reset() {
+ keyOff();
+ _timer = 0;
+ _keyScale2 = 0;
+ _currentLevel = 1023;
+
+ frequency(0);
+ detune(0);
+ scaleRate(0);
+ multiple(0);
+ updatePhaseIncrement();
+ attackRate(0);
+ decayRate(0);
+ releaseRate(0);
+ sustainRate(0);
+ feedbackLevel(0);
+ totalLevel(127);
+ ampModulation(false);
+}
+
+bool TownsPC98_FmSynthOperator::scaleRate(uint8 value) {
+ value = 3 - value;
+ if (_keyScale1 != value) {
+ _keyScale1 = value;
+ return true;
+ }
+
+ int k = _keyScale2;
+ int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0;
+ fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136;
+ fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0;
+ return false;
+}
+
+class TownsPC98_FmSynthSquareSineSource {
+public:
+ TownsPC98_FmSynthSquareSineSource(const uint32 timerbase, const uint32 rtt);
+ ~TownsPC98_FmSynthSquareSineSource();
+
+ 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);
+
+ void setVolumeIntern(int volA, int volB) {
+ _volumeA = volA;
+ _volumeB = volB;
+ }
+ void setVolumeChannelMasks(int channelMaskA, int channelMaskB) {
+ _volMaskA = channelMaskA;
+ _volMaskB = channelMaskB;
+ }
+
+ uint8 chanEnable() const {
+ return _chanEnable;
+ }
+private:
+ void updateRegs();
+
+ uint8 _updateRequestBuf[64];
+ 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;
+ const uint32 _rtt;
+
+ struct Channel {
+ int tick;
+ uint8 smp;
+ uint8 out;
+
+ uint8 frqL;
+ uint8 frqH;
+ uint8 vol;
+ } _channels[3];
+
+ uint8 _noiseGenerator;
+ uint8 _chanEnable;
+
+ uint8 **_reg;
+
+ uint16 _volumeA;
+ uint16 _volumeB;
+ int _volMaskA;
+ int _volMaskB;
+
+ bool _ready;
+};
+
+class TownsPC98_FmSynthPercussionSource {
+public:
+ TownsPC98_FmSynthPercussionSource(const uint32 timerbase, const uint32 rtt);
+ ~TownsPC98_FmSynthPercussionSource() {
+ delete[] _reg;
+ }
+
+ void init(const uint8 *instrData = 0);
+ void reset();
+ void writeReg(uint8 address, uint8 value);
+
+ void nextTick(int32 *buffer, uint32 bufferSize);
+
+ void setVolumeIntern(int volA, int volB) {
+ _volumeA = volA;
+ _volumeB = volB;
+ }
+ void setVolumeChannelMasks(int channelMaskA, int channelMaskB) {
+ _volMaskA = channelMaskA;
+ _volMaskB = channelMaskB;
+ }
+
+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;
+ const uint32 _rtt;
+
+ uint8 **_reg;
+
+ uint16 _volumeA;
+ uint16 _volumeB;
+ int _volMaskA;
+ int _volMaskB;
+
+ bool _ready;
+};
+
+TownsPC98_FmSynthSquareSineSource::TownsPC98_FmSynthSquareSineSource(const uint32 timerbase, const uint32 rtt) : _tlTable(0),
+ _rtt(rtt), _tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0), _reg(0), _rand(1), _outN(1),
+ _nTick(0), _evpUpdateCnt(0), _evpTimer(0x1f), _pReslt(0x1f), _attack(0), _cont(false), _evpUpdate(true),
+ _timer(0), _noiseGenerator(0), _chanEnable(0),
+ _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) {
+
+ memset(_channels, 0, sizeof(_channels));
+ memset(_updateRequestBuf, 0, sizeof(_updateRequestBuf));
+ _reg = new uint8 *[11];
+
+ _reg[0] = &_channels[0].frqL;
+ _reg[1] = &_channels[0].frqH;
+ _reg[2] = &_channels[1].frqL;
+ _reg[3] = &_channels[1].frqH;
+ _reg[4] = &_channels[2].frqL;
+ _reg[5] = &_channels[2].frqH;
+ _reg[6] = &_noiseGenerator;
+ _reg[7] = &_chanEnable;
+ _reg[8] = &_channels[0].vol;
+ _reg[9] = &_channels[1].vol;
+ _reg[10] = &_channels[2].vol;
+
+ reset();
+}
+
+TownsPC98_FmSynthSquareSineSource::~TownsPC98_FmSynthSquareSineSource() {
+ delete[] _tlTable;
+ delete[] _tleTable;
+ delete[] _reg;
+}
+
+void TownsPC98_FmSynthSquareSineSource::init(const int *rsTable, const int *rseTable) {
+ if (_ready) {
+ reset();
+ return;
+ }
+
+ 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;
+ }
+
+ 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_FmSynthSquareSineSource::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_FmSynthSquareSineSource::writeReg(uint8 address, uint8 value, bool force) {
+ if (!_ready)
+ return;
+
+ if (address > 10 || *_reg[address] == value) {
+ if ((address == 11 || address == 12 || address == 13) && value)
+ warning("TownsPC98_FmSynthSquareSineSource: unsupported reg address: %d", address);
+ return;
+ }
+
+ if (!force) {
+ if (_updateRequest >= 63) {
+ warning("TownsPC98_FmSynthSquareSineSource: event buffer overflow");
+ _updateRequest = -1;
+ }
+ _updateRequestBuf[++_updateRequest] = value;
+ _updateRequestBuf[++_updateRequest] = address;
+ return;
+ }
+
+ *_reg[address] = value;
+}
+
+void TownsPC98_FmSynthSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) {
+ if (!_ready)
+ return;
+
+ for (uint32 i = 0; i < bufferSize; i++) {
+ _timer += _tickLength;
+ while (_timer > _rtt) {
+ _timer -= _rtt;
+
+ if (++_nTick >= (_noiseGenerator & 0x1f)) {
+ if ((_rand + 1) & 2)
+ _outN ^= 1;
+
+ _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;
+ updateRegs();
+ }
+
+ int32 finOut = 0;
+ for (int ii = 0; ii < 3; ii++) {
+ int32 finOutTemp = ((_channels[ii].vol >> 4) & 1) ? _tleTable[_channels[ii].out ? _pReslt : 0] : _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0];
+
+ if ((1 << ii) & _volMaskA)
+ finOutTemp = (finOutTemp * _volumeA) / Audio::Mixer::kMaxMixerVolume;
+
+ if ((1 << ii) & _volMaskB)
+ finOutTemp = (finOutTemp * _volumeB) / Audio::Mixer::kMaxMixerVolume;
+
+ finOut += finOutTemp;
+ }
+
+ finOut /= 3;
+
+ buffer[i << 1] += finOut;
+ buffer[(i << 1) + 1] += finOut;
+ }
+}
+
+void TownsPC98_FmSynthSquareSineSource::updateRegs() {
+ for (int i = 0; i < _updateRequest;) {
+ uint8 b = _updateRequestBuf[i++];
+ uint8 a = _updateRequestBuf[i++];
+ writeReg(a, b, true);
+ }
+ _updateRequest = -1;
+}
+
+TownsPC98_FmSynthPercussionSource::TownsPC98_FmSynthPercussionSource(const uint32 timerbase, const uint32 rtt) :
+ _rtt(rtt), _tickLength(timerbase * 2), _timer(0), _ready(false), _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) {
+
+ memset(_rhChan, 0, sizeof(RhtChannel) * 6);
+ _reg = new uint8 *[40];
+
+ _reg[0] = _reg[1] = _reg[2] = _reg[3] = _reg[4] = _reg[5] = _reg[6] = _reg[7] = _reg[8] = _reg[9] = _reg[10] = _reg[11] = _reg[12] = _reg[13] = _reg[14] = _reg[15] = 0;
+ _reg[16] = &_rhChan[0].startPosL;
+ _reg[17] = &_rhChan[1].startPosL;
+ _reg[18] = &_rhChan[2].startPosL;
+ _reg[19] = &_rhChan[3].startPosL;
+ _reg[20] = &_rhChan[4].startPosL;
+ _reg[21] = &_rhChan[5].startPosL;
+ _reg[22] = &_rhChan[0].startPosH;
+ _reg[23] = &_rhChan[1].startPosH;
+ _reg[24] = &_rhChan[2].startPosH;
+ _reg[25] = &_rhChan[3].startPosH;
+ _reg[26] = &_rhChan[4].startPosH;
+ _reg[27] = &_rhChan[5].startPosH;
+ _reg[28] = &_rhChan[0].endPosL;
+ _reg[29] = &_rhChan[1].endPosL;
+ _reg[30] = &_rhChan[2].endPosL;
+ _reg[31] = &_rhChan[3].endPosL;
+ _reg[32] = &_rhChan[4].endPosL;
+ _reg[33] = &_rhChan[5].endPosL;
+ _reg[34] = &_rhChan[0].endPosH;
+ _reg[35] = &_rhChan[1].endPosH;
+ _reg[36] = &_rhChan[2].endPosH;
+ _reg[37] = &_rhChan[3].endPosH;
+ _reg[38] = &_rhChan[4].endPosH;
+ _reg[39] = &_rhChan[5].endPosH;
+}
+
+void TownsPC98_FmSynthPercussionSource::init(const uint8 *instrData) {
+ if (_ready) {
+ reset();
+ return;
+ }
+
+ const uint8 *start = instrData;
+ const uint8 *pos = start;
+
+ 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_FmSynthPercussionSource::reset() {
+ _timer = 0;
+ _totalLevel = 63;
+
+ 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_FmSynthPercussionSource::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_FmSynthPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) {
+ if (!_ready)
+ return;
+
+ for (uint32 i = 0; i < bufferSize; i++) {
+ _timer += _tickLength;
+ while (_timer > _rtt) {
+ _timer -= _rtt;
+
+ 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 <<= 1;
+
+ if (1 & _volMaskA)
+ finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume;
+
+ if (1 & _volMaskB)
+ finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume;
+
+ buffer[i << 1] += finOut;
+ buffer[(i << 1) + 1] += finOut;
+ }
+}
+
+void TownsPC98_FmSynthPercussionSource::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;
+}
+
+void TownsPC98_FmSynthPercussionSource::advanceInput(RhtChannel *ins) {
+ static const int8 adjustIndex[] = { -1, -1, -1, -1, 2, 5, 7, 9 };
+
+ 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++;
+
+ 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_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) :
+ _mixer(mixer),
+ _chanInternal(0), _ssg(0), _prc(0),
+ _numChan(type == kType26 ? 3 : 6), _numSSG(type == kTypeTowns ? 0 : 3), _hasPercussion(type == kType86 ? true : false),
+ _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0),
+ _rtt(type == kTypeTowns ? 0x514767 : 0x5B8D80), _baserate(55125.0f / (float)mixer->getOutputRate()),
+ _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255),
+ _regProtectionFlag(false), _ready(false) {
+
+ memset(&_timers[0], 0, sizeof(ChipTimer));
+ memset(&_timers[1], 0, sizeof(ChipTimer));
+ _timers[0].cb = &TownsPC98_FmSynth::timerCallbackA;
+ _timers[1].cb = &TownsPC98_FmSynth::timerCallbackB;
+ _timerbase = (uint32)(_baserate * 1000000.0f);
+}
+
+TownsPC98_FmSynth::~TownsPC98_FmSynth() {
+ Common::StackLock lock(_mutex);
+ _mixer->stopHandle(_soundHandle);
+ delete _ssg;
+ delete _prc;
+ delete[] _chanInternal;
+
+ delete[] _oprRates;
+ delete[] _oprRateshift;
+ delete[] _oprFrq;
+ delete[] _oprAttackDecay;
+ delete[] _oprSinTbl;
+ delete[] _oprLevelOut;
+ delete[] _oprDetune;
+}
+
+bool TownsPC98_FmSynth::init() {
+ if (_ready) {
+ reset();
+ return true;
+ }
+
+ generateTables();
+
+ _chanInternal = new ChanInternal[_numChan];
+ for (int i = 0; i < _numChan; i++) {
+ memset(&_chanInternal[i], 0, sizeof(ChanInternal));
+ for (int j = 0; j < 4; ++j)
+ _chanInternal[i].opr[j] = new TownsPC98_FmSynthOperator(_timerbase, _rtt, _oprRates, _oprRateshift, _oprAttackDecay, _oprFrq, _oprSinTbl, _oprLevelOut, _oprDetune);
+ }
+
+ if (_numSSG) {
+ _ssg = new TownsPC98_FmSynthSquareSineSource(_timerbase, _rtt);
+ _ssg->init(&_ssgTables[0], &_ssgTables[16]);
+ }
+
+ if (_hasPercussion) {
+ _prc = new TownsPC98_FmSynthPercussionSource(_timerbase, _rtt);
+ _prc->init(_percussionData);
+ }
+
+ _mixer->playStream(Audio::Mixer::kPlainSoundType,
+ &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+
+ _ready = true;
+
+ return true;
+}
+
+void TownsPC98_FmSynth::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;
+ }
+
+ writeReg(0, 0x27, 0x33);
+
+ if (_ssg)
+ _ssg->reset();
+
+ if (_prc)
+ _prc->reset();
+}
+
+void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {
+ if (_regProtectionFlag || !_ready)
+ return;
+
+ static const uint8 oprOrdr[] = { 0, 2, 1, 3 };
+
+ Common::StackLock lock(_mutex);
+
+ uint8 h = regAddress & 0xf0;
+ uint8 l = (regAddress & 0x0f);
+
+ ChanInternal *c = 0;
+ TownsPC98_FmSynthOperator **co = 0;
+ TownsPC98_FmSynthOperator *o = 0;
+
+ if (regAddress > 0x2F) {
+ c = &_chanInternal[(l & 3) + 3 * part];
+ co = c->opr;
+ o = c->opr[oprOrdr[(l - (l & 3)) >> 2]];
+ } else if (regAddress == 0x28) {
+ c = &_chanInternal[(value & 3) + ((value & 4) ? 3 : 0)];
+ co = c->opr;
+ }
+
+ switch (h) {
+ case 0x00:
+ // ssg
+ if (_ssg)
+ _ssg->writeReg(l, value);
+ break;
+ case 0x10:
+ // pcm rhythm channel
+ if (_prc)
+ _prc->writeReg(l, value);
+ break;
+ case 0x20:
+ if (l == 8) {
+ // Key on/off
+ for (int i = 0; i < 4; i++) {
+ if ((value >> (4 + i)) & 1)
+ co[oprOrdr[i]]->keyOn();
+ else
+ co[oprOrdr[i]]->keyOff();
+ }
+ } else if (l == 4) {
+ // Timer A
+ _timers[0].value = (_timers[0].value & 3) | (value << 2);
+ } else if (l == 5) {
+ // Timer A
+ _timers[0].value = (_timers[0].value & 0x3fc) | (value & 3);
+ } else if (l == 6) {
+ // Timer B
+ _timers[1].value = value & 0xff;
+ } else if (l == 7) {
+ if (value & 1) {
+ float spc = (float)(0x400 - _timers[0].value) / _baserate;
+ if (spc < 1) {
+ warning("TownsPC98_FmSynth: Invalid Timer A setting: %d", _timers[0].value);
+ spc = 1;
+ }
+
+ _timers[0].smpPerCb = (int32) spc;
+ _timers[0].smpPerCbRem = (uint32)((spc - (float)_timers[0].smpPerCb) * 1000000.0f);
+ _timers[0].smpTillCb = _timers[0].smpPerCb;
+ _timers[0].smpTillCbRem = _timers[0].smpPerCbRem;
+ _timers[0].enabled = true;
+ } else {
+ _timers[0].enabled = false;
+ }
+
+ if (value & 2) {
+ float spc = (float)(0x100 - _timers[1].value) * 16.0f / _baserate;
+ if (spc < 1) {
+ warning("TownsPC98_FmSynth: Invalid Timer B setting: %d", _timers[1].value);
+ spc = 1;
+ }
+
+ _timers[1].smpPerCb = (int32) spc;
+ _timers[1].smpPerCbRem = (uint32)((spc - (float)_timers[1].smpPerCb) * 1000000.0f);
+ _timers[1].smpTillCb = _timers[1].smpPerCb;
+ _timers[1].smpTillCbRem = _timers[1].smpPerCbRem;
+ _timers[1].enabled = true;
+ } else {
+ _timers[1].enabled = false;
+ }
+
+ if (value & 0x10) {
+ _timers[0].smpTillCb = _timers[0].smpPerCb;
+ _timers[0].smpTillCbRem = _timers[0].smpTillCbRem;
+ }
+
+ if (value & 0x20) {
+ _timers[1].smpTillCb = _timers[1].smpPerCb;
+ _timers[1].smpTillCbRem = _timers[1].smpTillCbRem;
+ }
+ } else if (l == 2) {
+ // LFO
+ if (value & 8)
+ warning("TownsPC98_FmSynth: TRYING TO USE LFO (NOT SUPPORTED)");
+ } else if (l == 10 || l == 11) {
+ // DAC
+ if (l == 11 && (value & 0x80))
+ warning("TownsPC98_FmSynth: TRYING TO USE DAC (NOT SUPPORTED)");
+ }
+ break;
+
+ case 0x30:
+ // detune, multiple
+ o->detune((value >> 4) & 7);
+ o->multiple(value & 0x0f);
+ c->updateEnvelopeParameters = true;
+ break;
+
+ case 0x40:
+ // total level
+ o->totalLevel(value & 0x7f);
+ break;
+
+ case 0x50:
+ // rate scaling, attack rate
+ o->attackRate(value & 0x1f);
+ if (o->scaleRate(value >> 6))
+ c->updateEnvelopeParameters = true;
+ break;
+
+ case 0x60:
+ // first decay rate, amplitude modulation
+ o->decayRate(value & 0x1f);
+ o->ampModulation(value & 0x80 ? true : false);
+ break;
+
+ case 0x70:
+ // secondary decay rate
+ o->sustainRate(value & 0x1f);
+ break;
+
+ case 0x80:
+ // secondary amplitude, release rate;
+ o->sustainLevel(value >> 4);
+ o->releaseRate(value & 0x0f);
+ break;
+
+ case 0x90:
+ warning("TownsPC98_FmSynth: TRYING TO USE SSG ENVELOPE SHAPES (NOT SUPPORTED)");
+ break;
+
+ 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_FmSynth: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)");
+ } else if (l == 12) {
+ // Ch 3/6 special mode frq
+ warning("TownsPC98_FmSynth: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)");
+ }
+ break;
+
+ 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;
+ c->ampModSensitivity((value & 0x30) >> 4);
+ c->frqModSensitivity(value & 3);
+ }
+ break;
+
+ default:
+ warning("TownsPC98_FmSynth: UNKNOWN ADDRESS %d", regAddress);
+ }
+}
+
+int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
+ Common::StackLock lock(_mutex);
+
+ memset(buffer, 0, sizeof(int16) * numSamples);
+ int32 *tmp = new int32[numSamples];
+ int32 *tmpStart = tmp;
+ memset(tmp, 0, sizeof(int32) * numSamples);
+ int32 samplesLeft = numSamples >> 1;
+
+ while (samplesLeft) {
+ int32 render = samplesLeft;
+
+ 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;
+
+ _timers[i].smpTillCbRem += _timers[i].smpPerCbRem;
+ if (_timers[i].smpTillCbRem >= _timerbase) {
+ _timers[i].smpTillCb++;
+ _timers[i].smpTillCbRem -= _timerbase;
+ }
+ }
+ render = MIN(render, _timers[i].smpTillCb);
+ }
+ }
+
+ samplesLeft -= render;
+
+ for (int i = 0; i < 2; i++) {
+ if (_timers[i].enabled && _timers[i].cb) {
+ _timers[i].smpTillCb -= render;
+ }
+ }
+
+ nextTick(tmp, render);
+
+ if (_ssg)
+ _ssg->nextTick(tmp, render);
+ if (_prc)
+ _prc->nextTick(tmp, render);
+
+ nextTickEx(tmp, render);
+
+ 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;
+ }
+
+ buffer += (render << 1);
+ tmp += (render << 1);
+ }
+
+ delete[] tmpStart;
+ return numSamples;
+}
+
+uint8 TownsPC98_FmSynth::readSSGStatus() {
+ return _ssg->chanEnable();
+}
+
+void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) {
+ Common::StackLock lock(_mutex);
+ _volumeA = CLIP<uint16>(volA, 0, Audio::Mixer::kMaxMixerVolume);
+ _volumeB = CLIP<uint16>(volB, 0, Audio::Mixer::kMaxMixerVolume);
+ if (_ssg)
+ _ssg->setVolumeIntern(_volumeA, _volumeB);
+ if (_prc)
+ _prc->setVolumeIntern(_volumeA, _volumeB);
+}
+
+void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB) {
+ Common::StackLock lock(_mutex);
+ _volMaskA = channelMaskA;
+ _volMaskB = channelMaskB;
+ if (_ssg)
+ _ssg->setVolumeChannelMasks(_volMaskA >> _numChan, _volMaskB >> _numChan);
+ if (_prc)
+ _prc->setVolumeChannelMasks(_volMaskA >> (_numChan + _numSSG), _volMaskB >> (_numChan + _numSSG));
+}
+
+void TownsPC98_FmSynth::generateTables() {
+ delete[] _oprRates;
+ _oprRates = new uint8[128];
+
+ WRITE_BE_UINT32(_oprRates + 32, _numChan == 6 ? 0x90900000 : 0x00081018);
+ WRITE_BE_UINT32(_oprRates + 36, _numChan == 6 ? 0x00001010 : 0x00081018);
+ memset(_oprRates, 0x90, 32);
+ memset(_oprRates + 96, 0x80, 32);
+ uint8 *dst = (uint8 *)_oprRates + 40;
+ for (int i = 0; i < 40; i += 4)
+ WRITE_BE_UINT32(dst + i, 0x00081018);
+ for (int i = 0; i < 48; i += 4)
+ WRITE_BE_UINT32(dst + i, 0x00081018);
+ dst += 40;
+ for (uint8 i = 0; i < 16; i ++) {
+ uint8 v = (i < 12) ? i : 12;
+ *dst++ = ((4 + v) << 3);
+ }
+
+ delete[] _oprRateshift;
+ _oprRateshift = new uint8[128];
+ memset(_oprRateshift, 0, 128);
+ dst = (uint8 *)_oprRateshift + 32;
+ for (int i = 11; i; i--) {
+ memset(dst, i, 4);
+ dst += 4;
+ }
+
+ delete[] _oprFrq;
+ _oprFrq = new uint32[0x1000];
+ for (uint32 i = 0; i < 0x1000; i++)
+ _oprFrq[i] = (uint32)(_baserate * (float)(i << 11));
+
+ delete[] _oprAttackDecay;
+ _oprAttackDecay = new uint8[152];
+ memset(_oprAttackDecay, 0, 152);
+ for (int i = 0; i < 36; i++)
+ WRITE_BE_UINT32(_oprAttackDecay + (i << 2), _adtStat[i]);
+
+ delete[] _oprSinTbl;
+ _oprSinTbl = new uint32[1024];
+ for (int i = 0; i < 1024; i++) {
+ double val = sin((double)(((i << 1) + 1) * PI / 1024.0));
+ double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0;
+ int32 i_dcb = (int32)(2.0 * d_dcb);
+ i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1);
+ _oprSinTbl[i] = (i_dcb << 1) + (val >= 0.0 ? 0 : 1);
+ }
+
+ delete[] _oprLevelOut;
+ _oprLevelOut = new int32[0x1a00];
+ for (int i = 0; i < 256; i++) {
+ double val = floor(65536.0 / pow(2.0, 0.00390625 * (double)(1 + i)));
+ int32 val_int = ((int32) val) >> 4;
+ _oprLevelOut[i << 1] = (val_int & 1) ? ((val_int >> 1) + 1) << 2 : (val_int >> 1) << 2;
+ _oprLevelOut[(i << 1) + 1] = -_oprLevelOut[i << 1];
+ for (int ii = 1; ii < 13; ++ii) {
+ _oprLevelOut[(i << 1) + (ii << 9)] = _oprLevelOut[i << 1] >> ii;
+ _oprLevelOut[(i << 1) + (ii << 9) + 1] = -_oprLevelOut[(i << 1) + (ii << 9)];
+ }
+ }
+
+ uint8 *dtt = new uint8[128];
+ memset(dtt, 0, 36);
+ memset(dtt + 36, 1, 8);
+ memcpy(dtt + 44, _detSrc, 84);
+
+ delete[] _oprDetune;
+ _oprDetune = new int32[256];
+ for (int i = 0; i < 128; i++) {
+ _oprDetune[i] = (int32)((float)dtt[i] * _baserate * 64.0);
+ _oprDetune[i + 128] = -_oprDetune[i];
+ }
+
+ delete[] dtt;
+}
+
+void TownsPC98_FmSynth::nextTick(int32 *buffer, uint32 bufferSize) {
+ if (!_ready)
+ return;
+
+ for (int i = 0; i < _numChan; i++) {
+ TownsPC98_FmSynthOperator **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 << 2) / ((_numChan + _numSSG - 3) / 3);
+
+ if ((1 << i) & _volMaskA)
+ finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume;
+
+ if ((1 << i) & _volMaskB)
+ finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume;
+
+ if (_chanInternal[i].enableLeft)
+ *leftSample += finOut;
+
+ if (_chanInternal[i].enableRight)
+ *rightSample += finOut;
+ }
+ }
+}
+
+const uint32 TownsPC98_FmSynth::_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_FmSynth::_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
+};
+
+const int TownsPC98_FmSynth::_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
+};
+
+const uint8 TownsPC98_FmSynth::_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
+};
+
+TownsPC98_FmSynth::ChanInternal::ChanInternal() {
+ memset(this, 0, sizeof(ChanInternal));
+}
+
+TownsPC98_FmSynth::ChanInternal::~ChanInternal() {
+ for (uint i = 0; i < ARRAYSIZE(opr); ++i)
+ delete opr[i];
+}
diff --git a/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
new file mode 100644
index 0000000000..3072503610
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
@@ -0,0 +1,177 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 TOWNS_PC98_FMSYNTH_H
+#define TOWNS_PC98_FMSYNTH_H
+
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+#include "common/list.h"
+
+class TownsPC98_FmSynthOperator;
+class TownsPC98_FmSynthSquareSineSource;
+class TownsPC98_FmSynthPercussionSource;
+
+enum EnvelopeState {
+ kEnvReady,
+ kEnvAttacking,
+ kEnvDecaying,
+ kEnvSustaining,
+ kEnvReleasing
+};
+
+class TownsPC98_FmSynth : public Audio::AudioStream {
+public:
+ enum EmuType {
+ kTypeTowns,
+ kType26,
+ kType86
+ };
+
+ TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type);
+ virtual ~TownsPC98_FmSynth();
+
+ virtual bool init();
+ virtual void reset();
+
+ void writeReg(uint8 part, uint8 regAddress, uint8 value);
+
+ // AudioStream interface
+ int readBuffer(int16 *buffer, const int numSamples);
+ bool isStereo() const {
+ return true;
+ }
+ bool endOfData() const {
+ return false;
+ }
+ int getRate() const {
+ return _mixer->getOutputRate();
+ }
+
+protected:
+ // Implement this in your inherited class if your driver generates
+ // additional output that has to be inserted into the buffer.
+ virtual void nextTickEx(int32 *buffer, uint32 bufferSize) {}
+
+ void toggleRegProtection(bool prot) {
+ _regProtectionFlag = prot;
+ }
+ uint8 readSSGStatus();
+
+ virtual void timerCallbackA() = 0;
+ virtual void timerCallbackB() = 0;
+
+ // The audio driver can store and apply two different audio settings
+ // (usually for music and sound effects). The channel mask will determine
+ // which channels get effected by the setting. The first bits will be
+ // the normal fm channels, the next bits the ssg channels and the final
+ // bit the rhythm channel.
+ void setVolumeIntern(int volA, int volB);
+ void setVolumeChannelMasks(int channelMaskA, int channelMaskB);
+
+ const int _numChan;
+ const int _numSSG;
+ const bool _hasPercussion;
+
+ Common::Mutex _mutex;
+private:
+ void generateTables();
+ void nextTick(int32 *buffer, uint32 bufferSize);
+ void generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed);
+
+ struct ChanInternal {
+ ChanInternal();
+ ~ChanInternal();
+
+ void ampModSensitivity(uint32 value) {
+ ampModSvty = (1 << (3 - value)) - (((value >> 1) & 1) | (value & 1));
+ }
+ void frqModSensitivity(uint32 value) {
+ frqModSvty = value << 5;
+ }
+
+ uint16 frqTemp;
+ bool enableLeft;
+ bool enableRight;
+ bool updateEnvelopeParameters;
+ int32 feedbuf[3];
+ uint8 algorithm;
+
+ uint32 ampModSvty;
+ uint32 frqModSvty;
+
+ TownsPC98_FmSynthOperator *opr[4];
+ };
+
+ TownsPC98_FmSynthSquareSineSource *_ssg;
+ TownsPC98_FmSynthPercussionSource *_prc;
+ ChanInternal *_chanInternal;
+
+ uint8 *_oprRates;
+ uint8 *_oprRateshift;
+ uint8 *_oprAttackDecay;
+ uint32 *_oprFrq;
+ uint32 *_oprSinTbl;
+ int32 *_oprLevelOut;
+ int32 *_oprDetune;
+
+ bool _regProtectionFlag;
+
+ typedef void (TownsPC98_FmSynth::*ChipTimerProc)();
+
+ struct ChipTimer {
+ bool enabled;
+ uint16 value;
+
+ int32 smpTillCb;
+ uint32 smpTillCbRem;
+ int32 smpPerCb;
+ uint32 smpPerCbRem;
+
+ ChipTimerProc cb;
+ };
+
+ ChipTimer _timers[2];
+
+ int _volMaskA, _volMaskB;
+ uint16 _volumeA, _volumeB;
+
+ const float _baserate;
+ uint32 _timerbase;
+ uint32 _rtt;
+
+ Audio::Mixer *_mixer;
+ Audio::SoundHandle _soundHandle;
+
+ static const uint8 _percussionData[];
+ static const uint32 _adtStat[];
+ static const uint8 _detSrc[];
+ static const int _ssgTables[];
+
+ bool _ready;
+};
+
+#endif
+
diff --git a/sound/softsynth/mt32.cpp b/sound/softsynth/mt32.cpp
index 612dce06b0..54366a4300 100644
--- a/sound/softsynth/mt32.cpp
+++ b/sound/softsynth/mt32.cpp
@@ -39,6 +39,7 @@
#include "common/system.h"
#include "common/util.h"
#include "common/archive.h"
+#include "common/translation.h"
#include "graphics/fontman.h"
#include "graphics/surface.h"
@@ -148,7 +149,7 @@ static void drawProgress(float progress) {
Common::Rect r(x, y, x + w, y + h);
uint32 col;
-
+
if (screenFormat.bytesPerPixel > 1)
col = screenFormat.RGBToColor(0, 171, 0);
else
@@ -183,7 +184,7 @@ static void drawMessage(int offset, const Common::String &text) {
uint16 y = g_system->getHeight() / 2 - h / 2 + offset * (h + 1);
uint32 col;
-
+
if (screenFormat.bytesPerPixel > 1)
col = screenFormat.RGBToColor(0, 0, 0);
else
@@ -323,7 +324,7 @@ int MidiDriver_MT32::open() {
}
_initialising = true;
- drawMessage(-1, "Initialising MT-32 Emulator");
+ drawMessage(-1, _s("Initialising MT-32 Emulator"));
if (!_synth->open(prop))
return MERR_DEVICE_NOT_AVAILABLE;
_initialising = false;
@@ -537,7 +538,7 @@ void MidiDriver_ThreadedMT32::onTimer() {
class MT32EmuMusicPlugin : public MusicPluginObject {
public:
const char *getName() const {
- return "MT-32 Emulator";
+ return _s("MT-32 Emulator");
}
const char *getId() const {
@@ -545,7 +546,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices MT32EmuMusicPlugin::getDevices() const {
@@ -554,23 +555,13 @@ MusicDevices MT32EmuMusicPlugin::getDevices() const {
return devices;
}
-Common::Error MT32EmuMusicPlugin::createInstance(MidiDriver **mididriver) const {
- *mididriver = new MidiDriver_MT32(g_system->getMixer());
-
- return Common::kNoError;
-}
-
-MidiDriver *MidiDriver_MT32_create() {
- // HACK: It will stay here until engine plugin loader overhaul
+Common::Error MT32EmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
if (ConfMan.hasKey("extrapath"))
SearchMan.addDirectory("extrapath", ConfMan.get("extrapath"));
- MidiDriver *mididriver;
-
- MT32EmuMusicPlugin p;
- p.createInstance(&mididriver);
+ *mididriver = new MidiDriver_MT32(g_system->getMixer());
- return mididriver;
+ return Common::kNoError;
}
//#if PLUGIN_ENABLED_DYNAMIC(MT32)
diff --git a/sound/softsynth/opl/dbopl.cpp b/sound/softsynth/opl/dbopl.cpp
index db07eaf8cc..857ed78436 100644
--- a/sound/softsynth/opl/dbopl.cpp
+++ b/sound/softsynth/opl/dbopl.cpp
@@ -418,7 +418,7 @@ Bits Operator::TemplateVolume( ) {
}
//In sustain phase, but not sustaining, do regular release
case RELEASE:
- vol += RateForward( releaseAdd );;
+ vol += RateForward( releaseAdd );
if ( GCC_UNLIKELY(vol >= ENV_MAX) ) {
volume = ENV_MAX;
SetState( OFF );
diff --git a/sound/softsynth/opl/mame.cpp b/sound/softsynth/opl/mame.cpp
index 9e7cbfe3dc..f6da659918 100644
--- a/sound/softsynth/opl/mame.cpp
+++ b/sound/softsynth/opl/mame.cpp
@@ -33,7 +33,7 @@
#include "mame.h"
-#if defined (_WIN32_WCE) || defined (__SYMBIAN32__) || defined(PALMOS_MODE) || defined(__GP32__) || defined(GP2X) || defined (__MAEMO__) || defined(__DS__) || defined (__MINT__) || defined(__N64__)
+#if defined (_WIN32_WCE) || defined (__SYMBIAN32__) || defined(__GP32__) || defined(GP2X) || defined (__MAEMO__) || defined(__DS__) || defined (__MINT__) || defined(__N64__)
#include "common/config-manager.h"
#endif
@@ -1212,7 +1212,7 @@ FM_OPL *makeAdLibOPL(int rate) {
// We need to emulate one YM3812 chip
int env_bits = FMOPL_ENV_BITS_HQ;
int eg_ent = FMOPL_EG_ENT_HQ;
-#if defined (_WIN32_WCE) || defined(__SYMBIAN32__) || defined(PALMOS_MODE) || defined(__GP32__) || defined (GP2X) || defined(__MAEMO__) || defined(__DS__) || defined (__MINT__) || defined(__N64__)
+#if defined (_WIN32_WCE) || defined(__SYMBIAN32__) || defined(__GP32__) || defined (GP2X) || defined(__MAEMO__) || defined(__DS__) || defined (__MINT__) || defined(__N64__)
if (ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) {
env_bits = FMOPL_ENV_BITS_HQ;
eg_ent = FMOPL_EG_ENT_HQ;
diff --git a/sound/softsynth/pcspk.cpp b/sound/softsynth/pcspk.cpp
index 396d9328f1..bdf9f112e8 100644
--- a/sound/softsynth/pcspk.cpp
+++ b/sound/softsynth/pcspk.cpp
@@ -24,6 +24,7 @@
*/
#include "sound/softsynth/pcspk.h"
+#include "sound/null.h"
namespace Audio {
@@ -128,3 +129,59 @@ int8 PCSpeaker::generateTriangle(uint32 x, uint32 oscLength) {
}
} // End of namespace Audio
+
+
+// Plugin interface
+// (This can only create a null driver since pc speaker support is not part of the
+// midi driver architecture. But we need the plugin for the options menu in the launcher
+// and for MidiDriver::detectDevice() which is more or less used by all engines.)
+
+class PCSpeakerMusicPlugin : public NullMusicPlugin {
+public:
+ const char *getName() const {
+ return _s("PC Speaker Emulator");
+ }
+
+ const char *getId() const {
+ return "pcspk";
+ }
+
+ MusicDevices getDevices() const;
+};
+
+MusicDevices PCSpeakerMusicPlugin::getDevices() const {
+ MusicDevices devices;
+ devices.push_back(MusicDevice(this, "", MT_PCSPK));
+ return devices;
+}
+
+class PCjrMusicPlugin : public NullMusicPlugin {
+public:
+ const char *getName() const {
+ return _s("IBM PCjr Emulator");
+ }
+
+ const char *getId() const {
+ return "pcjr";
+ }
+
+ MusicDevices getDevices() const;
+};
+
+MusicDevices PCjrMusicPlugin::getDevices() const {
+ MusicDevices devices;
+ devices.push_back(MusicDevice(this, "", MT_PCJR));
+ return devices;
+}
+
+//#if PLUGIN_ENABLED_DYNAMIC(PCSPK)
+ //REGISTER_PLUGIN_DYNAMIC(PCSPK, PLUGIN_TYPE_MUSIC, PCSpeakerMusicPlugin);
+//#else
+ REGISTER_PLUGIN_STATIC(PCSPK, PLUGIN_TYPE_MUSIC, PCSpeakerMusicPlugin);
+//#endif
+
+//#if PLUGIN_ENABLED_DYNAMIC(PCJR)
+ //REGISTER_PLUGIN_DYNAMIC(PCJR, PLUGIN_TYPE_MUSIC, PCjrMusicPlugin);
+//#else
+ REGISTER_PLUGIN_STATIC(PCJR, PLUGIN_TYPE_MUSIC, PCjrMusicPlugin);
+//#endif
diff --git a/sound/softsynth/sid.cpp b/sound/softsynth/sid.cpp
index e0dfd2efc0..e925f4a447 100644
--- a/sound/softsynth/sid.cpp
+++ b/sound/softsynth/sid.cpp
@@ -46,11 +46,6 @@ const int SID::FIXP_MASK = 0xffff;
WaveformGenerator::WaveformGenerator() {
sync_source = this;
- wave__ST = wave6581__ST;
- wave_P_T = wave6581_P_T;
- wave_PS_ = wave6581_PS_;
- wave_PST = wave6581_PST;
-
reset();
}
@@ -226,19 +221,19 @@ RESID_INLINE reg12 WaveformGenerator::outputN___() {
// Combined waveforms:
RESID_INLINE reg12 WaveformGenerator::output__ST() {
- return wave__ST[output__S_()] << 4;
+ return wave6581__ST[output__S_()] << 4;
}
RESID_INLINE reg12 WaveformGenerator::output_P_T() {
- return (wave_P_T[output___T() >> 1] << 4) & output_P__();
+ return (wave6581_P_T[output___T() >> 1] << 4) & output_P__();
}
RESID_INLINE reg12 WaveformGenerator::output_PS_() {
- return (wave_PS_[output__S_()] << 4) & output_P__();
+ return (wave6581_PS_[output__S_()] << 4) & output_P__();
}
RESID_INLINE reg12 WaveformGenerator::output_PST() {
- return (wave_PST[output__S_()] << 4) & output_P__();
+ return (wave6581_PST[output__S_()] << 4) & output_P__();
}
// Combined waveforms including noise:
@@ -506,7 +501,7 @@ Filter::Filter() {
+ sizeof(f0_points_6581)/sizeof(*f0_points_6581) - 1,
PointPlotter<sound_sample>(f0_6581), 1.0);
- mixer_DC = -0xfff*0xff/18 >> 7;
+ mixer_DC = (-0xfff*0xff/18) >> 7;
f0 = f0_6581;
f0_points = f0_points_6581;
diff --git a/sound/softsynth/sid.h b/sound/softsynth/sid.h
index d57ec73bad..c78f538441 100644
--- a/sound/softsynth/sid.h
+++ b/sound/softsynth/sid.h
@@ -118,15 +118,10 @@ protected:
reg12 outputNPST();
// Sample data for combinations of waveforms.
- static reg8 wave6581__ST[];
- static reg8 wave6581_P_T[];
- static reg8 wave6581_PS_[];
- static reg8 wave6581_PST[];
-
- reg8* wave__ST;
- reg8* wave_P_T;
- reg8* wave_PS_;
- reg8* wave_PST;
+ static const reg8 wave6581__ST[];
+ static const reg8 wave6581_P_T[];
+ static const reg8 wave6581_PS_[];
+ static const reg8 wave6581_PST[];
friend class Voice;
friend class SID;
diff --git a/sound/softsynth/wave6581.cpp b/sound/softsynth/wave6581.cpp
index 29998dcd0a..d1ddad1623 100644
--- a/sound/softsynth/wave6581.cpp
+++ b/sound/softsynth/wave6581.cpp
@@ -32,11 +32,9 @@
#include "sid.h"
-namespace Resid
-{
+namespace Resid {
-reg8 WaveformGenerator::wave6581__ST[] =
-{
+const reg8 WaveformGenerator::wave6581__ST[] = {
/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -551,8 +549,7 @@ reg8 WaveformGenerator::wave6581__ST[] =
/* 0xff8: */ 0x3e, 0x3e, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f,
};
-reg8 WaveformGenerator::wave6581_P_T[] =
-{
+const reg8 WaveformGenerator::wave6581_P_T[] = {
/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1067,8 +1064,7 @@ reg8 WaveformGenerator::wave6581_P_T[] =
/* 0xff8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
-reg8 WaveformGenerator::wave6581_PS_[] =
-{
+const reg8 WaveformGenerator::wave6581_PS_[] = {
/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1583,8 +1579,7 @@ reg8 WaveformGenerator::wave6581_PS_[] =
/* 0xff8: */ 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
};
-reg8 WaveformGenerator::wave6581_PST[] =
-{
+const reg8 WaveformGenerator::wave6581_PST[] = {
/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
diff --git a/sound/softsynth/ym2612.cpp b/sound/softsynth/ym2612.cpp
index e337bc4ab9..08331c6244 100644
--- a/sound/softsynth/ym2612.cpp
+++ b/sound/softsynth/ym2612.cpp
@@ -27,6 +27,7 @@
#include "sound/softsynth/ym2612.h"
#include "common/util.h"
#include "sound/musicplugin.h"
+#include "common/translation.h"
////////////////////////////////////////
//
@@ -758,7 +759,7 @@ void MidiDriver_YM2612::removeLookupTables() {
class TownsEmuMusicPlugin : public MusicPluginObject {
public:
const char *getName() const {
- return "FM Towns Emulator";
+ return _s("FM Towns Emulator");
}
const char *getId() const {
@@ -766,7 +767,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices TownsEmuMusicPlugin::getDevices() const {
@@ -775,21 +776,12 @@ MusicDevices TownsEmuMusicPlugin::getDevices() const {
return devices;
}
-Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_YM2612(g_system->getMixer());
return Common::kNoError;
}
-MidiDriver *MidiDriver_YM2612_create() {
- MidiDriver *mididriver;
-
- TownsEmuMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(TOWNS)
//REGISTER_PLUGIN_DYNAMIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin);
//#else
diff --git a/test/common/tokenizer.h b/test/common/tokenizer.h
index 3420b562aa..9c14875b81 100644
--- a/test/common/tokenizer.h
+++ b/test/common/tokenizer.h
@@ -5,7 +5,7 @@
class TokenizerTestSuite : public CxxTest::TestSuite {
public:
void test_nextToken() {
-
+
// test normal behavior
Common::StringTokenizer strTokenizer("Now, this is a test!", " ,!");
Common::String tokenArray[] = {"Now", "this", "is", "a", "test"};
@@ -17,7 +17,7 @@ public:
TS_ASSERT(strTokenizer.empty());
// Test edge cases:
-
+
// empty string
Common::StringTokenizer s1("");
TS_ASSERT_EQUALS("", s1.nextToken());
@@ -37,7 +37,7 @@ public:
TS_ASSERT_EQUALS("af", s4.nextToken());
}
- void test_resetAndEmpty() {
+ void test_resetAndEmpty() {
Common::StringTokenizer strTokenizer("Just, another test!", " ,!");
// test reset()
@@ -48,10 +48,10 @@ public:
TS_ASSERT_EQUALS(token2, "Just");
// test empty()
- TS_ASSERT(!strTokenizer.empty());
+ TS_ASSERT(!strTokenizer.empty());
strTokenizer.nextToken(); //another
strTokenizer.nextToken(); //test
- TS_ASSERT(strTokenizer.empty());
+ TS_ASSERT(strTokenizer.empty());
}
};
diff --git a/tools/convbdf.c b/tools/convbdf.c
index 4341eac2e7..fc13cff6ce 100644
--- a/tools/convbdf.c
+++ b/tools/convbdf.c
@@ -38,12 +38,12 @@
#include <time.h>
int READ_UINT16(void *addr) {
- unsigned char *buf = addr;
+ unsigned char *buf = (unsigned char *)addr;
return (buf[0] << 8) | buf[1];
}
void WRITE_UINT16(void *addr, int value) {
- unsigned char *buf = addr;
+ unsigned char *buf = (unsigned char *)addr;
buf[0] = (value >> 8) & 0xFF;
buf[1] = value & 0xFF;
}
@@ -611,7 +611,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf) {
/* determine whether font doesn't require encode table*/
l = 0;
for (i = 0; i < pf->size; ++i) {
- if (pf->offset[i] != l) {
+ if (pf->offset[i] != (unsigned long)l) {
encodetable = 1;
break;
}
@@ -648,7 +648,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf) {
/* reallocate bits array to actual bits used*/
if (ofs < pf->bits_size) {
- pf->bits = realloc(pf->bits, ofs * sizeof(bitmap_t));
+ pf->bits = (bitmap_t *)realloc(pf->bits, ofs * sizeof(bitmap_t));
pf->bits_size = ofs;
}
else {
@@ -919,7 +919,7 @@ int gen_c_source(struct font* pf, char *path) {
bbuf,
pf->defaultchar);
- fprintf(ofp, "\n" "#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))\n");
+ fprintf(ofp, "\n" "#if !(defined(__GP32__))\n");
fprintf(ofp, "extern const NewFont g_sysfont(desc);\n");
fprintf(ofp, "#else\n");
fprintf(ofp, "DEFINE_FONT(g_sysfont)\n");
diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp
index c1bcbc006c..85038a0820 100644
--- a/tools/create_kyradat/create_kyradat.cpp
+++ b/tools/create_kyradat/create_kyradat.cpp
@@ -45,7 +45,7 @@
#include <map>
enum {
- kKyraDatVersion = 70
+ kKyraDatVersion = 72
};
const ExtractFilename extractFilenames[] = {
@@ -163,6 +163,7 @@ const ExtractFilename extractFilenames[] = {
{ k1CreditsStrings, kTypeRawData, true },
// FM-TOWNS specific
+ { k1TownsMusicFadeTable, k3TypeRaw16to8, false },
{ k1TownsSFXwdTable, kTypeTownsWDSfxTable, false },
{ k1TownsSFXbtTable, kTypeRawData, false },
{ k1TownsCDATable, kTypeRawData, false },
@@ -500,7 +501,7 @@ bool checkIndex(PAKFile &file) {
void printHelp(const char *f) {
printf("Usage:\n");
- printf("%s output inputfiles ...", f);
+ printf("%s output inputfiles ...\n", f);
}
bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size);
@@ -898,6 +899,8 @@ const char *getIdString(const int id) {
return "k1GUIStrings";
case k1ConfigStrings:
return "k1ConfigStrings";
+ case k1TownsMusicFadeTable:
+ return "k1TownsMusicFadeTable";
case k1TownsSFXwdTable:
return "k1TownsSFXwdTable";
case k1TownsSFXbtTable:
diff --git a/tools/create_kyradat/create_kyradat.h b/tools/create_kyradat/create_kyradat.h
index 435e239381..d82e16fed0 100644
--- a/tools/create_kyradat/create_kyradat.h
+++ b/tools/create_kyradat/create_kyradat.h
@@ -138,6 +138,7 @@ enum kExtractID {
k1CreditsStrings,
+ k1TownsMusicFadeTable,
k1TownsSFXwdTable,
k1TownsSFXbtTable,
k1TownsCDATable,
diff --git a/tools/create_kyradat/games.cpp b/tools/create_kyradat/games.cpp
index 9976451067..008120868f 100644
--- a/tools/create_kyradat/games.cpp
+++ b/tools/create_kyradat/games.cpp
@@ -99,6 +99,7 @@ const Game lolGames[] = {
{ kLol, { EN_ANY, -1, -1 }, kPlatformPC, kDemoVersion, { "30bb5af87d38adb47d3e6ce06b1cb042", 0 } },
// DOS floppy (no language specifc strings)
+ { kLol, { EN_ANY, -1, -1 }, kPlatformPC, kNoSpecial, { "0cc764a204f7ba8cefe1a5f14c479619", 0 } },
{ kLol, { DE_DEU, -1, -1 }, kPlatformPC, kNoSpecial, { "6b843869772c1b779e1386be868c15dd", 0 } },
// PC98 (no language specifc strings)
@@ -411,6 +412,8 @@ const int kyra1TownsNeed[] = {
k1NewGameString,
k1ConfigStrings,
+ k1TownsMusicFadeTable,
+ k1TownsMusicFadeTable,
k1TownsSFXwdTable,
k1TownsSFXbtTable,
k1TownsCDATable,
diff --git a/tools/create_kyradat/tables.cpp b/tools/create_kyradat/tables.cpp
index a74f58e2c3..e2235b1b78 100644
--- a/tools/create_kyradat/tables.cpp
+++ b/tools/create_kyradat/tables.cpp
@@ -968,6 +968,12 @@ const ExtractEntrySearchData k1ConfigStringsProvider[] = {
EXTRACT_END_ENTRY
};
+const ExtractEntrySearchData k1TownsMusicFadeTableProvider[] = {
+ { UNK_LANG, kPlatformFMTowns, { 0x00000B10, 0x000076DE, { { 0x9F, 0x08, 0x5B, 0xD6, 0x25, 0x7F, 0x11, 0x08, 0x87, 0x45, 0x92, 0xD3, 0xE5, 0xA8, 0x7C, 0x2F } } } },
+
+ EXTRACT_END_ENTRY
+};
+
const ExtractEntrySearchData k1TownsSFXwdTableProvider[] = {
{ UNK_LANG, kPlatformFMTowns, { 0x00012608, 0x006717A1, { { 0x34, 0xDD, 0x2D, 0xA5, 0x14, 0x05, 0xEE, 0x2F, 0x93, 0x7C, 0x78, 0x4D, 0xCA, 0x13, 0xED, 0x93 } } } },
@@ -1275,6 +1281,7 @@ const ExtractEntrySearchData kLolIngamePakFilesProvider[] = {
};
const ExtractEntrySearchData kLolCharacterDefsProvider[] = {
+ { UNK_LANG, kPlatformPC, { 0x00000492, 0x000046B0, { { 0x7A, 0x94, 0x8B, 0xC6, 0xF7, 0xF1, 0x2F, 0xF3, 0xBC, 0x1B, 0x0B, 0x4E, 0x00, 0xC9, 0x44, 0x58 } } } }, // floppy
{ UNK_LANG, kPlatformPC, { 0x00000492, 0x000047FD, { { 0x8C, 0x0B, 0x8B, 0xCE, 0xE0, 0xB0, 0x8F, 0xA9, 0x06, 0xC3, 0x98, 0xE6, 0x2E, 0x09, 0xB6, 0x93 } } } }, // floppy
{ UNK_LANG, kPlatformPC, { 0x00000492, 0x00004ACD, { { 0xDF, 0x87, 0xFE, 0x89, 0x59, 0xCC, 0x01, 0xD7, 0xC7, 0xEB, 0x16, 0xA4, 0x09, 0xAF, 0x5D, 0xC0 } } } }, // CD
{ UNK_LANG, kPlatformPC98, { 0x00000492, 0x00005893, { { 0x7C, 0x7E, 0xFB, 0x80, 0xD9, 0xB6, 0x16, 0x87, 0x80, 0xB7, 0x46, 0x9B, 0x96, 0x1A, 0x6A, 0xBE } } } },
@@ -1613,6 +1620,7 @@ const ExtractEntrySearchData kLolScrollYBottomProvider[] = {
};
const ExtractEntrySearchData kLolButtonDefsProvider[] = {
+ { UNK_LANG, kPlatformPC, { 0x0000082A, 0x0000CAAE, { { 0xC1, 0x83, 0x0D, 0xA0, 0x66, 0x16, 0x3D, 0x31, 0xCE, 0x30, 0x9F, 0x4E, 0x00, 0x65, 0x5A, 0xC8 } } } }, // floppy
{ UNK_LANG, kPlatformPC, { 0x0000082A, 0x0000C34E, { { 0x7F, 0x9A, 0x0F, 0x28, 0x1A, 0x8F, 0x03, 0x46, 0x48, 0xEB, 0xC9, 0xB9, 0x23, 0x29, 0x5E, 0x50 } } } }, // floppy
{ UNK_LANG, kPlatformPC, { 0x0000082A, 0x0000C47B, { { 0xDF, 0x1A, 0x18, 0x1F, 0x58, 0x05, 0x1F, 0x56, 0xD8, 0x6D, 0xBB, 0x93, 0xEC, 0x35, 0x9D, 0xA5 } } } }, // CD
{ UNK_LANG, kPlatformPC98, { 0x0000082A, 0x0000AB58, { { 0xDD, 0x2B, 0xA9, 0x54, 0x60, 0x25, 0x2C, 0x74, 0xF8, 0x5D, 0xC6, 0xD2, 0x2C, 0x1A, 0x24, 0x44 } } } },
@@ -1669,6 +1677,7 @@ const ExtractEntrySearchData kLolButtonList8Provider[] = {
};
const ExtractEntrySearchData kLolLegendDataProvider[] = {
+ { UNK_LANG, kPlatformUnknown, { 0x00000030, 0x00000858, { { 0x63, 0x5E, 0x60, 0xC7, 0x62, 0x2C, 0x5D, 0x8F, 0x74, 0x71, 0x98, 0xB7, 0x09, 0xD2, 0x51, 0xC7 } } } },
{ UNK_LANG, kPlatformUnknown, { 0x0000003C, 0x00000A52, { { 0x81, 0xC5, 0xA4, 0xE7, 0x60, 0xDA, 0xD6, 0x5E, 0x19, 0xAB, 0xF3, 0xC7, 0xDD, 0xDB, 0x92, 0x5E } } } },
EXTRACT_END_ENTRY
@@ -1823,6 +1832,7 @@ const ExtractEntry extractProviders[] = {
{ k1SpecialPalette33, k1SpecialPalette33Provider },
{ k1GUIStrings, k1GUIStringsProvider },
{ k1ConfigStrings, k1ConfigStringsProvider },
+ { k1TownsMusicFadeTable, k1TownsMusicFadeTableProvider },
{ k1TownsSFXwdTable, k1TownsSFXwdTableProvider },
{ k1TownsSFXbtTable, k1TownsSFXbtTableProvider },
{ k1TownsCDATable, k1TownsCDATableProvider },
diff --git a/tools/create_msvc/create_msvc.cpp b/tools/create_msvc/create_msvc.cpp
index a2636dab21..fcae638c50 100644
--- a/tools/create_msvc/create_msvc.cpp
+++ b/tools/create_msvc/create_msvc.cpp
@@ -210,8 +210,9 @@ public:
* @param bits Number of bits the platform supports.
* @param defines Defines the platform needs to have set.
* @param prefix File prefix, used to add additional include paths.
+ * @param isWin32 Bitness of property file
*/
- virtual void outputGlobalPropFile(std::ofstream &properties, int bits, const std::string &defines, const std::string &prefix) = 0;
+ virtual void outputGlobalPropFile(std::ofstream &properties, int bits, const std::string &defines, const std::string &prefix, bool isWin32) = 0;
/**
* Generates the project properties for debug and release settings.
@@ -282,7 +283,7 @@ public:
void writeReferences(std::ofstream &output);
- void outputGlobalPropFile(std::ofstream &properties, int bits, const std::string &defines, const std::string &prefix);
+ void outputGlobalPropFile(std::ofstream &properties, int bits, const std::string &defines, const std::string &prefix, bool isWin32);
void createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32);
@@ -305,7 +306,7 @@ public:
void writeReferences(std::ofstream &output);
- void outputGlobalPropFile(std::ofstream &properties, int bits, const std::string &defines, const std::string &prefix);
+ void outputGlobalPropFile(std::ofstream &properties, int bits, const std::string &defines, const std::string &prefix, bool isWin32);
void createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32);
@@ -838,11 +839,14 @@ const Feature s_features[] = {
{ "mpeg2", "USE_MPEG2", "libmpeg2.lib", false, "mpeg2 codec for cutscenes" },
// ScummVM feature flags
- { "scalers", "USE_SCALERS", "", true, "Scalers" },
- { "hqscalers", "USE_HQ_SCALERS", "", true, "HQ scalers" },
- { "16bit", "USE_RGB_COLOR", "", true, "16bit color support" },
- { "mt32emu", "USE_MT32EMU", "", true, "integrated MT-32 emulator" },
- { "nasm", "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling.
+ { "scalers", "USE_SCALERS", "", true, "Scalers" },
+ { "hqscalers", "USE_HQ_SCALERS", "", true, "HQ scalers" },
+ { "16bit", "USE_RGB_COLOR", "", true, "16bit color support" },
+ { "mt32emu", "USE_MT32EMU", "", true, "integrated MT-32 emulator" },
+ { "nasm", "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling.
+ { "translation", "USE_TRANSLATION", "", true, "Translation support" },
+ { "langdetect", "USE_DETECTLANG", "", true, "System language detection support" } // This feature actually depends on "translation", there
+ // is just no current way of properly detecting this...
};
} // End of anonymous namespace
@@ -1326,7 +1330,7 @@ void ProjectProvider::createGlobalProp(const BuildSetup &setup) {
defines += *i;
}
- outputGlobalPropFile(properties, 32, defines, convertPathToWin(setup.filePrefix));
+ outputGlobalPropFile(properties, 32, defines, convertPathToWin(setup.filePrefix), true);
properties.close();
properties.open((setup.outputDir + '/' + "ScummVM_Global64" + getPropertiesExtension()).c_str());
@@ -1348,7 +1352,7 @@ void ProjectProvider::createGlobalProp(const BuildSetup &setup) {
defines += *i;
}
- outputGlobalPropFile(properties, 64, defines, convertPathToWin(setup.filePrefix));
+ outputGlobalPropFile(properties, 64, defines, convertPathToWin(setup.filePrefix), false);
}
void ProjectProvider::addFilesToProject(const std::string &dir, std::ofstream &projectFile,
@@ -1651,7 +1655,7 @@ void VisualStudioProvider::writeReferences(std::ofstream &output) {
output << "\tEndProjectSection\n";
}
-void VisualStudioProvider::outputGlobalPropFile(std::ofstream &properties, int bits, const std::string &defines, const std::string &prefix) {
+void VisualStudioProvider::outputGlobalPropFile(std::ofstream &properties, int bits, const std::string &defines, const std::string &prefix, bool isWin32) {
properties << "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n"
"<VisualStudioPropertySheet\n"
"\tProjectType=\"Visual C++\"\n"
@@ -1664,7 +1668,7 @@ void VisualStudioProvider::outputGlobalPropFile(std::ofstream &properties, int b
"\t\tName=\"VCCLCompilerTool\"\n"
"\t\tDisableLanguageExtensions=\"true\"\n"
"\t\tDisableSpecificWarnings=\"" << _globalWarnings << "\"\n"
- "\t\tAdditionalIncludeDirectories=\"" << prefix << ";" << prefix << "\\engines\"\n"
+ "\t\tAdditionalIncludeDirectories=\"" << prefix << ";" << prefix << "\\engines;$(SCUMMVM_LIBS)\\include\"\n"
"\t\tPreprocessorDefinitions=\"" << defines << "\"\n"
"\t\tExceptionHandling=\"0\"\n"
"\t\tRuntimeTypeInfo=\"false\"\n"
@@ -1681,6 +1685,7 @@ void VisualStudioProvider::outputGlobalPropFile(std::ofstream &properties, int b
"\t\tIgnoreDefaultLibraryNames=\"\"\n"
"\t\tSubSystem=\"1\"\n"
"\t\tEntryPointSymbol=\"WinMainCRTStartup\"\n"
+ "\t\tAdditionalLibraryDirectories=\"$(SCUMMVM_LIBS)\\libs\\" << (isWin32 ? "x86" : "x64") << "\"\n"
"\t/>\n"
"\t<Tool\n"
"\t\tName=\"VCResourceCompilerTool\"\n"
@@ -1899,12 +1904,6 @@ void MSBuildProvider::createProjectFile(const std::string &name, const std::stri
// Project version number
project << "\t<PropertyGroup>\n"
"\t\t<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\n";
-
- if (name == "scummvm")
- project << "<ExecutablePath>$(SCUMMVM_LIBS)\\bin;$(VCInstallDir)bin;$(WindowsSdkDir)bin\\NETFX 4.0 Tools;$(WindowsSdkDir)bin;$(VSInstallDir)Common7\\Tools\\bin;$(VSInstallDir)Common7\\tools;$(VSInstallDir)Common7\\ide;$(ProgramFiles)\\HTML Help Workshop;$(FrameworkSDKDir)\\bin;$(MSBuildToolsPath32);$(VSInstallDir);$(SystemRoot)\\SysWow64;$(FxCopDir);$(PATH)</ExecutablePath>\n"
- "<IncludePath>$(SCUMMVM_LIBS)\\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\\include;</IncludePath>\n"
- "<LibraryPath>$(SCUMMVM_LIBS)\\lib;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\\lib</LibraryPath>\n";
-
project << "\t</PropertyGroup>\n";
// Project-specific settings
@@ -2049,38 +2048,41 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s
project << "\t</ItemDefinitionGroup>\n";
}
-void MSBuildProvider::outputGlobalPropFile(std::ofstream &properties, int bits, const std::string &defines, const std::string &prefix) {
+void MSBuildProvider::outputGlobalPropFile(std::ofstream &properties, int bits, const std::string &defines, const std::string &prefix, bool isWin32) {
properties << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
- "<PropertyGroup>\n"
- "<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\n"
- "<_PropertySheetDisplayName>ScummVM_Global</_PropertySheetDisplayName>\n"
- "<OutDir>$(Configuration)" << bits << "\\</OutDir>\n"
- "<IntDir>$(Configuration)" << bits << "/$(ProjectName)\\</IntDir>\n"
- "</PropertyGroup>\n"
- "<ItemDefinitionGroup>\n"
- "<ClCompile>\n"
- "<DisableLanguageExtensions>true</DisableLanguageExtensions>\n"
- "<DisableSpecificWarnings>" << _globalWarnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n"
- "<AdditionalIncludeDirectories>" << prefix << ";" << prefix << "\\engines;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
- "<PreprocessorDefinitions>" << defines << ";%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
- "<ExceptionHandling>\n"
- "</ExceptionHandling>\n"
- "<RuntimeTypeInfo>false</RuntimeTypeInfo>\n"
- "<WarningLevel>Level4</WarningLevel>\n"
- "<TreatWarningAsError>false</TreatWarningAsError>\n"
- "<CompileAs>Default</CompileAs>\n"
- "</ClCompile>\n"
- "<Link>\n"
- "<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n"
- "<SubSystem>Console</SubSystem>\n"
- "<EntryPointSymbol>WinMainCRTStartup</EntryPointSymbol>\n"
- "</Link>\n"
- "<ResourceCompile>\n"
- "<PreprocessorDefinitions>HAS_INCLUDE_SET;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
- "<AdditionalIncludeDirectories>" << prefix << ";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
- "</ResourceCompile>\n"
- "</ItemDefinitionGroup>\n"
+ "\t<PropertyGroup>\n"
+ "\t\t<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\n"
+ "\t\t<_PropertySheetDisplayName>ScummVM_Global</_PropertySheetDisplayName>\n"
+ "\t\t<ExecutablePath>$(SCUMMVM_LIBS)\\bin;$(ExecutablePath)</ExecutablePath>\n"
+ "\t\t<LibraryPath>$(SCUMMVM_LIBS)\\libs\\" << (isWin32 ? "x86" : "x64") << ";$(LibraryPath)</LibraryPath>\n"
+ "\t\t<IncludePath>$(SCUMMVM_LIBS)\\include;$(IncludePath)</IncludePath>\n"
+ "\t\t<OutDir>$(Configuration)" << bits << "\\</OutDir>\n"
+ "\t\t<IntDir>$(Configuration)" << bits << "/$(ProjectName)\\</IntDir>\n"
+ "\t</PropertyGroup>\n"
+ "\t<ItemDefinitionGroup>\n"
+ "\t\t<ClCompile>\n"
+ "\t\t\t<DisableLanguageExtensions>true</DisableLanguageExtensions>\n"
+ "\t\t\t<DisableSpecificWarnings>" << _globalWarnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n"
+ "\t\t\t<AdditionalIncludeDirectories>" << prefix << ";" << prefix << "\\engines;$(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
+ "\t\t\t<PreprocessorDefinitions>" << defines << ";%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
+ "\t\t\t<ExceptionHandling>\n"
+ "\t\t\t</ExceptionHandling>\n"
+ "\t\t\t<RuntimeTypeInfo>false</RuntimeTypeInfo>\n"
+ "\t\t\t<WarningLevel>Level4</WarningLevel>\n"
+ "\t\t\t<TreatWarningAsError>false</TreatWarningAsError>\n"
+ "\t\t\t<CompileAs>Default</CompileAs>\n"
+ "\t\t</ClCompile>\n"
+ "\t\t<Link>\n"
+ "\t\t\t<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n"
+ "\t\t\t<SubSystem>Console</SubSystem>\n"
+ "\t\t\t<EntryPointSymbol>WinMainCRTStartup</EntryPointSymbol>\n"
+ "\t\t</Link>\n"
+ "\t\t<ResourceCompile>\n"
+ "\t\t\t<PreprocessorDefinitions>HAS_INCLUDE_SET;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
+ "\t\t\t<AdditionalIncludeDirectories>" << prefix << ";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
+ "\t\t</ResourceCompile>\n"
+ "\t</ItemDefinitionGroup>\n"
"</Project>\n";
properties.flush();
@@ -2107,6 +2109,8 @@ void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, b
"\t<ItemDefinitionGroup>\n"
"\t\t<ClCompile>\n";
+
+
if (isRelease) {
properties << "\t\t\t<IntrinsicFunctions>true</IntrinsicFunctions>\n"
"\t\t\t<WholeProgramOptimization>true</WholeProgramOptimization>\n"
diff --git a/tools/credits.pl b/tools/credits.pl
index 165834b9b9..f59c68021a 100755
--- a/tools/credits.pl
+++ b/tools/credits.pl
@@ -666,6 +666,10 @@ begin_credits("Credits");
begin_section("Backend Teams");
+ begin_section("Android");
+ add_person("Angus Lees", "Gus", "");
+ end_section();
+
begin_section("Dreamcast");
add_person("Marcus Comstedt", "", "");
end_section();
@@ -694,10 +698,6 @@ begin_credits("Credits");
add_person("Neil Millstone", "agent-q", "");
end_section();
- begin_section("PalmOS");
- add_person("Chris Apers", "chrilith ", "");
- end_section();
-
begin_section("PocketPC / WinCE");
add_person("Nicolas Bacca", "arisme", "(retired)");
add_person("Kostas Nakos", "Jubanka", "");
@@ -771,6 +771,7 @@ begin_credits("Credits");
begin_section("Retired Team Members");
begin_persons();
+ add_person("Chris Apers", "chrilith ", "Former PalmOS porter");
add_person("Ralph Brorsen", "painelf", "Help with GUI implementation");
add_person("Jamieson Christian", "jamieson630", "iMUSE, MIDI, all things musical");
add_person("Felix Jakschitsch", "yot", "Zak256 reverse engineering");
@@ -850,6 +851,37 @@ begin_credits("Credits");
add_person("Johannes Schickel", "LordHoto", "");
end_section();
end_section();
+
+ begin_section("Translations");
+ begin_persons();
+ add_person("Thierry Crozat", "criezy", "Translation Lead");
+ end_persons();
+ begin_section("Catalan");
+ add_person("Jordi Vilalta Prat", "jvprat", "");
+ end_section();
+ begin_section("French");
+ add_person("Thierry Crozat", "criezy", "");
+ end_section();
+ begin_section("German");
+ add_person("Simon Sawatzki", "SimSaw", "");
+ add_person("Lothar Serra Mari", "Lothar93", "");
+ end_section();
+ begin_section("Hungarian");
+ add_person("Alex Bevilacqua", "", "");
+ end_section();
+ begin_section("Italian");
+ add_person("Matteo Angelino", "Maff", "");
+ end_section();
+ begin_section("Russian");
+ add_person("Eugene Sandulenko", "sev", "");
+ end_section();
+ begin_section("Spanish");
+ add_person("Tom&aacute;s Maidagan", "Truido", "");
+ end_section();
+ begin_section("Ukrainian");
+ add_person("Lubomyr Lisen", "", "");
+ end_section();
+ end_section();
begin_section("Websites (design)");
begin_persons();
@@ -918,7 +950,7 @@ begin_credits("Credits");
add_person("Ravi I.", "", "SCI0 sound resource specification");
add_person("Ruediger Hanke", "", "Port to the MorphOS platform");
add_person("Rune Orsval", "", "Configuration file editor");
- add_person("Rickard Lind", "", "MT32->GM MIDI mapping magic, sound research");
+ add_person("Rickard Lind", "", "MT-32->GM MIDI mapping magic, sound research");
add_person("Rink Springer", "", "Port to the DOS platform, several bug fixes");
add_person("Robey Pointer", "", "Bug tracking system hosting");
add_person("Sergey Lapin", "", "Port of Carl's type 2 decompression code");
@@ -929,8 +961,8 @@ begin_credits("Credits");
add_person("Sean Terrell", "", "");
end_persons();
add_paragraph("Special thanks to Prof. Dr. Gary Nutt ".
- "for allowing the FreeSCI VM extension as a ".
- "course project in his Advanced OS course.");
+ "for allowing the FreeSCI VM extension as a ".
+ "course project in his Advanced OS course.");
add_paragraph("Special thanks to Bob Heitman and Corey Cole for their support of FreeSCI.");
end_section();
diff --git a/tools/make-scumm-fontdata.c b/tools/make-scumm-fontdata.c
index f251a22b80..991d49831a 100644
--- a/tools/make-scumm-fontdata.c
+++ b/tools/make-scumm-fontdata.c
@@ -821,7 +821,7 @@ static const unsigned char spanishCharsetDataV2[] = {
unsigned char *specialCharsetData = NULL;
int numSpecialChars = 0;
-void compressCharset(const unsigned char *data, char *var, char *name) {
+void compressCharset(const unsigned char *data, const char *var, const char *name) {
int i;
printf("// %s\n", name);
diff --git a/tools/md5table.c b/tools/md5table.c
index b69f3957cd..cb2959ed88 100644
--- a/tools/md5table.c
+++ b/tools/md5table.c
@@ -77,6 +77,7 @@ typedef struct {
* common/util.h).
*/
static const StringMap platformMap[] = {
+ { "2gs", "kPlatformApple2GS" },
{ "3DO", "kPlatform3DO" },
{ "Amiga", "kPlatformAmiga" },
{ "Atari", "kPlatformAtariST" },
diff --git a/tools/module.mk b/tools/module.mk
index 4117ceac77..5248454382 100644
--- a/tools/module.mk
+++ b/tools/module.mk
@@ -65,7 +65,6 @@ md5scumm: tools/md5table$(EXEEXT)
tools/md5table$(EXEEXT) --c++ < $(srcdir)/tools/scumm-md5.txt > $(srcdir)/engines/scumm/scumm-md5.h
cp $(srcdir)/tools/scumm-md5.txt $(srcdir)/../../web/trunk/data/scumm-md5.txt
-
#
# Rules which automatically and implicitly rebuild the credits and
# MD5 tables when needed.
diff --git a/tools/po2c b/tools/po2c
new file mode 100755
index 0000000000..10e15338c7
--- /dev/null
+++ b/tools/po2c
@@ -0,0 +1,277 @@
+#!/usr/bin/perl
+
+#
+# po2c - Converts .po files to C code
+#
+# Copyright (C) 2004 Angel Ortega <angel@triptico.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# http://www.triptico.com
+#
+
+$VERSION = "1.0.2-scummvm";
+
+if(scalar(@ARGV) == 0)
+{
+ print "Usage: po2c {po file[s]}\n";
+ exit 1;
+}
+
+%msgs = ();
+%msgids = ();
+
+# stage 1: loading
+
+# arguments are .po files
+foreach my $f (@ARGV)
+{
+ my ($lang);
+ my ($langDesc);
+
+ next unless(($lang) = ($f =~ /([^\/]+)\.po$/));
+
+ if(open F, $f)
+ {
+ my ($msgid, $val, %a);
+
+ while(<F>)
+ {
+ chomp;
+
+ # ignore blank lines or comments
+ next if /^$/ or /^#/;
+
+ if(/^msgid\s+\"(.*)\"\s*$/)
+ {
+ # store previous msgid
+ if(defined($msgid))
+ {
+ $a{$msgid} = $val;
+ $msgids{$msgid} ++;
+ }
+
+ # start of msgid
+ $val = $1;
+ }
+ elsif(/^msgstr\s+\"(.*)\"\s*$/)
+ {
+ # store previous msgid
+ $msgid = $val;
+
+ # start of msgstr
+ $val = $1;
+ }
+ elsif(/^\"(.*)\"\s*$/)
+ {
+ # add to current value
+ $val .= $1;
+ }
+ }
+
+ # store previous msgid
+ if(defined($msgid))
+ {
+ $a{$msgid} = $val;
+ $msgids{$msgid} ++;
+ }
+
+ close F;
+
+ # add to the global message pool
+ $msgs{$lang} = \%a;
+ }
+}
+
+# stage 2: convert the data
+
+# stores all sorted msgids into @msgids
+@msgids = sort(keys(%msgids));
+
+# travels again, storing indexes into %msgids
+for(my $n = 0;$n < scalar(@msgids);$n++)
+{
+ $msgids{$msgids[$n]} = $n;
+}
+
+# stage 3: dump as C++ code
+
+print "// generated by po2c $VERSION - Do not modify\n\n";
+
+# dump first the msgid array
+print "static const char * const _messageIds[] = {\n";
+
+for(my $n = 0;$n < scalar(@msgids);$n++)
+{
+ print "\t/* $n */ \"" . $msgids[$n] . "\",\n";
+}
+
+print "\tNULL\n};\n\n";
+
+# dump the lang structure
+print "struct PoMessageEntry {\n";
+print "\tint msgid;\n";
+print "\tconst char *msgstr;\n";
+print "};\n\n";
+
+# dump now each language
+
+foreach my $l (keys(%msgs))
+{
+ print "static const PoMessageEntry _translation_${l}\[\] = {\n";
+
+ # get the translation table for the language $l
+ my ($m) = $msgs{$l};
+
+# while (my ($msgstr, $msgid) = each (%$m))
+ foreach my $msgid (sort(keys(%$m)))
+ {
+ my ($msgstr) = "";
+
+ # make it 7-bit safe
+ foreach $c (split(//, $m->{$msgid})) {
+ if (ord($c) > 0x7f) {
+ $msgstr .= sprintf("\\%o", ord($c));
+ } else {
+ $msgstr .= $c;
+ }
+ }
+
+ print "\t{ " . $msgids{$msgid} . ", \"" . $msgstr . "\" },\n"
+ if $msgstr;
+ }
+
+ print "\t{ -1, NULL }\n};\n\n";
+}
+
+# finally, dump the languages
+
+print "struct PoLangEntry {\n";
+print "\tconst char *lang;\n";
+print "\tconst char *charset;\n";
+print "\tconst char *langname;\n";
+print "\tconst PoMessageEntry *msgs;\n";
+print "};\n\n";
+print "const PoLangEntry _translations[] = {\n";
+
+foreach my $l (keys(%msgs))
+{
+ # charset
+ $header = $msgs{$l}->{""};
+ $header =~ /charset=([^\\]+)/;
+ $charset = $1;
+ # user readable language name
+ $lang = "NULL";
+ $header = $msgs{$l}->{""};
+ $header =~ /Language:[\s]*([^\\]*)/;
+ unless ($1 eq "")
+ {
+ $lang = "\"" . $1 . "\"";
+ }
+ print "\t{ \"" . $l . "\", \"" . $charset . "\", " . $lang . ", _translation_${l} },\n";
+}
+
+print "\t{ NULL, NULL, NULL, NULL }\n};\n\n";
+
+print "// code\n";
+print << 'EOF';
+
+static const PoMessageEntry *_currentTranslation = NULL;
+static int _currentTranslationMessageEntryCount = 0;
+static const char *_currentTranslationCharset = NULL;
+
+void po2c_setlang(const char *lang) {
+ _currentTranslation = NULL;
+ _currentTranslationMessageEntryCount = 0;
+ _currentTranslationCharset = NULL;
+
+ // if lang is NULL or "", deactivate it
+ if (lang == NULL || *lang == '\0')
+ return;
+
+ // searches for a valid language array
+ for (int i = 0; _currentTranslation == NULL && _translations[i].lang != NULL; ++i) {
+ if (strcmp(lang, _translations[i].lang) == 0) {
+ _currentTranslation = _translations[i].msgs;
+ _currentTranslationCharset = _translations[i].charset;
+ }
+ }
+
+ // try partial searches
+ for (int i = 0; _currentTranslation == NULL && _translations[i].lang != NULL; ++i) {
+ if (strncmp(lang, _translations[i].lang, 2) == 0) {
+ _currentTranslation = _translations[i].msgs;
+ _currentTranslationCharset = _translations[i].charset;
+ }
+ }
+
+ // if found, count entries
+ if (_currentTranslation != NULL) {
+ for (const PoMessageEntry *m = _currentTranslation; m->msgid != -1; ++m)
+ ++_currentTranslationMessageEntryCount;
+ }
+}
+
+const char *po2c_gettext(const char *msgid) {
+ // if no language is set or msgid is empty, return msgid as is
+ if (_currentTranslation == NULL || *msgid == '\0')
+ return msgid;
+
+ // binary-search for the msgid
+ int leftIndex = 0;
+ int rightIndex = _currentTranslationMessageEntryCount - 1;
+
+ while (rightIndex >= leftIndex) {
+ const int midIndex = (leftIndex + rightIndex) / 2;
+ const PoMessageEntry * const m = &_currentTranslation[midIndex];
+
+ const int compareResult = strcmp(msgid, _messageIds[m->msgid]);
+
+ if (compareResult == 0)
+ return m->msgstr;
+ else if (compareResult < 0)
+ rightIndex = midIndex - 1;
+ else
+ leftIndex = midIndex + 1;
+ }
+
+ return msgid;
+}
+
+const char *po2c_getcharset(void) {
+ if (_currentTranslationCharset)
+ return _currentTranslationCharset;
+ else
+ return "ASCII";
+}
+
+int po2c_getnumlangs(void) {
+ return ARRAYSIZE(_translations) - 1;
+}
+
+const char *po2c_getlang(const int num) {
+ assert(num < ARRAYSIZE(_translations));
+ return _translations[num].lang;
+}
+
+const char *po2c_getlangname(const int num) {
+ assert(num < ARRAYSIZE(_translations));
+ if (_translations[num].langname != NULL)
+ return _translations[num].langname;
+ return _translations[num].lang;
+}
+EOF
+
+exit 0;
diff --git a/tools/scumm-md5.txt b/tools/scumm-md5.txt
index 7b9918ba43..b379bc837e 100644
--- a/tools/scumm-md5.txt
+++ b/tools/scumm-md5.txt
@@ -60,7 +60,7 @@ maniac Maniac Mansion
7f45ddd6dbfbf8f80c0c0efea4c295bc 1972 en DOS V1 V1 - Fingolfin
- 17f7296f63c78642724f057fd8e736a7 -1 gb NES NES -
+ 17f7296f63c78642724f057fd8e736a7 2082 gb NES NES -
91d5db93187fab54d823f73bd6441cb6 -1 us NES NES -
1c7e7db2cfab1ad62746ab680a634204 -1 fr NES NES -
3a5ec90d556d4920976c5578bfbfaf79 -1 de NES NES -
@@ -172,10 +172,10 @@ loom Loom
5d88b9d6a88e6f8e90cded9d01b7f082 8307 en DOS VGA VGA CD Version v1.0 from 10. Feb 92 (Talkie) Peter Eckerlein, Fingolfin
- c5d10e190d4b4d59114b824f2fdbd00e -1 en FM-TOWNS FM-TOWNS - - dhewg, Andrea Petrucci
+ c5d10e190d4b4d59114b824f2fdbd00e 7540 en FM-TOWNS FM-TOWNS - - dhewg, Andrea Petrucci
31b8fda4c8c7413fa6b39997e776eba4 -1 jp FM-TOWNS FM-TOWNS - - khalek, Andrea Petrucci
- 0aa050f4ad79402fbe9c4f78fb8ac494 -1 en PC-Engine PC-Engine - - Kirben
+ 0aa050f4ad79402fbe9c4f78fb8ac494 6532 en PC-Engine PC-Engine - - Kirben
79b05f628586837e7166e82b2279bb50 -1 jp PC-Engine PC-Engine - - clone2727
5a35e36fd777e9c37a49c5b2faca52f9 6108 en DOS EGA EGA Demo non-interactive Fingolfin
@@ -189,7 +189,7 @@ monkey The Secret of Monkey Island
49210e124e4c2b30f1290a9ef6306301 8357 en DOS EGA EGA 8 disk v1.0, 9/18/90 Fingolfin
1dd3c11ea4439adfe681e4e405b624e1 -1 fr DOS EGA EGA 8 disk Andrea Petrucci
- fc6b6148e80d67939d9a18697c0f626a -1 de DOS EGA EGA 8 disk ghoostkilla
+ fc6b6148e80d67939d9a18697c0f626a 8367 de DOS EGA EGA 8 disk ghoostkilla
910e31cffb28226bd68c569668a0d6b4 -1 es DOS EGA EGA 8 disk Andrea Petrucci
1d05cd189e4908f79b57e78a4402f292 -1 en DOS EGA EGA 4 disk Andrea Petrucci
ce6a4cef315b20fef58a95bc40a2d8d3 -1 fr DOS EGA EGA 4 disk Matthieu Milan
@@ -225,12 +225,12 @@ monkey The Secret of Monkey Island
c13225cb1bbd3bc9fe578301696d8021 -1 en SEGA SEGA - -
057c9b456dedcc4d71b991a3072a20b3 9465 jp SEGA SEGA - - GloKidd
- 8eb84cee9b429314c7f0bdcf560723eb -1 en FM-TOWNS FM-TOWNS - - Paul Priest, Andrea Petrucci
+ 8eb84cee9b429314c7f0bdcf560723eb 9925 en FM-TOWNS FM-TOWNS - - Paul Priest, Andrea Petrucci
e17db1ddf91b39ca6bbc8ad3ed19e883 -1 jp FM-TOWNS FM-TOWNS - - Paul Priest, Andrea Petrucci
71523b539491527d9860f4407faf0411 7607 en DOS Demo EGA Demo - Fingolfin
771bc18ec6f93837b839c992b211904b -1 de DOS Demo EGA Demo - khalek
- 54a936ad06161ff7bfefcb96200f7bff -1 en Amiga VGA VGA Demo - khalek
+ 54a936ad06161ff7bfefcb96200f7bff 7617 en Amiga VGA VGA Demo - khalek
pass Passport to Adventure
e6cd81b25ab1453a8a6d3482118c391e 7857 en DOS - - v1.0 9/14/90 Fingolfin
@@ -279,8 +279,9 @@ atlantis Indiana Jones and the Fate of Atlantis
1a6e5ae2777a6a33f06ffc0226210934 -1 en Mac - CD - Scott Summers
2d9d46f23cb07bbc90b8ad464d3e4ff8 -1 en Mac - CD Mac bundle Joachim Eberhard
8e9417564f33790815445b2136efa667 11915 jp Mac - CD - Petr Maruska
+ e8d0697906e53fee8b7e9f5652696da8 11915 jp DOS - CD - Petr Maruska, tracker #3017219
- c7be10f775404fd9785a8b92a06d240c -1 en FM-TOWNS - - - dhewg, Andrea Petrucci
+ c7be10f775404fd9785a8b92a06d240c 12030 en FM-TOWNS - - - dhewg, Andrea Petrucci
4d34042713958b971cb139fba4658586 -1 jp FM-TOWNS - - - Andrea Petrucci
035deab53b47bc43abc763560d0f8d4b -1 en DOS Floppy Demo -
@@ -325,7 +326,7 @@ samnmax Sam &amp; Max Hit the Road
0f6f2e716ba896a44e5059bba1de7ca9 -1 it All? - CD - Andrea Petrucci
4ba7fb331296c283e73d8f5b2096e551 -1 es All? - CD - Andrea Petrucci
d43352a805d78b5f4936c6d7779bf575 -1 ru DOS - CD -
- 166553538ff320c69edafeee29525419 -1 en Mac - CD Mac bundle Joachim Eberhard
+ 166553538ff320c69edafeee29525419 199195304 en Mac - CD Mac bundle Joachim Eberhard
3a5d13675e9a23aedac0bac7730f0ac1 -1 fr Mac - CD Mac bundle ThierryFR
c3196c5349e53e387aaff1533d95e53a -1 en DOS Floppy Demo -
@@ -386,7 +387,7 @@ football Backyard Football
7fc6cdb46b4c9d384c52327f4bca6416 -1 en All - - - sev
425205754fa749f4f0b0dd9d09fa45fd -1 en All - Demo - Joachim Eberhard
- 5bd335265a61caa3d78956ad9f88ba23 -1 en All - Demo - sev
+ 5bd335265a61caa3d78956ad9f88ba23 23135 en All - Demo - sev
football2002 Backyard Football 2002
a095616d2d23ccf43b8e257711202cba -1 en All - - - clone2727
@@ -484,6 +485,12 @@ freddi Freddi Fish 1: The Case of the Missing Kelp Seeds
a197a87ae77f3b3333f09a7a2c448fe2 -1 en Windows HE 99 Updated - Jonathan
af2bd1a43b50b55915d87994e093203d 34829 de Windows HE 99 Updated - Lightkey
57a5cfec9ef231a007043cc1917e8988 -1 en Wii HE 100 - - sanguinehearts
+ 56b5922751be7ffd771b38dda56b028b 34837 nl Wii HE 100 - - George Kormendi
+ 3ae7f002d9256b8bdf76aaf8a3a069f8 34837 gb Wii HE 100 - - George Kormendi
+ 30d1903b0715759af064be2127381cd0 34837 de Wii HE 100 - - George Kormendi
+ 4afb734df8315ee412669c812d4cf0a1 34837 fr Wii HE 100 - - George Kormendi
+ a59a438cb182124c30c4447d8ed469e9 34837 nb Wii HE 100 - - George Kormendi
+ 880c5ca5b944648b3f8b03feb41705a8 34837 se Wii HE 100 - - George Kormendi
c7c492a107ec520d7a7943037d0ca54a -1 nl Windows HE 71 Demo - DarthBo
084ed0fa98a6d1e9368d67fe9cfbd417 -1 en Windows HE 71 Demo - khalek
@@ -557,7 +564,7 @@ freddicove Freddi Fish 5: The Case of the Creature of Coral Cove
4ce2d5b355964bbcb5e5ce73236ef868 -1 ru Windows HE 100 - - sev
6b257bb2827dd894b8109a50a1a18b5a -1 nl All HE 100 Demo - Kirben, sev
- 45082a5c9f42ba14dacfe1fdeeba819d -1 en All HE 100 Demo - sev
+ 45082a5c9f42ba14dacfe1fdeeba819d 18422 en All HE 100 Demo - sev
maze Freddi Fish and Luther's Maze Madness
4f04b321a95d4315ce6d65f8e1dd0368 -1 us All HE 80 - - Kirben
@@ -587,7 +594,7 @@ airport Let's Explore the Airport with Buzzy
7ea2da67ebabea4ac20cee9f4f9d2934 -1 en Mac - Demo - khalek
8ffd618a776a4c0d8922bb28b09f8ce8 -1 en Windows - Demo - khalek
- e144f5f49d9241d2a9dee2576b3d09cb -1 en Windows - Demo - khalek
+ e144f5f49d9241d2a9dee2576b3d09cb 51152 en Windows - Demo - khalek
86c9902b7bec1a17926d4dae85beaa45 -1 en Windows HE 71 Demo - khalek
farm Let's Explore the Farm with Buzzy
@@ -599,7 +606,7 @@ farm Let's Explore the Farm with Buzzy
39fd6db10d0222d817025c4d3346e3b4 -1 en Mac - Demo - Joachim Eberhard
bf8b52fdd9a69c67f34e8e9fec72661c -1 en Windows HE 71 Demo - khalek, sev
0557df19f046a84c2fdc63507c6616cb -1 nl Windows HE 72 Demo - adutchguy
- 8d479e36f35e80257dfc102cf4b8a912 -1 en Windows HE 72 Demo - khalek, sev
+ 8d479e36f35e80257dfc102cf4b8a912 34333 en Windows HE 72 Demo - khalek, sev
jungle Let's Explore the Jungle with Buzzy
659942b9a6b519f123a13cca3c333a13 -1 en Mac - - - Joachim Eberhard
@@ -652,13 +659,13 @@ pajama3 Pajama Sam 3: You Are What You Eat From Your Head to Your Feet
f08145577e4f13584cc90b3d6e9caa55 -1 nl All - Demo - joostp
a654fb60c3b67d6317a7894ffd9f25c5 -1 us All - Demo - sev
a9f2f04b1ecaab9495b59befffe9bf88 -1 us All - Demo - sev
- 0c45eb4baff0c12c3d9dfa889c8070ab -1 de All - Demo - Joachim Eberhard
+ 0c45eb4baff0c12c3d9dfa889c8070ab 13884 de All - Demo - Joachim Eberhard
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
+ cf90b4db5486ef798db78fe6fbf897e5 13902 us Windows - Demo - khalek
pjgames Pajama Sam: Games to Play on Any Day
8a484262363a8e18be87112454f1456b -1 us All - - - Kirben
@@ -749,10 +756,10 @@ puttzoo Putt-Putt Saves the Zoo
3a3e592b074f595489f7f11e150c398d -1 us Windows HE 99 Updated - Adrian
c5cc7cba02a2fbd539c4439e775b0536 43470 de Windows HE 99 Updated - Lightkey
- 3486ede0f904789267d4bcc5537a46d4 -1 en Mac - Demo - khalek
+ 3486ede0f904789267d4bcc5537a46d4 14337 en Mac - Demo - khalek
d220d154aafbfa12bd6f3ab1b2dae420 -1 de Mac - Demo - Joachim Eberhard
aa81aa6d5545ce172fdba81f2e2f9d36 -1 nl Windows - Demo - DarthBo
- de4efb910210736813c9a1185384bace -1 en Windows HE 72 Demo - khalek
+ de4efb910210736813c9a1185384bace 14337 en Windows HE 72 Demo - khalek
f3d55aea441e260e9e9c7d2a187097e0 14337 en Windows - Demo - khalek
65fa23d6884e8ca23d5d2406d70de7e8 -1 fr Windows - Demo - gist974
2a446817ffcabfef8716e0c456ecaf81 -1 de Windows - Demo - Joachim Eberhard
@@ -831,7 +838,7 @@ spyfox2 SPY Fox 2: Some Assembly Required
90e2f0af4f779629695c6394a65bb702 -1 fr All - - - gist974, ThierryFR
bc4700bc0e12879f6d25d14d6be6cfdd -1 de All - - - Joachim Eberhard
cea91e3dd47f2518ea418e41611aa77f -1 ru All - - - sev
- 9fd66fb3b04703bd50da4356e4202558 -1 en Mac - - - pix_climber
+ 9fd66fb3b04703bd50da4356e4202558 51295 en Mac - - - pix_climber
71fe97c3108678cf604f14abe342341b -1 nl Windows - - - adutchguy
1c792d28376d45e145cb916bca0400a2 -1 nl All - Demo - joostp
@@ -850,7 +857,7 @@ spyozon SPY Fox 3: Operation Ozone
7015b059ab72cff3a0ef9fb4d5e9889d -1 de Windows - - - andy482
be39a5d4db60e8aa736b9086778cb45c -1 gb Windows - - -
- ebd0b2c8a387f18887282afe6cad894a -1 en All - Demo - Kirben
+ ebd0b2c8a387f18887282afe6cad894a 15317 en All - Demo - Kirben
a99c39ba65b6086be28aef576da69595 -1 fr Windows - Demo - Mevi
65563295c3a06493351870f20a1630cf 5235008 All All HE CUP Preview - sev
diff --git a/tools/update-version.pl b/tools/update-version.pl
index f151ae7514..81aa5c27f9 100755
--- a/tools/update-version.pl
+++ b/tools/update-version.pl
@@ -40,6 +40,7 @@ my @subs_files = qw(
dists/iphone/Info.plist
dists/irix/scummvm.spec
dists/wii/meta.xml
+ dists/android/AndroidManifest.xml
backends/platform/psp/README.PSP
);